1

次のようなlex正規表現があるとします

[aA][0-9]{2,2}[pP][sS][nN]? { return TOKEN; }

ユーザーが入力した場合

A75PsN
A75PS

一致します

しかし、ユーザーが次のようなことを言った場合

A75PKN

エラーで「文字 K が認識されません。S が必要です」と言ってほしいです。

私が今していることは、次のように書いているだけです

let [a-zA-Z]
num [0-9]

{let}{num}{2,2}{let}{2,3}

そして、本質的に Yacc で文字列を re-lex して、意味のあるエラー条件を設定できるようにします。

どうすればこれを回避できますか?

私が考えることができる唯一のことは、名前付きグループを使用することですか?

4

1 に答える 1

2

わお!興味深いスキーム。

字句アナライザーでそれを検出する場合は、「他の方法では認識されない文字列」を処理し、エラー メッセージを生成するキャッチオール ルールが必要です。

トラブルの原因がKであると判断するのは地獄です。

[^aA][0-9]{2,2}[pP][sS][nN]? { report_error(); return ERROR; }
[aA][0-9]{2,2}[^pP][sS][nN]? { report_error(); return ERROR; }
[aA][0-9]{2,2}[pP][^sS][nN]? { report_error(); return ERROR; }
[aA][0-9]{2,2}[pP][sS][^nN]  { report_error(); return ERROR; }

キャレットの配置と疑問符がないことに注意してください。数字以外、または数字が多すぎる、または数字が少なすぎる - うーん!

一般に、すべての「識別子」を認識してから、どれが問題ないかを検証する方がよいでしょう:

[a-zA-Z][0-9]{2,2}[a-zA-Z]{2,5} { return validate_id_string(); }

検証ルーチンに許可する毒を選択してください。入力されたものが OK かどうかを判断し、その戻り値によって、Lex ルールが文法に返すものを制御します。これは、キーワードと識別子を区別する 1 つの方法でもあります。

実際に何が起こるかに合わせて、正規表現を一般化および単純化します。

于 2009-09-30T06:33:03.363 に答える