2014-03-30 68 views
0

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

您可以发布[SSCCE](http://www.sscce.org/)包括一些输入吗? –

+0

@BartKiers,我已经为示例添加了完整的语法和测试代码。我也发现它只发生在ANTLR 4.2下。在4.2.1下,它不会发生。 – jahrel

回答

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