为什么我的 "equation" 语法会破坏解析器?

Why does my "equation" grammar break the parser?

目前,我的解析器文件如下所示:

%{

#include <stdio.h>
#include <math.h>

int yylex();
void yyerror (const char *s);

%}

%union {
    long num;
    char* str;
}

%start line

%token print
%token exit_cmd

%token <str> identifier
%token <str> string
%token <num> number

%%

line: assignment            {;}
    | exit_stmt             {;}
    | print_stmt            {;}
    | line assignment       {;}
    | line exit_stmt        {;}
    | line print_stmt       {;}
    ;

assignment: identifier '=' number       {printf("Assigning var %s to value %d\n", , );}
          | identifier '=' string       {printf("Assigning var %s to value %s\n", , );}
          ;

exit_stmt: exit_cmd         {exit(0);}
         ;

print_stmt: print print_expr      {;}
          ;

print_expr: string          {printf("%s\n", );}
          | number          {printf("%d\n", );}
          ;

%%

int main(void)
{
    return yyparse();

}

void yyerror (const char *s) {fprintf(stderr, "%s\n", s);}

给出输入:myvar = 3 给出输出 Assigning var myvar = 3 to value 3,正如预期的那样。但是,修改代码以包含 equation 语法规则会破坏此类分配。

方程语法:

equation: number '+' number             {$$ =  + ;}
    | number '-' number             {$$ =  - ;}
    | number '*' number             {$$ =  * ;}
    | number '/' number             {$$ =  / ;}
    | number '^' number             {$$ = pow(, );}
    | equation '+' number           {$$ =  + ;}
    | equation '-' number           {$$ =  - ;}
    | equation '*' number           {$$ =  * ;}
    | equation '/' number           {$$ =  / ;}
    | equation '^' number           {$$ = pow(, );}
    ;

相应地修改赋值语法:

assignment: identifier '=' number       {printf("Assigning var %s to value %d\n", , );}
          | identifier '=' equation     {printf("Assigning var %s to value %d\n", , );}
          | identifier '=' string       {printf("Assigning var %s to value %s\n", , );}
          ;

并在解析器的第一部分中为 equation 规则指定类型 num

%type <num> equation

提供相同的输入:var = 3 冻结程序。

我知道这是一个很长的问题,但是有人可以解释一下这里发生了什么吗?

此外,here's the lexer如果你想看一看。

它没有 "freeze the program"。该程序正在等待更多输入。

在您的第一个语法中,var = 3 是一个完整的语句,无法扩展。但是在你的第二个语法中,它可能是 var = 3 + 4 的开头,例如。所以解析器需要在 3 之后读取另一个标记。如果您希望输入行以换行符结束,您将需要修改您的扫描器以发送换行符作为标记,然后修改您的语法以期望在每个语句末尾都有一个换行符标记。如果您打算允许语句分布在多行中,您在输入时需要意识到这一点。

你的语法有几个问题,还有你的解析器。 (例如,Flex 不实现非贪婪重复。)请查看 bison 和 flex 手册中的示例