Используйте замыкание, как-то так:
def rangeCheck(minval=None, maxval=None):
if minval is None and maxval is None:
# this exception occurs not at parse time, but while defining the grammar
raise ValueError("minval or maxval must be specified")
def rangeCheckParseAction(string, loc, tokens):
parsedval = tokens[0]
if minval is not None:
if maxval is not None:
valid = minval <= parsedval <= maxval
else:
valid = minval <= parsedval
else:
if maxval is not None:
valid = parsedval <= maxval
if not valid:
raise ParseException(string, loc,
"value not in range (%s,%s)" % (minval, maxval))
return rangeCheckParseAction
integer = Combine(Optional(oneOf("+ -")) + Word(nums))
integer.setParseAction(lambda t:int(t[0]))
month = integer.copy().addParseAction(rangeCheck(1,12))
day = integer.copy().addParseAction(rangeCheck(1,31))
year = integer.copy().addParseAction(rangeCheck(2000))
SLASH = Suppress('/')
dateExpr = year + SLASH + month + SLASH + day
print dateExpr.parseString("2011/5/8")
print dateExpr.parseString("1999/12/31")
Печать:
[2011, 5, 8]
Traceback (most recent call last):
File "rangeCheck.py", line 21, in <module>
print dateExpr.parseString("1999/12/31")
File "c:\python26\lib\site-packages\pyparsing.py", line 1100, in parseString
raise exc
pyparsing.ParseException: value not in range (2000,None) (at char 0), (line:1, col:1)
Конечно, лучшим действием анализа будет проверка всей даты - например, этот текущий синтаксический анализатор будет принимать '2000/2/31'.
Вот упражнение для читателя: запишите действие разбора, чтобы преобразовать проанализированные токены даты в дату и время, а затем используйте точно такое же действие разбора rangeCheck, чтобы убедиться, что указанная отметка времени находится в допустимом диапазоне значений даты и времени.
(Обратите внимание, что я не включил преобразование string-> int в rangeCheck, но разбил его на 2 отдельных действия разбора, поэтому rangeCheck можно использовать для проверки любого типа, который поддерживает <и>. Просто обязательно вызовите addParseAction по сравнению с setParseAction, так что pyparsing продолжит сначала выполнять действие разбора целочисленного преобразования.)
Другие примеры, подобные этому, можно найти в самом pyparsing - withAttribute
- это такой метод, который создает действие синтаксического анализа для проверки того, что тег XML или HTML имеет определенный атрибут, необязательно с определенным значением.