目前,我的解析器文件如下所示:
%{
#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万一你想看看。
它不会“冻结程序”。该计划只是在等待更多的投入。
在你的第一个语法中,var = 3
是一个完整的陈述,无法扩展。但在你的第二个语法中,它可能是var = 3 + 4
的开头,例如。所以解析器需要在3
之后读取另一个令牌。如果您希望输入行以换行符结束,则需要修改扫描程序以将换行符作为标记发送,然后修改语法以在每个语句的末尾使用换行符。如果您打算允许语句分布在多行中,那么在键入输入时您需要注意这一事实。
你的语法有几个问题,你的解析器也有问题。 (例如,Flex不会实现非贪婪的重复。)请查看bison和flex手册中的示例