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    :  MINUS? left=term (operator=(PLUS | MINUS) right=exp)?
      ;

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

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

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

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

Using this grammar, I can compile and successfully execute this:

let int x = 3;
in print(x);

Or this:

let int x = 3;
in print(2-x);

But for example, this prints 5 instead of -1

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

This instead, works, it prints -1:

let
    int x = 2 - 3;
in
    print(x);

Is there something wrong or missing in the grammar? Should I post also the java class that implements the code generation step? How can I distinguish correctly between the minus operator and the minus sign?

SctALE
  • 509
  • 2
  • 10
  • 30
  • 1
    Without seeing how you evaluate the result of `exp : MINUS? left=term (operator=(PLUS | MINUS) right=exp)?`, it is hard to say anything sensible but it looks like you are not checking for the presence of the first `MINUS?`. FWIW, I don't think that grammar is right either; it parses `-x*y+7` as though it were `-(x*y)+7` rather than `((-x)*y)+7`. But with the multiplication, the wrong parse still produces the correct answer. (And so does division provided you regard integer division as truncating towards zero.) – rici Jan 15 '18 at 17:35
  • 1
    Also, the precedence of comparison operators is wrong. – rici Jan 15 '18 at 17:37
  • @rici how do you correct it? Why is the precedence of comparison operators wrong? – SctALE Jan 15 '18 at 17:50
  • 1
    You need one more precedence level for the unary minus operator between `term` and `factor` (and also consider adding the unary plus). If you're using ANTLR4 you can also stuff everything into the `exp` rule in order of precedence and let ANTLR handle this stuff for you, but you still need the separate level. Again, see how I did it [here](https://stackoverflow.com/a/29996191/3764814), take a look at the `# unaryExpr` part. – Lucas Trzesniewski Jan 15 '18 at 19:53

0 Answers0