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)

问题是两者都4具有2+3相同的第一个符号(INT),所以我有冲突。我试图弄清楚如何解决这个问题。

编辑

我几乎想通了,只是在为某种条件想出正确的重写时遇到了麻烦……

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();};

在上面的语法中,+作为中缀运算符优先于后缀版本,正如您在解析输入时看到的那样2+5+

在此处输入图像描述

于 2012-11-10T18:33:52.080 回答