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

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

Спецификация требует, чтобы лексер возвращал строки после перевода управляющих последовательностей. Следующий код является выдержкой из входного файла 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 }

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


person nimrodm    schedule 26.04.2011    source источник


Ответы (1)


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

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

person gasche    schedule 26.04.2011
comment
Спасибо! Золотая жила примеров. Я никогда не думал, что код компилятора Ocaml будет таким понятным. - person nimrodm; 26.04.2011
comment
@nimrodm, вы также должны иметь в виду, что часть кода там довольно старая, поэтому не все отражает текущую передовую практику разработки OCaml. - person gasche; 26.04.2011