ANTLR 语法没有选择正确的选项

ANTLR grammar not picking the right option

因此,我正在尝试将方法值分配给测试程序中的 var,我使用的是 Decaf 语法​​。

语法:

// Define decaf grammar
grammar Decaf;

// Reglas LEXER
// Definiciones base para letras y digitos
fragment LETTER: ('a'..'z'|'A'..'Z'|'_');
fragment DIGIT: '0'..'9';
// Las otras reglas de lexer de Decaf 
ID: LETTER (LETTER|DIGIT)*;
NUM: DIGIT(DIGIT)*;
CHAR: '\'' ( ~['\r\n\] | '\' ['\] ) '\'';
WS : [ \t\r\n\f]+  -> channel(HIDDEN);

COMMENT
    : '/*' .*? '*/' -> channel(2)
    ;

LINE_COMMENT
    : '//' ~[\r\n]* -> channel(2)
    ;

// -----------------------------------------------------------------------------------------------------------------------------------------

// Reglas PARSER
program:'class' 'Program' '{' (declaration)* '}';
declaration
    : structDeclaration
    | varDeclaration
    | methodDeclaration
    ;
varDeclaration
    : varType ID ';' 
    | varType ID '[' NUM ']' ';' 
    ;
structDeclaration:'struct' ID '{' (varDeclaration)* '}' (';')?;
varType 
    : 'int' 
    | 'char' 
    | 'boolean' 
    | 'struct' ID 
    | structDeclaration 
    | 'void' 
    ;
methodDeclaration: methodType ID '(' (parameter (',' parameter)*)* ')' block;
methodType
    : 'int'
    | 'char'
    | 'boolean' 
    | 'void'
    ;
parameter
    : parameterType ID
    | parameterType ID '[' ']' 
    | 'void'
    ;
parameterType
    : 'int' 
    | 'char' 
    | 'boolean'
    ;
block: '{' (varDeclaration)* (statement)* '}';
statement
    : 'if' '(' expression ')' block ( 'else' block )? #stat_if
    | 'while' '('expression')' block #stat_else
    | 'return' expressionOom ';' #stat_return
    | methodCall ';' #stat_mcall
    | block #stat_block
    | location '=' expression #stat_assignment
    | (expression)? ';' #stat_line
    ;
expressionOom: expression |;
location: (ID|ID '[' expression ']') ('.' location)?;
expression 
    : location #expr_loc
    | methodCall #expr_mcall
    | literal #expr_literal
    | '-' expression #expr_minus // Unary Minus Operation
    | '!' expression #expr_not // Unary NOT Operation
    | '('expression')' #expr_parenthesis
    | expression arith_op_fifth expression #expr_arith5 // * / % << >>
    | expression arith_op_fourth expression #expr_arith4 // + -
    | expression arith_op_third expression #expr_arith3 // == != < <= > >=
    | expression arith_op_second expression #expr_arith2 // &&
    | expression arith_op_first expression #expr_arith1 // ||
    ;

methodCall: ID '(' arg1 ')';
// Puede ir algo que coincida con arg2 o nada, en caso de una llamada a metodo sin parametro
arg1: arg2 |;
// Expression y luego se utiliza * para permitir 0 o más parametros adicionales
arg2: (arg)(',' arg)*;
arg: expression; 

// Operaciones
// Divididas por nivel de precedencia
// Especificación de precedencia: https://anoopsarkar.github.io/compilers-class/decafspec.html
rel_op : '<' | '>' | '<=' | '>=' ;
eq_op : '==' | '!=' ;
arith_op_fifth: '*' | '/' | '%' | '<<' | '>>';
arith_op_fourth: '+' | '-';
arith_op_third: rel_op | eq_op;
arith_op_second: '&&';
arith_op_first: '||';

literal : int_literal | char_literal | bool_literal ;
int_literal : NUM ;
char_literal : '\'' CHAR '\'' ;
bool_literal : 'true' | 'false' ;

而测试程序如下:

class Program
{

int factorial(int b)
{
    int n;
    n = 1;
    return n+2;
}

void main(void)
{
    int a;
    int b;
    b=0;
    a=factorial(b);
    factorial(b);
    return;
}

}

这个程序的解析树如下所示,至少我感兴趣的部分是 a=factorial(b):

这棵树是错误的,因为它应该看起来像 location = expression -> methodCall

下面的树是它在朋友的实现上的样子,如果语法正确实现它应该是这样的:

这是正确实现的,或者是我需要的结果,因为我希望树看起来像 location = expression -> methodCall 而不是 location = expression -> location。如果我从 a=factorial(b) 中删除参数并将其保留为 a=factorial(),它将被正确读取为 methodCall,所以我不确定我缺少什么。

所以我的问题是,我不确定我在语法上哪里搞砸了,我猜是在位置上还是在表达上,但我不确定如何调整它以按照我想要的方式运行它到。我只是从我们提供的规范中逐字地了解了规则。

在 ANTLR 规则中,替代项是从上到下的匹配项。所以在你的 expression 规则中:

expression
    : location #expr_loc
    | methodCall #expr_mcall
    ...
    ;

生成的解析器将在尝试匹配 methodCall 之前尝试匹配 location。尝试交换这两个:

expression
    : methodCall #expr_mcall
    | location #expr_loc
    ...
    ;