小さなプロジェクトの単純なパーサー/レクサーの例に取り組んでいますが、問題が発生しました。
私はこれらの行に沿ってコンテンツを解析しています:
Name SEP Gender SEP Birthday
Name SEP Gender SEP Birthday
…は、 、、または空白SEP
のいずれか (複数ではない!) です。|
,
ここで、フィールドの順序をレクサーの順序にロックしたくなかったので、非常に単純なトークンのセットを使用してこれを lex しようとしています。
%token <string> SEP
%token <string> VAL
%token NL
%token EOF
ここで、たとえば、gender
フィールドに決定ごとの値の小さなセットが含まれていない場合、解析エラーを生成するように指示されています{male,female,neither,unspecified}
。パーサーをラップしてこれに対処することはできますが、将来の拡張のために、この要件をオートマトンにエンコードしたいと考えています。
私の最初の試みは、次のように見えて、恐ろしく失敗しました:
doc:
| EOF { [] }
| it = rev_records { it }
;
rev_records:
| (* base-case: empty *) { [] }
| rest = rev_records; record; NL { record :: rest }
| rest = rev_records; record; EOF { record :: rest }
;
record:
last_name = name_field; SEP; first_name = name_field; SEP;
gender = gender_field; SEP; favourite_colour = colour_field; SEP;
birthday = date_field
{ {last_name; first_name; gender; favourite_colour; birthday} }
name_field: str = VAL { str }
gender_field:
| VAL "male" { Person.Male }
| VAL "female" { Person.Female }
| VAL "neither" { Person.Neither }
| VAL "unspecified" { Person.Unspecified }
;
ええ、サイコロはありません。明らかに、構造化されていないレクシングに対する私の試みは、すでにうまくいっていません。
このようなものを解析する慣用的な方法は何ですか?