9

F#レクサーとパーサーにfslex/fsyaccユーティリティを使用しています。入力テキストの構文が正しくない場合は、それが発生する場所を知る必要があります。

Lexerで誤った語彙素(トークン)を判別し、誤った記号または単語が使用された場合に例外をスローする可能性があります。

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

質問はパーサー(fsyacc)に関連しています-入力テキストに正しいトークンがあり、レクサーによって正常にトークン化されたが、解析中にエラーが発生した場合(たとえば、トークンの順序が正しくないか、ルールにトークンがない)

例外が発生した場合、これにより、解析が失敗した位置(行と列)がわかります。

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"}
4

1 に答える 1

9

「_」をスキップするだけで、シフト/削減の競合が発生するはずです。トークンの小さなセットの場合、それらすべてをリストできます。トークンのセットが大きいほど、問題が大きくなります。

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 でのエラー処理の詳細については、OCaml のマニュアル(パート III → レクサーとパーサー ジェネレーター → エラー処理) を参照してください。

于 2011-03-09T12:32:24.420 に答える