Поток парсера ocamlyacc из явного списка токенов?
Можно ли передать сгенерированному OCamlYacc синтаксическому анализатору явный список токенов для анализа?
Я хотел бы использовать OCamlLex для явного генерирования списка токенов, который я затем анализирую с использованием парсера, сгенерированного Yacc. Однако стандартный вариант использования генерирует синтаксический анализатор, который неявно вызывает лексер для следующего токена. Здесь токены вычисляются во время анализа yacc, а не раньше. Концептуально парсер должен работать только с токенами, но сгенерированный Yacc парсер предоставляет интерфейс, основанный на лексере, который в моем случае мне не нужен.
3 ответа
Если у вас уже есть список токенов, вы можете просто пойти по безобразному пути и полностью игнорировать буфер лексирования. В конце концов, функция parse-from-lexbuf, которую ожидает ваш анализатор, является не чистой функцией:
let my_tokens = ref [ (* WHATEVER *) ]
let token lexbuf =
match !my_tokens with
| [] -> EOF
| h :: t -> my_tokens := t ; h
let ast = Parser.parse token (Lexbuf.from_string "")
С другой стороны, из ваших комментариев видно, что у вас действительно есть функция типа Lexing.lexbuf -> token list
что вы пытаетесь вписаться в Lexing.lexbuf -> token
подпись вашего парсера. Если это так, вы можете легко использовать очередь для написания конвертера между двумя типами:
let deflate token =
let q = Queue.create () in
fun lexbuf ->
if not (Queue.is_empty q) then Queue.pop q else
match token lexbuf with
| [ ] -> EOF
| [tok] -> tok
| hd::t -> List.iter (fun tok -> Queue.add tok q) t ; hd
let ast = Parser.parse (deflate my_lexer) lexbuf
Как уже упоминалось Джеффри, Menhir специально предлагает в качестве части своей библиотеки времени выполнения модуль для анализаторов с любым видом потока токенов (он просто запрашивает unit -> token
функция): MenhirLib.Convert.
(Вы можете даже использовать этот код, не используя Menhir, вместо этого используйте ocamlyacc. На практике преобразование не так уж сложно, так что вы можете даже самостоятельно его заново реализовать.)
Интерфейс OCamlYacc выглядит довольно сложным; кажется, требуется Lexing.lexbuf
, Может быть, вы могли бы рассмотреть возможность использования Lexing.from_string
кормить фиксированную строку, а не фиксированную последовательность токенов. Вы также можете посмотреть на Менгира. Я не использовал его, но он получает отличные отзывы, когда кто-нибудь упоминает генераторы парсера OCaml. У него может быть более гибкий лексический интерфейс.