2013-05-20 10 views
5

Właśnie zacząłem używać tego wieczoru pyparsing i zbudowałem skomplikowaną gramatykę opisującą niektóre źródła, z którymi pracuję bardzo efektywnie. To było bardzo łatwe i bardzo potężne. Mam jednak problemy z działaniem z ParsedResults. Muszę umieć iterować nad zagnieżdżonymi tokenami w kolejności, w jakiej zostały znalezione, i stwierdzam, że to trochę frustrujące. Wyjaśniłem swój problem w prostym przypadku:`pyparsing`: powtarzanie` ParsedResults`

import pyparsing as pp 

word = pp.Word(pp.alphas + ',.')('word*') 
direct_speech = pp.Suppress('“') + pp.Group(pp.OneOrMore(word))('direct_speech*') + pp.Suppress('”') 
sentence = pp.Group(pp.OneOrMore(word | direct_speech))('sentence') 

test_string = 'Lorem ipsum “dolor sit” amet, consectetur.' 

r = sentence.parseString(test_string) 

print r.asXML('div') 

print '' 

for name, item in r.sentence.items(): 
    print name, item 

print '' 

for item in r.sentence: 
    print item.getName(), item.asList() 

o ile widzę, to powinno zadziałać? Oto wynik:

wyjście
<div> 
    <sentence> 
    <word>Lorem</word> 
    <word>ipsum</word> 
    <direct_speech> 
     <word>dolor</word> 
     <word>sit</word> 
    </direct_speech> 
    <word>amet,</word> 
    <word>consectetur.</word> 
    </sentence> 
</div> 

word ['Lorem', 'ipsum', 'amet,', 'consectetur.'] 
direct_speech [['dolor', 'sit']] 

Traceback (most recent call last): 
    File "./test.py", line 27, in <module> 
    print item.getName(), item.asList() 
AttributeError: 'str' object has no attribute 'getName' 

XML wydaje się wskazywać, że ciąg jest analizowany dokładnie tak, jak pragnę, ale nie mogę iteracyjne nad zdaniu, na przykład, aby go odtworzyć.

Czy istnieje sposób, aby zrobić to, co muszę?

Dzięki!

edit:

Używam tego:

for item in r.sentence: 
    if isinstance(item, basestring): 
     print item 
    else: 
     print item.getName(), item 

ale to nie wszystko, co mi pomogło, bo nie można rozróżnić różne rodzaje sznurka. Tutaj jest nieco rozszerzony przykład:

word = pp.Word(pp.alphas + ',.')('word*') 
number = pp.Word(pp.nums + ',.')('number*') 

direct_speech = pp.Suppress('“') + pp.Group(pp.OneOrMore(word | number))('direct_speech*') + pp.Suppress('”') 
sentence = pp.Group(pp.OneOrMore(word | number | direct_speech))('sentence') 

test_string = 'Lorem 14 ipsum “dolor 22 sit” amet, consectetur.' 

r = sentence.parseString(test_string) 

for i, item in enumerate(r.sentence): 
    if isinstance(item, basestring): 
     print i, item 
    else: 
     print i, item.getName(), item 

wyjście jest:

0 Lorem 
1 14 
2 ipsum 
3 word ['dolor', '22', 'sit'] 
4 amet, 
5 consectetur. 
nie

zbyt pomocne. Nie mogę rozróżnić między word i number, a element direct_speech jest oznaczony jako word?!

Najwyraźniej czegoś brakuje. Wszystko, co chcę zrobić to:

for item in r.sentence: 
    if (item is a number): 
     do something 
    elif (item is a word): 
     do something else 
etc. ... 

Czy powinienem podchodzić do tego inaczej?

Odpowiedz

1

dobrze, próbowałem kilka różnych podejść teraz i nie mogę dostać to, czego potrzebuję, więc (choć wydaje się absurdalne), używam .asXML() i analizowania wynikowy XML.Oto mój przykład:

import pyparsing as pp 

word = pp.Word(pp.alphas + ',.')('word*') 
number = pp.Word(pp.nums + ',.')('number*') 
direct_speech = pp.Suppress('“') + pp.Group(pp.OneOrMore(word | number))('direct_speech*') + pp.Suppress('”') 
sentence = pp.Group(pp.OneOrMore(word | number | direct_speech))('sentence') 

test_string = 'Lorem 14 ipsum “dolor 22 sit” amet, consectetur.' 
r = sentence.parseString(test_string) 

from lxml import etree 
xml = etree.fromstring(r.sentence.asXML('sentence')) 
for el in xml: 
    if len(el): 
     print el.tag 
     for sub_el in el: 
      print ' ', sub_el.tag, ':', sub_el.text 
    else: 
     print el.tag, ':', el.text 

która wyprowadza:

word : Lorem 
number : 14 
word : ipsum 
direct_speech 
    word : dolor 
    number : 22 
    word : sit 
word : amet, 
word : consectetur. 

wydaje się długa droga wokół domów, ale nie wydaje się być lepszy sposób.

5

r.sentence Zawiera kombinację ciągów i ParseResults i tylko ParseResults obsługuje getName(). Czy próbowałeś po prostu powtórzyć nad r.sentence? Gdybym go wydrukować przy użyciu asList(), otrzymuję:

['Lorem', 'ipsum', ['dolor', 'sit'], 'amet,', 'consectetur.'] 

Albo ten fragment:

for item in r.sentence: 
    print type(item),item.asList() if isinstance(item,pp.ParseResults) else item 

Daje:

<type 'str'> Lorem 
<type 'str'> ipsum 
<class 'pyparsing.ParseResults'> ['dolor', 'sit'] 
<type 'str'> amet, 
<type 'str'> consectetur. 

nie jestem pewien, że odpowiedział na to pytanie, ale czy to rzuca światło na to, gdzie pójść dalej?

(Witamy Pyparsing)