2

これは、単純なネストされた式の基本構造です...

infix   :   prefix (INFIX_OP^ prefix)*;

prefix  :   postfix | (PREFIX_OP postfix) -> ^(PREFIX_OP postfix);

postfix :   INT (POSTFIX_OP^)?;

POSTFIX_OP : '!';
INFIX_OP :  '+';
PREFIX_OP : '-';
INT :   '0'..'9'*;

これらの式のリストを作成したい場合は、次を使用できます...

list:   infix (',' infix)*;

ここでは区切り文字として「,」を使用します。

区切り記号なしで式のリストを作成できるようにしたい。

したがって、文字列があれば、それを次の4 5 2+3 1 6ように解釈できるようにしたいと思います(4) (5) ^(+ 2 3) (1) (6)

問題は、両方が同じ最初のシンボル (INT)42+3持っているため、競合が発生することです。私はこれをどのように解決できるかを理解しようとしています。

編集

特定の条件に対して正しい書き換えを思いつくのに苦労しているだけで、ほとんど理解できました...

expr: (a=atom -> $a)
(op='+' b=atom-> {$a.text != "+" && $b.text != "+"}? ^($op $expr $b) // infix
-> {$b.text != "+"}? // HAVING TROUBLE COMING UP WITH THIS CORRECT REWRITE!
-> $expr $op $b)*; // simple list

atom: INT | '+';
INT : '0'..'9'+;

これは、私が欲しいものです1+2+3++4+5+^(+ ^(+ 1 2) 3) (+) (+) ^(+ 4 5) (+)

++1+2として解析されるように、書き換えルールを完成させようとしてい(+) (+) ^(+ 1 2)ます。全体として、トークンのリストが必要で、すべての中置式を見つけて、残りをリストとして残します。

4

1 に答える 1

1

INTルールに問題があります:

INT : '0'..'9'*;

空の文字列に一致します。常に少なくとも 1 文字と一致する必要があります。

INT : '0'..'9'+;

それに加えて、それはうまく機能しているようです。

文法を考えると:

grammar T;

options {
  output=AST;
}

tokens {
  LIST;
}

parse      : list EOF -> list;
list       : infix+ -> ^(LIST infix+);
infix      : prefix (INFIX_OP^ prefix)*;
prefix     : postfix -> postfix
           | PREFIX_OP postfix -> ^(PREFIX_OP postfix)
           ;
postfix    : INT (POSTFIX_OP^)?;

POSTFIX_OP : '!';
INFIX_OP   : '+';
PREFIX_OP  : '-';
INT        : '0'..'9'+;
SPACE      : ' ' {skip();};

入力を解析します:

4 5 2+3 1 6

次の AST に変換します。

ここに画像の説明を入力

編集

後置式と中置式の両方で使用できる演算子を導入すると、listあいまいになります (以下の私のバージョンでは、つまり... :))。したがって、このデモではコンマをそのままにしておきます。

grammar T;

options {
  output=AST;
}

tokens {
  LIST;
  P_ADD;
}

parse        : list EOF -> list;
list         : expr (',' expr)* -> ^(LIST expr+);
expr         : postfix_expr;
postfix_expr : (infix_expr -> infix_expr) (ADD -> ^(P_ADD infix_expr))?;
infix_expr   : atom ((ADD | SUB)^ atom)*;
atom         : INT;

ADD   : '+';
SUB   : '-';
INT   : '0'..'9'+;
SPACE : ' ' {skip();};

上記の文法では、+as an infix 演算子が postfix-version よりも優先されます。これは、次のような入力を解析するときにわかるように2+5+:

ここに画像の説明を入力

于 2012-11-10T18:33:52.080 に答える