当前,我的解析器文件如下所示:
%{
#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,以防您想看看。
答案 0 :(得分:4)
它不会“冻结程序”。该程序只是在等待更多输入。
在您的第一个语法中,var = 3
是无法扩展的完整语句。但是,在第二个语法中,例如,它可能是var = 3 + 4
的开头。因此,解析器需要在3
之后读取另一个令牌。如果希望输入行由换行符终止,则需要修改扫描程序以将换行符作为令牌发送,然后修改语法以在每条语句的末尾使用换行符。如果您打算允许语句分布在多行中,则在输入内容时需要注意这一事实。
您的语法以及解析器都存在一些问题。 (例如,Flex不实现非贪婪重复。)请查看bison和flex手册中的示例