我有一个符号表,其中包含变量/符号的名称,数据和数据类型(存储为char)。我想这样的符号被视为一个iexpr,如果它是一个整数或rexpr,如果它是一个真实的。这些是我现在拥有的规则:
iexpr: INT_TOKEN
| iexpr PLUS iexpr { $$ = $1 + $3; }
| iexpr MINUS iexpr { $$ = $1 - $3; }
| iexpr DIVIDE iexpr {$$ = $1/$3;}
| iexpr MOD iexpr{$$ = $1 % $3;}
| LPARENT iexpr RPARENT{$$=$2;}
| SYMBOL { symrec *s;
s = getsym($1);
if(s!=0){
if(s->type == 'i'){
$$ = atoi(s->data);
}
}
}
;
rexpr: REAL_TOKEN
| rexpr PLUS rexpr { $$ = $1 + $3; }
| rexpr MINUS rexpr { $$ = $1 - $3; }
| iexpr PLUS rexpr { $$ = (double) $1 + $3; }
| iexpr MINUS rexpr { $$ = (double) $1 - $3; }
| rexpr PLUS iexpr { $$ = $1 + (double) $3; }
| rexpr MINUS iexpr { $$ = $1 - (double) $3; }
| rexpr DIVIDE rexpr {$$ = $1/$3;}
| rexpr MULTIPLY rexpr{$$ = $1 * $3;}
| rexpr DIVIDE iexpr {$$ = $1 / (double) $3;}
| rexpr MULTIPLY iexpr {$$= $1 * (double) $3;}
| iexpr DIVIDE rexpr {$$ = (double) $1 / $3;}
| iexpr MULTIPLY rexpr {$$ = (double) $1 * $3;}
| rexpr MOD rexpr {$$ = (int)$1 % (int)$3;}
| rexpr MOD iexpr {$$ = (int)$1 % $3;}
| iexpr MOD rexpr {$$ = $1 % (int)$3;}
| LPARENT rexpr RPARENT{$$ =$2;}
| SYMBOL { symrec *s;
s = getsym($1);
if(s!=0){
if(s->type == 'r'){
$$ = atof(s->data);
}
}
}
;
然而,rexpr中的规则从未被使用,因为它只将它视为iexpr。我怎样才能使它根据类型描述符被视为该类型而不仅仅是一个整数?
编辑:所以我试图更改我的lex文件,以便它为每种类型返回一个不同的标记。为此,我需要包含我的符号表头文件,以便我可以检查该名称并根据其类型返回不同的符号。这是代码:
[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;
}
}
但现在我有一个错误,说我对我的标题函数有多个定义,因为我将它包含在两个文件中。
答案 0 :(得分:2)
如果您希望令牌类型根据符号的声明类型而变化,则需要在词法分析器中查找符号(因为这是生成令牌类型的原因)。
您实际上需要返回三种不同令牌类型中的一种:
一般来说,最好在解析完成后在AST上单独传递中进行类型检查。 (或者,如果您没有生成AST,则可以在语义操作中执行此操作。)这样可以生成更好的错误消息,并且可以在类型错误后继续解析更容易。 / p>
答案 1 :(得分:1)
如果你想这样做,你需要让词法分析器为ISYMBOL
和RSYMBOL
返回不同的标记,否则你会在{{{{}}的两次减少之间得到减少/减少冲突1}}因为解析器不知道它是什么。这意味着您需要在词法分析器操作中执行符号表查找,而不是在解析器操作中。
通常,尝试在解析器中进行这样的类型检查是一个坏主意,因为它会使语法更加复杂并导致许多难以解决的冲突。