Happy & Alex - Предотвращение влияния просмотра вперед на связь парсер-лексер

В настоящее время я пишу парсер для компилятора игрушечного языка, используя Happy & Alex. Поскольку требуется некоторая форма дополнительного макета, я должен изменить состояние Алекса перед сопоставлением с нетерминалом block. К сожалению, кажется, что упреждающий токен, требуемый Хэппи, считывается до того, как у меня появляется возможность изменить состояние Алекса.

Вот небольшой фрагмент, демонстрирующий проблему:

funcDef : header localDefs block
                          ^ I have to change alex's state 
                            before the underlying lexer
                            starts reading the block tokens.

Есть ли общий подход к этой проблеме?


person Liarokapis Alexandros    schedule 25.03.2017    source источник
comment
Как узнать, где начинается блок? Я предполагаю, что localDefs не является самозавершающимся, поэтому должна быть какая-то лексическая функция, которую вы можете использовать, чтобы узнать, где начинается блок. Не могли бы вы немного пояснить?   -  person rici    schedule 25.03.2017
comment
@rici Блок либо окружен ключевыми словами начала/конца, либо иным образом основан на отступе. В основном это определяется как начало stmts+ end или stmts autoend. Лексер должен быть уведомлен об отсутствии начала, чтобы создать автоматическое завершение при обнаружении изменения идентификации. Весь подход кажется очень хакерским, должен быть лучший способ.   -  person Liarokapis Alexandros    schedule 25.03.2017
comment
Я только что решил эту точную проблему две недели назад. Не думал, что кто-то еще на него наткнется.   -  person Alec    schedule 25.03.2017
comment
@Алек с нетерпением ждет подробностей!   -  person Liarokapis Alexandros    schedule 25.03.2017
comment
Я подожду, чтобы увидеть, что напишет @alec, но мой подход будет заключаться в том, чтобы сделать новую строку видимой для синтаксического анализатора, и в этом случае изменение лексера может быть выполнено до токена триггера, или обработать все это в лексере. Оба немного хакерские, но синтаксис тоже :) Сравните использование Python с двоеточием.   -  person rici    schedule 25.03.2017
comment
@rici Пожалуйста, опубликуйте свое решение - мне было бы очень интересно посмотреть, что еще возможно. В моем случае я застрял с лексером, который я не мог изменить (я хотел, чтобы он вел себя как эталонная реализация), поэтому вместо этого я сделал обратное сальто в синтаксическом анализаторе.   -  person Alec    schedule 25.03.2017


Ответы (1)


Я предполагаю, что вы используете многопоточный лексер (поэтому Happy и Alex работают в одной и той же монаде). Уловка, которую я использовал, столкнувшись с похожей проблемой, состоит в том, чтобы создать пустое производственное правило, которое вы подсовываете в свое правило.

changeAlexState :: { () }
  : {- empty -} {%% \tok -> changeAlexState *> pushTok tok }

funcDef : header localDefs changeAlexState block

Затем вам нужно добавить к вашей монаде некоторое состояние для поддержки pushTok :: Token -> P () (где P — это ваша лексическая/парсинговая монада) и убедиться, что вы всегда выталкиваете этот токен, когда вы лексируете. То, что делает %%, задокументировано здесь.

n : t_1 ... t_n {%% <expr> }

... Тип <expr> тот же [все еще Token -> P a], но в этом случае упреждающая лексема фактически отбрасывается, и из ввода считывается новая лексема. Это может быть полезно, когда вы хотите изменить следующий токен и продолжить синтаксический анализ.

Я упоминал, что делал что-то подобное не так давно. Вот мой " пустое" правило, вот пример его использования, здесь определяется моя функция нажатия и здесь я "извлекаю" токены. Дайте мне знать, как это происходит!

person Alec    schedule 25.03.2017