野牛在表达类型之间施放

时间:2018-04-27 07:31:41

标签: c bison yacc

我有以下野牛代码,以下声明可以正常使用。

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

虽然这两种类型在他们自己的分支中工作正常,但结构(显然)非常不理想,重复重复,但我不知道如何解决,我不知道如何在他们之间施放。

1 个答案:

答案 0 :(得分:1)

还有其他一些方法可以解决这个问题:

  1. 最简单的解决方案(如果您不需要类型信息)将使整数适合double类型,然后您就可以合并规则{{1}和parti等等。但是,这确实会改变结构,所以它可能不是你想要的。

  2. 如果你需要类型信息,就像Paul Ogilvie sugested那样,你可能需要一些partf结构,它包含一个带有类型标记的整数/ double的并集。同样,这可能不是你想要的,因为它需要更多的努力。但是......

  3. 我想到了这一点,也许可能有一个可能的解决方案,可以最大限度地减少对现有语言格式的更改。基本上,我们添加&#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 + 1expri)。您可能需要查看glr-parsingmerging glr parses来解决一些含糊之处。我希望这可能是你正在寻找的东西。

  4. 前两个是更优雅的解决方案,但也许如果你真的需要,第三个选项是可行的选项,(我建议使用exprf尝试调试这些冲突,如果你选择这个选项,并且尝试在野牛中玩耍吧。