Bison ... 不要过度思考这个问题。其实一切都很简单,没有魔法%union非常神奇,它所做的就是根据%type或%token声明中声明的“类型”(实际上是一个标记),在堆栈引用之后插入一个union成员标记。感谢您的输入。另一个问题。假设一个数字生成被定义为数字
Bison ... 不要过度思考这个问题。其实一切都很简单,没有魔法%union非常神奇,它所做的就是根据%type或%token声明中声明的“类型”(实际上是一个标记),在堆栈引用之后插入一个union成员标记。感谢您的输入。另一个问题。假设一个数字生成被定义为数字,bison,yacc,Bison,Yacc,... 不要过度思考这个问题。其实一切都很简单,没有魔法%union非常神奇,它所做的就是根据%type或%token声明中声明的“类型”(实际上是一个标记),在堆栈引用之后插入一个union成员标记。感谢您的输入。另一个问题。假设一个数字生成被定义为数字:“0”|“1”|“2”|“3”|“4”|“5”|“6”|“7”|“8”| 9”。在这种情况下,如果不使用if(isidgit(c)),我将如何提取语义值?有可能吗?@flashburn:在yacc/bison中,你不能将一个动作附加到多个产品
... 不要过度思考这个问题。其实一切都很简单,没有魔法
%union
非常神奇,它所做的就是根据%type
或%token
声明中声明的“类型”(实际上是一个标记),在堆栈引用之后插入一个union成员标记。感谢您的输入。另一个问题。假设一个数字生成被定义为数字:“0”|“1”|“2”|“3”|“4”|“5”|“6”|“7”|“8”| 9”
。在这种情况下,如果不使用if(isidgit(c))
,我将如何提取语义值?有可能吗?@flashburn:在yacc/bison中,你不能将一个动作附加到多个产品上,因此在这种情况下你需要十个动作。这应该给你一个很好的解决方案的线索:)(当然,当解析器看到其中一个终端时,它不需要调用isdigit。)我不清楚的是识别的值存储在哪里?我很难理解$
、$1
、$2
的含义以及它们与yylval
和%union
的关系。我真的很感谢你在这方面的帮助。也许我们可以在这方面创建一个新的主题,以避免评论中的讨论。。它们存储在解析器堆栈上,与令牌本身和解析器状态(以及源位置,如果该功能已启用)一起<代码>%union定义语义值数据类型yylval
是将新扫描终端的语义值传递给解析器的机制;当令牌移位时,它被推到堆栈上$$
是在语义操作中计算的产品的语义值<代码>$n是RHS组件(堆栈上)的语义值。。。。不要过度思考这个问题。其实一切都很简单,没有魔法%union
非常神奇,它所做的就是根据%type
或%token
声明中声明的“类型”(实际上是一个标记),在堆栈引用之后插入一个union成员标记。
number -> number digit
digit -> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
%{
#include <stdio.h>
#include <ctype.h>
int yylex();
int yyerror();
%}
%token NUMBER
%%
command : exp { printf("%d\n", $1); }
; /* allows printing of the result */
exp : exp '+' term { $$ = $1 + $3; }
| exp '-' term { $$ = $1 - $3; }
| term { $$ = $1; }
;
term : term '*' factor { $$ = $1 * $3; }
| factor { $$ = $1; }
;
factor : NUMBER { $$ = $1; }
| '(' exp ')' { $$ = $2; }
;
%%
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' {$$ = $1;}
factor : number {$$ = $1;}
if (isdigit(c)) {
ungetc(c, stdin);
scanf("%d", &yylval);
return (NUMBER);
}
%{
#include <stdio.h>
#include <ctype.h>
int yylex();
int yyerror();
%}
%%
command : exp { printf("%d\n", $1); }
; /* allows printing of the result */
exp : exp '+' term { $$ = $1 + $3; }
| exp '-' term { $$ = $1 - $3; }
| term { $$ = $1; }
;
term : term '*' factor { $$ = $1 * $3; }
| factor { $$ = $1; }
;
factor : number { $$ = $1; }
| '(' exp ')' { $$ = $2; }
;
number : '1' { $$ = $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 */
number : '1' { $$ = $1; }
number : '1' { $$ = 1; }
if (isdigit(c)) yylval = c - '0';
return c;