0

最近、次のような式の文法を作成する必要がありました。

rule1 & rule2 & rule3 => produces binary tree 
  (AndNode (AndNode RuleNode(rule1) RuleNode(rule2)) RuleNode(rule3))
rule1 | (rule2 & rule3) => produces binary tree
  (OrNode RuleNode(rule1) (AndNode RuleNode(rule2) RuleNode(rule3)))

RuleNode、AndNode、および OrNode は、後で式全体が評価されるときに使用されるクラスです。rule1、rule2 などは単に私のドメインの概念であり、パーサーまたはレクサー ルールとは何の関係もありません。

文法は次のとおりです。

RULE      : ('a'..'z'|'A'..'Z')('a'..'z'|'A'..'Z'|'0'..'9')*;
QUOTE     : '\'';
PARAM     : QUOTE ( ~('\'') )* QUOTE;
LPAREN    : '(';
RPAREN    : ')';
DELIMITER : ',';
AND       : '&';
OR        : '|';
WS        : (' ' | '\t')+ {$channel = HIDDEN;};

params    : LPAREN! PARAM (DELIMITER! PARAM)* RPAREN!;
rule      : RULE<RuleNode>^ params?;

expr      : andexpr;
andexpr   : orexpr (AND<AndNode>^ orexpr)*;
orexpr    : atom (OR<OrNode>^ atom)*;
atom      : rule | LPAREN! expr RPAREN!;

parse     : expr;

AND 演算子をデフォルトのものにする必要があるまでは、すべて問題なく機能していたので、次のような例を書くことができました。

rule1 rule2 rule3
rule1 | (rule2 rule3)

私は別の方法で anexpr ルールを指定しようとしました:

1)

andexpr   : orexpr+ -> (^(AND<AndNode> orexpr))+;

結果 - バイナリ ツリーではなく、AndNode をルートとしても持たないツリーを生成します。

(nil RuleNode(rule1) RuleNode(rule2) RuleNode(rule3)) 

2)

ANTLR ツリー構築(演算子セクション)の最初の例に基づいて、次のことも試しました。

andexpr   : (a=orexpr->$a) (b=orexpr -> ^(AND<AndNode> $andexpr $b))*;

結果 - 1) と同じフラット ツリー

2) からカスタム ノードを削除した場合:

andexpr   : (a=orexpr->$a) (b=orexpr -> ^(AND $andexpr $b))*;

次に、パーサーはバイナリ ツリーを生成します。

(AND (AND RuleNode(rule1) RuleNode(rule2)) RuleNode(rule3))

残念ながら、AND は私のカスタム AndNode ではありません。AndNode の構築と関係があると思われます - 元の例では「&」が必要で、コンストラクターは

AndNode(Token token) { this.token = token; } 

しかし、オプションの「&」を使用した文法の場合、新しいものを実装する必要がありました

AndNode(int type) { } 

トークンをパラメーターとして受け入れなくなりました。

この場合のルールを書くのを手伝ってください。そうすれば、バイナリ ツリーとカスタム ノードの両方が得られます。私は立ち往生しています。

4

1 に答える 1

0

^({new AndNode(AND)} ...の代わりに使用できるはずです^(AND<AndNode> ...

于 2013-01-15T14:00:13.067 に答える