在开发类似语言的小python时进行缩进控制

时间:2010-04-30 02:34:58

标签: c++ c yacc lex compiler-theory

我正在使用flex,byacc(用于词汇和解析)和C ++开发一个类似语言的小python,但我对范围控制有一些问题。

就像python一样,它使用白色空格(或制表符)进行缩进,不仅如此,但我想实现索引破坏,例如,如果你在while循环中键入“break 2”,那么在另一个while循环中它不仅会从最后一个中断,但也从第一个循环中断(因此中断后的数字2),依此类推。

示例:

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文件会很好作为指南(尝试在谷歌上看,没有运气)。

提前感谢。

2 个答案:

答案 0 :(得分:8)

我目前正在实现一种与此类似的编程语言(包括奇怪的多级中断)。我的解决方案是让tokenizer根据缩进发出缩进和dedent标记。例如:

while 1: # colons help :)
    print('foo')
    break 1

变为:

["while", "1", ":",
    indent,
    "print", "(", "'foo'", ")",
    "break", "1",
    dedent]

它使得tokenizer对'\ n'的处理有点复杂。另外,我从头开始编写了tokenizer和parser,所以我不确定这在lex和yacc中是否可行。

编辑:

半工作伪代码示例:

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

答案 1 :(得分:3)

非常有趣的运动。您是否可以使用end关键字来检查范围何时结束?

另一方面,我从未见过一种允许你同时突破几个嵌套循环的语言。可能有充分的理由......