处理yacc中的块
我正在使用lex+yacc为以下简单语言构建解析器:处理yacc中的块,c,yacc,C,Yacc,我正在使用lex+yacc为以下简单语言构建解析器: lines are parsed ok foo { lines of the "foo" category come here } # closing this block 在我的语法中,块的以下定义有效: item : block | lines; /* lines without a block */ block: WORD BRACE_OPEN NL lines BRACE_CLOSE { printf(
lines are parsed ok
foo {
lines of the "foo" category come here
} # closing this block
在我的语法中,块的以下定义有效:
item : block
| lines; /* lines without a block */
block: WORD BRACE_OPEN NL lines BRACE_CLOSE
{ printf("category: %s\n", $1 );}
问题是printf
发生在解析块之后,但我需要获取类别名称(“示例中的foo”)作为解析块内行的信息
我想出了一个解决方案,但它似乎不太优雅:
item : line
| block_open
| block_close;
block_open : WORD BRACE_OPEN { printf("%s {\n", $1); };
block_close : BRACE_CLOSE { printf("}\n"); };
我现在可以在打开块时获取“类别”名称。但这是正确的还是最好的方法
谢谢
问题是printf发生在解析块之后
这是因为yacc是一个自底向上的解析器。AST的叶在中间节点之前构建
如果希望块的类型影响其内部的解析,则自顶向下的方法(如递归下降解析器)可能更自然
但我需要获取类别名称(示例中的“foo”)作为解析块中的行的信息
我认为最简单的方法是为每种类型的块使用不同的语法规则,而不是通用的“块”规则。例如:
foo_block: FOO BRACE_OPEN foo_lines BRACE_CLOSE;
bar_block: BAR BRACE_OPEN bar_lines BRACE_CLOSE;
baz_block: BAZ BRACE_OPEN baz_lines BRACE_CLOSE;
这假设“foo”和“bar”以及“baz”是词法分析人员知道的关键字,而不仅仅是一般性的单词
block: WORD BRACE_OPEN NL lines BRACE_CLOSE
{ printf("category: %s\n", $1 );}
您可以将操作放在任何位置(尽管它可能会导致s/r冲突):
这相当于
block
: category BRACE_OPEN NL lines BRACE_CLOSE
;
category
: WORD
{ printf("category: %s\n", $1 );}
;
您可能更喜欢后者。块内的行的语法是否因类别而异?不,与“类别”块外的行的语法相同。
block
: category BRACE_OPEN NL lines BRACE_CLOSE
;
category
: WORD
{ printf("category: %s\n", $1 );}
;