无法弄清楚为什么 yacc/bison 语法不起作用
can't figure out why yacc/bison grammar doesn't work
这不是家庭作业,虽然它来自一本书。
我得到了一个 yacc/bison 规范文件。任务是添加一个新的production
number -> number digit
digit -> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
计算数字的值并取消 NUMBER
标记。语法如下。
%{
#include <stdio.h>
#include <ctype.h>
int yylex();
int yyerror();
%}
%token NUMBER
%%
command : exp { printf("%d\n", ); }
; /* allows printing of the result */
exp : exp '+' term { $$ = + ; }
| exp '-' term { $$ = - ; }
| term { $$ = ; }
;
term : term '*' factor { $$ = * ; }
| factor { $$ = ; }
;
factor : NUMBER { $$ = ; }
| '(' exp ')' { $$ = ; }
;
%%
int main() {
return yyparse();
}
int yylex() {
int c;
while((c = getchar()) == ' ');
/* eliminate blanks*/
if (isdigit(c)) {
ungetc(c, stdin);
scanf("%d", &yylval);
return (NUMBER);
}
if (c == '\n') return 0;
/* makes the parse stop */
return (c);
}
int yyerror(char * s) {
fprintf(stderr, "%s\n", s);
return 0;
} /* allows for printing of an error message */
作为一项确保我做的一切都正确的实验,我删除了数字标记,添加了以下产生式:
number : '1' {$$ = ;}
将 factor
生产更改为
factor : number {$$ = ;}
并被淘汰
if (isdigit(c)) {
ungetc(c, stdin);
scanf("%d", &yylval);
return (NUMBER);
}
来自 yylex()
函数。换句话说,规范文件如下所示:
%{
#include <stdio.h>
#include <ctype.h>
int yylex();
int yyerror();
%}
%%
command : exp { printf("%d\n", ); }
; /* allows printing of the result */
exp : exp '+' term { $$ = + ; }
| exp '-' term { $$ = - ; }
| term { $$ = ; }
;
term : term '*' factor { $$ = * ; }
| factor { $$ = ; }
;
factor : number { $$ = ; }
| '(' exp ')' { $$ = ; }
;
number : '1' { $$ = ; }
;
%%
int main() {
return yyparse();
}
int yylex() {
int c;
while((c = getchar()) == ' ');
/* eliminate blanks*/
if (c == '\n') return 0;
/* makes the parse stop */
return (c);
}
int yyerror(char * s) {
fprintf(stderr, "%s\n", s);
return 0;
} /* allows for printing of an error message */
然而,在我 运行 以下表达式的代码之后:1+1,我得到了 0 的答案。
有人来帮帮我吗?我究竟做错了什么?
number : '1' { $$ = ; }
这表示解析器可以将终端 '1'
(单个字符标记)减少为 number
,并且当它这样做时,它应该复制语义值。
很好。但是'1
'的语义值是什么?与任何其他令牌一样,当它 returns 令牌类型时,它是 yylex
存储到 yylval
中的值。例如,在原始代码中,yylex
使用 scanf("%d", &yylval)
来设置 NUMBER
标记的语义值。但是在新代码中,yylex
没有履行其合同。它从不将 yylval
设置为任何东西,因此它 returns 的任何标记的语义值都是未定义的。 (只要解析器从不使用令牌的语义值就完全可以。'+'
也没有给出语义值,但解析器不期望一个。)
在令牌 '1'
的情况下,解析器确实不需要扫描器的帮助:很清楚语义值应该是什么:
number : '1' { $$ = 1; }
或者,扫描仪可以提供帮助:
if (isdigit(c)) yylval = c - '0';
return c;
这不是家庭作业,虽然它来自一本书。
我得到了一个 yacc/bison 规范文件。任务是添加一个新的production
number -> number digit
digit -> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
计算数字的值并取消 NUMBER
标记。语法如下。
%{
#include <stdio.h>
#include <ctype.h>
int yylex();
int yyerror();
%}
%token NUMBER
%%
command : exp { printf("%d\n", ); }
; /* allows printing of the result */
exp : exp '+' term { $$ = + ; }
| exp '-' term { $$ = - ; }
| term { $$ = ; }
;
term : term '*' factor { $$ = * ; }
| factor { $$ = ; }
;
factor : NUMBER { $$ = ; }
| '(' exp ')' { $$ = ; }
;
%%
int main() {
return yyparse();
}
int yylex() {
int c;
while((c = getchar()) == ' ');
/* eliminate blanks*/
if (isdigit(c)) {
ungetc(c, stdin);
scanf("%d", &yylval);
return (NUMBER);
}
if (c == '\n') return 0;
/* makes the parse stop */
return (c);
}
int yyerror(char * s) {
fprintf(stderr, "%s\n", s);
return 0;
} /* allows for printing of an error message */
作为一项确保我做的一切都正确的实验,我删除了数字标记,添加了以下产生式:
number : '1' {$$ = ;}
将 factor
生产更改为
factor : number {$$ = ;}
并被淘汰
if (isdigit(c)) {
ungetc(c, stdin);
scanf("%d", &yylval);
return (NUMBER);
}
来自 yylex()
函数。换句话说,规范文件如下所示:
%{
#include <stdio.h>
#include <ctype.h>
int yylex();
int yyerror();
%}
%%
command : exp { printf("%d\n", ); }
; /* allows printing of the result */
exp : exp '+' term { $$ = + ; }
| exp '-' term { $$ = - ; }
| term { $$ = ; }
;
term : term '*' factor { $$ = * ; }
| factor { $$ = ; }
;
factor : number { $$ = ; }
| '(' exp ')' { $$ = ; }
;
number : '1' { $$ = ; }
;
%%
int main() {
return yyparse();
}
int yylex() {
int c;
while((c = getchar()) == ' ');
/* eliminate blanks*/
if (c == '\n') return 0;
/* makes the parse stop */
return (c);
}
int yyerror(char * s) {
fprintf(stderr, "%s\n", s);
return 0;
} /* allows for printing of an error message */
然而,在我 运行 以下表达式的代码之后:1+1,我得到了 0 的答案。
有人来帮帮我吗?我究竟做错了什么?
number : '1' { $$ = ; }
这表示解析器可以将终端 '1'
(单个字符标记)减少为 number
,并且当它这样做时,它应该复制语义值。
很好。但是'1
'的语义值是什么?与任何其他令牌一样,当它 returns 令牌类型时,它是 yylex
存储到 yylval
中的值。例如,在原始代码中,yylex
使用 scanf("%d", &yylval)
来设置 NUMBER
标记的语义值。但是在新代码中,yylex
没有履行其合同。它从不将 yylval
设置为任何东西,因此它 returns 的任何标记的语义值都是未定义的。 (只要解析器从不使用令牌的语义值就完全可以。'+'
也没有给出语义值,但解析器不期望一个。)
在令牌 '1'
的情况下,解析器确实不需要扫描器的帮助:很清楚语义值应该是什么:
number : '1' { $$ = 1; }
或者,扫描仪可以提供帮助:
if (isdigit(c)) yylval = c - '0';
return c;