【发布时间】:2011-08-04 05:08:43
【问题描述】:
我知道如何让 YACC 生成一个 AST,但是你是怎么得到它的呢?我的意思是,你如何从 YACC 中获取根节点的值?
【问题讨论】:
-
你们似乎都不明白我的问题。 我实际上从哪里获得根非终结符的语义值?
我知道如何让 YACC 生成一个 AST,但是你是怎么得到它的呢?我的意思是,你如何从 YACC 中获取根节点的值?
【问题讨论】:
Yacc 一次只给你一个节点,它总是是你在早些时候给 yacc 的东西,即你想从减少的生产中返回的任何东西,或者你想要的任何东西从终端符号返回。 (抱歉,你说你知道,但有些人可能不知道。)
所以,把你想从根或顶级规则返回的任何内容,并以你喜欢的任何方式保存(在你附加的 C 简化代码中)。
【讨论】:
toprule: expression_list { some_global = whatever_you_were_going_to_return }; 换句话说,你只需写 { globalsym = e; } 而不是 { $$ = e; }。
Yacc 为您提供的是解析树,它与 AST 不同。在遍历解析树的每个节点(通过 yacc)时,您需要自己构建 AST。
【讨论】:
我就是这样做的:
在 yacc 文件 (your_grammar.y) 中:
%parse-param {AstNode **pproot}
%parse-param {char **errmsg}
在调用程序(your_program.c)中:
res = yyparse(&pAst, &errmsg);
AST 节点在 yyparse() 中被分配和链接为树(你自己做逻辑),根节点的地址在 pAst 指针中传回。
【讨论】:
它不像让解析器直接返回一个 AST 那样优雅,但我想出的最好的方法是拥有一个全局数据结构(例如向量或链表),以及线程安全的插入方法如果需要线程安全,并让顶级 yacc 规则将其结果(又名$$)添加到该数据结构。然后您可以在其他功能中访问此结果。当然,如果您只想输出一个 AST,可能只需要一个指向该 AST 的全局指针,而不是一个充满它们的数据结构。
【讨论】: