2012-06-05 3 views
4

Возможно ли передать обработанный OCamlYacc парсер явным списком токенов для анализа?Корректировать парсер ocamlyacc из явного списка токенов?

Я бы хотел использовать OCamlLex для явного создания списка токенов, который затем анализирую с помощью парсера, сгенерированного Yacc. Тем не менее, стандартный вариант использования генерирует парсер, который вызывает лексер неявно для следующего токена. Здесь токены вычисляются во время анализа yacc, а не раньше. Концептуально парсер должен работать только на токенах, но парсер, созданный Yacc, предоставляет интерфейс, который опирается на лексер, который в моем случае мне не нужен.

ответ

4

Если у вас уже есть список жетонов, вы можете просто уйти от уродливого способа и вообще игнорировать буфер лексинга. В конце концов, функция разбора из-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, что вы» re пытается вписаться в подпись вашего парсера 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 
+0

Парсер, созданный yacc, предоставляет семантические действия доступ к информации о местоположении, скрытой в состоянии 'lexbuf'. Поэтому я не уверен, что 'deflate' будет работать, но это дает мне представление. –

1

Интерфейс OCamlYacc выглядит довольно сложно; он, кажется, требует Lexing.lexbuf. Возможно, вы могли бы использовать Lexing.from_string для подачи фиксированной строки, а не фиксированной последовательности токенов. Вы также можете посмотреть Menhir. Я не использовал его, но он получает отличные отзывы здесь, когда кто-либо упоминает генераторы парсеров OCaml. Он может иметь более гибкий интерфейс лексинга.

+0

Menhir выглядит как хорошая альтернатива OCamlYacc для много причин. Тем не менее, он также кажется довольно тесно привязанным к lexer. 'Lexing.from_string' не является альтернативой, потому что основная проблема заключается в том, что некоторые действия lexer генерируют два токена, а не один, потому что я могу распознать токен только за произвольной строкой и в конечном итоге с помощью токена строки и следующего за ним. Поэтому я планировал сначала составить список токенов. Возможно, мне нужно ввести странные гибридные жетоны, чтобы обойти ограничения. –

7

Как уже упоминался Джеффри, Menhir конкретно предлагает, как часть своей библиотеки времени выполнения, модуль для парсеров с любым видом токена (он просто запрашивает функцию unit -> token): MenhirLib.Convert.

(Вы можете даже использовать этот код без использования Менгира с ocamlyacc вместо этого. На практике преобразование не очень сложно, так что вы можете даже повторно реализовать его самостоятельно.)

+0

Это очень полезно. Я никогда не использовал Menhir, но руководство выглядело очень убедительно (я упустил модуль 'Convert'), и его автор пользуется большим уважением в сообществе OCaml. –

 Смежные вопросы

  • Нет связанных вопросов^_^