pyparsing und Whitespace

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.
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

pyparsing und Whitespace

Beitragvon Leonidas » Dienstag 2. September 2008, 02:52

Hi,

Ich komme gerade nicht drauf - ich würde gerne Leerzeilen als Tokens haben, d.h. \n\n wäre eine Leerzeile, \n\n\n wären zwei etc. Aber irgendwie verschluckt trotz meines umstellen der Whitespacechars pyparsing \n dennoch generell. Das erste Problem wäre Pyparsing sagen, dass es \n\n matchen soll.

Code: Alles auswählen

from pyparsing import Word, Literal, Optional, Group, OneOrMore, nums

watchseries = Word(nums, exact=4)
watchrev = Word(nums, exact=1)

watchname = Group(watchseries + Optional('M') + '-' + watchrev)

leaveempty = Literal('EMPTY')
pagebreak = Literal('\n\n')
pagebreak.setWhitespaceChars(' \t\r')

all = OneOrMore(watchname ^ leaveempty ^ pagebreak)
all.setWhitespaceChars(' \t\r')

t1 = "2134M-2"
t2 = """3245-3
3456M-5"""
t3 = """3256-4

 4563-4"""
t4 = """4562M-6
 EMPTY
3246-5"""

print all.parseString(t3)

Wie man sieht habe ich hier einige kleine Testcases.

In Zukunft würde ich gerne aus \n+x*\n gerne x NEWLINE-Tokens haben, aber ich weiß gar nicht, ob so etwas überhaupt mit Pyparsing abbildbar ist. Ggf. werde ich wohl den Output durchfiltern und einzeln stehende NEWLINES löschen und NEWLINE-Gruppen einfach um ein Newline kürzen, das sollte wohl auch zum Ziel führen. Oder gibt es einen besseren Weg?

Nur eben wie kann man denn Pyparsing sagen, dass es Linebreaks nicht verschlucken soll?
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Dienstag 2. September 2008, 16:03

Hmm, bin jetzt etwas weitergekommen, aber so richtig toll funktioniert das noch nicht:

Code: Alles auswählen

from pyparsing import (Word, Literal, Optional, Group, OneOrMore, Regex,
        Combine, ParserElement, nums)

ParserElement.setDefaultWhitespaceChars(' \t\r')

watchseries = Word(nums, exact=4)
watchrev = Word(nums, exact=1)

watchname = Combine(watchseries + Optional('M') + '-' + watchrev)

leaveempty = Literal('EMPTY').setParseAction(
    lambda s, loc, tokens: ['<EMPTY>'])

def breaks(s, loc, tokens):
    tokens[0].pop()
    return ['<PAGEBREAK>' for token in tokens[0]]

pagebreak = Group(Literal('\n') + OneOrMore(Literal('\n'))).setParseAction(breaks)

all = OneOrMore(watchname ^ leaveempty ^ pagebreak)

tests = [
    "2134M-2",
    """3245-3
    3456M-5""",
    """3256-4

    4563-4""",
    """4562M-6
     EMPTY
    3246-5"""
]

for test in tests:
    print all.parseString(test)

Jetzt tut <EMPTY> nicht mehr, und die Leerzeilen funktionieren auch noch nicht so ganz wie ich das wollte.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
BlackJack

Beitragvon BlackJack » Dienstag 2. September 2008, 16:21

Hast Du schon in der englischsprachingen Python-Newsgroup gefragt? Der `pyparsing`-Autor liest da mit und beantwortet Fragen zum Modul in der Regel.
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Dienstag 2. September 2008, 16:28

BlackJack hat geschrieben:Hast Du schon in der englischsprachingen Python-Newsgroup gefragt?

Nein, noch nicht - werde ich wohl gleich nachholen.

Soweit bin ich gekommen (\n\n ist eine selten dämliche Idee, ich suche eigentlich Linestart, optionales Whitespace und Lineend aber das will irgendwie dennoch nicht).

Code: Alles auswählen

from pyparsing import (Word, Literal, Optional, Group, OneOrMore, Regex,
        Combine, ParserElement, nums, LineStart, LineEnd, White)

watchseries = Word(nums, exact=4)
watchrev = Word(nums, exact=1)

watchname = Combine(watchseries + Optional('M') + '-' + watchrev)

leaveempty = Literal('EMPTY')

def breaks(s, loc, tokens):
    print repr(tokens[0])
    #return ['<PAGEBREAK>' for token in tokens[0]]
    return ['<PAGEBREAK>']

#pagebreak = Regex('^\s*$').setParseAction(breaks)
pagebreak = LineStart() + Optional(White()) + LineEnd().setParseAction(breaks)

all = OneOrMore(watchname ^ leaveempty ^ pagebreak)

tests = [
    "2134M-2",
    """3245-3
    3456M-5""",
    """3256-4

    4563-4""",
    """4562M-6
     EMPTY
    3246-5"""
]

for test in tests:
    print all.parseString(test)
My god, it's full of CARs! | Leonidasvoice vs Modvoice

Wer ist online?

Mitglieder in diesem Forum: mollyman