我有以下野牛代码,以下声明可以正常使用。
1 + 1
1.0 + 1.0
但我希望以下声明能够发挥作用
1.0 + 1
我知道下面的代码不是最理想的,但我被要求保留这种格式。
%{
#include <stdio.h>
#include <math.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
/* Prototypes */
int yylex(void);
void yyerror(char *);
int isFloat = 0;
%}
%union {
int iVal;
double fVal;
}
%token <iVal> INTEGER
%token <fVal> FLOAT
%type <iVal> expri termi utermi factori parti
%type <fVal> exprf termf utermf factorf partf
%%
command : expri {printf("%d\n", $1); return;}
| exprf {printf("%f\n", $1); return;}
;
expri : expri '+' termi {$$ = $1 + $3;}
| expri '-' termi {$$ = $1 - $3;}
| utermi {$$ = $1;}
;
termi : termi '*' factori {$$ = $1 * $3;}
| termi '/' factori {$$ = $1 / $3;}
| termi '%' factori {$$ = $1 % $3;}
| factori {$$ = $1;}
;
utermi : utermi '*' factori {$$ = $1 * $3;}
| utermi '/' factori {$$ = $1 / $3;}
| utermi '%' factori {$$ = $1 % $3;}
| '-' factori {$$ = -$2;}
| factori {$$ = $1;}
;
factori : factori '^' parti {$$ = pow($1, $3);}
| parti {$$ = $1;}
;
parti : '(' expri ')' {$$ = $2;}
| INTEGER {$$ = $1;}
;
/* FLOAT RULES */
exprf : exprf '+' termf {$$ = $1 + $3;}
| exprf '-' termf {$$ = $1 - $3;}
| utermf {$$ = $1;}
;
termf : termf '*' factorf {$$ = $1 * $3;}
| termf '/' factorf {$$ = $1 / $3;}
| termf '%' factorf {$$ = fmodf($1, $3);}
| factorf {$$ = $1;}
;
utermf : utermf '*' factorf {$$ = $1 * $3;}
| utermf '/' factorf {$$ = $1 / $3;}
| utermf '%' factorf {$$ = fmodf($1,$3);}
| '-' factorf {$$ = -$2;}
| factorf {$$ = $1;}
;
factorf : factorf '^' partf {$$ = pow($1, $3);}
| partf {$$ = $1;}
;
partf : '(' exprf ')' {$$ = $2;}
| FLOAT {$$ = $1;}
;
%%
虽然这两种类型在他们自己的分支中工作正常,但结构(显然)非常不理想,重复重复,但我不知道如何解决,我不知道如何在他们之间施放。
答案 0 :(得分:1)
还有其他一些方法可以解决这个问题:
最简单的解决方案(如果您不需要类型信息)将使整数适合double
类型,然后您就可以合并规则{{1}和parti
等等。但是,这确实会改变结构,所以它可能不是你想要的。
如果你需要类型信息,就像Paul Ogilvie sugested那样,你可能需要一些partf
结构,它包含一个带有类型标记的整数/ double的并集。同样,这可能不是你想要的,因为它需要更多的努力。但是......
我想到了这一点,也许可能有一个可能的解决方案,可以最大限度地减少对现有语言格式的更改。基本上,我们添加&#34;扩大&#34;转换规则从整数到浮点数:
Val
这将是一个非常hacky和笨拙的解决方案,因为会产生减少 - 减少和转移 - 减少冲突,弹出。 (例如,表达式exprf: /* other exprf rules */
| expri { $$ = $1; /* Implicit integer widening conversion*/}
termf: /* other termf rules */
| termi { $$ = $1; }
utermf: /* other utermf rules */
| utermi { $$ = $1; }
/* ... */
可以减少为1 + 1
或expri
)。您可能需要查看glr-parsing和merging glr parses来解决一些含糊之处。我希望这可能是你正在寻找的东西。
前两个是更优雅的解决方案,但也许如果你真的需要,第三个选项是可行的选项,(我建议使用exprf
尝试调试这些冲突,如果你选择这个选项,并且尝试在野牛中玩耍吧。