Antlr 文法に関する質問の量にいくらか安心していますが (このヤクの形をしたものを剃ろうとしているのは私だけではありません)、私の問題に役立つ質問/回答は見つかりませんでした。
Token/Parser lexer が混在する Antlr3.3 を使用しています。
gUnit を使用して文法を証明し、いくつかの jUnit テストを行っています。ここから楽しみが始まります。
解析したい単純な構成ファイルがあります。
identifier foobar {
port=8080
stub plusone.google.com {
status-code = 206
header = []
body = []
}
}
「識別子」(この例では foobar) の解析に問題があります: 許可したい有効な名前は次のとおりです:
foobar
foo-bar
foo_bar
foobar2
foo-bar2
foo_bar2
3foobar
_foo-bar3
などであるため、有効な名前には次の文字を使用できます。'a..z'|'A..Z', '0..9' '_' and '-'
私がたどり着いた文法はこれです(これは完全な文法ではなく、この質問に関連する部分だけであることに注意してください):
fragment HYPHEN : '-' ;
fragment UNDERSCORE : '_' ;
fragment DIGIT : '0'..'9' ;
fragment LETTER : 'a'..'z' |'A'..'Z' ;
fragment NUMBER : DIGIT+ ;
fragment WORD : LETTER+ ;
IDENTIFIER : DIGIT | LETTER (LETTER | DIGIT | HYPHEN | UNDERSCORE)*;
および対応する gUnit テスト
IDENTIFIER:
"foobar" OK
"foo_bar" OK
"foo-bar" OK
"foobar1" OK
"foobar12" OK
"foo-bar2" OK
"foo_bar2" OK
"foo-bar-2" OK
"foo-bar_2" OK
"5foobar" OK
"f_2-a" OK
"aA0_" OK
// no "funny chars"
"foo@bar" FAIL
// not with whitepsace
"foo bar" FAIL
gUnit テストの実行は、「5foobar」に対してのみ失敗します。難しいものをなんとか解析できましたが、識別子を解析するという一見単純なタスクに打ちのめされました。
誰かが私が間違っている場所を指摘できますか? 貪欲にならずにマッチングするにはどうすればよいですか?
よろしくお願いします。
- アップデート -
Bartsの回答に従って、文法を次のように変更しました。
IDENTIFIER : ('0'..'9'| 'a'..'z'|'A'..'Z' | '_'|'-') ('_'|'-'|'a'..'z'|'A'..'Z'|'0'..'9')* ;
これにより、失敗したgUnitテストが修正されましたが、「ポート」パラメーターをテストする関連のないjUnitテストが壊れました。次の文法は、上記の構成スニペットの「port=8080」要素を扱います。
configurationStatement[MiddlemanConfiguration config]
: PORT EQ port=NUMBER {
config.setConfigurationPort(Integer.parseInt(port.getText())); }
| def=proxyDefinition { config.add(def); }
;
私が得るメッセージは次のとおりです。
mismatched input '8080' expecting NUMBER
NUMBER は次のように定義されます。NUMBER : ('0'..'9')+ ;
IDENTIFIER ブロックの上に NUMBER のルールを移動して、この問題を修正しました。