Инструменты 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 #. Я нахожу это легко читать и поддерживать. В моем рабочем коде производительность была более чем достаточной.