我有以下野牛代码,以下语句工作正常。

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;}
            ;
    %%


虽然这两种类型都可以在各自的分支中正常工作,但是结构(很明显)不是很理想,而且重复很重,但是我不知道要解决什么问题,也不知道如何在它们之间进行转换。

最佳答案

还有其他几种方法可以解决此问题:


最简单的解决方案(如果不需要类型信息)是使整数适合double类型,然后您可以将规则partipartf等合并为一个。但是,这确实会改变结构,因此可能不是您想要的。
如果您需要类型信息(如Paul Ogilvie所说),则可能需要一些Val结构,该结构包含一个带类型标记的整数/双精度联合。同样,这可能不是您想要的,因为它确实需要更多的努力。但...
我考虑了一下,也许有可能的解决方案可以最大程度地减少对现有语言格式的更改。本质上,我们将“加宽”转换规则从整数添加到浮点数:

exprf: /* other exprf rules */
     | expri { $$ = $1; /* Implicit integer widening conversion*/}
termf: /* other termf rules */
     | termi { $$ = $1; }
utermf: /* other utermf rules */
      | utermi { $$ = $1; }
/* ... */


这将是一个非常笨拙且笨拙的解决方案,因为由此而产生的reduce-reduce和shift-reduce冲突会弹出。 (例如,表达式1 + 1可以简化为expriexprf)。您可能需要研究glr-parsingmerging glr parses来解决一些歧义。我希望这可能是您正在寻找的东西。


前两个是更优雅的解决方案,但是也许您确实需要,第三个选项是一个可行的选择,(如果您选择此选项,我建议使用bison -v尝试调试这些冲突,然后尝试在野牛中玩耍一点点)。

10-08 08:20
查看更多