如何将值传递给pyparsing的解析动作?
我想写一个通用的解析函数,这个函数可以检查数字的范围。我想把最小值和最大值传给这个函数。这样做可以吗?
2 个回答
0
嗯,你是指像这样的东西吗:
def parseaction(num, min = -100, max = 100):
return min < num < max
6
使用闭包,像这样:
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'这样的日期。
这里有个练习给读者:写一个解析动作,把解析出来的日期信息转换成日期时间格式,然后用完全相同的范围检查解析动作来验证一个给定的时间戳是否在允许的日期时间范围内。
(注意,我没有在范围检查中包括字符串到整数的转换,而是把它分成了两个独立的解析动作,这样范围检查可以用来验证任何支持小于和大于比较的类型。记得使用addParseAction而不是setParseAction,这样pyparsing会先进行整数转换的解析动作。)
你可以在pyparsing中找到其他类似的例子——withAttribute
就是这样一个方法,它创建一个解析动作来验证一个XML或HTML标签是否具有特定的属性,且可以选择性地验证这个属性的值。