在使用fslex和fsyacc时,是否有一种简单的方法可以让lexing和解析同时运行?
我正在为f#Lexer和Parser使用fslex/fsyacc实用程序.如果输入文本的语法不正确,则必须知道它发生的位置.
可以在Lexer中确定不正确的词位(标记),如果使用了错误的符号或单词则抛出异常:
rule token = parse
...
| integer { INT (Int32.Parse(lexeme lexbuf)) }
| "*=" { failwith "Incorrect symbol" }
| eof { EOF }
Run Code Online (Sandbox Code Playgroud)
这个问题更多地与Parser(fsyacc)有关 - 如果输入文本具有正确的令牌并且被Lexer成功地标记化,但是在解析期间发生了错误(例如,错误的令牌顺序或规则中缺少令牌)
我知道如果捕获异常,这会给位置(行和列),解析失败:
try
Parser.start Lexer.token lexbuf
with e ->
let pos = lexbuf.EndPos
let line = pos.Line
let column = pos.Column
let message = e.Message // "parse error"
...
Run Code Online (Sandbox Code Playgroud)
但是有可能(如果是 - 如何做?)也确定AST类,解析失败.
例如,是否可以在我的parser.fsy文件中编写类似于以下内容的内容:
Expression1:
| INT { Int $1 }
...
| _ { failwith "Error with parsing in Expression1"}
Run Code Online (Sandbox Code Playgroud) 在阅读了一个2年历史的网页后,真的扯掉fslex/fsyacc,越野车,慢,愚蠢等等与他们的OCamel同行相比,我想知道什么是最好的选择lexing解析需求?
我之前使用过ANTLR和C#绑定,但我目前正在学习F#,当我看到它带有解析器生成器时很兴奋.由于F#现在正式发布,似乎微软真的希望支持和发展.你会说fslex和fsyacc对于生产代码是否值得?
我正在学习F#,因为我想写一个词法分析器和解析器.我对这种处理有一点经验,但确实需要正确地学习它和F#.
在学习F#的lexing/parsing功能时,学习lex和yacc是否足够?
或者是否存在一些差异,这意味着lex/yacc的代码将无法与fslex和fsyacc一起使用?
我正在尝试恢复我在vs 2008工作的旧f#解析器项目与vs 2013一起工作.它使用FsLexYacc.
我通过使用预建步骤使其构建正常:
fslex --unicode "$(ProjectDir)XpathLexer.fsl"
fsyacc --module XpathParser "$(ProjectDir)XpathParser.fsy"
Run Code Online (Sandbox Code Playgroud)
但这并不理想,因为无论输入是否发生变化,它总是会执行.
然后我尝试使用旧的MsBuild操作:
<FsYacc Include="XpathParser.fsy">
<FsLex Include="XpathLexer.fsl">
Run Code Online (Sandbox Code Playgroud)
但这些在构建过程中似乎完全被忽略了.是对的吗?以某种方式删除了这些构建任务吗?
然后我发现在vs C++下记录的一些我觉得可能有用的东西:
<CustomBuild Include="XpathParser.fsy">
<Message>Calling FsYacc</Message>
<Command>fsyacc --module XpathParser "$(ProjectDir)XpathParser.fsy"</Command>
<Outputs>$(ProjectDir)XpathParser.fs</Outputs>
</CustomBuild>
Run Code Online (Sandbox Code Playgroud)
和
<PropertyGroup>
<CustomBuildBeforeTargets>CoreCompile</CustomBuildBeforeTargets>
</PropertyGroup>
Run Code Online (Sandbox Code Playgroud)
(我检查了Microsoft.Fsharp.Targets文件以提出"CoreCompile"目标.)
唉,还是没有雪茄.
是否有人能够确定是否确实可以将fslex/yacc正确地集成到vs 2013解决方案中,如果是,如何?
我正在尝试实现具有扩展解析功能的库.我决定使用fsyacc,因为我从大学就知道了.不幸的是我遇到了以下问题
我为我的语法(Head)的头部定义了一个类,并将其实现放在一个文件中.然后我将解析器定义为:
...
%start head
%type <Head> head
...
Run Code Online (Sandbox Code Playgroud)
Fsyacc生成seeparated模块(Parser).为了成功,必须按以下顺序编译:Head.fs
Parser.fs
为了使这个库与您在.NET中可以找到的类似,我想向Head添加一个静态Parse方法.不幸的是,我需要使用Parser模块中的方法.
我知道这种类型的依赖关系可以通过' 和 '运算符来解决,但它只适用于在一个文件中定义的类型.
有没有其他方法可以创建相互依赖的类型,即使它们位于不同的文件中?我正在寻找声明/实现分离机制,就像在C/C++中那样,但我找不到任何东西.
我开始玩Fslex/Fsyacc了.尝试使用此输入生成解析器时
Parser.fsy:
%{
open Ast
%}
// The start token becomes a parser function in the compiled code:
%start start
// These are the terminal tokens of the grammar along with the types of
// the data carried by each token:
%token <System.Int32> INT
%token <System.String> STRING
%token <System.String> ID
%token PLUS MINUS ASTER SLASH LT LT EQ GTE GT
%token LPAREN RPAREN LCURLY RCURLY LBRACKET RBRACKET COMMA
%token ARRAY IF THEN ELSE WHILE FOR TO DO LET IN END …
Run Code Online (Sandbox Code Playgroud) 我试图捕获没有引号的引用字符串.我有这个终端
%token <string> STRING
Run Code Online (Sandbox Code Playgroud)
而这个生产
constant:
| QUOTE STRING QUOTE { String($2) }
Run Code Online (Sandbox Code Playgroud)
以及这些词法规则
| '\'' { QUOTE }
| [^ '\'']* { STRING (lexeme lexbuf) } //final regex before eof
Run Code Online (Sandbox Code Playgroud)
它似乎正在解释导致QUOTE
单个词汇的所有内容,而不是解析.所以也许我的问题在语法的其他地方 - 不确定.我是以正确的方式来做这件事的吗?在我尝试从字符串中排除引号之前,它解析得很好.
我认为以下词法分析器规则可能存在一些含糊之处
let name = alpha (alpha | digit | '_')*
let identifier = name ('.' name)*
Run Code Online (Sandbox Code Playgroud)
之前的规则如下 STRING
| identifier { ID (lexeme lexbuf) }
Run Code Online (Sandbox Code Playgroud)
有没有办法消除这些歧义,而不包括STRING
正则表达式中的引号?
我是F#的新手,并不太熟悉整个模式匹配的想法.我试图找到一个更好的解决方案,但我担心我甚至无法正确表达问题 - 我希望问题标题至少有些准确.
我想要做的是从中提取2个"参数" listMethod
.
listMethod
是具有字符串和Expression
"参数" 的几种类型之一(我怀疑参数是错误的术语):
let (varDecl, listExpr) =
match listMethod with
| Select (var, expr) -> (var, expr)
| Where (var, expr) -> (var, expr)
| Sum (var, expr) -> (var, expr)
| Concat (var, expr) -> (var, expr)
Run Code Online (Sandbox Code Playgroud)
然后我继续使用varDecl
,最后有一个类似的匹配表达式与实际的listMethod代码,它使用我创建的几个临时变量varDecl
.
我现在的问题是:如何使上述代码更紧凑?
我希望匹配所有具有2个参数(类型string
和类型Expression
)的类型,而不是自己列出它们,这有点丑陋且难以维护.
该ListMethod
类型声明如下(整个事情是一个FsLex/FsYacc项目):
type ListMethod =
| Select of string * Expr
| Where of string * Expr
| Sum of string * …
Run Code Online (Sandbox Code Playgroud)