PLY: C解析器中的令牌移动问题

3 投票
3 回答
874 浏览
提问于 2025-04-11 09:17

我正在用 PLY 写一个 C 语言解析器,最近遇到了一个问题。

这段代码:

typedef int my_type;
my_type x;

是正确的 C 代码,因为 my_type 在使用之前已经定义过了。我通过在解析器中填充一个类型符号表来处理这个问题,这个符号表会被词法分析器用来区分类型和简单的标识符。

但是,虽然类型声明规则以分号(';')结束,PLY 在决定第一个声明完成之前,就已经把第二行的 my_type 这个标记移走了。因此,我没有机会把类型符号表的更新传递给词法分析器,结果它把 my_type 视为一个标识符,而不是一个类型。

有没有什么解决办法?

完整代码可以在这里找到:http://code.google.com/p/pycparser/source/browse/trunk/src/c_parser.py。我不太确定怎么从中创建一个更小的示例。

编辑:

问题解决了。请看我下面的解决方案。

3 个回答

1

我觉得你需要把检查一个ID是否是TYPEID的这部分,从c_lexer.py移动到c_parser.py。

正如你所说,解析器只看前面一个标记,所以在词法分析器里无法做出这个判断。

相反,你应该修改你的解析器,去检查ID是否在声明中是TYPEID,如果不是,就生成一个错误。

正如Pax Diablo在他精彩的回答中提到的,词法分析器/标记器的工作不是去做这些关于标记的判断。这是解析器的工作。

3

我不太明白你为什么要在词法分析器中进行这么复杂的分析。

词法分析的主要任务是把输入的数据流分成一个个词法单元,比如数字、换行符、关键字等等。真正进行深入分析的应该是解析阶段,这个阶段会处理像类型定义查找这样的事情。

这就是我一直以来在使用lex和yacc这两个工具时,分配任务的方式。

2

在Dave Beazley(PLY的创始人)的一些帮助下,我的问题解决了。

这个想法是使用特殊的子规则,并在其中执行操作。在我的例子中,我把declaration规则拆分成了:

def p_decl_body(self, p):
    """ decl_body : declaration_specifiers init_declarator_list_opt
    """
    # <<Handle the declaration here>>        

def p_declaration(self, p):
    """ declaration : decl_body SEMI 
    """
    p[0] = p[1]

decl_body总是在处理分号(SEMI)后面的标记之前被简化,所以我的操作在正确的时间执行。

撰写回答