2016-04-17 9 views
0

Ich kenne diesen Teil meiner Grammatik Ursache Fehler, aber ich weiß nicht, wie es zu beheben Ich benutze sogar% links und rechts, aber es hat nicht geholfen. Kann mir bitte jemand helfen, herauszufinden, was das Problem mit dieser Grammatik ist. Vielen Dank im Voraus für Ihre Hilfe.shift/reduce Fehler in yacc

%token VARIABLE NUM 
%right '=' 
%left '+' '-' 
%left '*' '/' 
%left '^' 
%start S_PROOP 

EQUATION_SEQUENCE 
    : FORMULA '=' EQUATION 
    ; 
EQUATION 
    : FORMULA 
    | FORMULA '=' EQUATION 
    ; 
FORMULA 
    : SUM EXPRESSION 
    | PRODUCT EXPRESSION 
    | EXPRESSION '+' EXPRESSION 
    | EXPRESSION '*' EXPRESSION 
    | EXPRESSION '/' EXPRESSION 
    | EXPRESSION '^' EXPRESSION 
    | EXPRESSION '-' EXPRESSION 
    | EXPRESSION 
    ; 
EXPRESSION 
    : EXPRESSION EXPRESSION 
    | '(' EXPRESSION ')' 
    | NUM 
    | VARIABLE   
    ; 

Antwort

0

Normalformat niedrigen Fall für nicht-Terminals und Großbuchstaben für die Klemmen zu verwenden; Großbuchstaben zu verwenden macht wahllos deine Grammatik schwerer zu lesen (zumindest für diejenigen von uns, die gewöhnliche yacc/bison-Stile gewohnt sind). Also habe ich diese Antwort geschrieben, ohne auf den Feststelltaste zu drücken.

Die grundlegende Frage ist die Produktion

expression: expression expression 

, die offensichtlich nicht eindeutig ist, da es keine Anzeichen für eine Assoziativität bietet. Darin ist es nicht anders

expression: expression '+' expression 

aber dieser Konflikt kann mit einem Vorrang Erklärung aufgelöst werden:

%left '+' 

Der Unterschied besteht darin, dass die erste Produktion keinen Terminal-Symbol hat, das macht es Unmöglich, Präzedenzregeln zu verwenden, um zu disambiguieren: In Yacc/Bison ist der Vorrang immer ein Vergleich zwischen einer potenziellen Reduktion und einer möglichen Verschiebung. Die mögliche Reduzierung ist eine Produktion, die reduziert werden könnte; Die potentielle Verschiebung ist ein Endsymbol, das in der Lage sein könnte, etwas Produktion zu verlängern. Da die Potentialverschiebung ein Endsymbol sein muss, wird dies in der Präzedenzerklärung verwendet. Standardmäßig wird der Vorrang der potenziellen Reduzierung durch das letzte Terminal-Symbol auf der rechten Seite definiert. Es ist jedoch möglich, mit einem %prec Marker ein anderes Terminal anzugeben. In jedem Fall beinhaltet der Vorrang gegen ein Terminal-Symbol, und wenn die Grammatik Nebeneinander von zwei Anschlüssen ermöglicht, gibt es kein relevantes Terminal-Symbol.

, das einfach zu umgehen, da Sie nicht verpflichtet sind, den Vorrang zu verwenden, um Konflikte zu lösen. Sie könnten nur vermeiden, den Konflikt:

/* Left associative rule */ 
expr_sequence: expr | expr_sequence expr 

/* Alternative: right associative rule */ 
expr_sequence: expr | expr expr_sequence 

Da es keine Anhaltspunkte dafür gibt, was Sie durch das Nebeneinander beabsichtigen, ich bin nicht in der Lage eine oder die andere der oben genannten Alternativen zu empfehlen, aber normalerweise würde ich in Richtung des ersten neigte .

Das ist nicht schrecklich anders als Ihre Grammatik für equation_sequence, obwohl equation_sequence tatsächlich ein Terminal-Symbol verwendet, so könnte es mit einer Präzedenzfall-Deklaration behandelt worden sein. Es ist erwähnenswert, dass equation_sequence, wie geschrieben, rechtsassoziativ ist. Das ist in der Regel korrekt für Zuweisungsoperator betrachtet, (a = b = c + 3, in einer Sprache wie C, wird als a = (b = c + 3) analysiert und nicht als (a = b) = c + 3, Zuordnung zu einem der wenigen rechts assoziativen Operatoren.) Aber wenn Sie mit = als Gleichheitsoperator, es ist vielleicht nicht das, was Sie vorhaben.