我是解析新手。以下是Bison中解析器的代码片段:
Parser.y :
%{
#include <stdio.h>
%}
/* declare tokens */
%token NUMBER
%token ADD SUB MUL DIV ABS
%token EOL
%%
calclist: /* nothing */
| calclist exp EOL { printf("= %d\n", $1); }
;
exp: factor
| exp ADD factor { $$ = $1 + $3; }
| exp SUB factor { $$ = $1 - $3; }
;
factor: term
| factor MUL term { $$ = $1 * $3; }
| factor DIV term { $$ = $1 / $3; }
;
term: NUMBER
| ABS term { $$ = $2 >= 0? $2 : - $2; }
;
%%
main(int argc, char **argv)
{ yyparse();
}
yyerror(char *s)
{ fprintf(stderr, "error: %s\n", s);
}
我很难理解如何根据运算符优先级解析/处理输入字符串10 - 3 * 2 + 6
。任何人都可以一步一步地描述解析机制吗?对于例如
Step1: 10 is read and token NUMBER is returned
Step2: etc....
感谢任何帮助。
感谢。
答案 0 :(得分:3)
野牛解析器会很高兴地通过使用野牛的trace facility来告诉你他们正在做什么。
要获得以下跟踪,我使用您的输入文件进行了少量更改:
我修复了没有返回值(main
和yyerror
)的原型,并添加了yylex
和yyerror
的前向声明。
我修复了printf
中的calclist
以打印表达式($2
)的值,而不是没有值的calclist本身。
我将单个字符代币(ADD
,SUB
等)更改为实际的单个字符('+'
,-
等)为了简化扫描仪
我添加了一个微不足道的词法分析器。
最后,我通过向yydebug = 1;
函数添加main
并使用-t
标记调用bison来启用跟踪。
使用您提供的表达式的结果如下。要了解状态转换,您需要打印出状态转换表。使用-v
选项进行野牛。
$ ./trace <<< '10 - 3 * 2 + 6'
Starting parse
Entering state 0
Reducing stack by rule 1 (line 13):
-> $$ = nterm calclist ()
Stack now 0
Entering state 1
Reading a token: Next token is token NUMBER ()
Shifting token NUMBER ()
Entering state 3
Reducing stack by rule 10 (line 22):
$1 = token NUMBER ()
-> $$ = nterm term ()
Stack now 0 1
Entering state 9
Reducing stack by rule 7 (line 19):
$1 = nterm term ()
-> $$ = nterm factor ()
Stack now 0 1
Entering state 8
Reading a token: Next token is token '-' ()
Reducing stack by rule 4 (line 16):
$1 = nterm factor ()
-> $$ = nterm exp ()
Stack now 0 1
Entering state 7
Next token is token '-' ()
Shifting token '-' ()
Entering state 14
Reading a token: Next token is token NUMBER ()
Shifting token NUMBER ()
Entering state 3
Reducing stack by rule 10 (line 22):
$1 = token NUMBER ()
-> $$ = nterm term ()
Stack now 0 1 7 14
Entering state 9
Reducing stack by rule 7 (line 19):
$1 = nterm term ()
-> $$ = nterm factor ()
Stack now 0 1 7 14
Entering state 18
Reading a token: Next token is token '*' ()
Shifting token '*' ()
Entering state 15
Reading a token: Next token is token NUMBER ()
Shifting token NUMBER ()
Entering state 3
Reducing stack by rule 10 (line 22):
$1 = token NUMBER ()
-> $$ = nterm term ()
Stack now 0 1 7 14 18 15
Entering state 19
Reducing stack by rule 8 (line 20):
$1 = nterm factor ()
$2 = token '*' ()
$3 = nterm term ()
-> $$ = nterm factor ()
Stack now 0 1 7 14
Entering state 18
Reading a token: Next token is token '+' ()
Reducing stack by rule 6 (line 18):
$1 = nterm exp ()
$2 = token '-' ()
$3 = nterm factor ()
-> $$ = nterm exp ()
Stack now 0 1
Entering state 7
Next token is token '+' ()
Shifting token '+' ()
Entering state 13
Reading a token: Next token is token NUMBER ()
Shifting token NUMBER ()
Entering state 3
Reducing stack by rule 10 (line 22):
$1 = token NUMBER ()
-> $$ = nterm term ()
Stack now 0 1 7 13
Entering state 9
Reducing stack by rule 7 (line 19):
$1 = nterm term ()
-> $$ = nterm factor ()
Stack now 0 1 7 13
Entering state 17
Reading a token: Next token is token '\n' ()
Reducing stack by rule 5 (line 17):
$1 = nterm exp ()
$2 = token '+' ()
$3 = nterm factor ()
-> $$ = nterm exp ()
Stack now 0 1
Entering state 7
Next token is token '\n' ()
Shifting token '\n' ()
Entering state 12
Reducing stack by rule 3 (line 15):
$1 = nterm calclist ()
$2 = nterm exp ()
$3 = token '\n' ()
= 10
-> $$ = nterm calclist ()
Stack now 0
Entering state 1
Reading a token: Now at end of input.
Shifting token $end ()
Entering state 2
Stack now 0 1 2
Cleanup: popping token $end ()
Cleanup: popping nterm calclist ()