2009-03-11 2 views
2

Я пытаюсь пирафинг python для синтаксического анализа. Я застрял, делая рекурсивный парсер.Нужна помощь в создании рекурсивного анализатора с использованием pyparsing

Позвольте мне объяснить проблему

Я хочу, чтобы декартово произведение элементов. Синтаксис

cross({elements },{element}) 

я положил в более специфический способ

cross({a},{c1}) or cross({a,b},{c1}) or cross({a,b,c,d},{c1}) or 

Таким образом, общая форма первая группа будет иметь п элементов (а, б, в, г). Вторая группа будет иметь один элемент, поэтому окончательный вывод будет декартовым.

Синтаксис должен быть сделан рекурсивным, поскольку он может перейти к н уровне, как

cross(cross({a,b},{c1}),{c2}) 

Это означает, пересекают а, Ь с c1. Давайте скажем, результат. Мы снова пересечь его с Y c2

Это может быть до креста п уровня (крест (крест (крест ......

Что я хочу, чтобы иметь объект инициализируется с помощью setparseAction

Таким образом, у меня будет 2 класс

class object1(object): 
    This will be used by a,b,c,d 

class object2(object): 
     This will hold cross elements 

мне нужна помощь по этому вопросу я не могу сделать рекурсивный парсер.

ответ

6

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

Например, посмотрите, как определяется умножение.

Это не

{expression} * {expression} 

Поскольку рекурсия трудно иметь дело, и нет подразумеваемой слева направо заказ. То, что вы видите чаще всего являются такие вещи, как

{term} + {factor} 
{factor} * {unary-expression} 

который ставит приоритеты и лево-направо порядок вокруг операторов.

Посмотрите на что-то вроде http://www.cs.man.ac.uk/~pjj/bnf/c_syntax.bnf на примеры того, как обычно такие вещи структурированы.

+0

Мне не нужно выражение, которое будет использоваться. Мне нужно это сделать в python, используя только pyparsing. Синтаксис написан исправлен, и я думаю, что это можно сделать с помощью рекурсивного синтаксического анализатора. – 2009-03-11 13:40:26

+0

@asb: Поскольку другие люди не используют рекурсивные парсеры для такого рода вещей, я предлагаю вам быть более успешными, если вы измените определение (а не синтаксис, но способ его определения), чтобы устранить запутанную рекурсию. –

3

Я согласен с @ S.Lott, вы должны пересмотреть свою грамматику.

Рекурсивные определения могут быть введены с использованием Forward():

from pyparsing import (Literal, Word, OneOrMore, Forward, nums, alphas) 

def BNF(): 
    """ 
    element  :: id 
    elements  :: '{' element [ ',' element ]+ '}' 
        | 'cross' '(' elements ',' '{' element '}' ')' 
    """ 
    lcb, rcb, lb, rb, comma = [Literal(c).suppress() for c in '{}(),'] 
    element = Word(alphas, alphas+nums+"_") # id 
    elements = Forward() 
    elements << ((lcb + element + OneOrMore(comma + element) + rcb) 
       | (Literal('cross') + lb + elements + comma 
        + lcb + element + rcb + rb)) 
    return elements 

print BNF().parseString("cross(cross({a,b},{c1}),{c2})") 

Выход:

['cross', 'cross', 'a', 'b', 'c1', 'c2'] 
3

Я не знаю, если это любая помощь, но вот как вы могли бы сделать то, что вы хотите в ЮЛПП. Поскольку грамматика кажется правильной, я предполагаю, что ее легко перевести на pyparsing.

from lepl import * 

def compile_parser(): 

    class Cross(Node): pass 

    word = Token('[a-z0-9]+') 
    par, en, bra, ket = [~Token('\\'+c) for c in '(){}'] 
    comma = ~Token(',') 

    cross = Delayed() 
    vector = bra & word[1:,comma] & ket     > list 
    arg = vector | cross 
    cross += ~word('cross') & par & arg[2,comma] & en > Cross 

    parser = cross.string_parser() 
    return lambda expr: parser(expr)[0] 


if __name__ == '__main__': 

    parser = compile_parser() 
    print parser('cross({a},{c1})') 
    print parser('cross({a,b},{c1})') 
    print parser('cross({a,b,c,d},{c1})') 
    print parser('cross(cross({a,b},{c1}),{c2})') 

Выход:

Cross 
+- [u'a'] 
`- [u'c1'] 

Cross 
+- [u'a', u'b'] 
`- [u'c1'] 

Cross 
+- [u'a', u'b', u'c', u'd'] 
`- [u'c1'] 

Cross 
+- Cross 
| +- [u'a', u'b'] 
| `- [u'c1'] 
`- [u'c2'] 
Смежные вопросы