2016-12-12 21 views
1

С помощью библиотеки синтаксического анализа pyparsing Я хочу, чтобы анализировать конструкции, как это:Как сделать первую часть двух частей синтаксического эквивалентных необязательных при анализе с Pyparsing

123 456 

-^- -^- 
[A] B 

где обе части и B только содержат номера и часть A не является обязательным. Вот некоторые примеры того, как синтаксический анализатор для этого будет ломают строк вниз в их части:

123 456 ==> A="123", B="456" 
456  ==> A="", B="456" 
123  ==> A="", B="123" 
1 123 ==> A="1", B="123" 

Уроженец подход написать парсер выглядит следующим образом:

a = pp.Optional(pp.Word(pp.nums)).setName("PART_A") 
b = pp.Word(pp.nums).setName("PART_B") 
expr = a('A') + b('B') 

Этот анализатор работает для "123 456" возвращения, как ожидается, {'A': '123', 'B': '456'} , Однако он не на "456" с:

ParseException: 
Expected PART_B (at char 3), (line:1, col:4) 
"456>!<" 

Это понятно, так как необязательная часть уже потребляет текст, который должен соответствовать частям B даже если был необязательным ... Моя идея состояла в том, чтобы установить stopOn= вариант, но для этого нужно остановиться на выражение того же типа, что и выражение он хочет, чтобы соответствовать ...

Update: Моя вторая идея состояла в том, чтобы переписать Optional конструкт Int К О Or конструкция:

a = pp.Word(pp.nums).setName("PART_A")('A') 
b = pp.Word(pp.nums).setName("PART_B")('B') 
just_b = b 
a_and_b = a + b 
expr = pp.Or(just_b, a_and_b) 

Однако это сейчас не выполняется для текстов вида "123 456" - несмотря на то, что a_and_b является альтернативой в Or классе ...

Любое предложение, что делать?

ответ

1

Вы misconstructing на Или, это должно быть:

expr = pp.Or([just_b, a_and_b]) 

, как вы строите его, или строится только с just_b, с a_and_b передается в качестве логического аргумента savelist.

Пожалуйста, рассмотрите возможность использования перегрузок оператора для построения И, Или, MatchFirst и Каждое выражение.

integer = pp.Word(pp.nums) 

a = integer("A") 
b = integer("B") 

expr = a + b | b 

Явный стиль выглядит просто так, хорошо, Java-ish.

Чтобы ответить на вопрос в своем названии, вы в значительной степени уже решили это: обязательно попробуйте сопоставить полное выражение a_and_b, поставив его сначала в MatchFirst (как это делает мой пример кода) или с помощью Или выражение (используя оператор «^», или путем построения «Или», используя список выражений just_b и a_and_b).

+0

Работает отлично. Какой надзор с моей стороны: или ожидает списки! – halloleo

+0

Итак, правильно ли я понимаю, что класс 'Optional' не нужен при использовании' a + b | b' construct? – halloleo

+1

Правильно, поскольку вы явно описываете два разрешенных случая. Ведущий необязательный сам по себе не будет работать так, как вы обнаружили. Если вы хотите, чтобы «b» был необязательным, вы могли бы сделать «a + b | a' или просто 'a + Необязательный (b)'. Но, как вы видели, ведущий факультатив не так прост. 'Необязательно (a) + b' будет терпеть неудачу на '456', потому что« 456 »будет соответствовать« a », а затем не будет« b ». Мы должны заставить парсер мыслить так, как мы. То есть, мы знаем, что присутствует только, если следовать b. Поэтому это должно работать, если вы хотите использовать опцию: expr = необязательный (a + FollowedBy (b)) + b'. – PaulMcG

 Смежные вопросы

  • Нет связанных вопросов^_^