如何从YACC获取AST?

9

我知道如何让YACC生成一个抽象语法树(AST),但是你怎么才能得到它呢?我的意思是,你怎么才能从YACC中获得根节点的值呢?


1
你们似乎都不理解我的问题。我到底在哪里得到根非终端的语义值? - mtk358
4个回答

8

Yacc每次只返回一个节点,而且它总是你之前在reduced production中想要返回的任何内容,或者从终端符号中想要返回的任何内容。把根规则或顶级规则中想要返回的任何内容保存下来(在你附加的C reduction代码中),以任何你喜欢的方式保存。

(抱歉,你说你知道这个,但是有些人可能不知道。)


2
我该如何获取顶部规则返回的内容?这就是我的整个问题所在! - mtk358
简单来说,就像这样:toprule: expression_list { some_global = whatever_you_were_going_to_return }; 换句话说,你可以用 { globalsym = e; } 来代替 { $$ = e; } - DigitalRoss
2
嗯,那不是线程安全的。你能想出一个线程安全的解决方案吗?顺便说一句:我在bison中使用了一个纯推解析器。 - Flavius

2
Yacc提供的是语法分析树,不同于抽象语法树(AST)。在遍历每个语法分析树节点时(通过yacc),您需要自行构建AST。

1
这是什么意思,它与我的问题有什么关联? - mtk358
AST与解析树在本质上是不同的。解析树仍然在树中包含语法信息,而AST则没有。Yacc不能给你AST,它只能给你解析树。您可以从维基百科了解它们的区别。 因此,您无法从yacc中获取它的答案。您必须定义自己的AST节点并从解析树构建它。 - ryaner
请向我解释一下yacc在这里如何_不_生成AST:http://pastebin.com/SBfbMXNB - mtk358
哦,这明显是个误解,我的错。看起来问题实际上是关于如何从C++与yacc和lex接口。 对于这种情况,我没有头脑中的答案,抱歉 =(。 我能做的最好的事情就是给你展示一些例子(如果您正在使用bison),请参见此处http://en.wikipedia.org/wiki/GNU_bison。还可以阅读官方手册,例如:http://www.gnu.org/software/bison/manual/bison.html#C_002b_002b-Bison-Interface。 - ryaner

1
这是我的做法:
在yacc文件(your_grammar.y)中:
%parse-param {AstNode **pproot}
%parse-param {char **errmsg}

在调用程序中(your_program.c):
res = yyparse(&pAst, &errmsg);

AST节点在yyparse()函数内部被分配和链接成树形结构(您需要编写逻辑),根节点的地址通过pAst指针返回。


0

虽然不如解析器直接返回AST那样优雅,但我想到的最好方法是使用一个全局数据结构(例如向量或链表),如果需要线程安全,则使用线程安全的插入方法,并且让顶层yacc规则将其结果(即$$)添加到该数据结构中。然后,您可以在其他函数中访问此结果。当然,如果您只打算输出一个单独的AST,那么只需要一个指向该AST的全局指针,而不是一个充满它们的数据结构。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接