Как сохранить несколько семантических значений при разборе с Happy/Haskell
Я пытаюсь создать простой лексер / парсер с Alex/Happy в Haskell, и я хотел бы сохранить некоторую информацию о локализации из текстового файла в моем окончательном AST.
Мне удалось построить лексер, используя Alex, который строит список токенов с локализацией:
data Token = Token AlexPosn Foo Bar
lexer :: String -> [Token]
в моем файле Happy, когда я объявляю часть токена%, я могу объявить семантическую часть токена с символом $$
%token FOO { Token _ $$ _ }
и в правиле разбора $ i будет ссылаться на этот $$.
foo_list: FOO { [$1] }
| foo_list FOO { $2 : $1 }
Есть ли способ сослаться на часть AlexPosn и часть Foo токена FOO? Прямо сейчас я знаю только, как относиться только к одному из них. Я могу найти информацию о том, как "добавить несколько $$", и обратиться к ним позже.
Есть ли способ сделать это?
V.
2 ответа
В итоге я нашел 2 решения:
упакуйте все значащие данные в кортеж, чтобы $$ указывал на этот кортеж, а затем извлекал данные по проекции:
data Token = Token (AlexPosn,Foo) Bar %token FOO { Token $$ some_bar } rule : FOO { Ast (fst $1) (snd $1) }
вообще не используйте $$: если вы не используете $$, happy предоставит вам полный токен во время синтаксического анализа, так что вы можете извлечь из этого токена то, что вам действительно нужно:
data Token = Token AlexPosn Foo Bar %token FOO = { Token _ _ some_bar } rule : FOO { Ast (get_pos $1) (get_foo $1) } get_pos :: Token -> AlexPosn get_foo :: Token -> Foo
...
Я думаю, что первый из них самый элегантный. Второй может быть довольно сложным с точки зрения строк кода, если вы несете много информации: вам придется создавать "проекции" вручную (сопоставление с образцом и т. Д.), И безопасное выполнение этого может быть сложным если ваш тип токена довольно большой.
Также возможно сохранить несколько значений следующим образом:
data Token = Token AlexPosn Foo Bar
%token FOO { Token pos foo some_bar }
rule : FOO { Ast pos foo }
Хотя я не уверен, что Happy действительно гарантирует, что это всегда будет работать. Причина того, почему это (возможно) работает, состоит в том, что happy сгенерирует код, которому соответствует шаблон Token pos foo some_bar
, делая pos
а также foo
доступно в Ast pos foo
,