为什么我的“方程式”语法打破了解析器?

问题描述 投票:0回答:1

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

%{

#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万一你想看看。

parsing bison flex-lexer yacc lex
1个回答
4
投票

它不会“冻结程序”。该计划只是在等待更多的投入。

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

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

© www.soinside.com 2019 - 2024. All rights reserved.