野牛多规则符号
Bison multi-rule symbol
我有一个符号 table,它包含 variable/symbol 的名称、数据和数据类型(存储为字符)。我希望它是这样的符号,如果它是整数,则被视为 iexpr;如果它是实数,则被视为 reexpr。这些是我现在的规则:
iexpr: INT_TOKEN
| iexpr PLUS iexpr { $$ = + ; }
| iexpr MINUS iexpr { $$ = - ; }
| iexpr DIVIDE iexpr {$$ = /;}
| iexpr MOD iexpr{$$ = % ;}
| LPARENT iexpr RPARENT{$$=;}
| SYMBOL { symrec *s;
s = getsym();
if(s!=0){
if(s->type == 'i'){
$$ = atoi(s->data);
}
}
}
;
rexpr: REAL_TOKEN
| rexpr PLUS rexpr { $$ = + ; }
| rexpr MINUS rexpr { $$ = - ; }
| iexpr PLUS rexpr { $$ = (double) + ; }
| iexpr MINUS rexpr { $$ = (double) - ; }
| rexpr PLUS iexpr { $$ = + (double) ; }
| rexpr MINUS iexpr { $$ = - (double) ; }
| rexpr DIVIDE rexpr {$$ = /;}
| rexpr MULTIPLY rexpr{$$ = * ;}
| rexpr DIVIDE iexpr {$$ = / (double) ;}
| rexpr MULTIPLY iexpr {$$= * (double) ;}
| iexpr DIVIDE rexpr {$$ = (double) / ;}
| iexpr MULTIPLY rexpr {$$ = (double) * ;}
| rexpr MOD rexpr {$$ = (int) % (int);}
| rexpr MOD iexpr {$$ = (int) % ;}
| iexpr MOD rexpr {$$ = % (int);}
| LPARENT rexpr RPARENT{$$ =;}
| SYMBOL { symrec *s;
s = getsym();
if(s!=0){
if(s->type == 'r'){
$$ = atof(s->data);
}
}
}
;
然而,rexpr 中的规则从未被使用,因为它只将它视为 iexpr。我怎样才能根据类型描述符将其视为该类型而不仅仅是整数?
编辑:所以我尝试更改我的 lex 文件,以便它将 return 每种类型的不同标记。为此,我需要包含我的符号 table 头文件,以便我可以检查该名称和 return 基于其类型的不同符号。这是代码:
[a-zA-Z]+ { yylval.string = strdup(yytext);
symrec *s;
s = getsym(yylval.string);
if(s!=0){
if(s->type == 'r'){
return RSYMBOL;
}else if(s->type == 'i'){
return ISYMBOL;
}
}else{
return SYMBOL;
}
}
但是现在我有一个错误说我有多个头函数定义,因为我将它包含在两个文件中。
如果你想这样做,你需要为 ISYMBOL
和 RSYMBOL
设置词法分析器 return 不同的标记,否则你会在 reduce/reduce 之间发生冲突SYMBOL
的两个缩减,因为解析器不知道它是哪个。这意味着您需要在词法分析器操作中查找符号表,而不是在解析器操作中。
一般来说,尝试在解析器中进行这样的类型检查不是一个好主意,因为它会使语法变得更加复杂并导致许多难以解决的冲突。
如果您希望令牌类型根据符号的声明类型而变化,您需要在词法分析器中查找符号(因为这是生成令牌类型的原因)。
您实际上需要 return 三种不同的令牌类型之一:
- INT_SYMBOL
- REAL_SYMBOL
- UNDECLARED_SYMBOL
一般来说,解析完成后,最好在 AST 的单独传递中进行类型检查。 (或者,如果您不生成 AST,则可以在进行归约时在语义操作中执行此操作。)这将使您产生更好的错误消息,并且在类型错误后更容易继续解析。
我有一个符号 table,它包含 variable/symbol 的名称、数据和数据类型(存储为字符)。我希望它是这样的符号,如果它是整数,则被视为 iexpr;如果它是实数,则被视为 reexpr。这些是我现在的规则:
iexpr: INT_TOKEN
| iexpr PLUS iexpr { $$ = + ; }
| iexpr MINUS iexpr { $$ = - ; }
| iexpr DIVIDE iexpr {$$ = /;}
| iexpr MOD iexpr{$$ = % ;}
| LPARENT iexpr RPARENT{$$=;}
| SYMBOL { symrec *s;
s = getsym();
if(s!=0){
if(s->type == 'i'){
$$ = atoi(s->data);
}
}
}
;
rexpr: REAL_TOKEN
| rexpr PLUS rexpr { $$ = + ; }
| rexpr MINUS rexpr { $$ = - ; }
| iexpr PLUS rexpr { $$ = (double) + ; }
| iexpr MINUS rexpr { $$ = (double) - ; }
| rexpr PLUS iexpr { $$ = + (double) ; }
| rexpr MINUS iexpr { $$ = - (double) ; }
| rexpr DIVIDE rexpr {$$ = /;}
| rexpr MULTIPLY rexpr{$$ = * ;}
| rexpr DIVIDE iexpr {$$ = / (double) ;}
| rexpr MULTIPLY iexpr {$$= * (double) ;}
| iexpr DIVIDE rexpr {$$ = (double) / ;}
| iexpr MULTIPLY rexpr {$$ = (double) * ;}
| rexpr MOD rexpr {$$ = (int) % (int);}
| rexpr MOD iexpr {$$ = (int) % ;}
| iexpr MOD rexpr {$$ = % (int);}
| LPARENT rexpr RPARENT{$$ =;}
| SYMBOL { symrec *s;
s = getsym();
if(s!=0){
if(s->type == 'r'){
$$ = atof(s->data);
}
}
}
;
然而,rexpr 中的规则从未被使用,因为它只将它视为 iexpr。我怎样才能根据类型描述符将其视为该类型而不仅仅是整数?
编辑:所以我尝试更改我的 lex 文件,以便它将 return 每种类型的不同标记。为此,我需要包含我的符号 table 头文件,以便我可以检查该名称和 return 基于其类型的不同符号。这是代码:
[a-zA-Z]+ { yylval.string = strdup(yytext);
symrec *s;
s = getsym(yylval.string);
if(s!=0){
if(s->type == 'r'){
return RSYMBOL;
}else if(s->type == 'i'){
return ISYMBOL;
}
}else{
return SYMBOL;
}
}
但是现在我有一个错误说我有多个头函数定义,因为我将它包含在两个文件中。
如果你想这样做,你需要为 ISYMBOL
和 RSYMBOL
设置词法分析器 return 不同的标记,否则你会在 reduce/reduce 之间发生冲突SYMBOL
的两个缩减,因为解析器不知道它是哪个。这意味着您需要在词法分析器操作中查找符号表,而不是在解析器操作中。
一般来说,尝试在解析器中进行这样的类型检查不是一个好主意,因为它会使语法变得更加复杂并导致许多难以解决的冲突。
如果您希望令牌类型根据符号的声明类型而变化,您需要在词法分析器中查找符号(因为这是生成令牌类型的原因)。
您实际上需要 return 三种不同的令牌类型之一:
- INT_SYMBOL
- REAL_SYMBOL
- UNDECLARED_SYMBOL
一般来说,解析完成后,最好在 AST 的单独传递中进行类型检查。 (或者,如果您不生成 AST,则可以在进行归约时在语义操作中执行此操作。)这将使您产生更好的错误消息,并且在类型错误后更容易继续解析。