Как передавать значения в pyparsing parseactions?

#python #pyparsing

#python #pyparsing

Вопрос:

В частности, я хочу написать универсальную функцию parseaction, которая будет проверять диапазоны чисел. Я хочу передать min amp; max функции. Возможно ли это?

Ответ №1:

Используйте замыкание, что-то вроде этого:

 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:python26libsite-packagespyparsing.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’.

Вот упражнение для читателя: напишите действие parse для преобразования проанализированных маркеров даты в datetime, а затем используйте точно такое же действие rangeCheck parse, чтобы убедиться, что данная временная метка находится в пределах допустимого диапазона значений datetime.

(Обратите внимание, что я не включил преобразование string-> int в rangeCheck, но разбил это на 2 отдельных действия синтаксического анализа, поэтому rangeCheck можно использовать для проверки любого типа, который поддерживает < и> . Просто не забудьте вызвать addParseAction или setParseAction, так что pyparsing продолжит сначала выполнять действие синтаксического анализа преобразования целых чисел.)

Вы можете найти другие примеры, подобные этому, в самом pyparsing — withAttribute это такой метод, который создает действие синтаксического анализа для проверки того, что тег XML или HTML имеет определенный атрибут, необязательно с определенным значением.

Комментарии:

1. Спасибо. Узнал несколько новых вещей: функцию copy() и diff. между addParseAction и setParseAction

2. expr.copy() теперь можно записать как просто expr() .

Ответ №2:

Эм, ты имеешь в виду что-то вроде:

 def parseaction(num, min = -100, max = 100):
    return min < num < max
  

Комментарии:

1. Это должно быть специфично для ParseElement.setParseAction(function) в pyparsing. wikispaces.com

2. Эм .. извините, не могу помочь с этим : (