Использование Ocamllex для лексинга строк (компилятор Tiger)

#ocaml #lex #tiger #ocamllex

#ocaml #лекс #тигр #окамллекс #lex #tiger #ocamllex

Вопрос:

Я пытаюсь следовать «Современной реализации компилятора Appel в ML» и пишу лексер с использованием Ocamllex.

Спецификация запрашивает, чтобы лексер возвращал строки после перевода escape-последовательностей. Следующий код представляет собой выдержку из входного файла ocamllex:

  rule tiger = parse
 ...
 | '"'
     { let buffer = Buffer.create 1 in
       STRING (stringl buffer lexbuf)
     }
 and  stringl buffer = parse
 | '"' { Buffer.contents buffer }
 | "\t" { Buffer.add_char buffer 't'; stringl buffer lexbuf }
 | "\n" { Buffer.add_char buffer 'n'; stringl buffer lexbuf }
 | "\n" { Buffer.add_char buffer 'n'; stringl buffer lexbuf }
 | '\' '"' { Buffer.add_char buffer '"'; stringl buffer lexbuf }
 | '\' '\' { Buffer.add_char buffer '\'; stringl buffer lexbuf }
 | eof { raise End_of_file }
 | _ as char { Buffer.add_char buffer char; stringl buffer lexbuf }
  

Есть ли способ лучше?

Ответ №1:

Возможно, вам будет интересно посмотреть, как это делает лексер Ocaml (поиск and string ). По сути, это тот же метод, что и ваш, без хорошего локального буфера (я нахожу ваш код более приятным в этом вопросе, но это немного менее эффективно), немного более сложный, потому что поддерживается больше экранирования, и с использованием escape-таблицы (char_for_backslash) для факторизации аналогичных правил.

Кроме того, у вас есть правило, которое "\n" повторяется дважды, и я думаю, 1 что это очень пессимистичная оценка вашей длины строки, я бы предпочел использовать 20 здесь (чтобы избежать ненужного изменения размера).

Комментарии:

1. Спасибо! Золотая жила примеров. Я никогда не думал, что код компилятора Ocaml будет таким понятным.

2. @nimrodm вы также должны иметь в виду, что часть кода там довольно старая, поэтому не все отражает текущую лучшую практику разработки OCaml.