Problem: Hänge das Ergebnis des rekursiven Aufrufs...

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Gisi

Hi,

bin mal wieder am Verzweifeln. Folgender Pseudocode

http://www.cl.uni-heidelberg.de/kurs/ws ... pseudo.pdf

soll die Lösung der zweiten Aufgabe dieses Blattes

http://www.cl.uni-heidelberg.de/kurs/ws ... latt10.pdf

sein. Bisher sieht mein nicht funktionierender Code so aus:

Code: Alles auswählen

import operator
import re
def parseBracketStructure(tokens):
	result = []
	liste = tokenize(tokens)
	while len(liste) > 0:
		element = liste.pop(0)
		if element == "<":
			result.append(parseBracketStructure(tokens))
		if element == ">":
			return result
		else:
			result.append(element)
			
	return result

def tokenize(text):
	return map(str.strip, 
		filter(operator.truth, re.split("([<>])", text)))
Ich glaube zu wissen, dass das Problem in der Zeile:

[code = py]if element == "<":
result.append(parseBracketStructure(tokens))[/code]

liegt. Lasse ich nämlich als tokens zB "hallo" oder auch "hallo>" laufen, funktioniert das ganze. Nur sobald ein "<" in tokens auftaucht, kommt ein RuntimeError.

Kann mir da wer helfen?

besten dank,

Gisi



[/code]
Joghurt
User
Beiträge: 877
Registriert: Dienstag 15. Februar 2005, 15:07

Beim rekursiven Aufruf darfst du nur den rest der Liste übergeben, nicht wieder dieselben Daten, die du schon bekommen hast, das führt nämlich zu einer Endlosschleife:

Besser (ungetestet):

Code: Alles auswählen

def parseBracketStructure(tokens):
    result = []
    while len(tokens) > 0:
        element = tokens.pop(0)
        if element == "<":
            result.append(parseBracketStructure(tokens))
        if element == ">":
            return result
        else:
            result.append(element)
           
    return result
Aufruf dann mit

parseBracketStructure(tokenize(text))
Mad-Marty
User
Beiträge: 317
Registriert: Mittwoch 18. Januar 2006, 19:46

Da waren mehrere Fehler, ich habs mal gelöst inkl. Zusatz .


Richtig wäre:

Code: Alles auswählen

import operator
import re
def parseBracketStructure(liste):
    result = []
    while len(liste) > 0:
        element = liste.pop(0)
        if element == "<":
            result.append(parseBracketStructure(liste))
        elif element == ">":
            return result
        else:
            result.append(element)
    return result

def tokenize(text):
    if text.count("<") != text.count(">"):
        print "Warning, not all parantheses closed !"
    return map(str.strip,
        filter(operator.truth, re.split("([<>])", text)))


tokens = tokenize("<a <b c> d<ef> g")
print parseBracketStructure(tokens)
#print parseBracketStructure(tokenize("<a <b c> d<ef> g"))  ---> [['a', ['b c'], 'd', ['ef'], 'g']]
BlackJack

Eine "Lösung" mit `pyparsing`:

Code: Alles auswählen

from pyparsing import Suppress, OneOrMore, CharsNotIn, Forward, Group, \
                      StringEnd, ParseException

OPEN = Suppress('<')
CLOSE = Suppress('>')
data = OneOrMore(CharsNotIn('<>'))
mylist = Forward()
mylist << OneOrMore(data | Group(OPEN + mylist + CLOSE))
parser = mylist + StringEnd()

# 
# Test
# 
tests = ('<a <b c> d<ef> g',
         '<a <b c> d<ef> g>',
         '<<der><hund>><<beisst><<den><mann>>>',
         '<<der><hund>><<beisst><<den><mann>>>>')

for i, test in enumerate(tests):
    print '-' * 40
    print 'Test %d: %s' % (i + 1, test)
    try:
        result = parser.parseString(test)
        print result.asList()
    except ParseException, error:
        print 'Error:'
        print error.pstr
        print ' ' * (error.loc - 1), '^'
        print error.msg
Ist natürlich keine Lösung der Hausaufgabe weil dort ja gelernt werden soll wie man einen rekursiven Parser selber schreibt, aber das kann ich schon. ;-)
Gisi

Geniel, besten Dank euch beiden. Mein Problem war, dass ich nicht gesehen habe, dass auf dem Aufgabenblatt die Beispiele schon mit der tokenize Funktion in die Eingabe geschrieben wurden. Deshalb hab ich immer versucht, das in die parseBracketStructure Funktion einzubauen. Wäre aber ohne eure Hilfe nicht drauf gekommen, also herzlichen Dank nochmal.

Die von Mad-Marty gelöste Zusatzaufgabe kann ich nachvollziehen. Nur sollte das ganze dann abbrechen, momentan wird ja zwar die Fehlermeldung ausgegeben, das ganze läuft aber weiter und gibt eine Liste zurück. Mit der Fehlermeldung sollte dann aber Schluss ein.

Aber daran probier ich mich jetzt selber noch ;-)

Gruß,

Gisi
Mad-Marty
User
Beiträge: 317
Registriert: Mittwoch 18. Januar 2006, 19:46

kleiner tip, es fängt mit "raise" an ;)
Gast

Hi,

habs jetzt gelöst, indem ich die tokenize Funktion zuerst verändert habe:

Code: Alles auswählen

def tokenize(text):
    if text.count("<") != text.count(">"):
        print "Warning, not all parantheses closed !"
        return None
    else:
        return map(str.strip,
         filter(operator.truth, re.split("([<>])", text)))
und dann oben noch eingefügt habe:

Code: Alles auswählen

if tokens != None:
        while...
...der ganze Kram also nur dann ausgeführt wird, wenn auch wirklich von tokenize was zurückgegeben wird.

Und wie sähe das mit raise aus?

Gisi

Edit by Gerold: Code-Tags gesetzt
Mad-Marty
User
Beiträge: 317
Registriert: Mittwoch 18. Januar 2006, 19:46

Schau dir das an, um zu sehen wie du Exceptions raise'st.

(Ich schreibs jetzt absichtlich nicht fertig hin, für deine extrapunkte sollst du schonmal da reinschauen. )

http://docs.python.org/tut/node10.html# ... 0000000000
Antworten