为什么我的“等式”语法破坏了解析器?

时间:2019-03-25 03:45:08

标签: parsing bison flex-lexer yacc lex

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

%{

#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", $1, $3);}
          | identifier '=' string       {printf("Assigning var %s to value %s\n", $1, $3);}
          ;

exit_stmt: exit_cmd         {exit(0);}
         ;

print_stmt: print print_expr      {;}
          ;

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

%%

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             {$$ = $1 + $3;}
    | number '-' number             {$$ = $1 - $3;}
    | number '*' number             {$$ = $1 * $3;}
    | number '/' number             {$$ = $1 / $3;}
    | number '^' number             {$$ = pow($1, $3);}
    | equation '+' number           {$$ = $1 + $3;}
    | equation '-' number           {$$ = $1 - $3;}
    | equation '*' number           {$$ = $1 * $3;}
    | equation '/' number           {$$ = $1 / $3;}
    | equation '^' number           {$$ = pow($1, $3);}
    ;

也相应地修改作业语法:

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

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

%type <num> equation

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

我知道这是一个很长的问题,但是任何人都可以解释一下这是怎么回事吗?

还有here's the lexer,以防您想看看。

1 个答案:

答案 0 :(得分:4)

它不会“冻结程序”。该程序只是在等待更多输入。

在您的第一个语法中,var = 3是无法扩展的完整语句。但是,在第二个语法中,例如,它可能是var = 3 + 4的开头。因此,解析器需要在3之后读取另一个令牌。如果希望输入行由换行符终止,则需要修改扫描程序以将换行符作为令牌发送,然后修改语法以在每条语句的末尾使用换行符。如果您打算允许语句分布在多行中,则在输入内容时需要注意这一事实。

您的语法以及解析器都存在一些问题。 (例如,Flex不实现非贪婪重复。)请查看bison和flex手册中的示例