Поток парсера 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. У него может быть более гибкий лексический интерфейс.

Другие вопросы по тегам