Прошло много времени с тех пор, как я использовал что-то похожее на yacc, но вот несколько советов, которые могут или не могут помочь.
Похоже, что в этой ситуации вам нужен взгляд из двух токенов. Парсер доходит до последнего PrologHeader , и он должен решить, является ли следующая конструкция PrologHeader или PrologBody , и он не может сказать это от KW_Declare. Если в этой ситуации есть директива по увеличению количества запросов, это, вероятно, решит проблему.
Вы также можете ввести контекст в свои действия: вместо того, чтобы определять PrologHeaderList и PrologBodyList , определять PrologRuleList и иметь действия, вызывающие ошибку, если появляется заголовок после тела. Ужасно, но иногда вам приходится это делать: то, что кажется простым в грамматике, может быть непростым в сгенерированном парсере.
Хакерский подход может заключаться в объединении токенов: вместо KW_Declare и KW_Variable , ваш лексер распознает пространство и использует KW_Declare_Variable . Поскольку оба являются ключевыми словами, вы не столкнетесь с проблемами столкновения пространства имен.