Использовать токен как переменную в pyparsing

Недавно я начал использовать python/pyparsing для обработки строки шестнадцатеричных значений, и у меня возникли проблемы с этим: рассмотрим эту строку:

string = "10020304059917368584304025326"

Я хочу, чтобы конечный результат был таким:

['10', '02', '03', ['04', '05', '9917365843'], ['04', '02', '5326']]

Предположим, что 04 — это тег, означающий данные (та же концепция, что и в ASN.1), а 05 — это размер этих данных. Я не понимаю, как использовать переменную размера в коде pyparsing. Лучшее, что я могу сделать, это:

byte = Word(hexnums, exact=2)
process = byte + byte + byte + Word(hexnums)
newstring = process.parseString(string)
print (newstring.dump())

Любая помощь будет принята с благодарностью.


PS: после помощи Hooked мой окончательный код:

from pyparsing import *

string = "10 02 03 04 05 99 17 36 58 43 04 02 53 26"

tag = Word(hexnums, exact=2)
size =  Word(hexnums)
array = Group(tag + countedArray(size))

process = tag + tag + tag + ZeroOrMore(array)

newstring = process.parseString(string)
print (newstring.dump())

Что печатает:

['10', '02', '03', ['04', ['99', '17', '36', '58', '43']], ['04', ['53', '26']]]

Надеюсь, это поможет в будущем.


person Kiji    schedule 19.06.2012    source источник


Ответы (2)


Я задал тот же вопрос в более общем смысле: Может ли BNF обрабатывать прямое потребление?. Ответ на этот вопрос был отрицательным, так как контекстно-свободная грамматика не может знать, что происходит. К счастью, pyparsing — это больше, чем контекстно-свободная грамматика, как указывает автор пакета :

Pyparsing включает помощника countedArray, который делает именно то, что вы просите. Он принимает один аргумент expr и будет анализировать целое число, за которым следуют «n» экземпляров expr.

В его ответе приведено гораздо более полное решение с минимальным рабочим примером. Вопрос: PyParsing lookaheads и greedy expressions также является хорошей ссылкой на то, что вы пытаетесь делать также.

person Hooked    schedule 20.06.2012
comment
Спасибо, это именно то, что мне было нужно. - person Kiji; 20.06.2012

Будет ли это работать? Он не использует pyparsing, но записывает подсписки переменной длины, когда видит «04».

def func( s ):
    d = []
    # while s isn't empty
    while len(s) != 0:
        b = s[0:2]
        if b != '04':
            # if b isn't '04' append it to d
            d.append( b )   
            # shorten s
            s = s[2:]
        else:
            # take the length, as a string
            l = s[2:4]
            # take the length, as an integer
            n = int(s[2:4])
            # record b='04', the length, and then the next values
            d.append( [ b, l, s[4:4+n*2] ] )
            # shorten s
            s = s[4+n*2:]
    return d
person cjohnson318    schedule 19.06.2012
comment
К сожалению, не для меня. Пример, который я привел, является лишь простой частью того, что я собираюсь сделать, поэтому очень важно, чтобы я использовал pyparsing (у меня есть большое количество тегов, которые представляют разные размеры). Хотя спасибо за помощь! - person Kiji; 19.06.2012