2016-05-01 15 views
4

Ich versuche, Grammatik für GNU MathProg Sprache aus Glpk-Paket zu erstellen https://www3.nd.edu/~jeff/mathprog/glpk-4.47/doc/gmpl.pdf
Leider Grammatik, die ich bisher geschrieben habe, ist mehrdeutig. Ich kann Bison nicht sagen, welcher Ast des Parsing-Baums korrekt ist, wenn ein Bezeichner verwendet wird. Zum Beispiel:Kann nicht herausfinden, wie zu beheben, reduzieren/reduzieren Konflikt

numericExpression : numericLiteral 
       | identifier 
       | numericFunctionReference 
       | iteratedNumericExpression 
       | conditionalNumericExpression 
       | '(' numericExpression ')' %prec PARENTH 
       | '-' numericExpression %prec UNARY 
       | '+' numericExpression %prec UNARY 
       | numericExpression binaryArithmeticOperator numericExpression 
       ; 

symbolicExpression : stringLiteral 
       | symbolicFunctionReference 
       | identifier 
       | conditionalSymbolicExpression 
       | '(' symbolicExpression ')' %prec PARENTH 
       | symbolicExpression '&' symbolicExpression 
       ; 

indexingExpression : '{' indexingEntries '}' 
       | '{' indexingEntries ':' logicalExpression '}' 
       ; 

setExpression : literalSet 
      | identifier 
      | aritmeticSet 
      | indexingExpression 
      | iteratedSetExpression 
      | conditionalSetExpression 
      | '(' setExpression ')' %prec PARENTH 
      | setExpression setOperator setExpression 
      ; 


numericLiteral : INT 
      | FLT 
      ; 

linearExpression : identifier 
      | iteratedLinearExpression 
      | conditionalLinearExpression 
      | '(' linearExpression ')' %prec PARENTH 
      | '-' linearExpression %prec UNARY 
      | '+' linearExpression %prec UNARY 
      | linearExpression '+' linearExpression 
      | linearExpression '-' linearExpression 
      | linearExpression '*' numericExpression 
      | numericExpression '*' linearExpression 
      | linearExpression '/' numericExpression 
      ; 

logicalExpression : numericExpression 
       | relationalExpression 
       | iteratedLogicalExpression 
       | '(' logicalExpression ')' %prec PARENTH 
       | NOT logicalExpression %prec NEG 
       | logicalExpression AND logicalExpression 
       | logicalExpression OR logicalExpression 
       ; 

identifier : SYMBOLIC_NAME 
     | SYMBOLIC_NAME '[' listOfIndices ']' 
     ; 

listOfIndices : SYMBOLIC_NAME 
    | listOfIndices ',' SYMBOLIC_NAME 
    ; 

Kennung ist einfach der Name 'Variable'. Die Variable hat einen bestimmten Typ (Parameter, Menge, Entscheidungsvariable) und kann indexiert werden. Im Code muss der Programmierer den Variablentyp in Anweisungen wie zB deklarieren.

param p1; 
param p2{1, 2} >=0; 
set s1; 
set s2{i in 1..5}; 
var v1 >=0; 
var v2{S1,S2}; 

Aber wenn Bison sieht Kennung nicht weiß, welche Regel verwendet werden soll, und ich bin immer verringern/verringern Konflikte wie

113 numericExpression: identifier . 
123 symbolicExpression: identifier . 

'&'   reduce using rule 123 (symbolicExpression) 
ELSE   reduce using rule 113 (numericExpression) 
ELSE   [reduce using rule 123 (symbolicExpression)] 
INTEGER  reduce using rule 113 (numericExpression) 
INTEGER  [reduce using rule 123 (symbolicExpression)] 
BINARY  reduce using rule 113 (numericExpression) 
BINARY  [reduce using rule 123 (symbolicExpression)] 
ASIGN  reduce using rule 113 (numericExpression) 
ASIGN  [reduce using rule 123 (symbolicExpression)] 
','   reduce using rule 113 (numericExpression) 
','   [reduce using rule 123 (symbolicExpression)] 
'>'   reduce using rule 113 (numericExpression) 
'>'   [reduce using rule 123 (symbolicExpression)] 
'}'   reduce using rule 113 (numericExpression) 
'}'   [reduce using rule 123 (symbolicExpression)] 

113 numericExpression: identifier . 
123 symbolicExpression: identifier . 
130 setExpression: identifier . 

UNION   reduce using rule 130 (setExpression) 
DIFF   reduce using rule 130 (setExpression) 
SYMDIFF   reduce using rule 130 (setExpression) 
ELSE   reduce using rule 113 (numericExpression) 
ELSE   [reduce using rule 123 (symbolicExpression)] 
ELSE   [reduce using rule 130 (setExpression)] 
WITHIN   reduce using rule 130 (setExpression) 
IN    reduce using rule 113 (numericExpression) 
IN    [reduce using rule 123 (symbolicExpression)] 

Ich habe auch andere Probleme, aber dieses ist Blocker für mich

+0

Können Sie auch Ihren Parser zeigen? Ich versuche, Ihre Grammatik durchzulesen und suche weiter nach "param" "var" strings – aec

+0

Hier ist die komplette Bison-Datei. Beachten Sie, dass es noch nicht fertig ist. Es fehlen einige Operatoren und einige tabellarische Regeln. http://wklej.org/id/2370457/ – Lisu

+0

Ich habe das Gefühl, dass ich mich bei Ausdrücken semantisch verzweige und nicht kategorisch dazu tendiere, Probleme wie diese zu erzeugen. Wäre es nicht ausreichend, zB "numericExpression" und "logicalExpression" zu haben? beide bewerten oft dasselbe: "Ausdruck". Sie verwenden diese spezifischeren Ausdrücke zur Validierung. – aec

Antwort

1

Grundsätzlich ist das Problem ist, dass identifier in mehreren Regeln angezeigt:

numericExpression : identifier 
symbolicExpression : identifier 
setExpression: identifier 

, die im selben Kontext gelten können. Eine Möglichkeit, dies zu lösen, ist verschiedene Token-Typen für Satznamen und Skalar (Parameter und Variablen) Namen vorstellen:

symbolicExpression : SCALAR_NAME 
setExpression: SET_NAME 

Dieser Konflikt mit Set-Namen auflösen wird. Ich glaube nicht, dass Sie diese Regel brauchen

numericExpression : identifier 

, weil es eine automatische Umwandlung von Strings in Zahlen in AMPL und daher MathProg ist, die eine Teilmenge von AMPL ist, so symbolicExpression sollte im Rahmen der numericExpression erlaubt sein .

Beachten Sie, dass die Grammatik nicht kontextfrei ist. Daher müssen Sie zusätzliche Informationen wie die obige Kategorie aus der Symboltabelle abrufen, um solche Probleme zu lösen.

ist mein flex ein wenig eingerostet, aber ich denke man so etwas in einer Kennung Regel tun können:

return is_setname(...) ? TOK_SET_NAME : TOK_SCALAR_NAME; 

wo is_setname eine Funktion ist zu prüfen, ob die aktuelle Kennung ein Satz ist. Sie müssen eine solche Funktion definieren und die erforderlichen Informationen aus einer Symboltabelle abrufen.

+0

Wie würden Sie SCALAR_NAME und SET_NAME unterscheiden? Beide werden einfach durch flex regulären Ausdruck generiert > SYMBOLIC_NAME [a-zA-Z _] [a-zA-Z0-9 _] * Vielleicht sollte ich einige Pre-Lex-Analyse und fügen Sie Präfixe wie param_name1, var_name2 – Lisu

+0

Ich denke Sie sollten dies in einer Flex-Regel tun können, indem Sie ein entsprechendes Token zurückgeben. Ich habe die Antwort aktualisiert. – vitaut