我正在使用 flex、byacc(用于词法和解析)和 C++ 开发一种类似 python 的小型语言,但我有一些关于范围控制的问题。
就像 python 一样,它使用空格(或制表符)进行缩进,不仅如此,我还想实现索引中断,例如,如果您在另一个 while 循环内的 while 循环内键入“break 2”,它不仅会从最后一个,但也来自第一个循环(因此break后的数字为2),依此类推。
example:
while 1
while 1
break 2
'hello world'!! #will never reach this. "!!" outputs with a newline
end
'hello world again'!! #also will never reach this. again "!!" used for cout
end
#after break 2 it would jump right here
但由于我没有“反”制表符来检查作用域何时结束(例如 C,我只会使用“}”字符),我想知道这种方法是否是最好的:
我将在 yacc 文件上定义一个全局变量,例如“int tabIndex”,我将使用 extern 在 lex 文件中访问该变量。然后每次我在 lex 文件上找到制表符时,我都会将该变量增加 1。在解析 yacc 文件时,如果我找到“break”关键字,我会减少从 tabIndex 变量中在其后面键入的金额,并且当编译后到达 EOF,得到 tabIndex != 0 我会输出编译错误。
现在的问题是,查看缩进是否减少的最佳方法是什么,我应该从 lex 读取 \b (退格)字符,然后减少 tabIndex 变量(当用户不使用break时)?
另一种方法来实现这一目标?
还有另一个小问题,我希望每个可执行文件都在名为 start() 的函数上有其起点,我应该将其硬编码到我的 yacc 文件中吗?
很抱歉问了这么长的问题,非常感谢任何帮助。另外,如果有人可以为 python 提供 yacc 文件作为指南,那就太好了(尝试在 Google 上查找,但没有运气)。
提前致谢。
我目前正在实现一种与此非常相似的编程语言(包括奇怪的多级中断)。我的解决方案是让标记生成器根据缩进发出缩进和缩进标记。例如:
while 1: # colons help :)
print('foo')
break 1
becomes:
["while", "1", ":",
indent,
"print", "(", "'foo'", ")",
"break", "1",
dedent]
但这使得分词器对 '\n' 的处理有些复杂。另外,我从头开始编写了分词器和解析器,所以我不确定这在 lex 和 yacc 中是否可行。
Edit:
半工作伪代码示例:
level = 0
levels = []
for c = getc():
if c=='\n':
emit('\n')
n = 0
while (c=getc())==' ':
n += 1
if n > level:
emit(indent)
push(levels,n)
while n < level:
emit(dedent)
level = pop(levels)
if level < n:
error tokenize
# fall through
emit(c) #lazy example
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)