Aufgabenblatt 6 - Nr 6.2

Einen Parser, bitte :wink:

Disclaimer: Dieser Thread wurde aus dem alten Forum importiert. Daher werden eventuell nicht alle Formatierungen richtig angezeigt. Der ursprüngliche Thread beginnt im zweiten Post dieses Threads.

Aufgabenblatt 6 - Nr 6.2
Hab ein wenig rumgespielt mit dem Parser, die Implementierung scheint nicht so dramatisch aber ich tät gerne wissen was für Testexpressions der so verstehen sollte oder nicht sollte.

Ich habs getestet mit:
Gültig:
2*(3+5), 2+(35), (23+5), 1+2, 1*2, 1

Ungültig:
1++1, 1**1, 2*(3+5))

Hat irgendwer Fälle die problematisch sind? Die oben scheinen mir alle ziehmlich klar zu sein … wüsste gerne ob es irgendwas gibt worauf man besonders achten muss oder so…


also leute ich spiel auch schon die ganze zeit :wink:

nun die Frage: liege ich mit dem folgendem code total daneben oder gehts wenigstens in die richtige richtung?

private boolean isExpression() {
		if (isTerm()){
			if (currentChar == parseString.length-1) { return true;	}
			else if (isExpression()) {
				if (nextChar() == '+') {
					if (isTerm()){ return true; }
					else { return false; }
				}
				else { return false; }
			}
			else{ return false; }
		}
		else { return false; }
	}
	
	private boolean isTerm() {
		if (isTerm()) {
			if (nextChar() == '*') {
		 		proceed();
		 		if (isFactor()) {	return true; }
		 	}
			else if (isFactor()) { return true; }
			else { return false; }
		}
		return false;
	}

würde mich sehr freuen wenn mir jemand sagt warum ich nur 5 % hab :frowning:


@Anteru: Ne, ich habs genauso getestet. Sämmtliche Ketten sind gültig, die kannst auch ewig lang verschachteln:
23+(2*(3)+39+7+(3*(456+597))+2*4)*3+5
usw…

An ungültigen Sachen hab ich ihm auch doppelte Zeichen gegeben wie du, Klammern falsch gesetzt, dann halt noch so Sachen wie andere Zeichen einbauen… Aber das wars auch schon

Wüsste nicht, wie mans sonst noch testen sollte.
Und Testcase sagt ja auch 100%

Also wenn dein Zeug mit dem allen wunderbar klappt, dann wars das halt schon :wink:


Schau z.B. sowas mal genau an…
Das führt zu ner unendlich langen Rekursion. Er ruft isTerm() auf. Danach geht er zum ersten „if“ und ruft wieder isTerm() auf. Bei diesem neuen Aufruf geht er wieder bis zum „if“ und und und


oops stimmt hast recht …


Was ihr auch auf jeden Fall testen solltet, sind Wörter wie 1+2+3. Diesen offensichtlich korrekten Ausdruck hat mein Parser als ungültig verworfen, obwohl der Testcase bereits 100% angezeigt hat. Mal wieder ein Beispiel dafür, dass diese Testcases absolut unzureichend sind…
Inzwischen klappt bei mir alles.
Ein Tipp noch: Falls ihr beim Ausführen die verwirrende Meldung “java: no match” bekommen solltet, dann setzt das Argument einfach in Anführungszeichen!
Also java ExpressionParser “123” statt java ExpressionParser 123.
Dieses Problem hatte ich heute Nachmittag im CIP unter Linux. Bei TheFlow unter MacOS und bei TheChip unter Windows kam es meines Wissens nicht vor.


hm nochmal überarbeitet aber immernoch kein stück weiter…

kann mir da jemand noch ne initialzündung geben was den fehler betrifft?

private boolean isExpression() {
		if (isTerm()){
			if (currentChar == parseString.length-1) { return true;	}
			else if (isExpression()) {
				if (nextChar() == '+') {
					if (isTerm()){ 
						proceed();
						return true; }
					else { return false; }
				}
				else { return false; }
			}
			else{ return false; }
		}
		else { return false; }
	}
	
	private boolean isTerm() {
		if (isFactor()) {
			proceed();
			return true;
		}
		else if (isTerm()) {
			if (nextChar() == '*') {
				proceed();
				if (isFactor()) { return true; }
			}
			else { return false; }
		}
		else {return false;}
		return false;
	}

@MuMu: Da du ja noch ewig Zeit hast, will ich dir nicht alles vorsagen. Aber: Was du immer machen kannst: einfach mal im Kopf Durchdenken.
Nehm dir den hypothetischen Ausdruck “1+2” und geh einfach mal Schritt für Schritt durch, was dein Code macht. Dann sieht man oft, wo Denkfehler sind!

Noch was: Lasst die Testcases erstmal die Testcases sein! Andauerndes hochladen is doch Schwachsin.
Einfach selber “testen”. Das gilt für alle Programmieraufgaben.
In dem Fall hier: Programm kompilieren und in ner Konsolenumgebung per " java ExpressionParser “BLABLA” " starten oder in Eclipse “Run” wählen und bei “Arguments” BLABLA eingeben und starten. Wobei BLABLA halt ein von euch gewählter Testausdruck ist, am Anfang halt erstmal 1+2.


@anteru:

du schreibst: bei 1 ungültig. Aber lt. Ableitungsregel E → T → F → number müsste es eigentlich gültig sein…also macht mein programm eigentlich auch gültig.

P.S. meine geht jetzt auch!!!

aber 23+(2*(3)+39+7(3*(456+597))+2*4)*3+5 geht nicht …hm…
EDIT: geht doch, chip hatte nur vergessen nach der 7 ein * oder + zu setzen…


ach krampf jo 1 ist gültig, sorry. edite es gleich …

btw bei dir ist ein tippfehler, es müsste 23+(2*(3)+39+7 * (3*(456+597))+2*4)*3+5 heißen dann isses wieder valid :slight_smile:


Hopla, ja, da fehlt ein + oder ein * :wink:


gut, mein programm geht (diese grammatik ist echt brainfuck) … was ich grad aber nicht direkt rausbekomme ist die theoriefrage. Was für ein Problem kann denn auftreten? Da der Code ja geht nehm ich an dass das Problem umschifft ist, nur ist die frage wodurch :wink:


Vll. gibt es ein Problem, da das statisch Importierte in Konflikt mit einer lokal definierten Methode kommen kann.


Also ich weiß zwar nicht ob sie genau darauf hinauswollen, aber ist dir bei der
Implementation denn nichts aufgefallen?
Mach dir speziell Gedanken darüber warum bei der isFactor Methode
die Produktionen eins zu eins in if-clauses umgesetzt werden konnten.


Wenn man isTerm() und isExpression() genau so wie isFactor() implementiert funtioniert der Parser nicht. Man kann also die Grammatiken nicht direkt so implementieren wie sie in der Angabe stehen. z.B: T-> F | T * F
private boolean isTerm() {
if (isFactor()) {
return true;
} else if (isTerm()) {
if (nextChar() != ‘*’) return false;
proceed();
if (!isFactor()) return false;
return true;
}
return false;
}
funtioniert nicht.


Und dann wäre da auch noch die Sache mit dem hässlichen “sentinel” wie sie
es nennen. Kann man sich ja auch mal überlegen warum man den braucht…


ich glaube ohne einen kleinen tip kommt man nicht drauf, ich zumindest auch nicht. auch versuche mit einfachen argumenten das script durchzuspielen führten mich nicht weiter… hat den keiner einen kleinen tip wie die rekursion bei dem isTerm aussehen muss ohne eine endlosschleife zu kriegen?


Also aufgrund der Prefixgleichheit der Produktionen E → … und T → … kannst du das natürlich nur als verschachtelte Kontrollanweisung realisieren.
Zeig doch einfach mal auf was du so gekommen bist.


Vielleicht ist es einfacher, wenn man sich denkt, dass “E → E + T” das selbe ist wie E → “T +” “T +” “T +” …
Equivalent dann T nach F.