这是简单嵌套表达式的基本结构......
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)
。
总的来说,我想要一个令牌列表并查找所有中缀表达式,并将其余部分留作列表。
答案 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:
介绍可以在后缀和中缀表达式中使用的运算符会使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+
之类的输入时所看到的那样: