Shift Уменьшить Конфликт

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 ::=;

Возникает конфликт сдвига/уменьшения при попытке разобраться с этой грамматикой для простого языка, который я пытаюсь построить :-(. Может ли кто-нибудь направить меня в правильном свете, пожалуйста?


person ferronrsmith    schedule 30.11.2009    source источник


Ответы (1)


«Некоторый сдвиг/уменьшение конфликта»? Я получаю 38 конфликтов S/R, а затем слишком много предупреждений.

Возможно, мне следует просто проанализировать первую.

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

Таким образом, похоже, что за оператором может следовать [something], поэтому синтаксический анализатор не знает, продолжать ли синтаксический анализ (сдвиг) или уменьшить (как это бывает, дробное) оператор, который у него уже есть.

Это хороший пример того, как конфликты сдвига/уменьшения в синтаксических анализаторах LALR(1) не обязательно являются ошибками. Обычно вы хотите сделать сдвиг, поэтому действие по умолчанию вполне разумно, а конфликт — это просто очевидная и бессмысленная чисто техническая двусмысленность.

Возможно, было бы полезнее, если бы вы задали вопрос, похожий на «Моя грамматика не будет анализировать '... это...', почему бы и нет?»

person DigitalRoss    schedule 30.11.2009
comment
эй спасибо за понимание :). Можете ли вы объяснить и помочь мне в исправлении этого плз. - person ferronrsmith; 30.11.2009
comment
Исправление чего? Мы не знаем, обязательно ли эти конфликты являются ошибками. У Cup, вероятно, есть способ сообщить ему об ожидании определенного количества конфликтов S/R. Прочтите документацию, присвойте ей большое число и запустите грамматику. Посмотрите, что он может сделать, а что нет. Если есть реальная проблема, задайте конкретный вопрос. Радоваться, веселиться! - person DigitalRoss; 30.11.2009
comment
В данном конкретном случае проблема вызвана оператором PROC. В конечном счете, столкнувшись с (например) идентификатором PROC ‹stmt-1› ‹stmt-2›, синтаксический анализатор должен выбрать между включением stmt-2› в тело PROC или обработкой его как независимого оператора. У вас здесь неоднозначная грамматика, и исправление состоит в том, чтобы изменить ваш язык, чтобы вы могли указать однозначную грамматику. - person Stephen C; 30.11.2009
comment
Вы уверены, что PROC вызывает проблему? Я только что закомментировал оператор PROC и все равно получил 37 конфликтов S/R. Я останусь при своем первоначальном анализе. Да, это мой последний ответ. :-) - person DigitalRoss; 30.11.2009
comment
в любом случае спасибо. удается сузить его до 4 ошибок. спасибо за помощь дай Бог здоровья, с праздником :-) - person ferronrsmith; 30.11.2009
comment
Нет, я не уверен. Но я не думаю, что имеет значение, уверен ли я. Что нужно сделать ОП, так это проанализировать каждый из этих конфликтов, выяснить, что его вызывает, решить, безвреден он или вреден, и что-то с этим сделать. Просто отмахиваться от конфликта как от безобидного, не понимая, почему, в высшей степени неразумно! - person Stephen C; 30.11.2009