2016-12-07 17 views
1

Хорошо, я кладу вместе парсер для разбора выражений, какПочему `OneOrMore` терпит неудачу с более чем одним выражением в pyparsing?

abc def ghi LONG|SHORT 12345 

----^------ ----^----- --^-- 
A: alphas B: choice C: num 

Анализатор написан в pyparsing выглядит следующим образом:

a = pp.OneOrMore(pp.Word(pp.alphas)).setName("PRT_A") 
b = pp.Or(['LONG','SHORT']).setName("PRT_B") 
c = pp.Word(pp.nums).setName("PRT_C") 
expr = a('A') + b('B') + c('C') 

Когда я кормлю «что-то сказал SHORT 13» в него:

res = expr.parseString("something said SHORT 13") 

Я получаю ошибку:

ParseException: 
Expected {"LONG"^"SHORT"} (at char 21), (line:1, col:22) 
"something said SHORT >!<13" 

Почему? Я думал, что OneOrMore должен сложить все слова до тех пор, LONG | SHORT выбор приходит ...

+0

@ user2357112 Я упростил вопрос только содержать предпросмотр проблема - делает вопрос намного яснее и ценнее других, думаю. Не могли бы вы соответственно усовершенствовать (теперь принятый) ответ (т. Е. Вывести материал о «Комбинате»)? – halloleo

+0

Ответ обновлен, но вы также должны обновить сообщение об ошибке в вопросе. Версия без 'Combine' должна вызывать ошибку в более позднем местоположении. – user2357112

ответ

2

Проблема здесь состоит в том, что pp.Word(pp.alphas) включает в себя как "LONG" и "SHORT", предотвращая b от соответствия. Вы должны предотвратить его соответствие этих ключевых слов, такие как с отрицательным предпросмотром:

b = pp.Or(['LONG','SHORT']).setName("PRT_B") 
a = pp.OneOrMore(~b + pp.Word(pp.alphas)).setName("PRT_A") 

или с stopOn вариантом для OneOrMore:

b = pp.Or(['LONG','SHORT']).setName("PRT_B") 
a = pp.OneOrMore(pp.Word(pp.alphas), stopOn=b).setName("PRT_A") 
+0

Дело не в Combine, а в OneOrMore. Эта же проблема возникает без окружающего Combine. (Может быть, мне следует избавиться от комбайна для примера ...) – halloleo

+0

@halloleo: Нет, просто получается, что у вас есть две ошибки, ошибка Combine и вторая ошибка. Если вы выберете комбинат, вы получите другую ошибку. – user2357112

+1

К сожалению, ignore() используется для включения выражений, которые являются невежественными, так же, как и пустое пространство, игнорируемое - обычно комментарии. Но ваше описание второй ошибки мертво. Чтобы решить эту проблему, OneOrMore имеет опцию stopOn, чтобы остановить сопоставление, если будет видно выражение, которое обычно совпадает с выражением OneOrMore. Кроме того, Combine также вызывает сомнения, как вы говорите - возможно, группа более уместна. – PaulMcG