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

Usunięta treść Dodana treść
zamiana {{Nawigacja|Python|->{{Nawigacja|Zanurkuj w Pythonie| [[Python/->[[../
Piotr (dyskusja | edycje)
poprawki
Linia 1:
{{Podświetl|py}}
== Wszystko razem==
 
Przemierzyliśmy kawał drogi. Zatrzymajmy się na chwilę i zobaczmy jak te wszystkie elementy do siebie pasują.
Zaczniemy od skryptu, który pobiera argumenty z linii poleceń używając modułu <ttcode>getopt</ttcode>.
 
def main(argv):
...
try:
opts, args = getopt.getopt(argv, "hg:d", ["help", "grammar="])
except getopt.GetoptError:
...
for opt, arg in opts:
...
Tworzymy nową instancję klasy <ttcode>KantGenerator</ttcode> i przekazujemy jej plik z gramatyką oraz źródło, które może być, ale nie musi, podane w linii poleceń.
 
k = KantGenerator(grammar, source)
 
Instancja klasy <ttcode>KantGenerator</ttcode> automatycznie wczytuje gramatykę, która jest plikiem XML. Wykorzystujemy naszą funkcję <ttcode>openAnything</ttcode> do otwarcia pliku (który może być ulokowany lokalnie lub na zdalnym serwerze), następnie używamy wbudowanego zestawu funkcji parsujących <ttcode>minidom</ttcode> do sparsowania XML-a do postaci drzewa obiektów Pythona.
 
def _load(self, source):
sock = toolbox.openAnything(source)
xmldoc = minidom.parse(sock).documentElement
sock.close()
 
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.
 
def loadGrammar(self, grammar):
for ref in self.grammar.getElementsByTagName("ref"):
self.refs[ref.attributes["id"].value] = ref
 
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.
 
def getDefaultSource(self):
xrefs = {}
for xref in self.grammar.getElementsByTagName("xref"):
xrefs[xref.attributes["id"].value] = 1
xrefs = xrefs.keys()
standaloneXrefs = [e for e in self.refs.keys() if e not in xrefs]
return '<xref id="%s"/>' % random.choice(standaloneXrefs)
 
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.
 
def parse_Element(self, node):
handlerMethod = getattr(self, "do_%s" % node.tagName)
handlerMethod(node)
 
Przelatujemy przez gramatykę, parsując wszystkie elementy potomne każdego elementu <tt>p</tt>,
Linia 51 ⟶ 50:
def do_p(self, node):
...
if doit:
for child in node.childNodes: self.parse(child)
 
zastępując elementy <ttcode>choice</ttcode> losowym elementem potomnym,
 
def do_choice(self, node):
self.parse(self.randomChildElement(node))
 
i zastępując elementy <tt>xref</tt> losowym elementem potomnym odpowiedniego elementu <tt>ref</tt>, który wcześniej został zachowany w buforze.
 
def do_xref(self, node):
id = node.attributes["id"].value
self.parse(self.randomChildElement(self.refs[id]))
 
W końcu parsujemy wszystko do zwykłego tekstu,
 
def parse_Text(self, node):
text = node.data
...
self.pieces.append(text)
 
który wypisujemy.
Linia 76 ⟶ 75:
def main(argv):
...
k = KantGenerator(grammar, source)
print k.output()
 
<noinclude>
{{Nawigacja|Zanurkuj w Pythonie|
[[../Tworzenie oddzielnych funkcji obsługi względem typu węzła|Tworzenie oddzielnych funkcji obsługi względem typu węzła/]]|
[[../Skrypty i strumienie - podsumowanie|Podsumowanie]]|
}}
{{Podświetl|py}}
</noinclude>