конфликты: 2 сдвига / уменьшения - PullRequest
0 голосов
/ 18 января 2019

Я пытаюсь написать небольшого переводчика с GNU Bison. Я хотел спросить, может ли кто-нибудь объяснить разницу между директивой% right и% left и где моя ошибка в коде ниже.

%token <flo> FLO
%token <name> NAME
%right '='
%left '+' '-'
%left '*' '/' '%'
%left '&' '|' 'x'
%left NEG NOT LOGIC_NOT
%left '^'
%left ARG

%type <flo> exp

%%

language:     /* nothing */
            | language statment

statment:     '\n'
            | exp
            | error                     { yyerrok; }
;

exp:      FLO                           { $$ = $1; }
        | NAME '(' ')'                  { $$ = ycall($1); }
        | NAME '(' exp ')'              { $$ = ycall($1, $3); }
        | NAME '(' exp ',' exp ')'      { $$ = ycall($1, $3, $5); }
        | NAME '=' exp                  { $$ = 1; ysetvar($1, $3); }
        | NAME %prec VAR                { $$ = ygetvar($1); }
        | '_' exp %prec ARG             { $$ = ygetarg($2, args); }
        | '(' exp ')'                   { $$ = $2; }
        /* 1 Operand */
        | '-' exp %prec NEG             { $$ = - $2; }
        | '~' exp %prec NOT             { $$ = ~ static_cast<int>($2); }
        | '!' exp %prec LOGIC_NOT       { $$ = ! static_cast<int>($2); }
        /* 2 Operands */
        | exp '+' exp                   { $$ = $1 + $3; }
        | exp '-' exp                   { $$ = $1 - $3; }
        | exp '*' exp                   { $$ = $1 * $3; }
        | exp '/' exp                   { $$ = $1 / $3; }
        | exp '%' exp                   { $$ = static_cast<int>($1) % static_cast<int>($3); }
        | exp '^' exp                   { $$ = pow($1, $3); }
        | exp '&' exp                   { $$ = static_cast<int>($1) & static_cast<int>($3); }
        | exp '|' exp                   { $$ = static_cast<int>($1) | static_cast<int>($3); }
        | exp 'x' exp                   { $$ = static_cast<int>($1) ^ static_cast<int>($3); }
;

1 Ответ

0 голосов
/ 18 января 2019

Посмотрите на файл y.output, созданный yacc или bison с аргументом -v. Первый конфликт в состоянии 5:

State 5

    7 exp: NAME . '(' ')'
    8    | NAME . '(' exp ')'
    9    | NAME . '(' exp ',' exp ')'
   10    | NAME . '=' exp
   11    | NAME .

    '='  shift, and go to state 14
    '('  shift, and go to state 15

    '('       [reduce using rule 11 (exp)]
    $default  reduce using rule 11 (exp)

В этом случае конфликт возникает, когда после NAME стоит '(' - это неоднозначность в вашей грамматике, в которой это может быть выражение вызова или простое выражение NAME, за которым следует выражение в скобках, потому что у вас нет разделителя между операторами на вашем языке.

Второй конфликт:

State 13

    4 statment: exp .
   17 exp: exp . '+' exp
   18    | exp . '-' exp
   19    | exp . '*' exp
   20    | exp . '/' exp
   21    | exp . '%' exp
   22    | exp . '^' exp
   23    | exp . '&' exp
   24    | exp . '|' exp
   25    | exp . 'x' exp

    '+'  shift, and go to state 21
    '-'  shift, and go to state 22
    '*'  shift, and go to state 23
    '/'  shift, and go to state 24
    '%'  shift, and go to state 25
    '&'  shift, and go to state 26
    '|'  shift, and go to state 27
    'x'  shift, and go to state 28
    '^'  shift, and go to state 29

    '-'       [reduce using rule 4 (statment)]
    $default  reduce using rule 4 (statment)

, что по сути та же проблема, на этот раз с '-' - вход NAME - NAME может быть одним двоичным оператором вычитания, или это может быть два оператора - ИМЯ, за которым следует унарный отрицательный знак.

Если вы добавите разделитель между операторами (например, ;), оба этих конфликта исчезнут.

...