【发布时间】:2014-06-05 08:47:41
【问题描述】:
我是编译器构建的新手。我们可以通过 Google 找到很多 =-*/ 操作的示例,但是 lex 中这些示例中的标记通常只处理一种类型,例如 %token<DOUBLE> NUMBER,然后 yacc 中的表达式类型也将是DOUBLE,例如%type<DOUBLE> expr factor term。
我为此提供了一个示例语法:
lines
:
| lines expression '\n' { printf(" = %lf\n", $2); }
;
expr
: term { $$ = $1; }
| expr '+' term { $$ = $1 + $3; }
| expr '-' term { $$ = $1 - $3; }
;
term
: factor { $$ = $1; }
| term '*' factor { $$ = $1 * $3; }
| term '/' factor { $$ = $1 / $3; }
;
factor
: NUMBER { $$ = $1; }
| group { $$ = $1; }
;
group
: '(' expression ')' { $$ = $2; }
;
如果我想处理不同的类型,例如 FLOAT 和 INTEGER 而不是 DOUBLE,我会这样做:
%type<INTEGER> Integer
%type<FLOAT> Float
lines
:
| lines expression '\n' { printf(" = %lf\n", $2); }
;
expr
: term { $$ = $1; }
| expr '+' term { $$ = $1 + $3; }
| expr '-' term { $$ = $1 - $3; }
;
term
: factor { $$ = $1; }
| term '*' factor { $$ = $1 * $3; }
| term '/' factor { $$ = $1 / $3; }
;
factor
: Integer { $$ = $1; }
| Float { $$ = $1;}
| group { $$ = $1; }
;
group
: '(' expression ')' { $$ = $2; }
;
expr、factor、term、constant等表达式的类型如何定义?
如果我不为它们分配类型,则会出现错误,指出表达式是无类型的,但如果我为它们分配类型 INTEGER,也会出现错误,因为该因子可以简化为 INTEGER 或 FLOAT。
如何处理?
【问题讨论】:
-
如果输入
1+2,表达式是什么类型?如果输入3.0*2.75,表达式是什么类型?您希望通过语法中的一个expression产生式处理这个还是两个(例如expression_type_int和expression_type_float)? -
我想知道是否有任何解决方案可以通过一个表达式来处理它,就像您说的类型 1+2 和在我的语法中键入 3.0*2.75 一样。
-
好的,所以你想要一些可以同时处理实数和整数,甚至更多的东西,所有这些都在一个单一的数据类型中。您可能想要使用 union,或者更准确地说,使用标记的 union。您必须自己处理所有可能的组合,因为内置算术运算符不适用于联合。为每个运算符编写一个函数,例如
MyNumberType add(MyNumberType n1, MyNumberType n2)并分析其中的每个组合。你会打电话给例如$$=add($1,$3). -
所以如果我们想处理不同的类型,我们必须设计一个函数。我们还应该定义表达式的类型吗?感谢您的回复!
-
表达式的类型是
MyNumberType,需要自己定义。您可以通过定义 YYSTYPE 宏(旧的 yacc 方式)或定义%define api.value.type {MyNumberType}(新的 bison 方式)来实现。您也可以像以前一样使用 %type 声明,但您必须对 所有 作品这样做。
标签: c compiler-construction yacc lex