Вот упрощенный файл yaac:
%token CONTEXT_ // the corresponding string is "context"
%token CONTEXTREF_ //"contextref"
%token IS_ //"is"
%token ID_L //"id_l"
%token ID_L1 //"id_l1"
%token LIB_
%start design_file
%%
design_file :design_unit
|design_file design_unit
;
design_unit :context_cl LIB_
|context_decl
;
context_cl : /* empty */ { }
|context_cl context_ref
;
context_decl :CONTEXT_ ID_L IS_ ';'
;
context_ref :CONTEXT_ ID_L1 '.' ID_L ';'
;
Есть 2 конфликта сдвига/уменьшения.
CONTEXT_ shift, and go to state 1 CONTEXT_ [reduce using rule 5 (context_cl)]
Правило 5 – context_cl : /* empty */ { }
.
Как правило, это не имеет значения, парсер большую часть времени работает хорошо. Но в одном странном случае для исходного файла, как показано ниже:
context id_l is ...
...
Синтаксический анализатор будет не сдвигать, а уменьшать, поэтому для анализа context id_l is ...
используется context_ref :CONTEXT_ ID_L1 '.' ID_L ';'
, что вызывает синтаксические ошибки.
Так что я должен устранить конфликты. Я предполагаю, что они вызваны правилом context_decl
и context_ref
, оба из которых имеют CONTEXT_
в начале.
Чтобы подтвердить свою догадку, я просто изменил context_ref :CONTEXT_ ID_L1 '.' ID_L ';'
на context_ref :CONTEXTREF_ ID_L1 '.' ID_L ';'
. Тогда нет конфликта и нет синтаксической ошибки.
Однако я не могу заменить context_ref
таким образом. Это стандарт.
Итак, как я могу избежать этих двух конфликтов другими способами? Или есть общий метод разрешения конфликтов такого рода?
И для конфликтов сдвига/уменьшения выберет ли парсер сокращение, а не сдвиг? Потому что я думаю, что синтаксический анализатор всегда будет переключаться на сокращение.
context id_l is ;
в режиме отладки; он распознал ввод без ошибок. Он не будет анализироватьcontext id_l1 ...
из-за разрешения конфликта сдвига/уменьшения. Это то, что вы имели в виду? Если это так, пожалуйста, отредактируйте свой вопрос, и я постараюсь ответить на него. В противном случае, минимально воспроизводимый пример, пожалуйста, с упором на полный и проверяемый. - person rici   schedule 10.05.2017