Эта слегка измененная грамматика работает:
%token CLASS EXTENDS ID LBRACE RBRACE SEMICOLON NATTYPE LPAREN RPAREN DIGIT COMMA
%%
classDeclaration : CLASS ID EXTENDS ID LBRACE declarationList RBRACE
;
declarationList : /* Empty */
| declarationList declaration
;
declaration : variableDeclaration
| methodDeclaration
;
variableDeclaration : parameterDeclaration SEMICOLON
;
type : NATTYPE | ID
;
methodDeclaration : parameterDeclaration LPAREN parameterDeclarationList RPAREN
variableExpressionBlock
;
variableExpressionBlock : LBRACE DIGIT RBRACE
;
parameterDeclarationList : /* empty */
| parameterDeclarationList COMMA parameterDeclaration
;
parameterDeclaration : type ID
;
Возможно, вы захотите переименовать нетерминал 'parameterDeclaration' во что-то вроде 'singleVariableDeclaration', но избегая наличия двух возможно пустых правил в строке (оригинальные 'variableDeclarationList' и 'methodDeclarationList', вы избегаете неоднозначности.
Это позволяет синтаксически разрешать методы, чередующиеся с переменными в объявлении класса. Если это по какой-то причине неприемлемо, рассмотрите возможность сделать это семантическойошибка, а не синтаксическая ошибка. Если это должна быть синтаксическая ошибка, то кому-то придется подумать; я голосую, чтобы заставить вас думать.
Если вы настаиваете хотя быодно объявление метода, тогда грамматика однозначна:
methodDeclarationList : methodDeclarationList methodDeclaration
| methodDeclaration /* empty */
;
Если вы попытаетесь сделать то же самое со списком объявлений переменных, грамматика по-прежнему будет иметь два конфликта S / R.
Одна возможность, нечтобы быть полностью проигнорированным, это использовать функцию Зубр, %expect 2
, чтобы указать, что 2 сожидаются конфликты с повышением / уменьшением.
%expect 2
%token CLASS EXTENDS ID LBRACE RBRACE SEMICOLON NATTYPE LPAREN RPAREN DIGIT COMMA
%%
classDeclaration : CLASS ID EXTENDS ID LBRACE variableDeclarationList methodDeclarationList RBRACE
;
variableDeclarationList : variableDeclarationList variableDeclaration
| /* empty */
;
variableDeclaration : singleVariableDeclaration SEMICOLON
;
type : NATTYPE | ID
;
methodDeclarationList : methodDeclarationList methodDeclaration
| /* empty */
;
methodDeclaration : singleVariableDeclaration LPAREN parameterDeclarationList RPAREN variableExpressionBlock
;
variableExpressionBlock : LBRACE DIGIT RBRACE
;
parameterDeclarationList : /* empty */
| parameterDeclarationList COMMA parameterDeclaration
;
parameterDeclaration : singleVariableDeclaration
;
singleVariableDeclaration : type ID
;