ANTLR表达式列表冲突

时间:2012-11-10 17:31:32

标签: parsing antlr conflict infix-notation postfix-notation

这是简单嵌套表达式的基本结构......

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)

问题是42+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)。 总的来说,我想要一个令牌列表并查找所有中缀表达式,并将其余部分留作列表。

1 个答案:

答案 0 :(得分:1)

您的INT规则存在问题:

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

匹配空字符串。它应始终匹配至少1个char:

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:

enter image description here

修改

介绍可以在后缀和中缀表达式中使用的运算符会使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();};

在上面的语法中,作为中缀运算符的+优先于postfix-version,正如你在解析像2+5+之类的输入时所看到的那样:

enter image description here