Я пытаюсь разобрать слова, которые можно разбить на несколько строк с помощью комбинации обратной косой черты и новой строки ("\\n
"), используя pyparsing . Вот что я сделал:
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''')
Вывод, который я получаю, равен ['super']
, а ожидаемый вывод - ['super', 'cali', fragi', 'listic']
. Еще лучше было бы объединить их всех в одно слово (что, я думаю, я могу просто сделать с multi_line_word.parseAction(lambda t: ''.join(t))
.
Я пытался посмотреть на этот код в помощнике по копированию , но он выдает ошибку, maximum recursion depth exceeded
.
РЕДАКТИРОВАТЬ 2009-11-15: Позже я понял, что pyparsing становится немного щедрым в отношении пустого пространства, и это приводит к некоторым ошибочным предположениям о том, что то, что, как я думал, я анализировал, было намного более свободным , Иными словами, мы не хотим видеть пробелов между какими-либо частями слова, escape и символом EOL.
Я понял, что приведенной выше небольшой примерной строки недостаточно в качестве контрольного примера, поэтому я написал следующие модульные тесты. Код, который проходит эти тесты, должен соответствовать тому, что я интуитивно считаю словом «escape-split» - и « only escape-split-word». Они не будут соответствовать базовому слову, которое не является escape-разбиением. Мы можем & mdash; и я считаю, что & mdash; использовать для этого другую грамматическую конструкцию. Это поддерживает все в порядке, имея два отдельных.
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()