Java 减少冲突
当我试图为我试图构建的一种简单语言整理语法时,会产生一些移位/减少冲突:-(.有人能给我提供正确的指导吗?“一些移位/减少冲突”?我会遇到38个S/R冲突,然后是太多的警告错误 也许我应该分析一下第一个Java 减少冲突,java,parsing,compiler-construction,interpreter,cups,Java,Parsing,Compiler Construction,Interpreter,Cups,当我试图为我试图构建的一种简单语言整理语法时,会产生一些移位/减少冲突:-(.有人能给我提供正确的指导吗?“一些移位/减少冲突”?我会遇到38个S/R冲突,然后是太多的警告错误 也许我应该分析一下第一个 import java_cup.runtime.*; import java.io.*; import java.util.*; /* Preliminaries to set up and use the scanner. */ parser code {: SMPLLex
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 ::=;
因此,一条语句后面可能跟有[something]
,因此解析器不知道是继续解析(shift)还是减少它已经拥有的(碰巧是分数)语句
这是一个很好的例子,说明了LALR(1)解析器中的shift/reduce冲突不一定是错误。通常,您希望执行shift,因此默认操作是完全合理的,冲突只是一个明显的、毫无意义的纯技术歧义
如果你问的问题更像是“我的语法不会解析“…这个…”,为什么不呢?”嘿,谢谢你的见解:)。你能解释并帮助我修理这个plz吗?修理什么?我们不知道这些冲突是否一定是错误。Cup可能有一种方式告诉它,期待一定数量的S/R冲突。阅读文档,给它一个大数字,然后运行语法。看看它能做什么,不能做什么。如果真的有问题,问一个具体的问题。玩得高兴在这种特殊情况下,问题是由PROC语句引起的。最终,当遇到(例如)PROC id时,解析器必须在包括在PROC主体中或将其视为独立语句之间进行选择。这里有一个不明确的语法,修复方法是更改您的语言,以便您可以指定一个明确的语法。您确定是PROC导致了这个问题吗?我刚刚注释掉了PROC语句,仍然有37个S/R冲突。我将坚持我最初的分析。“是的,这是我最后的答案。”:-)谢谢你。设法将其缩小到4个错误。感谢上帝的帮助,节日快乐:-)
> Warning : *** Shift/Reduce conflict
> found in state #106 between cmdList
> ::= statementList (*) and
> statement ::= (*) LBRACKET varList
> RBRACKET under symbol LBRACKET
> Resolved in favor of shifting.