我有一个ANTLR4语法,它有一些规则试图匹配语言中表达式的部分应用。简化它们,规则看起来像这样:
grammar PartialExpression;
program
: (function '.')+
;
function
: name '=>' expression (';' expression)*
;
name
: SYMBOL
;
expression
: functionCall
| closure
| literal
| expression binaryOperator expression
| unaryOperator expression
| '(' expression ')'
;
functionCall
: name
;
closure
: '[' '=>'? expression (';' expression)* ']'
| '[' partialExpression ']'
;
partialExpression
: binaryOperator expression # leftPartialExpression
| expression binaryOperator # rightPartialExpression
;
unaryOperator
: ('-' | '+' | '~')
;
binaryOperator
: ('=' | '<' | '>' | '@' | '^' | '+' | '-' | '*' | '/' | '$' | '!' | ':' | '|')+
;
literal
: NUMBER
;
SYMBOL
: ('a'..'z'| 'A'..'Z')+
;
NUMBER
: '-'? [0-9]+ ('.' [0-9]+)? ([eE] '-'? [0-9]+)?
;
WS
: [ \n\r\t\,] -> skip
;
COMMENT
: '%' ~[\r\n]* -> skip
;
除了partialExpression
中的最后一个子规则之外,所有内容都解析得很好,尽管在TestRig中出现了正确的解析,然后返回expression
,然后按预期返回binaryOperator
,但现在包含三个孩子:正确的expression
,正确的binaryOperator
和一个空的expression
,而不仅仅是它应该是expression
。用于测试它的代码是:
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
public class TestPartialExpression
{
public static class Printer extends PartialExpressionBaseListener
{
@Override public void enterRightPartialExpression(PartialExpressionParser.RightPartialExpressionContext ctx)
{
System.out.println("Right Expression: " + ctx.expression().getText());
}
@Override public void enterLeftPartialExpression(PartialExpressionParser.LeftPartialExpressionContext ctx)
{
System.out.println("Left Expression: " + ctx.expression().getText());
}
}
public static void main(String[] args) throws Exception
{
ANTLRInputStream input = new ANTLRInputStream("fc => [m *].");
PartialExpressionLexer lexer = new PartialExpressionLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
PartialExpressionParser parser = new PartialExpressionParser(tokens);
ParseTreeWalker walker = new ParseTreeWalker();
Printer printer = new Printer();
walker.walk(printer, parser.program());
}
}
代码的预期输出为m
。实际输出为m*
。
由于规则的性质是左递归,这是预期的吗?
答案 0 :(得分:0)
我将程序转换为C#并从打印机类中删除static
,输出为m
,如预期的那样。
RightPartialExpressionContext中只有两个孩子。
也许您可以粘贴输出或发布显示三个孩子的调试窗口的屏幕截图?
private static void partialExpressionTest()
{
AntlrInputStream input = new AntlrInputStream("fc => [m *].");
PartialExpressionLexer lexer = new PartialExpressionLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
PartialExpressionParser parser = new PartialExpressionParser(tokens);
ParseTreeWalker walker = new ParseTreeWalker();
Printer printer = new Printer();
walker.Walk(printer, parser.program());
// prints "Right Expression: m"
}
public class Printer : PartialExpressionBaseListener
{
override public void EnterRightPartialExpression(PartialExpressionParser.RightPartialExpressionContext ctx)
{
Console.WriteLine("Right Expression: " + ctx.expression().GetText());
}
override public void EnterLeftPartialExpression(PartialExpressionParser.LeftPartialExpressionContext ctx)
{
Console.WriteLine("Left Expression: " + ctx.expression().GetText());
}
}