使野牛开始使用除开始规则以外的其他规则进行解析 [英] Make bison start parsing with a rule other than the start rule
问题描述
当前,我正在使用源到源编译器,并且已经编写了一个野牛解析器,可以为输入正确创建AST.我现在需要对语法树进行一些转换,因此需要在树中插入许多节点.
Currently I'm working on a source-to-source compiler and I have already written a bison parser that creates the AST for the input correctly. I need to do several transformations on the syntax tree now and therefore I need to insert many nodes to the tree.
我可以手动创建要添加到语法树中的所有结构/联合,但这似乎非常,需要很多工作.
I could create all the structs/unions that I want to add to the syntax tree manually, but this seems to be very much work.
对我来说,创建一个字符串要容易得多,并且我希望该字符串由已经拥有的解析器进行解析.然后解析器应返回此字符串的树,我可以将其插入原始语法树中.
It would be much easier for me to create a string and I want this string to be parsed by the parser I already have. The parser should then return the tree for this string, which I can insert in my original syntax tree.
不幸的是,无法使用解析器的开始规则来解析字符串,因为它必须由子规则解析(例如,我的解析器解析包含语句的函数列表,字符串是单个语句).
Unfortunately, the string cannot be parsed with the start rule of my parser, since it must be parsed by a subrule (e.g. my parser parses a list of functions containing statements, the string is a single statement).
我如何使野牛解析一个字符串,并从与起始规则不同的规则开始?
How can I make bison parse a string, starting with a rule different from the start rule?
提前谢谢!
推荐答案
There is a simple hack, which is described in the bison FAQ..
基本上,对于要使用的每个非终端,创建一个伪令牌,然后创建元启动"非终端,该非终端选择要使用的终端:
Basically, for each non-terminal which you would like to be able to use, you create one pseudo-token, and then you create a "meta-start" non-terminal which selects the terminal you want to use:
%token START_PROGRAM
%token START_STATEMENT
%token START_EXPRESSION
%start meta_start
%%
meta_start: START_PROGRAM program
| START_STATEMENT statement
| START_EXPRESSION expression
;
(在每个生产中的操作中,您将$2
的值保存在调用者可以使用的位置.)
(In the action for each of those productions, you would save the value of $2
somewhere that your caller can get at it.)
现在,您只需要安排词法分析器来交付正确的开始令牌即可.您可以通过使用纯解析器和纯词法分析器,然后通过共享数据结构传递消息来做到这一点.那将是最好的方法,但是出于这个答案的目的,我将仅演示如何使用全局变量,因为其原理是相同的:
Now you just need to arrange for your lexer to deliver the correct start token. You can do this by using a pure parser and a pure lexer and delivering the message through a shared datastructure. That would be the best way to do it, but for the purposes of this answer I'll just show how to do it with a global variable, since the principle is the same:
extern int start_token;
// If all your start non-terminals produce a value of the same type, possibly a union
// type, you could arrange to return it instead of the error report.
int yyparse(int start) {
// I left out the code to cause the lexer to scan a given string.
start_token = start;
return real_yyparse();
}
int yylex() {
int rv = start_token;
if (start_token)
start_token = 0;
else
rv = real_yylex();
return rv;
}
这篇关于使野牛开始使用除开始规则以外的其他规则进行解析的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!