在北美野牛的简单计算器

时间:2016-03-29 20:28:32

标签: parsing bison flex-lexer

我是解析新手。以下是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....

感谢任何帮助。

感谢。

1 个答案:

答案 0 :(得分:3)

野牛解析器会很高兴地通过使用野牛的trace facility来告诉你他们正在做什么。

要获得以下跟踪,我使用您的输入文件进行了少量更改:

  • 我修复了没有返回值(mainyyerror)的原型,并添加了yylexyyerror的前向声明。

  • 我修复了printf中的calclist以打印表达式($2)的值,而不是没有值的calclist本身。

    < / LI>
  • 我将单个字符代币(ADDSUB等)更改为实际的单个字符('+'-等)为了简化扫描仪

  • 我添加了一个微不足道的词法分析器。

  • 最后,我通过向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 ()