Parsing 如何在F中处理解析过程中的错误#

Parsing 如何在F中处理解析过程中的错误#,parsing,f#,error-handling,fsyacc,Parsing,F#,Error Handling,Fsyacc,我的F#Lexer和解析器使用了fslex/fsyacc实用程序。如果输入文本的语法不正确,则有必要知道它发生的位置 可以在Lexer中确定不正确的lexeme(token),并在使用不正确的符号或单词时引发异常: rule token = parse ... | integer { INT (Int32.Parse(lexeme lexbuf)) } | "*=" { failwith "Incorrect symbol" } | eo

我的F#Lexer和解析器使用了fslex/fsyacc实用程序。如果输入文本的语法不正确,则有必要知道它发生的位置

可以在Lexer中确定不正确的lexeme(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类

例如,是否可以在my parser.fsy文件中编写类似于以下内容的内容:

Expression1: 
   | INT         { Int $1 }
     ...
   | _           { failwith "Error with parsing in Expression1"}
仅仅跳过“u”应该会导致移位/减少冲突。对于一小组令牌,您可以将它们全部列出。对于更大的令牌集,问题更大

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 }
您可以在中看到整个文件


有关ocamlyacc/fsyacc中错误处理的更多信息,请参阅(第三部分)→ Lexer和解析器生成器→ 错误处理)。

谢谢您的回答-它给了我们很多。尝试在我的代码中添加解决方案这两种解决方案(使用空白标记的规则中的键和使用recover的示例)对我都有效,因此再次感谢您。我把答案标记为已接受