2

これが私がそれのASTを作ろうとしているものです:

{{ name }}
{{ name | option }}
{{ name | option1 | option2 }}
{{ name | key=value }}
{{ name | option1 | key=value }}
{{ name | option1 | {{ another }} | option3 }}

したがって、実際には常に名前(a..zA..Z0..9)があり、オプションはキー値形式の場合もあれば、単純で値形式のない場合もあります。

ANTLRでレクサー/パーサー文法を書き込もうとしていますが、さまざまなことについてしつこく言い続けています。これが私のベストショットです:

start   :   box+;
box :   '{{' Name  ('|'  Options )* '}}';
Options :   (SimpleOption | KeyValue | box);
Name    :   ID;
SimpleOption:   ID;
KeyValue:       ID '=' ID;
fragment
 ID  :  ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')* ;
WS  :   ( ' ' | '\t' | '\r' | '\n'  {$channel=HIDDEN;}  ;

NameとSimpleOptionがあいまいなため、これは明らかに間違っています。インラインルールでさえ役に立たない:

box :   '{{' Name  ('|'  (ID | KeyValue | box) )* '}}';

これは、KeyValueを取得せず、「=」との遭遇時に不一致例外を与えるためです。

この文法をどのように書きますか?

4

2 に答える 2

4

使用しているレクサールールが多すぎます。ルールは、記号の前後にスペースKeyValueがない場合にのみ一致します。パーサールールである必要があります(小文字で開始)。パーサールールの場合のみ、の周りにスペースを含めることができ、その場合は破棄されます。ID '=' ID==

レクサールールとパーサールールの違いを必ず理解してください。参照: ANTLRのパーサールールとレクサールールの実際的な違いは?

これはそれを行う必要があります:

grammar T;

start     : box+ EOF;
box       : '{{' ID ('|' opts)* '}}';
opts      : key_value | ID | box; // note that 'options' is a reserved word in ANTLR!
key_value : ID '=' ID;
ID        : ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '0'..'9' | '_')*;
WS        : (' ' | '\t' | '\r' | '\n') {skip();};

入力を解析します

{{ name | option1 = value1 | {{ another | k=v }} | option3 }}

次のように:

ここに画像の説明を入力してください

于 2012-07-05T17:37:06.913 に答える
0

これはあなたのために働きますか:

Options :   (SimpleOptionOrKeyValue | box);
SimpleOptionOrKeyValue:   ID ( '=' ID | );

=これにより、符号の先読みが不要になります。(かっこ内の出現順序を逆に編集しました。ANTLR がこれをどのように処理するかはわかりません。)

単純なオプションとキー値の区別は、セマンティック レベルで実行できます。

おそらく関連:ANTLR同じ開始を持つレクサールールを使用する方法は?

于 2012-07-04T21:49:48.253 に答える