语法中后缀和前缀子规则的不同结果

时间:2014-03-30 19:26:20

标签: antlr4

我有一个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*

由于规则的性质是左递归,这是预期的吗?

1 个答案:

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