Как написать небольшой парсер DSL с операторским модулем в Python - PullRequest
2 голосов
/ 01 июня 2011

См. Ниже матричные данные:

    A   B   C   D   E   F   G
1   89  92  18  7   90  35  60
2   62  60  90  91  38  30  50
3   59  91  98  81  67  88  70
4   20  28  31  9   91  6   18
5   80  27  66  1   33  91  18
6   82  30  47  8   39  22  32
7   14  11  70  39  18  10  56
8   98  95  84  47  28  62  99

Мне нужно определить "правило", функция может возвращать "истину" или "ложь" для строки ниже утверждаемой для каждой строки данных:

A=B and B=C
A>C
B>C
C>D and D<E or D>F
A+B<30
A+B<=30                # this may using "A+B<30 or A+B=30" as alternative
str(A) march regex"[2-5][0-2]" 
myfoo(A) > 100 
A in myfoo(B)
A not_in $listname
A in $listname

Например, "A = B и B = C" . Если я передам строку 1 в это правило, я хочу, чтобы правило вернуло false, поскольку в данном случае оно неверно.

Мои вопросы:

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

  2. Я заметил, что в операции модуля есть много математических функций, которые я могу повторно использовать для определения правила. Могу ли я создать «маппер» для этих ключевых слов для использования парсером DSL? Это может выглядеть так:

    Keywords = {"+": operation.add (), "/": operation.div (), "и": my_and_define () }

  3. , если выше 2 возможны, как я могу обработать «A в $ listname» в лямбде и в маппере?

Спасибо за вашу помощь.

RGS,

KC

Ответы [ 2 ]

1 голос
/ 01 июня 2011

Вот так.

class Rule( object ):
    def __init__( self, text ):
        self.text= text
    def test( self, A, B, C, D, E, F, G ):
        return eval( self.text )

r1= Rule( "A==B" )
r2= Rule( "A==B and B==C" )
r3= Rule( "A in {listname!s}".format( listname=someList ) )

и т.д.

>>> r1.test( 89,  92,  18,  7,   90,  35, 60 )
False

Edit.

  • str (A) регулярное выражение марта "[2-5] [0-2]"
  • myfoo (A)> 100
  • А в myfoo (B)

Это все тривиальный код Python. Я не уверен, почему этот комментарий даже был интересным или сложным.

r4= Rule( "re.match( r'[2-5][0-2]', str(A) )" )
r5= Rule( "myfoo(A) > 100" )
r6= Rule( "A in myfoo(B)" )

В этом есть хитрость. Хитрость заключается в написании кода Python; а затем заключите код в кавычки. Любой Код Python допустим.

Если аспект этих правил, связанный с Python, является путаницей, может быть полезно руководство по Python.

1 голос
/ 01 июня 2011

Насколько важен пример синтаксиса вашего DSL?Простейшим подходом было бы использование синтаксиса выражений Python и eval ().В противном случае можно будет перевести из вашей формы что-то в состоянии eval ().

...