0

私のlexer.mll中で私は次のように宣言しEOSました:

let line_feed = '\n' (* %x200A *)
let carriage_return = '\r' (* %x200D *)
let line_terminator = line_feed | carriage_return | carriage_return line_feed 
(* KO: %x2028 | %x2029 *)
let LINE_END = line_terminator

let tab_character = '\x09' (* CHARACTER TABULATION *)
let eom_character = '\x19' (* END OF MEDIUM *)
let space_character = '\x20' (* SPACE *)
let underscore = '\x5F' (* LOW LINE or SPACING UNDERSCORE *)

let WSC = tab_character | eom_character | space_character 
let line_continuation = WSC* underscore WSC* line_terminator
let WS = (WSC | line_continuation)+
let EOL = WS? LINE_END
let EOS = EOL*

rule token = parse
  | WS       { token lexbuf }
  | LINE_END { newline lexbuf; token lexbuf }
  | EOS      { EOS }

parser.mlyの には、次のようなものがあります。

%token EOS
...
%%
nonterminal :
    statement EOS 
    statement { semantic-action }

test_KO.txt以下のように編集すると、Emacs解析中にエラーが発生します。

a_statement
b_statement

spaceただし、次のように 1 つ追加するa_statementと、解析に合格します。

a_statement(space)
b_statement

line_terminator理由は とが認識できないためだと思いtest_KO.txtますが、a_statemntb_statementは同じ行にありません。line_terminatorそれらの間に1つあれば認識できspaceます。

x2028x2029を追加line_terminatorすると問題が解決すると思いますか? ocamllexおそらくユニコードを十分にサポートしていないため、テストするのは複雑です...

それ以外の場合、問題に対する他の解決策はありますか?

4

1 に答える 1

2

問題は、WS、LINE_END、および EOS ルールがすべて同じ文字列に一致しようとする可能性があることです。どの正規表現が実際に一致するかを選択するために使用される「最長一致」ルールについては、OCamllex のマニュアルを参照してください。

ステートメント間に 1 つの行終端記号があるだけの場合、'LINE_END' と 'EOS' ルールの両方が 1 文字しか一致しませんが、'LINE_END' ルールが先に発生するため、選択されます。EOS トークンは発行されず、文法からエラーが発生します。

スペースと行末記号の両方がある場合、'WS' のルールは 1 文字に一致し、EOS のルールは 2 文字 (スペースと改行の両方) に一致するため、EOS のルールが選択されます。EOS トークンが発行され、文法が期待どおりに機能します。

おそらく最も簡単なのは、lexer と文法から EOS トークンを削除することです。

于 2013-04-21T12:31:17.327 に答える