Ich versuche, Wörter zu analysieren, die über mehrere Zeilen mit einer Backslash-Newline-Kombination (\\n
) pyparsing aufgeteilt werden können. Hier ist, was ich getan habe:Mit pyparsing ein Wort Escape-Split über mehrere Zeilen analysieren
from pyparsing import *
continued_ending = Literal('\\') + lineEnd
word = Word(alphas)
split_word = word + Suppress(continued_ending)
multi_line_word = Forward()
multi_line_word << (word | (split_word + multi_line_word))
print multi_line_word.parseString(
'''super\\
cali\\
fragi\\
listic''')
Der Ausgang ich erhalte, ist ['super']
, während die erwartete Ausgabe ['super', 'cali', fragi', 'listic']
ist. Besser wäre noch alle von ihnen als ein Wort verbunden (was ich denke, ich kann mit multi_line_word.parseAction(lambda t: ''.join(t))
gerade tun.
habe ich versucht, auf diesem Code in pyparsing helper suchen, aber es gibt mir einen Fehler, maximum recursion depth exceeded
.
EDIT 2009-11-15: Später wurde mir klar, dass das Puparsing in Bezug auf Leerraum ein wenig großzügiger wird, und das führt zu einigen schlechten Annahmen, dass das, wofür ich dachte, viel loser war, das heißt, wir wollen es sehe keinen Leerraum zwischen irgendeinem der Teile des Wortes, des Escape und des EOL-Zeichens
Ich erkannte, dass die Der obige kleine Beispielstring ist als Testfall nicht ausreichend, daher schrieb ich die folgenden Komponententests. Code, der diese Tests besteht, sollte in der Lage sein, das, was ich intuitiv als Escape-Split-Wort — und nur ein Escape-Split-Wort denken. Sie werden keinem Grundwort entsprechen, das nicht aus der Not geteilt ist. Wir können — und ich glaube, dass — ein anderes grammatikalisches Konstrukt dafür verwenden sollte. Dies hält alles sauber, die zwei getrennt zu haben.
import unittest
import pyparsing
# Assumes you named your module 'multiline.py'
import multiline
class MultiLineTests(unittest.TestCase):
def test_continued_ending(self):
case = '\\\n'
expected = ['\\', '\n']
result = multiline.continued_ending.parseString(case).asList()
self.assertEqual(result, expected)
def test_continued_ending_space_between_parse_error(self):
case = '\\ \n'
self.assertRaises(
pyparsing.ParseException,
multiline.continued_ending.parseString,
case
)
def test_split_word(self):
cases = ('shiny\\', 'shiny\\\n', ' shiny\\')
expected = ['shiny']
for case in cases:
result = multiline.split_word.parseString(case).asList()
self.assertEqual(result, expected)
def test_split_word_no_escape_parse_error(self):
case = 'shiny'
self.assertRaises(
pyparsing.ParseException,
multiline.split_word.parseString,
case
)
def test_split_word_space_parse_error(self):
cases = ('shiny \\', 'shiny\r\\', 'shiny\t\\', 'shiny\\ ')
for case in cases:
self.assertRaises(
pyparsing.ParseException,
multiline.split_word.parseString,
case
)
def test_multi_line_word(self):
cases = (
'shiny\\',
'shi\\\nny',
'sh\\\ni\\\nny\\\n',
' shi\\\nny\\',
'shi\\\nny '
'shi\\\nny captain'
)
expected = ['shiny']
for case in cases:
result = multiline.multi_line_word.parseString(case).asList()
self.assertEqual(result, expected)
def test_multi_line_word_spaces_parse_error(self):
cases = (
'shi \\\nny',
'shi\\ \nny',
'sh\\\n iny',
'shi\\\n\tny',
)
for case in cases:
self.assertRaises(
pyparsing.ParseException,
multiline.multi_line_word.parseString,
case
)
if __name__ == '__main__':
unittest.main()
Die Verwendung von "Kombinieren" erzwingt auch keine dazwischen liegenden Leerräume. – PaulMcG
Interessant. versucht 'multi_line_word = Kombinieren (Kombinieren (OneOrMore (split_word)) + Optional (Wort)) aber es bricht auf die" sh \\\ n iny "Fall in dem es keine Ausnahme, sondern statt gibt '[' sh '] 'zurück. Fehle ich etwas? – gotgenes
Nun, dein Wort besteht nicht nur aus Buchstaben, die ein '\' - Zeilenumbruch überspannen, aber da ist dieser Raum vor dem Buchstaben 'i', der als Wortbruch zählt, also hört Combine nach dem 'sh' auf. Sie * können * ändern Kombinieren Sie mit einem benachbarten = False-Konstruktor-Argument, aber Vorsicht - Sie könnten am Ende die gesamte Datei als ein einziges Wort aufzusaugen! Oder Sie können Ihre Definition von continuous_ending neu definieren, um nach der ZeileEnde beliebige Leerzeichen einzufügen, wenn Sie auch führende Leerzeichen ausblenden möchten. – PaulMcG