Tom*_*cek 10
Fslex和fsyacc当然可以用于生产.毕竟,它们在Microsoft Visual Studio 2010中使用,因为F#lexer和解析器是使用它们编写的(F#编译器源代码也是演示如何有效使用它们的一个很好的示例).
我不确定fslex/fsyacc与他们的OCaml等价物或ANTLR相比如何.但是,Frederik Holmstrom有一篇文章将ANTLR与用IronJS中使用的 F#编写的手写解析器进行了比较.不幸的是,他没有fslex/fsyacc版本,所以没有直接比较.
要回答一些特定问题 - 您可以获得运行fslex/fsyacc的MSBUILD任务作为构建的一部分,因此它可以很好地集成.你没有得到语法高亮,但我不认为这是一个大问题.它可能比OCaml版本慢,但只有在更改解析器时才会影响编译 - 我对F#解析器进行了一些修改,但没有发现编译时间有问题.
Lau*_*ent 10
F#编译器使用Fslex和fsyacc,因此它们很有用.几年前我用过它们,它足以满足我的需求.
但是,我的经验是,在F#中,lex/yacc比在OCaml中成熟得多.OCaml社区中的许多人已经使用它们多年,包括许多学生(似乎用它们编写一个小的解释器/编译器是一种常见的练习).我不认为很多F#开发人员使用它们,我认为F#团队最近没有对这些工具做过大量工作(例如,VS集成并不是优先考虑的事项).如果你不是很紧急,Fslex和fsyacc对你来说已经足够了.
一个解决方案可能是使Menhir(具有几个不错的功能的camlyacc替换)与F#一起使用.我不知道会有多少工作.
就个人而言,我现在每次需要编写解析器时都使用FParsec.它使用起来完全不同,但它也更加灵活,它可以生成良好的解析错误消息.我对此非常满意,当我遇到问题时,它的作者一直非常乐于助人.
fslex和fsyacc工具专门为F#编译器编写,不适合更广泛的使用.也就是说,由于这些工具,我已经设法将重要的代码库从OCaml移植到F#,但由于F#端完全缺乏VS集成,因此很费力(OCaml具有出色的性能)与语法突出显示集成,跳转到定义和错误倒退).特别是,我尽可能多地将F#代码移出词法分析器和解析器.
我们经常需要编写解析器并要求微软为fslex和fsyacc添加官方支持,但我不相信这会发生.
我的建议是只在你翻译使用ocamllex和ocamlyacc的大型传统OCaml代码库时才使用fslex和fsyacc.否则,从头开始编写解析器.
我个人不是解析器组合库的粉丝,而是喜欢使用看起来像这个s-expression解析器的活动模式来编写解析器:
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
Run Code Online (Sandbox Code Playgroud)
这种方法不需要任何VS集成,因为它只是vanilla F#代码.我发现它易于阅读和维护.在我的生产代码中,性能已经足够了.