2009-11-30 5 views
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 ::=; 

Obtenir un certain changement/réduire les conflits en essayant de trier cette grammaire pour une langue simple, je suis en train de construire :-(. Quelqu'un peut-il me guider dans la plz lumière droite?Maj Réduire les conflits

Répondre

2

« Certains changement/réduire les conflits »? Je reçois 38 S/conflits R, puis une erreur trop grand nombre-avertissements.

peut-être que je devrais analyser la première.

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

, il ressemble une déclaration pourrait éventuellement être suivi par [something], de sorte que l'analyseur ne sait pas s'il faut garder l'analyse (shift) ou réduire l'instruction (en l'occurrence, fractionnaire) qu'il a déjà.

Ceci est un bon exemple de la façon dont les conflits de décalage/réduction dans les analyseurs LALR (1) ne sont pas nécessairement des erreurs. Habituellement, vous voulez faire le changement et donc l'action par défaut est parfaitement raisonnable et le conflit est juste une ambiguïté purement technique et évidente.

Il pourrait être plus utile si vous posiez une question plus comme "ma grammaire ne va pas analyser '... ceci ...', pourquoi pas?"

+0

hé merci pour la perspicacité :). Pouvez-vous expliquer et m'aider à résoudre ce problème? – ferronrsmith

+0

Comment faire quoi? Nous ne savons pas si ces conflits sont nécessairement des erreurs. Cup a probablement un moyen de lui faire attendre un certain nombre de conflits S/R. Lisez les documents, donnez-en un grand nombre et exécutez la grammaire. Voyez ce qu'il peut faire et ce qu'il ne peut pas faire. S'il y a un vrai problème, posez une question spécifique. S'amuser! – DigitalRoss

+0

Dans ce cas particulier, le problème est dû à l'instruction PROC. En fin de compte, face à (par exemple) l'ID PROC , l'analyseur doit choisir entre inclure dans le corps du PROC, ou le traiter comme une instruction indépendante. Vous avez ici une grammaire ambiguë, et la solution est de changer votre langue pour que vous puissiez spécifier une grammaire non ambiguë. –