Как правило, классы Or, And, MatchFirst и Each очень редко используются открыто при преобразовании. Рекомендуемый стиль - использовать их аналогичные операторские перегрузки. В вашем случае вы используете обе формы, и это только мешает вам.
Вот ваше выражение лица после небольшой уборки:
key = Word(alphanums + "/-_.?=%&")
QUOT = Suppress('"')
uri = ("-" | QUOT
+ http_method
+ key("request_uri")
+ http_protocol
+ QUOT
)
Аргументами Word являются строки символов, представляющие наборы разрешенных символов. Если используется только один аргумент (как в вашем случае), то строка интерпретируется как просто набор символов, которые могут быть проанализированы как часть Word. Если заданы 2 строки, то первая представляет набор допустимых начальных символов, а вторая представляет набор допустимых символов тела (полезно при определении чего-то вроде имени переменной, которое, например, в Python допускает только альфы и «_» для начальный символ, но также допускает числовые цифры в теле. Это будет Word(alphas+'_', alphanums+'_')
. Поскольку аргументы Word являются просто строками, нет необходимости отдельно добавлять "/" + "-" + "_" + ...
, просто объединить их в одну строку.
'|' Разграничение операторов допускает альтернативы, генерируя выражение MatchFirst. Он называется MatchFirst, потому что анализатор прекратит попытки после совпадения первого заданного выражения. Так что если при разборе строки «abc» с помощью Word(alphas) | Word(nums)
, pyparsing даже не попытается сопоставить выражение Word(nums)
- первое альтернативное совпадение. Это становится сложнее, если есть некоторые совпадения в том, что вы хотите. Допустим, вы хотите сопоставить слова букв, слова альфа или слова букв и альфа, и вы хотите проанализировать строку «abc123». Этот парсер:
Word(alphas) | Word(nums) | Word(alphanums)
проанализирует открывающий 'abc' строки с ведущим Word(alphas)
. Мы часто можем решить такую проблему, переставив альтернативы, такие как:
Word(alphanums) | Word(alphas) | Word(nums)
но не во всех случаях так легко рефакторинг. Поэтому pyparsing также поддерживает выражение Or, определенное с помощью оператора «^» (который я выбрал, потому что «^» напоминает мне пару разделителей рисовальщика для измерения длины). Выражение Or пытается применить all указанных альтернатив и выбирает longon , соответствующий одному. Таким образом, вы можете написать мой маленький тестовый пример как:
Word(alphas) ^ Word(nums) ^ Word(alphanums)
и теперь pyparsing не остановится при сопоставлении «abc», но попробует все альтернативы и в конечном итоге выберет третий вариант, соответствующий «abc123», потому что он дает более длинное совпадение.
Для определения URI нет необходимости выполнять или сопоставлять. Нет никакого способа, которым парсер будет путать начальный '-' с командной строкой HTTP в кавычках. Таким образом, используя MatchFirst, который вы сделали с помощью '|' оператор, вполне адекватный.
Некоторые другие предметы:
Не пишите "\""
на Python, если можете помочь. По этой причине Python поддерживает оба символа кавычек. Используйте '"'
вместо этого. Обратная косая черта предназначена для программистов на C и имен файлов Windows.
expr.setResultsName("name")
был упрощен до expr("name")
, начиная с 1.4.6. Сокращенный синтаксис действительно помогает удобочитаемости определений вашего синтаксического анализатора.
Используйте Группу, только если вы хотите сохранить некоторую структуру в своих результатах или если у вас есть повторяющаяся структура, которая имеет некоторое внутреннее выражение с именем результатов. На самом деле не требуется для вашего анализатора, он просто добавляет еще одну упаковку контейнера списка к результатам, требуя дополнительного индекса [0]
для доступа к вашим проанализированным данным.
(Если вы do решите, что хотите явно вызвать Or
, And
и т. Д., Обязательно передайте список выражений, а не просто перечисляйте их в качестве аргументов для конструктор выражений - см. Почему упорядоченный выбор в pyparsing не удался для моего варианта использования? о том, как такая опечатка может все испортить, поэтому я рекомендую использовать арифметические операторы для составления ваших парсеров.)