Zanurkuj w Pythonie/Skrypty i strumienie - wszystko razem: Różnice pomiędzy wersjami

Usunięta treść Dodana treść
Beau (dyskusja | edycje)
drobne techniczne
Nie podano opisu zmian
 
Linia 4:
Zaczniemy od skryptu, który pobiera argumenty z linii poleceń używając modułu <code>getopt</code>.
 
<sourcesyntaxhighlight lang="python">def main(argv):
# ...
try:
Linia 12:
for opt, arg in opts:
# ...
</syntaxhighlight>
</source>
Tworzymy nową instancję klasy <code>KantGenerator</code> i przekazujemy jej plik z gramatyką oraz źródło, które może być, ale nie musi, podane w linii poleceń.
 
<sourcesyntaxhighlight lang="python">k = KantGenerator(grammar, source)</sourcesyntaxhighlight>
 
Instancja klasy <code>KantGenerator</code> automatycznie wczytuje gramatykę, która jest plikiem XML. Wykorzystujemy naszą funkcję <code>openAnything</code> do otwarcia pliku (który może być ulokowany lokalnie lub na zdalnym serwerze), następnie używamy wbudowanego zestawu funkcji parsujących <code>minidom</code> do sparsowania XML-a do postaci drzewa obiektów Pythona.
 
<sourcesyntaxhighlight lang="python">def _load(self, source):
sock = toolbox.openAnything(source)
xmldoc = minidom.parse(sock).documentElement
sock.close()</sourcesyntaxhighlight>
 
Ach i po drodze wykorzystujemy naszą wiedzę o strukturze dokumentu XML do utworzenia małego bufora referencji, którymi są po prostu elementy dokumentu XML.
 
<sourcesyntaxhighlight lang="python">def loadGrammar(self, grammar):
for ref in self.grammar.getElementsByTagName("ref"):
self.refs[ref.attributes["id"].value] = ref</sourcesyntaxhighlight>
 
Jeśli został podany jakiś materiał źródłowy w linii poleceń, używamy go. W przeciwnym razie na podstawie gramatyki wyszukujemy referencję na najwyższym poziomie (tą do której nie mają odnośników żadne inne elementy) i używamy jej jako punktu startowego.
 
<sourcesyntaxhighlight lang="python">def getDefaultSource(self):
xrefs = {}
for xref in self.grammar.getElementsByTagName("xref"):
Linia 39:
xrefs = xrefs.keys()
standaloneXrefs = [e for e in self.refs.keys() if e not in xrefs]
return '<xref id="%s"/>' % random.choice(standaloneXrefs)</sourcesyntaxhighlight>
 
Teraz przedzieramy się przez materiał źródłowy. Ten materiał to także XML i parsujemy go węzeł po węźle. Aby podzielić nieco kod i uczynić go łatwiejszym w utrzymaniu, używamy oddzielnych funkcji obsługi (ang. ''handlers'') dla każdego typu węzła.
 
<sourcesyntaxhighlight lang="python">def parse_Element(self, node):
handlerMethod = getattr(self, "do_%s" % node.tagName)
handlerMethod(node)</sourcesyntaxhighlight>
 
Przelatujemy przez gramatykę, parsując wszystkie elementy potomne każdego elementu <tt>p</tt>,
 
<sourcesyntaxhighlight lang="python">def do_p(self, node):
# ...
if doit:
for child in node.childNodes: self.parse(child)</sourcesyntaxhighlight>
 
zastępując elementy <code>choice</code> losowym elementem potomnym,
 
<sourcesyntaxhighlight lang="python">def do_choice(self, node):
self.parse(self.randomChildElement(node))</sourcesyntaxhighlight>
 
i zastępując elementy <tt>xref</tt> losowym elementem potomnym odpowiedniego elementu <tt>ref</tt>, który wcześniej został zachowany w buforze.
 
<sourcesyntaxhighlight lang="python">def do_xref(self, node):
id = node.attributes["id"].value
self.parse(self.randomChildElement(self.refs[id]))</sourcesyntaxhighlight>
 
W końcu parsujemy wszystko do zwykłego tekstu,
 
<sourcesyntaxhighlight lang="python">def parse_Text(self, node):
text = node.data
# ...
self.pieces.append(text)</sourcesyntaxhighlight>
 
który wypisujemy.
 
<sourcesyntaxhighlight lang="python">def main(argv):
# ...
k = KantGenerator(grammar, source)
print k.output()</sourcesyntaxhighlight>
 
<noinclude>