F # fslex fsyacc подходит для производственного кода? - PullRequest
9 голосов
/ 22 марта 2011

После прочтения 2-летней веб-страницы, которая действительно разрывает fslex / fsyacc, глючит, работает медленно, глупо и т. Д. По сравнению с их коллегами из OCamel, я задаюсь вопросом, какие из них лучше всего подойдут для анализа парсинга?

Я раньше использовал ANTLR с привязками C #, но в настоящее время я нахожусь в процессе изучения F # и был взволнован, когда увидел, что он поставляется с генератором синтаксического анализатора. Поскольку F # официально выпущен, и похоже, что Microsoft действительно стремится поддерживать и развивать. Вы сказали бы, что fslex и fsyacc того стоят для производственного кода?

Ответы [ 3 ]

10 голосов
/ 23 марта 2011

Fslex и fsyacc используются компилятором F #, поэтому они вроде работают.Я использовал их несколько лет назад, это было достаточно для моих нужд.

Однако мой опыт показывает, что lex / yacc гораздо менее зрел в F #, чем в OCaml.Многие люди из сообщества OCaml использовали их в течение многих лет, включая многих студентов (кажется, что написание небольшого интерпретатора / компилятора с ними - обычное упражнение).Я не думаю, что многие разработчики F # использовали их, и я не думаю, что команда F # в последнее время проделала большую работу над этими инструментами (например, интеграция VS не была приоритетом).Если вы не очень требовательны, вам может подойти Fslex и fsyacc.

Решением может быть адаптация Menhir (замена camlyacc с несколькими приятными функциями) для использования его с F #.Я понятия не имею, сколько это будет стоить.

Лично я теперь использую FParsec каждый раз, когда мне нужно написать парсер.Он совершенно другой в использовании, но он также гораздо более гибкий и генерирует хорошие сообщения об ошибках разбора.Я был очень доволен этим, и его автор всегда очень помогал, когда у меня возникали вопросы.

10 голосов
/ 22 марта 2011

Fslex и fsyacc, безусловно, готовы к производственному использованию. В конце концов, они используются в Microsoft Visual Studio 2010, потому что лексер и синтаксический анализатор F # написаны с использованием их (исходный код компилятора F # также является хорошим примером, демонстрирующим, как эффективно их использовать).

Я не уверен, как fslex / fsyacc сравниваются с их эквивалентами OCaml или с ANTLR. Однако у Фредерика Холмстрома есть статья, в которой сравнивается ANTLR с рукописным синтаксическим анализатором, написанным на F # , используемом в IronJS . К сожалению, у него нет версии fslex / fsyacc, поэтому прямого сравнения нет.

Чтобы ответить на некоторые конкретные вопросы - вы можете получить задачи MSBUILD для запуска fslex / fsyacc как часть сборки, так что она достаточно хорошо интегрируется. Вы не получаете подсветку синтаксиса, но я не думаю, что это так важно. Это может быть медленнее, чем версия OCaml, но это влияет на компиляцию только при изменении парсера - я внес некоторые изменения в парсер F # и не нашел время компиляции проблемой.

5 голосов
/ 05 октября 2013

Инструменты fslex и fsyacc были специально написаны для компилятора F # и не были предназначены для более широкого использования. Тем не менее, мне удалось получить значительную базу кода, портированную с OCaml на F #, благодаря этим инструментам, но это было трудоемким из-за полного отсутствия интеграции VS на стороне F # (OCaml имеет превосходную интеграцию с подсветкой синтаксиса перейти к определению и возврату ошибки). В частности, я удалил как можно больше кода F # из лексера и анализатора.

Нам часто приходилось писать парсеры и просили Microsoft добавить официальную поддержку fslex и fsyacc, но я не верю, что это произойдет.

Мой совет - использовать fslex и fsyacc только в том случае, если вам приходится переводить большую унаследованную базу кода OCaml, в которой используются ocamllex и ocamlyacc. В противном случае напишите парсер с нуля.

Лично я не фанат библиотек комбинатора синтаксических анализаторов и предпочитаю писать парсеры, используя активные шаблоны, которые выглядят примерно так: парсер s-выражений:

let alpha = set['A'..'Z'] + set['a'..'z']
let numeric = set['0'..'9']
let alphanumeric = alpha + numeric

let (|Empty|Next|) (s: string, i) =
  if i < s.Length then Next(s.[i], (s, i+1)) else Empty

let (|Char|_|) alphabet = function
  | Empty -> None
  | s, i when Set.contains s.[i] alphabet -> Some(s, i+1)
  | _ -> None

let rec (|Chars|) alphabet = function
  | Char alphabet (Chars alphabet it)
  | it -> it

let sub (s: string, i0) (_, i1) =
  s.Substring(i0, i1-i0)

let rec (|SExpr|_|) = function
  | Next ((' ' | '\n' | '\t'), SExpr(f, it)) -> Some(f, it)
  | Char alpha (Chars alphanumeric it1) as it0 -> Some(box(sub it0 it1), it1)
  | Next ('(', SExprs(fs, Next(')', it))) -> Some(fs, it)
  | _ -> None
and (|SExprs|) = function
  | SExpr(f, SExprs(fs, it)) -> box(f, fs), it
  | it -> null, it

Этот подход не требует какой-либо интеграции VS, потому что это просто ванильный код F #. Я нахожу это легко читать и поддерживать. В моем рабочем коде производительность была более чем достаточной.

...