PyParsing Or выполняется как matchFirst Or - PullRequest
0 голосов
/ 01 февраля 2019

Я построил 2 грамматики, которые частично перекрывают друг друга.Я хотел бы, чтобы грамматика лучше всего соответствовала тексту, который будет выбран.Поэтому я написал третью грамматику с оператором Or.Я искал в Интернете и понял, что ^ выбирает грамматику, возвращающую самый длинный текст, вместо того, чтобы выбирать только первую грамматику в операторе Or.

Когда я запускаю код, он всегда выбирает первую грамматику вместосоответствие лучшему.Это также тот случай, когда я переворачиваю две грамматики в выражении ^.Кто-нибудь знает, почему это происходит?

Я использую Python 2.7.13 и PyParsing 2.1.4.

(оператор Or можно найти в грамматике type1 в третьей строке)

advice1 = (ZeroOrMore(~Literal('Home') + WORD) + Literal('Home')
    + OneOrMore(~Literal('Street') + WORD)('Home').setParseAction(' '.join, standardizeStrings)
    + Literal('Street') + UPPERCASEWORDS('Facility').setParseAction(''.join, standardizeStrings)
    + SkipTo("-----") + restOfLine + EOL #1
    + OneOrMore(~AMOUNT + WORD).setParseAction(' '.join) + AMOUNT + AMOUNT('CPB').setParseAction(convertAmountString) + DATE
    + SkipTo("-----") + restOfLine + EOL #2
    + OneOrMore(~AMOUNT + WORD).setParseAction(' '.join) + AMOUNT + AMOUNT('TOI').setParseAction(convertAmountString) + Optional(DATE)
    + SkipTo("_____") + restOfLine + EOL #3
    + DATE + DATE + Word(nums) + CURRENCY + AMOUNT + RATE + AMOUNT
    + SkipTo("-----") + restOfLine + EOL #4
    + OneOrMore(~AMOUNT + WORD).setParseAction(' '.join) + AMOUNT + AMOUNT('PB').setParseAction(convertAmountString) + DATE('New_Date').setParseAction(convertDateString)
)

advice2 = (ZeroOrMore(~Literal('Home') + WORD) + Literal('Home')
    + OneOrMore(~Literal('Street') + WORD)('Home').setParseAction(' '.join, standardizeStrings)
    + Literal('Street') + UPPERCASEWORDS('Facility').setParseAction(''.join, standardizeStrings)
    + SkipTo("-----") + restOfLine + EOL #1
    + OneOrMore(~AMOUNT + WORD).setParseAction(' '.join) + AMOUNT + AMOUNT('CPB').setParseAction(convertAmountString) + DATE
    + SkipTo("-----") + restOfLine + EOL #2
    + (OneOrMore(~AMOUNT + WORD).setParseAction(' '.join) ^ AMOUNT) + AMOUNT + AMOUNT('TIA').setParseAction(convertAmountString) + Optional(DATE)
    + SkipTo("-----") + restOfLine + EOL #3
    + OneOrMore(~AMOUNT + WORD).setParseAction(' '.join) + AMOUNT + AMOUNT('TOI').setParseAction(convertAmountString) + Optional(DATE)
    + SkipTo("_____") + restOfLine + EOL #4
    + DATE + DATE + Word(nums) + CURRENCY + AMOUNT + RATE + AMOUNT
    + SkipTo("-----") + restOfLine + EOL #5
    + OneOrMore(~AMOUNT + WORD).setParseAction(' '.join) + AMOUNT + AMOUNT('PB').setParseAction(convertAmountString) + DATE('New_Date').setParseAction(convertDateString)
)

type1 = (OneOrMore(~Literal('Effective') + WORD)
    + Literal('Effective') + SEP + DATE('Effective_Date').setParseAction(convertDateString)
    + OneOrMore(Group(advice1 ^ advice2))('Facility') # OR statement
    + Optional(OneOrMore(~Literal("rate is") + WORD) + Literal("rate is") + RATE('Rate').setParseAction(convertRateString))
    + OneOrMore(~DATE + WORD) + DATE('Date').setParseAction(convertDateString)
    + Optional(notifications)
    + ZeroOrMore(~Literal('Home') + WORD)
)
...