16

私は ocamlyacc と ocamllex を使用しています。カスタム例外を通知する文法のエラー生成があります。これまでのところ、エラーの位置を報告するように取得できます。

| error { raise (Parse_failure (string_of_position (symbol_start_pos ()))) }

しかし、どのトークンが読み取られたかも知りたいです。方法があるはずです---誰か知っていますか?

ありがとう。

4

3 に答える 3

22

ocamlyaccパーサーをデバッグする最善の方法は、 OCAMLRUNPARAMparam に文字を含めるように設定pすることです。これにより、パーサーは通過するすべての状態を出力し、各シフト/リデュースが実行されます。

bash を使用している場合は、次のコマンドでこれを行うことができます。

$ export OCAMLRUNPARAM='p'
于 2010-07-29T07:02:30.240 に答える
16

トークンはレクサーによって生成されるため、エラーが発生したときに現在のレクサー トークンを使用できます。

  let parse_buf_exn lexbuf =
    try
      T.input T.rule lexbuf
    with exn ->
      begin
        let curr = lexbuf.Lexing.lex_curr_p in
        let line = curr.Lexing.pos_lnum in
        let cnum = curr.Lexing.pos_cnum - curr.Lexing.pos_bol in
        let tok = Lexing.lexeme lexbuf in
        let tail = Sql_lexer.ruleTail "" lexbuf in
        raise (Error (exn,(line,cnum,tok,tail)))
      end

Lexing.lexeme lexbuf必要なものです。他のパーツは必須ではありませんが便利です。 ruleTailユーザーがエラーの位置を簡単に特定できるように、残りのすべてのトークンを文字列に連結します。lexbuf.Lexing.lex_curr_p正しい位置を含むようにレクサーで更新する必要があります。(ソース

于 2009-12-21T09:05:52.633 に答える
2

yacc と同様に、トークンは文法規則の記号に対応する変数に格納されると思います。printfここではシンボル(エラー)が 1 つあるので、 などを使用して $1 を単純に出力できる場合があります。

編集:コメントに応答します。

なぜエラー端末を使うのですか?解析エラーが発生したときに特別なエラー処理ルーチンが呼び出されるという ocamlyacc チュートリアルを読んでいます。そのようです:

3.1.5. エラー報告ルーチン

パーサー関数が構文エラーを検出するparse_errorと、文字列 "syntax error" を引数として名前が付けられた関数を呼び出します。デフォルトparse_error関数は何もせずに戻り、エラー回復を開始します (エラー回復を参照)。ユーザーは、次のように、文法ファイルのヘッダー セクションでカスタマイズされた parse_error 関数を定義できます。

let parse_error s = (* Called by the parser function on error *)
  print_endline s;
  flush stdout

ただし、その関数では「構文エラー」しか発生しないようです。詳細については、しばらくお待ちください。

于 2009-12-19T15:42:39.830 に答える