0

This is my grammar:

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

I think that there is a problem in the grammar concerning the precedence of operator. In particular, this one

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

prints 7, while this one:

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

prints 9. Why the first one works? How can I make the second one working, only changing the grammar? I think there is something to change in exp, term or factor.

This is the first parse tree http://it.tinypic.com/r/2nj8tqw/9 . This is the second parse tree http://it.tinypic.com/r/2iv02z6/9 .

2
  • For this I think it would be useful to look at the parse tree the respective input produces. The TestRig that is shipped with ANTLR provides functionality for visualizing such a tree... Commented Jan 23, 2018 at 17:13
  • @Raven I added parse trees Commented Jan 25, 2018 at 15:51

1 Answer 1

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

This produces parse tree that is causing it. Simply put, 5 - 2 + 4 will be parsed as:

term  PLUS       exp
 2         term MINUS exp
            2        term
                      4

This should help, although you'll have to change the evaluation logic:

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

Same for factor and any other possible binary operations.

Sign up to request clarification or add additional context in comments.

9 Comments

doing that to exp, I have this error: The following sets of rules are mutually left-recursive [exp]
That means parser cannot decide whether to use the optional part or not. I thought aNTLR4 might handle it but it doesn't. Please see updated answer.
Doing that exp : left=term (operator=(PLUS | MINUS) right=term)*, I don't have antlr errors, but the output is the same (-1 in the wrong example)
And what does the parse tree look like? Also, please post your evaluation logic for that part.
This is the first one: it.tinypic.com/r/245wzv6/9 And this is the second one: it.tinypic.com/r/2rdzq13/9
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.