繁体   English   中英

ANTLR4运算符的优先级

[英]ANTLR4 precedence of operator

这是我的语法:

grammar FOOL;

@header {
    import java.util.ArrayList;
}

@lexer::members {
   public ArrayList<String> lexicalErrors = new ArrayList<>();
}

/*------------------------------------------------------------------
 * PARSER RULES
 *------------------------------------------------------------------*/

prog   : exp SEMIC                      #singleExp
       | let exp SEMIC                  #letInExp
       | (classdec)+ SEMIC (let)? exp SEMIC #classExp
       ;

classdec  : CLASS ID ( EXTENDS ID )? (LPAR (vardec ( COMMA vardec)*)? RPAR)?  (CLPAR ((fun SEMIC)+)? CRPAR)?;

let       : LET (dec SEMIC)+ IN ;

vardec  : type ID ;

varasm     : vardec ASM exp ;

fun    : type ID LPAR ( vardec ( COMMA vardec)* )? RPAR (let)? exp ;

dec   : varasm           #varAssignment
      | fun              #funDeclaration
      ;


type   : INT
        | BOOL
        | ID
      ;

    exp    : left=term (operator=(PLUS | MINUS) right=term)*
       ;

term   : left=factor (operator=(TIMES | DIV) right=factor)*
       ;

factor : left=value (operator=(EQ | LESSEQ | GREATEREQ | GREATER | LESS | AND | OR ) right=value)*
       ;

value  :  MINUS?INTEGER                                   #intVal
      | (NOT)? ( TRUE | FALSE )                       #boolVal
      | LPAR exp RPAR                                 #baseExp
      | IF cond=exp THEN CLPAR thenBranch=exp CRPAR (ELSE CLPAR elseBranch=exp CRPAR)?  #ifExp
      | MINUS?ID                                             #varExp
      | THIS                                              #thisExp
      | funcall        #funExp
      | (ID | THIS) DOT funcall   #methodExp
      | NEW ID ( LPAR (exp (COMMA exp)* )? RPAR)?             #newExp
      | PRINT ( exp )                                 #print
      ;
/* PRINT LPAR exp RPAR */

funcall
    : ID ( LPAR (exp (COMMA exp)* )? RPAR )
    ;


/*------------------------------------------------------------------
 * LEXER RULES
 *------------------------------------------------------------------*/
SEMIC  : ';' ;
COLON  : ':' ;
COMMA  : ',' ;
EQ     : '==' ;
ASM    : '=' ;
PLUS   : '+' ;
MINUS  : '-' ;
TIMES  : '*' ;
DIV    : '/' ;
TRUE   : 'true' ;
FALSE  : 'false' ;
LPAR   : '(' ;
RPAR   : ')' ;
CLPAR  : '{' ;
CRPAR  : '}' ;
IF        : 'if' ;
THEN   : 'then' ;
ELSE   : 'else' ;
PRINT : 'print' ;
LET    : 'let' ;
IN     : 'in' ;
VAR    : 'var' ;
FUN    : 'fun' ;
INT    : 'int' ;
BOOL   : 'bool' ;
CLASS   : 'class' ;
EXTENDS   : 'extends' ;
THIS   : 'this' ;
NEW    : 'new' ;
DOT    : '.' ;
LESSEQ    : ('<=' | '=<') ;
GREATEREQ    : ('>=' | '=>') ;
GREATER: '>' ;
LESS   : '<' ;
AND    : '&&' ;
OR     : '||' ;
NOT    : '!' ;


//Numbers
fragment DIGIT : '0'..'9';
INTEGER       : DIGIT+;

//IDs
fragment CHAR  : 'a'..'z' |'A'..'Z' ;
ID              : CHAR (CHAR | DIGIT)* ;

//ESCAPED SEQUENCES
WS              : (' '|'\t'|'\n'|'\r')-> skip;
LINECOMENTS    : '//' (~('\n'|'\r'))* -> skip;
BLOCKCOMENTS    : '/*'( ~('/'|'*')|'/'~'*'|'*'~'/'|BLOCKCOMENTS)* '*/' -> skip;

ERR_UNKNOWN_CHAR
    :   . { lexicalErrors.add("UNKNOWN_CHAR " + getText()); }
    ;

我认为语法中存在关于运算符优先级的问题。 特别是这个

let int x = (5-2)+4; in print x;

打印7,而这一个:

    let
    int x = 5-2+4;
in
    print x;

版画9.为什么第一个可行? 我如何才能使第二种方法起作用,仅更改语法? 我认为exp,术语或因素有一些变化。

这是第一个解析树http://it.tinypic.com/r/2nj8tqw/9 这是第二个解析树http://it.tinypic.com/r/2iv02z6/9

exp    :  left=term (operator=(PLUS | MINUS) right=exp)?

这将产生引起它的解析树。 简而言之,将5-2 5 - 2 + 4解析为:

term  PLUS       exp
 2         term MINUS exp
            2        term
                      4

这应该有所帮助,尽管您必须更改评估逻辑:

exp    :  left=term (operator=(PLUS | MINUS) right=term)*

对于factor和任何其他可能的二进制运算相同。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM