Предупреждение о конфликтах Bison shift/reduce

У меня возникли проблемы с исправлением конфликтов сдвига/уменьшения в моей грамматике. Это грамматика:

body: variable_decl function_list
    | variable_decl
    ;

variable_decl: variable variable_decl
             | /* no variables declaration */

variable: KW_STATIC basictypes varhelp2 SEMICOLON
        | basictypes varhelp2 SEMICOLON 
        ;

varhelp2: varhelp2 COMA id varhelp1
        | id varhelp1
        ;

varhelp1: dimarray
        | ASSIGN constants
        ;

dimarray: /* no array */ 
        | LBRACKET id RBRACKET dimarray
        ;

constants: pint
         | real
         | bool
         ;

basictypes: KW_INTEGER 
          | KW_BOOLEAN 
          | KW_CHARACTER 
          | KW_REAL 
          | KW_STRING
          ;

function_list: function_list function
             | function
             ;

function: KW_VOID id LEFT_PARENTHESIS function_help1 RIGHT_PARENTHESIS
        | basictypes id LEFT_PARENTHESIS function_help1 RIGHT_PARENTHESIS
        ;

function_help1: /* empty */ 
              | function_help2
              ;

function_help2: function_help2 COMA basictypes id
              | basictypes id 
              ;

Я думаю, что проблема вызвана function_list и variable_decl. И функции, и переменные могут начинаться с basictypes и id. Как мне сделать function_list, чтобы решить эту проблему?

Я много чего пробовал, несколько раз менял грамматику, но конфликты сдвига/уменьшения остаются. Я только начал работать с bison, и мне не хватает опыта, поэтому любая помощь будет принята с благодарностью.

Вот вывод отладки bison:

State 0

    0 $accept: . program $end
    1 program: . body
    7 body: . variable_decl function_list
    8     | . variable_decl
    9 variable_decl: . variable variable_decl
   10              | . %empty  [$end, KW_BOOLEAN, KW_INTEGER, KW_CHARACTER, KW_REAL, KW_STRING, KW_VOID]
   11 variable: . KW_STATIC basictypes varhelp2 SEMICOLON
   12         | . basictypes varhelp2 SEMICOLON
   27 basictypes: . KW_INTEGER
   28           | . KW_BOOLEAN
   29           | . KW_CHARACTER
   30           | . KW_REAL
   31           | . KW_STRING

    KW_STATIC     shift, and go to state 1
    KW_BOOLEAN    shift, and go to state 2
    KW_INTEGER    shift, and go to state 3
    KW_CHARACTER  shift, and go to state 4
    KW_REAL       shift, and go to state 5
    KW_STRING     shift, and go to state 6

    KW_BOOLEAN    [reduce using rule 10 (variable_decl)]
    KW_INTEGER    [reduce using rule 10 (variable_decl)]
    KW_CHARACTER  [reduce using rule 10 (variable_decl)]
    KW_REAL       [reduce using rule 10 (variable_decl)]
    KW_STRING     [reduce using rule 10 (variable_decl)]
    $default      reduce using rule 10 (variable_decl)

    program        go to state 7
    body           go to state 8
    variable_decl  go to state 9
    variable       go to state 10
    basictypes     go to state 11




State 10

    9 variable_decl: . variable variable_decl
    9              | variable . variable_decl
   10              | . %empty  [$end, KW_BOOLEAN, KW_INTEGER, KW_CHARACTER, KW_REAL, KW_STRING, KW_VOID]
   11 variable: . KW_STATIC basictypes varhelp2 SEMICOLON
   12         | . basictypes varhelp2 SEMICOLON
   27 basictypes: . KW_INTEGER
   28           | . KW_BOOLEAN
   29           | . KW_CHARACTER
   30           | . KW_REAL
   31           | . KW_STRING

    KW_STATIC     shift, and go to state 1
    KW_BOOLEAN    shift, and go to state 2
    KW_INTEGER    shift, and go to state 3
    KW_CHARACTER  shift, and go to state 4
    KW_REAL       shift, and go to state 5
    KW_STRING     shift, and go to state 6

    KW_BOOLEAN    [reduce using rule 10 (variable_decl)]
    KW_INTEGER    [reduce using rule 10 (variable_decl)]
    KW_CHARACTER  [reduce using rule 10 (variable_decl)]
    KW_REAL       [reduce using rule 10 (variable_decl)]
    KW_STRING     [reduce using rule 10 (variable_decl)]
    $default      reduce using rule 10 (variable_decl)

    variable_decl  go to state 18
    variable       go to state 10
    basictypes     go to state 11

person Mike7    schedule 29.04.2017    source источник
comment
По сути, это та же проблема, что и stackoverflow.com/questions/43579367/shift-reduce- конфликт (возможно, ваш одноклассник :-) ), и если бы я ответил, я бы дал в основном тот же ответ. Так что прочитайте и посмотрите, поможет ли это.   -  person rici    schedule 29.04.2017
comment
Кстати, старайтесь использовать осмысленные имена. Избегайте множественного числа, если нетерминал производит только один токен (basic_type и constant, а не basictypes и constants); используйте множественное число или список слов (последовательно!) для нетерминалов, которые создают список (variable_decl_list, а не variable_decl, и обычно пытаются быть описательными (optional_parameters и parameter_list, а не function_help1 и function_help2); постоянно используйте символы подчеркивания или не используйте их вообще ; и используйте нижний регистр для нетерминалов и верхний регистр для терминалов (не pint, real и bool)...   -  person rici    schedule 29.04.2017
comment
Точно так же используйте односимвольные токены, если это возможно, и, если они не соответствуют вашим именам. Например, идеальными являются '(', ')', '[', ']', но если вы чувствуете острую необходимость назвать (почему?), тогда используйте LBRACKET и LPARENTHESIS или LEFT_BRACKET и LEFT_PARENTHESIS. Смешивание LBRACKET и LEFT_PARENTHESIS создает впечатление, что вы копируете и вставляете из разных источников, а не пишете свой собственный код.   -  person rici    schedule 29.04.2017