parsing - 在F#中解析时如何处理错误

标签 parsing f# error-handling fsyacc

我正在为我的F#Lexer和Parser使用fslex/fsyacc实用程序。如果输入文本的语法不正确,则必须知道发生位置。

如果在Lexer中使用了不正确的符号或单词,则可能会确定不正确的词素( token )并引发异常:

rule token = parse
          ...      
  | integer   { INT (Int32.Parse(lexeme lexbuf)) }
  | "*="      { failwith "Incorrect symbol" }
  | eof       { EOF }

这个问题更多地与解析器(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"
    ... 

但是是否有可能(如果是,怎么做?)还确定AST类,因此解析失败

例如,是否可以在parser.fsy文件中编写类似于以下内容的内容:
Expression1: 
   | INT         { Int $1 }
     ...
   | _           { failwith "Error with parsing in Expression1"}

最佳答案

仅跳过“_”应导致移位/减少冲突。对于少量标记,您可以将它们全部列出。对于更大的 token 集,这更成问题。

F#编译器通过定义较早规则的前缀来执行类似的操作,并设置错误状态:

atomicPattern:
  ...
  | LPAREN parenPatternBody RPAREN 
      {  let m = (lhs(parseState)) in SynPat.Paren($2 m,m) } 
  | LPAREN parenPatternBody recover 
      { reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen()); $2 (rhs2 parseState 1 2) }
  | LPAREN error RPAREN 
      { (* silent recovery *) SynPat.Wild (lhs(parseState)) }
  | LPAREN recover 
      {  reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedParen()); SynPat.Wild (lhs(parseState))}  

recover: 
   | error { true }  
   | EOF { false }

您可以在the repository中看到整个文件。

可以在OCaml manual中找到有关ocamlyacc/fsyacc中错误处理的更多信息(第III部分→Lexer和解析器生成器→错误处理)。

关于parsing - 在F#中解析时如何处理错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5244656/

相关文章:

json - 我可以使用 powershell 获取 json 中属性的层次结构路径吗?

scala - Scala 的 transient 集合?

c++ - 如何使用参数抛出错误消息?

java - 与 “JAVA exception handling mindset”相比, “C++ exception handling”是什么?

android - Canvas Touch在S4 Android设备中不起作用

parsing - 在应用解析中苦苦挣扎

javascript - 将扁平化的键->值对转换为嵌套对象

f# - 我可以对 Deedle 相框进行分类吗?

android - Jsoup - Android - 从表单数据/输入中解析信息

f# - 选择列的子集(即通过列键的集合过滤数据框)