Как получить местоположение совпадающих токенов с помощью pyparsing? - PullRequest
2 голосов
/ 08 марта 2012

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

>>> from pyparsing import *
>>> 
>>> Z = Literal('0')
>>> POINT = Literal('.')
>>> BIN_DIGITS = Word('01')
>>> OCT_DIGITS = Word('01234567')
>>> DEC_DIGITS = Word('0123456789')
>>> HEX_DIGITS = Word('0123456789abcdefABCDEF')
>>> DEC_INT = DEC_DIGITS.setParseAction(lambda t: int(t[0]))
>>> BIN_INT = Combine(Z + ((Literal('b') | 'B')) + BIN_DIGITS).\
...         setParseAction(lambda t: int(t[0], 2))
>>> OCT_INT = Combine(Z + ((Literal('o') | 'O')) + OCT_DIGITS).\
...         setParseAction(lambda t: int(t[0], 8))
>>> HEX_INT = Combine(Z + ((Literal('x') | 'X')) + HEX_DIGITS).\
...         setParseAction(lambda t: int(t[0], 16))
>>> INTEGER = HEX_INT | OCT_INT | BIN_INT | DEC_INT
>>> EXP = Combine(CaselessLiteral('E') + Optional(Literal('+') | '-') + DEC_INT)
>>> POINT_FLOAT = Combine(Optional(DEC_INT) + POINT + DEC_INT) | \
...         Combine(DEC_INT + POINT)
>>> EXP_FLOAT = Combine(DEC_INT + EXP) | Combine(POINT_FLOAT + EXP)
>>> FLOAT = (EXP_FLOAT | POINT_FLOAT).setParseAction(lambda t: float(t[0]))
>>> 
>>> 
>>> def p(s, l, t):
...     print 'Location of %s:  %s' % (t[0], l,)
... 
>>> 
>>> NUMBER = (FLOAT | INTEGER).setParseAction(p)
>>> NUMBER.parseString('    12345')
Location of 12345:  0
([12345], {})
>>> NUMBER.parseString(' 12345')
Location of 12345:  0
([12345], {})
>>> NUMBER.parseString('12345')
Location of 12345:  0
([12345], {})

Местоположение всегда равно 0 независимо от того, где я расположил число «12345» в строке. Однако, если я попытаюсь:

>>> LITERAL = Literal('someword').setParseAction(p)
>>> LITERAL.parseString('    someword')
Location of someword:  4
(['someword'], {})
>>> LITERAL.parseString(' someword')
Location of someword:  1
(['someword'], {})
>>> LITERAL.parseString('someword')
Location of someword:  0
(['someword'], {})

Работает как положено. Что я делаю не так в первом примере?

1 Ответ

0 голосов
/ 09 марта 2012

Хорошо, благодаря совету Пола, мне удалось обойти эту проблему, скомбинировав выражение «И» с подавленным выражением пробела и используя его для анализа строки. Вот конечный результат:

>>> from pyparsing import *
>>> 
>>> def p(s,l,t):
...     print 'Location of %s: %s' % (s, l,)
... 
>>> Z = Literal('0')
>>> POINT = Literal('.')
>>> BIN_DIGITS = Word('01')
>>> OCT_DIGITS = Word('01234567')
>>> DEC_DIGITS = Word('0123456789')
>>> HEX_DIGITS = Word('0123456789abcdefABCDEF')
>>> DEC_INT = DEC_DIGITS.copy().setParseAction(lambda t: int(t[0]))
>>> BIN_INT = Combine(Z + ((Literal('b') | 'B')) + BIN_DIGITS).\
...         setParseAction(lambda t: int(t[0], 2))
>>> OCT_INT = Combine(Z + ((Literal('o') | 'O')) + OCT_DIGITS).\
...         setParseAction(lambda t: int(t[0], 8))
>>> HEX_INT = Combine(Z + ((Literal('x') | 'X')) + HEX_DIGITS).\
...         setParseAction(lambda t: int(t[0], 16))
>>> INTEGER = HEX_INT | OCT_INT | BIN_INT | DEC_INT
>>> EXP = Combine(CaselessLiteral('E') + Optional(Literal('+') | Literal('-')) + DEC_DIGITS)
>>> POINT_FLOAT = Combine(Optional(DEC_DIGITS) + POINT + DEC_DIGITS) | \
...         Combine(DEC_DIGITS + POINT)
>>> EXP_FLOAT = Combine(DEC_DIGITS + EXP) | Combine(POINT_FLOAT + EXP)
>>> FLOAT = (EXP_FLOAT | POINT_FLOAT).setParseAction(lambda t: float(t[0]))
>>> NUMBER = (FLOAT | INTEGER).setParseAction(p)
>>> NUMBER2 = Combine(ZeroOrMore(White(exact=1)).suppress() + NUMBER)
>>> 
>>> NUMBER2.parseString('    12345')
Location of     12345: 4
(['12345'], {})
...