views:

231

answers:

1
import java_cup.runtime.*;
import java.io.*;
import java.util.*;

/* Preliminaries to set up and use the scanner. */

parser code {:
     SMPLLexer lexer;


      public SMPLParser (SMPLLexer lex) {
      super(lex);
      lexer = lex;
     }

     public void report_error(String message, Object info) {
         System.err.println(message + info);
     }

     public void syntax_error(Symbol cur_token) {
         System.err.print("Line " + lexer.getLine() +
            " near char " + lexer.getChar() + ": ");
         report_error("Syntax error while reading: ", cur_token);
         System.err.println ("Last token read is " +
         lexer.getText());
     }

     public void unrecover_syntax_error(Symbol cur_token) {
      System.err.println("Line " + lexer.getLine() +
         "near char " + lexer.getChar() + ": ");
          syntax_error(cur_token);
        }

        :};


/* Terminals (tokens returned by the scanner). */

// special symbols
terminal LBRACKET, RBRACKET, LCBRACKET, RCBRACKET, LPAREN, RPAREN, /* LBRACE, RBRACE, */ SEMI, ASSIGN, COLON, COMMA, EMPTYLIST; /*, DOT, AT; */

// opeartors: base
terminal PAIR, CAR, CDR, LIST, SIZE, SUBSTRING, PROC, CALL, LAZY, LET, BE, DEFINE, PRINT, PRINTLN, READ, READINT;

// operators: equality
terminal PAIREQ, EQV, EQUAL;

// commands: commands
terminal CLEAR, SETBGCOLOR, SETFGCOLOR, PATH, CPATH, PT, CANVAS, RECT, CIRCLE;

// commands: conditional
terminal IF, THEN, ELSE, REPEAT; /* , CASE, WHILE, FOR, TRUE, FALSE; */

// operators: arithmetic
terminal PLUS, MINUS, MUL, DIV, MOD, EXPT;

// operators: relational
terminal LT, GT, EQ, LTEQ, GTEQ, NOTEQ;

//operators: logical
terminal AND, OR, NOT;

// operators:  bitwise
terminal BITAND, BITOR, INVERT;

// terminals with values
terminal Integer INTEGER;
terminal String STRING;
terminal String VAR;
terminal String ID;

/* Non terminals */
// (You're on your own for the IR classes)
non terminal IRProgram program;
non terminal IRCmd statement;
non terminal IRExp expression;
non terminal IRExp arithExp;
non terminal IRExp relExp;
non terminal IRExp logExp;
non terminal IRExp bitExp;
non terminal IRExp term;
non terminal IRExp expt;
non terminal IRExp factor;

non terminal ArrayList statementList;
non terminal IRCmdSeq cmdList;

non terminal ArrayList varList;
non terminal ArrayList expList;
non terminal ArrayList assList;

// non terminal ArrayList sequence;
non terminal empty;


/* Precedence */

precedence left OR;
precedence left AND;
precedence left NOT;
precedence left EQ, GT, LT, LTEQ, GTEQ, NOTEQ;
precedence left BITAND, BITOR;
precedence left PLUS, MINUS;
precedence left MUL, DIV, MOD;
precedence right INVERT;

/* Grammar rules */

start with program;

program ::= statementList:lst SEMI {: RESULT = new IRProgram(lst); :} |
         statementList:lst {: RESULT = new IRProgram(lst); :} | 
         STRING:str {: RESULT = new IRCmdSeq(lst); :}       

;

cmdList ::= statementList:lst {: RESULT = new IRCmdSeq(lst); :};

statementList ::= statementList:lst statement:s {:lst.add(s); RESULT = lst; :} |
                  empty {: RESULT = new ArrayList(); :};

statement ::= 

    PAIR statement:s1 statement:s2  {: RESULT = new IRPAIR(s1,s2); :} |

    PAIREQ LPAREN PAIR:p RPAREN {: new IRPAIR(p); :} |

    CAR varList:s1 {: RESULT = new IRCAR(s1); :} |

    CDR varList:s1 {: RESULT = new IRCDR(s1); :} |

    EQV expression:e1 expression:e2  {: RESULT = new IREQV(e1,e2); :} |

    EQUAL expression:e1 expression:e2  {: RESULT = new IREQUAL(e1,e2); :} |

    SUBSTRING STRING:v arithExp:e1 arithExp:e2  {: RESULT = new IRSUBSTR(v,e1,e2); :} |

    SIZE LIST:n {: RESULT = new IRSIZE(n); :} |

    PROC ID:n cmdList:e {: RESULT = new IRPROC(n,e); :} |

    CALL expression:e1 cmdList:body {: RESULT = new IRCALL(e1,body); :} |

    LAZY expression:e1 {: RESULT = new IRLAZY(e1); :} |

  DEFINE ID:pred expression:e1 {: RESULT = new IRDEFINE(pred,e1); :} |

    LIST LPAREN varList:s RPAREN {: RESULT = new IRLIST(s); :} |

    LIST LPAREN LBRACKET varList:s RBRACKET RPAREN {: RESULT = new IRLIST(s); :} |

    LBRACKET varList:s RBRACKET {: RESULT = new IRLIST(s); :} |

    LCBRACKET varList:s RCBRACKET {: RESULT = new IRLIST(s); :} |

    //LBRACKET sequence:s RBRACKET {: RESULT = new IRLIST(s); :} |

    ID:n ASSIGN expression:n {: RESULT = new IRASSIGN(n); :} |

    ID:n ASSIGN expList:n {: RESULT = new IRASSIGN(n); :} | 

    LET ID:n BE expression:e {: RESULT = new IRLET(n,e); :} | 


    /** Graphic Components **/ 
  CLEAR {: RESULT = new IRCmdClear(); :} |

    CANVAS LPAREN arithExp:e1 arithExp:e2 RPAREN {: RESULT = new IRCmdCanvas(e1,e2); :} |

    PT LPAREN arithExp:e1 arithExp:e2 RPAREN {: RESULT = new IRCmdPT(e1,e2); :} |

    PATH LPAREN arithExp:e1 arithExp:e2 RPAREN {: RESULT = new IRCmdPath(e1,e2); :} |

    CIRCLE LPAREN arithExp:e1 arithExp:e2 arithExp:e3 RPAREN {: RESULT = new IRCmdCircle(e1,e2,e3); :} |

    CPATH LPAREN arithExp:e1 arithExp:e2 RPAREN {: RESULT = new IRCmdCPath(e1,e2); :} |

    SETFGCOLOR LPAREN arithExp:e1 arithExp:e2 arithExp:e3 RPAREN {: RESULT = new IRCmdSetFG(e1,e2,e3); :} |

    SETBGCOLOR LPAREN arithExp:e1 arithExp:e2 arithExp:e3 RPAREN {: RESULT = new IRCmdSetBG(e1,e2,e3); :} |

    RECT LPAREN arithExp:e1 arithExp:e2 arithExp:e3 RPAREN {: RESULT = new IRCmdRect(e1,e2,e3); :} |


    //conditionals

    IF expression:pred THEN cmdList:cond ELSE cmdList:alt {: RESULT = new IRCmdIf(pred, cond, alt); :} |

    // TODO CASE LBRACE expList RBRACE

    PRINT cmdList:e1 {: RESULT = new IRPRINT(e1); :} |

    PRINTLN cmdList:e1 {: RESULT = new IRPRINTLN(e1); :} | 

    READ STRING:n {: RESULT = new IRREAD(n); :} |

    READINT STRING:n {: new IRREADINT(n);:} |

    //iteration
    REPEAT arithExp:count cmdList:body {: RESULT = new IRCmdRepeat(count, body); :} |

    EMPTYLIST {: RESULT = new ArrayList(); :} 

    ;

varList ::= 
      varList:lst COMMA expression:i COLON PROC:p {: lst.add(new IRVarList(i,p)); RESULT = lst; :} |
      varList:lst COMMA expression:i {: lst.add(i); RESULT = lst; :} |
        empty {: RESULT = new ArrayList(); :};

// list of expressions
expList ::= 
      expList:lst COMMA expression:v {: lst.add(v); RESULT = lst; :} |
      expList:lst expression:v {: lst.add(v); RESULT = lst; :} |
        empty {: RESULT = new ArrayList(); :};

/*
sequence ::= 
      sequence:s expression:e COMMA {: RESULT = s.add(e); } |
      sequence:s expression:e {: RESULT = s.add(e); } |
      empty {: RESULT = new ArrayList(); :};
*/    


/* I'm giving you the expression hierarchy already done. (Am I not nice?) */
expression ::= 

     arithExp:ae {: RESULT = ae; :} |
     bitExp:be {: RESULT = be; :} |
     relExp:re {: RESULT = re; :} |
     logExp:le {: RESULT = le; :};

     //relational expressions
relExp ::= 

     //relational ops
     arithExp:e1 EQ arithExp:e2 {: RESULT = new IRExpEq(e1, e2); :} |
      arithExp:e1 LT arithExp:e2 {: RESULT = new IRExpLt(e1, e2); :} |
      arithExp:e1 GT arithExp:e2 {: RESULT = new IRExpGt(e1, e2); :} |
      arithExp:e1 LTEQ arithExp:e2 {: RESULT = new IRExpLtEq(e1, e2); :} |
      arithExp:e1 GTEQ arithExp:e2 {: RESULT = new IRExpGtEq(e1, e2); :} |
      arithExp:e1 NOTEQ arithExp:e2 {: RESULT = new IRExpNotEq(e1, e2); :}
      ;

logExp  ::= 

     //logical ops
      arithExp:e1 AND arithExp:e2 {: RESULT = new IRExpAnd(e1, e2); :} |
      arithExp:e1 OR arithExp:e2 {: RESULT = new IRExpOr(e1, e2); :} |
      arithExp:e1 NOT arithExp:e2 {: RESULT = new IRExpNot(e1, e2); :}
     ;

bitExp ::=

     //bitwise ops
      arithExp:e1 BITAND arithExp:e2 {: RESULT = new IRExpBitAnd(e1, e2); :} |
      arithExp:e1 BITOR arithExp:e2 {: RESULT = new IRExpBitOr(e1, e2); :} |
      arithExp:e1 INVERT arithExp:e2 {: RESULT = new IRExpIvert(e1, e2); :}
     ; 

      //arithmetic expressions
arithExp ::= 

     arithExp:e PLUS term:t {: RESULT = new IRExpAdd(e, t); :} |
     arithExp:e MINUS term:t {: RESULT = new IRExpSub(e, t); :} |
     term:t {: RESULT = t; :}

     ;

term ::= 

     term:t MUL expt:x {: RESULT = new IRExpMul(t, x); :} |
     term:t MOD expt:x {: RESULT = new IRExpMod(t, x); :} |
     term:t DIV expt:x {: RESULT = new IRExpDiv(t, x); :} |
     expt:x {: RESULT = x; :}

    ;

expt ::= 
    expt:x EXPT factor:f {: RESULT = new IRExpExpt(x, f); :} |
    factor:f {: RESULT = f; :}

    ;

factor ::= 
    INTEGER:n {: RESULT = new IRExpConst(n.intValue()); :} |
    VAR:var {: RESULT = new IRExpVar(var); :} |
    STRING:n {: RESULT = new IRExpString(n); :} |
    LPAREN arithExp:e RPAREN {: RESULT = e; :} 
    // LBRACE arithExp:e RBRACE {: RESULT = e :}
     ;

empty ::=;

Getting some shift/reduce conflict when trying to sort out this grammar for a simple language i'm trying to build :-(. Can anyone guide me in the right light plz?

+1  A: 

"Some shift/reduce conflict"? I get 38 S/R conflicts and then a too-many-warnings error.

Perhaps I should just analyze the first one.

> Warning : *** Shift/Reduce conflict
> found in state #106   between cmdList
> ::= statementList (*)    and    
> statement ::= (*) LBRACKET varList
> RBRACKET    under symbol LBRACKET  
> Resolved in favor of shifting.

So, it looks like a statement could possibly be followed by [something], so the parser doesn't know whether to keep parsing (shift) or reduce the (as it happens, fractional) statement that it already has.

This is a good example of how shift/reduce conflicts in LALR(1) parsers are not necessarily errors. Usually, you want to do the shift and so the default action is perfectly reasonable and the conflict is just an obvious and meaningless purely technical ambiguity.

It might be more useful if you were to ask a question more like "my grammar won't parse '...this...', why not?"

DigitalRoss
hey thanks for the insight :). can u expound and aid me in fixing this plz.
ferronrsmith
Fixing what? We don't know if those conflicts are necessarily errors. Cup probably has a way of telling it to expect a certain number of S/R conflicts. Read the docs, give it a big number, and run the grammar. See what it can do and what it can't. If there is a real problem, ask a specific question. Have fun!
DigitalRoss
In this particular case, the problem is caused by the PROC statement. Ultimately, when faced with (for example) PROC id <stmt-1> <stmt-2>, the parser has to choose between including <stmt-2> in the body of the PROC, or treating it as an independent statement. You've got an ambiguous grammar here, and the fix is to change your language so that you can specify an unambiguous grammar.
Stephen C
Are you sure about PROC causing the problem? I just commented out the PROC statement and still got 37 S/R conflicts. I'm going to stand by my original analysis. "Yes, this is my final answer." :-)
DigitalRoss
thanks anyways. manage to narrow it down to 4 errors. thanks for the help God bless, happy holidays :-)
ferronrsmith
No I'm not sure. But I don't think it matters whether I'm sure. What the OP needs to do is to analyse each and every one of those conflicts, figure out what is causing it, decide if it is harmless or harmful, and do something about it. Simply dismissing a conflict as harmless without understanding why is unwise in the extreme!
Stephen C