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
hé merci pour la perspicacité :). Pouvez-vous expliquer et m'aider à résoudre ce problème? – ferronrsmith
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
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ë. –