Parsen mit java_cup - Shift/Reduce Problem

adalbert

Mitglied
Hallo zusammen!

Ich bastle gerade an einer Templateing-eingine und definiere definiere dafür eine eigene, kleine Sprache. Die Sprache soll mit JFlex und java_cup analysiert werden und damit ein Code-Baum erzeugt werden, welcher dann interpretiert wird.

Ich hab dabei u.a. folgende Anforderung: Es gibt if-statements, welche conditions auswerten und je nach dem ihren "Körper" ausführen oder nicht.
Eine Art der Conditions sind Relationale Bedingungen, also Vergleiche von Werten, wie 5 >= 3, a < 7 oder b + 4 < 6 *(a -1). Neben numerischen Werten gibts auch Strings und logische Werte, welche bei Vergleichen auch berücksichtigt werden müssen (also z.B. a == "hallo welt" soll möglich sein)!
a und b sind hier Variablen, die über ihren Namen (= Identifier) angesprochen werden können.

Der Kern meines Problem sieht so aus (ohne actions o. überflüssiges Zeug):

Code:
// ########################################################
// # Terminals
// ########################################################

terminal        LPA, RPA;                       // ( and )
terminal        STRING, BOOLEAN, INT, WORD;     // Literals for Strings, Logic values and numeric values
terminal        EQ, LT;                         // rel. operators == <
terminal        IF, THEN, ENDIF;
terminal        BODY;                           // all real statements
terminal        PLUS, MINUS;                    // arith. operators
terminal        IDENTIFIER;                     // identifier which can be resolved to a value

// ########################################################
// # NonTerminals
// ########################################################

non terminal    prog;                           // the goal
non terminal    if;
non terminal    condition;

non terminal    num_lit, str_lit, log_lit;      // literals for numeric, string and logic values
non terminal    id;
non terminal    value;                          // any kind of value
non terminal    arith;                          // any kind of arith. expression

// ########################################################
// # Precedences
// ########################################################

precedence left PLUS, MINUS;
precedence left LPA;

// ########################################################
// # Production rules
// ########################################################

prog    ::= if;

if      ::= IF condition THEN BODY ENDIF;

condition
        ::= value EQ value
        |   value LT value
        ;
        
value   ::= str_lit
        |   log_lit
        |   arith
        |   id
        ;
        
str_lit ::= STRING;

log_lit ::= BOOLEAN;

num_lit ::= INT
        |   WORD
        ;
        
arith   ::= arith PLUS arith
        |   arith MINUS arith
        |   LPA arith RPA
        ;

arith   ::= num_lit
        |   id
        ;
        
id      ::= IDENTIFIER
        ;

Wie man sieht ist das nonterminal id sowohl in der Regel für value als auch für arith enthalten. Das das nicht gut geht und es zu Konflikten kommt, ist mir mittlerweile klar, nur weis ich nicht, wie ich das lösen soll.

Die Vergleiche an sich sind so implementiert, dass sie nur einen Wert (value) wollen und zur Laufzeit entscheiden ob die beiden Werte überhaupt verglichen werden können. Ich kann auch zur Laufzeit bestimmen ob hinter a ein String oder ein DWORD oder sowas steht (Typ ist also bekannt).

Weis jemand wie man so ein Problem lösen kann? Mir raucht schon ganz schön der Kopf...

Gruß,
adalbert
 
S

SlaterB

Gast
inwiefern besteht denn überhaupt ein Problem, hast du konkrete Fehlermeldungen von einem Framework welches mit diesen Regeln gefüttert wird oder so?

was mir auffällt:
"arith ::= " steht zweimal da, arith wird als einziges Element 2x definiert, ist das ok?
 

adalbert

Mitglied
Hallo SlaterB,
die Meldung die CUP ausgibt lautet
Code:
Warning : *** Reduce/Reduce conflict found in state #5
  between arith ::= id (*)
  and     value ::= id (*)
  under symbols: {EQ, LT, THEN}
  Resolved in favor of the second production.

Warning : *** Shift/Reduce conflict found in state #5
  between arith ::= id (*)
  under symbol EQ
  Resolved in favor of shifting.

Warning : *** Shift/Reduce conflict found in state #5
  between arith ::= id (*)
  under symbol LT
  Resolved in favor of shifting.

Warning : *** Shift/Reduce conflict found in state #5
  between arith ::= id (*)
  under symbol THEN
  Resolved in favor of shifting.

Warning : *** Shift/Reduce conflict found in state #5
  between value ::= id (*)
  under symbol EQ
  Resolved in favor of shifting.

Warning : *** Shift/Reduce conflict found in state #5
  between value ::= id (*)
  under symbol LT
  Resolved in favor of shifting.

Warning : *** Shift/Reduce conflict found in state #5
  between value ::= id (*)
  under symbol THEN
  Resolved in favor of shifting.

Daran sieht man eben (in der ersten Meldung), dass er nicht weis, ob er aus id einen value oder ein arith machen soll (ist eben nicht eindeutig).

Das arith ::= doppelt vorkommt ist kein Problem. Das darf man machen um z.B. die Lesbarkeit zu erhöhen indem man logisch zusammengehörige Regeln zusammenfasst.
 
S

SlaterB

Gast
nicht dass ich wirklich was verstehe, hatte auf meinem Doppler gehofft, jetzt mit Erzwingen der Fehlermeldung sicher was beigetragen ;)
und sonst zumindest ne Stunde auf andere Antworten abgewartet,

aber einen Versuch gönne ich mir noch:
kann eine arith direkt zu einer id ausgewertet werden?
dann lasse doch bei value nur arith zu, darüber kann es letztlich auch id werden

generell sollte aber sicher besser funktionieren..
 

HoaX

Top Contributor
Wie slaterb sagt einfach das id bei value rausnehmen. Ansonsten muss ich sagen dass das alles etwas wirr aussieht.
Wenn du auch Dinge wie "if a then...." oder "if (a < b) == (d < e) then ..." zulassen willst, dann geht das ganze imo auch einfacher:

Code:
condition ::= simple
    | condition + condition
    | condition - condition
    | condition < condition
    | condition > condition
    | LPA condition RPA

simple ::= STRING | BOOLEAN | ...
Die Bindungskraft der Operatoren kannst du dann schön der precedence festlegen.
 

adalbert

Mitglied
Hallo SlaterB,

es ist leider nicht möglich eine arith (== Arithmetic expression) in eine id "umzuwandeln". Hinter einer id steht eben zur Laufzeit eine Variable und deren Inhalt möchte ich, sofern dieser ein numerischer Wert ist, in einer arith benutzen.

Da das auch für String-Werte und logische Werte gelten soll sehe ich kaum eine andere Möglichkeit als zu sagen, dass ein value durch eine id gegeben sein kann oder aber durch ein Literal.

Und da habe ich eben diese Mehrdeutigkeit (value -> arith -> id bzw. value -> id).

Ich hab auch schon überlegt, die Regel für arith wie folgt zu definieren:

Code:
arith   ::= arith PLUS arith
        |   arith MINUS arith
        |   LPA arith RPA
        ;

arith   ::= num_lit
        |   value
        ;

Also value statt id, was aber zu einer Rekursion führt und mich auch nicht weiter bringt....

Natürlich hast du recht, die Meldung vom CUP hätte ich schon mit beifügen sollen :)
 

adalbert

Mitglied
Hallo HoaX,

ich weis nicht so recht, ob es gut ist zu sagen, dass man Bedingungen "addieren" oder miteinander vergleichen kann (condition + condition bzw. condition < condition).

Ich denke mir einfach, dass eine Berechnung nichts anderes darstellt als einen Wert. Und ein Wert kann sein:
* Ein Literal (Also Strings, Boolean und Zahlen), also etwas was direkt in den Quellcode geschrieben wird.
* Das Ergebnis einer Berechnung
* Der Wert einer Variablen

Zahlen werden oben nicht direkt als Literal erkannt, sondern in eine "Berechnung" gepackt und deren Wert wird eben dann genutzt.

Wie könnte man das einfacher lösen?
 

HoaX

Top Contributor
Ich sehe trotz deiner Erklärung keinen Grund wieso du nicht id bei value entfernen kannst.

Ich denke es wäre einfacher wenn du mal ein paar aussagekräftige Beispiele beifügst was gehen soll, und ebenso was nicht gehen soll.
 
S

SlaterB

Gast
> es ist leider nicht möglich eine arith (== Arithmetic expression) in eine id "umzuwandeln"

verstehe ich nicht, steht das nicht im direkten Widerspruch zu deiner Regel
> arith ::= id ;
?

nicht umwandeln, sondern auswerten, es kann eine id als eine arith gelten?
dann auch ein value als id, denn ein value kann ein arith sein?

----

kann ein value letzlich ein num_lit sein? wieso ist das über den Umweg arith eingebaut,
aber num_lit bei value selber nicht aufgezählt so wie id bei beiden?
 

adalbert

Mitglied
Hier ein paar Beispiele:

if ("hallo welt" == a) then ...
if (TRUE == b) then
if (5+4 >= c) then
if (3*c + d != a) then
if (a * 4 > "Hallo Welt") then -> macht keinen sinn, soll aber nicht fehlschlagen; semantische Analyse wird das dann finden!

Wenn ich die id aus value rausnehme, dann geht z.B. if ("hallo welt" == a) then nicht mehr, weil der parser versucht aus a ein arith zu machen. Das arith kann aber nur mit numerischen Werten gebildet werden.

Ich könnte aber versuchen den Wert trozdem im Arith zu speichern.
Schonmal Danke für eure Vorschläge!

-----------
@ SlaterB:
Es ist möglich einen numerischen Wert aus einer id zu laden und zu benutzen (z.B. in einer Berechnung)
Es ist aber nicht möglich den Wert einer Berechnung in eine ID zu schreiben (zumindest solange im Quellcode nichts anderes steht)
 
Zuletzt bearbeitet:

HoaX

Top Contributor
Hallo HoaX,

ich weis nicht so recht, ob es gut ist zu sagen, dass man Bedingungen "addieren" oder miteinander vergleichen kann (condition + condition bzw. condition < condition).

Ich denke mir einfach, dass eine Berechnung nichts anderes darstellt als einen Wert. Und ein Wert kann sein:
* Ein Literal (Also Strings, Boolean und Zahlen), also etwas was direkt in den Quellcode geschrieben wird.
* Das Ergebnis einer Berechnung
* Der Wert einer Variablen

Zahlen werden oben nicht direkt als Literal erkannt, sondern in eine "Berechnung" gepackt und deren Wert wird eben dann genutzt.

Wie könnte man das einfacher lösen?

Darum meine Frage was es sonst noch alles können soll. Da wären mehr gültige und auch ungültige Beispiele hilfreich.

Wenn du keine Addition von Condition magst, dann zieh die eben raus, wie du es schon hast, dann kommst du zu sowas ungefähr:
Code:
condition ::= expression LT expression
    | expression EQ expression

expression ::= expression + expression
    | expression - expression
    | LPA expression RPA
    | simple

simple ::= NUMBER | STRING | ...
 

adalbert

Mitglied
Hallo ihr beiden!

eben hat es einen lauten Knall gemacht und der Denk-Knoten in meinem Kopf ist geplatzt. Ihr habt vollkommen recht, ich hab da zu kompliziert gedacht. Manchmal hat man einfach ein Brett vorm Kopf.

Wenn ich schon sage, dass alles ein Wert ist, kann ich auch sagen, dass ich mit Werten rechne und muss nicht versuchen von den Werten nur die numerischen Werte für die Berechnungen rauszufischen.

FYI ich habs jetzt so gemacht (Das entspricht so ziemlich dem was HoaX gepostet hat):

Code:
value   ::= STRING
        |   BOOLEAN
        |   INT
        |   WORD
        |   id
        |   LPA value RPA
        ;

value   ::= value PLUS value
        |   value MINUS value
        ;

condition  ::= value EQ value
        |   value LT value
        ;

Ob das was sinnvolles gibt, kann man sehr leicht dann später analysieren sobald der Baum fertig ist.

You 2 made my day!
Danke nochmals!
 

HoaX

Top Contributor
Spaßig wird es wenn du Ausdrücke wie "if -6 < 5 then..." zulassen willst, aber nicht "if 6 --5 < 4 then..." ;) Ich hab da bestimmt einen Tag dran gesessen bis es Klick gemacht hatte und die völlig offensichtliche Lösung hatte.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
martin82 Java-Code aus Text-Datei parsen Allgemeine Java-Themen 3
C Java Quellcode parsen Allgemeine Java-Themen 8
K Inhalte Parsen von Website Allgemeine Java-Themen 15
W JSON parsen eines ,mit JS.stringify erstellten Strings Allgemeine Java-Themen 27
C Parsen einer sich updatenden Html mithilfe von jsoup Allgemeine Java-Themen 4
O JSON in Integer parsen Allgemeine Java-Themen 5
S Ini Text aus String parsen Allgemeine Java-Themen 1
OnDemand Datenbankdatei parsen Allgemeine Java-Themen 2
N svg(xml) parsen und manipulieren? Allgemeine Java-Themen 3
OnDemand CSV parsen mehrere Zeilen Allgemeine Java-Themen 22
2 mehrere Json Werte Parsen Allgemeine Java-Themen 3
G JSON parsen Allgemeine Java-Themen 3
W String Parsen und auf eigenes Muster anwenden (kein Regex) Allgemeine Java-Themen 11
looparda Datei parsen Allgemeine Java-Themen 1
T Jsoup: Mehrere Links nacheinander parsen Allgemeine Java-Themen 11
C Benutzereingabe von EXCEL-Funktionen parsen Allgemeine Java-Themen 4
B Such-String parsen mit Klammern Allgemeine Java-Themen 2
L Windows CMD werte Parsen. Allgemeine Java-Themen 2
B XML parsen Allgemeine Java-Themen 13
H Bestimmten Wert aus String parsen Allgemeine Java-Themen 7
0 Parsen Allgemeine Java-Themen 7
W Best Practice Dateien parsen Allgemeine Java-Themen 3
X Tags "parsen" Allgemeine Java-Themen 8
C Roboter, Befehle parsen Allgemeine Java-Themen 12
M Informationen aus komplexen String parsen Allgemeine Java-Themen 13
W Dateinamen dynamisch Parsen Allgemeine Java-Themen 12
F JavaMail - Lokale eMail-Datei einlesen und parsen? Allgemeine Java-Themen 9
T String in Date parsen (*ohne* bekanntes Format) Allgemeine Java-Themen 8
M Dateien mit Quelltext parsen Allgemeine Java-Themen 7
W RegEx Zeile parsen Medium Allgemeine Java-Themen 8
S Dateiname mit Regex parsen Allgemeine Java-Themen 3
K _alle_ Sonderzeichen parsen Allgemeine Java-Themen 2
S Feher beim Parsen eines Datums Allgemeine Java-Themen 4
E Reguläre Txt in Tree parsen Allgemeine Java-Themen 2
S Strings zu Color-Instanzen parsen? Allgemeine Java-Themen 7
S Überprüfung/Parsen eines Byte-Arrays Allgemeine Java-Themen 9
A String zu Datum parsen - SimpleDateFormat Problem Allgemeine Java-Themen 8
A Datum parsen Allgemeine Java-Themen 9
G Parsen von: if(a > 15 AND (b == 3 OR c != 4)) Allgemeine Java-Themen 3
G String nach Float parsen Allgemeine Java-Themen 2
P OutOfMemoryError beim XML erstellen bzw parsen, mehr RAM? Allgemeine Java-Themen 4
H2SO3- Exception beim date parsen des Jahres 00 Allgemeine Java-Themen 6
H2SO3- date mit pm and am parsen Allgemeine Java-Themen 3
Z Datum ohne Format-Kenntnisse parsen Allgemeine Java-Themen 5
T Wie kontinuierlichen asci input parsen? Allgemeine Java-Themen 3
alexpetri Date Parsen Allgemeine Java-Themen 3
G String parsen und Problem mit escaped zeichen Allgemeine Java-Themen 4
M Html parsen Allgemeine Java-Themen 2
D Parameter parsen? Allgemeine Java-Themen 15
V Datum parsen Allgemeine Java-Themen 6
MQue String parsen Allgemeine Java-Themen 11
M wie sinnvoll parsen ? Allgemeine Java-Themen 4
M Link parsen bzw. zerlegen Allgemeine Java-Themen 9
padde479 String in double parsen Allgemeine Java-Themen 6
W Package via Reflection parsen Allgemeine Java-Themen 4
M MP3 Datei selber parsen/werte auslesen Allgemeine Java-Themen 13
J parsen von verschiedenen dokument typen Allgemeine Java-Themen 3
B textzeile parsen Allgemeine Java-Themen 6
T Schlüsseldatei mit Umlauten parsen, aber wie. Allgemeine Java-Themen 6
G mail body parsen (->attachment & filename) Allgemeine Java-Themen 2
J DirectPlay Server-Antwort parsen Allgemeine Java-Themen 2
S String parsen Allgemeine Java-Themen 15
V LogFile parsen Allgemeine Java-Themen 5
E Field-Objekt in JTextField parsen Allgemeine Java-Themen 3
L Prozesse parsen ? Allgemeine Java-Themen 2
OnDemand Java Deployment Vaadin Allgemeine Java-Themen 3
D Hat Java eine Library um JavaScript auszuwerten? Allgemeine Java-Themen 2
Zrebna Wieso sind eigentlich JUnit-Tests in src/test/java platziert - nur Konvention? Allgemeine Java-Themen 7
N LlaMA, KI, java-llama.cpp Allgemeine Java-Themen 39
V Java-Codierungsherausforderung: Navigieren durch die Macken der Datumsmanipulation Allgemeine Java-Themen 2
E Output Fehler (Java-Programm Kuchen) Allgemeine Java-Themen 11
M java: unexpected type Allgemeine Java-Themen 2
harrytut Java Input/Output Tests Junit Allgemeine Java-Themen 3
B Java Discord bot auf ein Root Server? Allgemeine Java-Themen 1
BetziTheRealOne Java PKIX path building failed as non Admin Allgemeine Java-Themen 15
D Linux, Java-Version wird nicht erkannt bzw. welche Einstellung fehlt noch? Allgemeine Java-Themen 19
KonradN Java 21 Release Allgemeine Java-Themen 5
V Umgang mit fehlenden Daten in einer Java-Datenanalyseanwendung Allgemeine Java-Themen 5
P Fehler: Hauptklasse Main konnte nicht gefunden oder geladen werden Ursache: java.lang.ClassNotFoundException: Main Allgemeine Java-Themen 24
K Java Anwendung machen Anleitung Allgemeine Java-Themen 5
G java.io.listFiles() Allgemeine Java-Themen 3
8u3631984 Frage zu Java Streams min / max Allgemeine Java-Themen 17
S Java Programm lässt sich vom USB-Stick starten, aber nicht von HDD Allgemeine Java-Themen 16
K Java-Projekt Allgemeine Java-Themen 11
K Java-Projekt Allgemeine Java-Themen 0
ruutaiokwu Welcher Browser unterstützt heutzutage noch Java Applets? Allgemeine Java-Themen 5
Jose05 Java-Klasse im extra cmd-Fenster ausführen Allgemeine Java-Themen 3
rode45e Java Threads Allgemeine Java-Themen 4
G java.io.listFiles() Allgemeine Java-Themen 2
N Java Dynamic Proxy Allgemeine Java-Themen 3
N Leichte Java Gegner Ki Allgemeine Java-Themen 10
A Java modul Problem Allgemeine Java-Themen 4
Thomasneuling Java Jar datei erstellen, von Projekt, dass auch Javafx Dateien, FXML Dateien und CSS Dateien, sowie Bilder enthält? Allgemeine Java-Themen 14
V Funktionale Schnittstelle in Java Allgemeine Java-Themen 3
OnDemand Java String in Hashmap als Key NULL Allgemeine Java-Themen 27
urmelausdemeis Exception in thread "main" java.lang.Error: Unresolved compilation problem: Allgemeine Java-Themen 7
berserkerdq2 Wenn ich bei Intelij javafx mit maven importieren will, muss ich das in die pom.xml reintun, aber warum noch in module-info.java? Allgemeine Java-Themen 3
KonradN Java 20 am 21. März Allgemeine Java-Themen 1
O Java Website Stock Bot Allgemeine Java-Themen 3
J Front-/Backend in Java Allgemeine Java-Themen 14

Ähnliche Java Themen

Neue Themen


Oben