4

私は ocamlyacc と ocamllex で書かれたパーサーとレクサーを持っています。行末のセミコロンを忘れた場合のように、解析するファイルが途中で終わっても、アプリケーションは構文エラーを発生させません。私はEOFを発生させてキャッチしているため、lexerが未完成のルールを無視しているためだと認識していますが、構文エラーを発生させるにはどうすればよいですか?

これが私の現在のパーサーです(簡略化)、

%{
    let parse_error s = Printf.ksprinf failwith "ERROR: %s" s
%}

%token COLON
%token SEPARATOR
%token SEMICOLON
%token <string> FLOAT
%token <string> INT
%token <string> LABEL

%type <Conf.config> command
%start command
%%
  command:
      | label SEPARATOR data SEMICOLON    { Conf.Pair ($1,$3)     }
      | label SEPARATOR data_list         { Conf.List ($1,$3)     }
      | label SEMICOLON                   { Conf.Single ($1)      }
  label :
      | LABEL                             { Conf.Label $1         }
  data :
      | label                             { $1                    }
      | INT                               { Conf.Integer $1       }
      | FLOAT                             { Conf.Float $1         }
  data_list :
      | star_data COMMA star_data data_list_ending
                                          { $1 :: $3 :: $4        }
  data_list_ending:
      | COMMA star_data data_list_ending  { $2 :: $3              }
      | SEMICOLON                         { []                    }

およびレクサー (簡体字)、

{
    open ConfParser
    exception Eof
}

rule token = parse
    | ['\t' ' ' '\n' '\010' '\013' '\012']
                        { token lexbuf   }
    | ['0'-'9']+ ['.'] ['0'-'9']* ('e' ['-' '+']? ['0'-'9']+)? as n
                        { FLOAT n        }
    | ['0'-'9']+ as n   { INT n          }
    | '#'               { comment lexbuf }
    | ';'               { SEMICOLON      }
    | ['=' ':']         { SEPARATOR      }
    | ','               { COMMA          }
    | ['_' 'a'-'z' 'A'-'Z']([' ']?['a'-'z' 'A'-'Z' '0'-'9' '_' '-' '.'])* as w
                        { LABEL w        }
    | eof               { raise Eof      }

and comment = parse
    | ['#' '\n']        { token lexbuf   }
    | _                 { comment lexbuf }

サンプル入力ファイル、

one = two, three, one-hundred;
single label;
list : command, missing, a, semicolon

解決策の 1 つは、コマンド ルールに再帰呼び出しを最後に追加し、空のルールを追加することです。これらはすべて、メイン プログラムに戻るリストを作成します。私はおそらくEofを期待として解釈し、レクサーのエラーではなく終了条件を解釈していると思いますが、これは正しいですか?

4

1 に答える 1

5

ocamlyacc必ずしも入力全体を消費するわけではありません。入力全体が解析可能でない場合に強制的に失敗させたい場合はEOF、文法を一致させる必要があります。Eofレクサーを上げる代わりに、トークンを追加してシンボルを次のようにEOF変更しますstart

%type <Conf.config list> main

main:
    EOF { [] }
  | command main { $1::$2 }
于 2009-09-18T19:53:07.807 に答える