Python 如何使用pyparsing从VC++;autoexp.dat?

Python 如何使用pyparsing从VC++;autoexp.dat?,python,pyparsing,Python,Pyparsing,我无法理解如何使用python解析以下数据。我不明白如何从嵌套的#(和#if() 使用组在已解析的令牌中创建层次结构。然后,您可以导航组列表并访问其中的命名字段。类似如下: from pyparsing import * LPAR,RPAR,COMMA,HASH,COLON = map(Suppress, '(),#:') ident = Word(alphas+'_', alphanums+'_') fnumber = Regex(r'[+-]?\d+\.\d*').setParseActi

我无法理解如何使用python解析以下数据。我不明白如何从嵌套的#(和#if()


使用组在已解析的令牌中创建层次结构。然后,您可以导航组列表并访问其中的命名字段。类似如下:

from pyparsing import *

LPAR,RPAR,COMMA,HASH,COLON = map(Suppress, '(),#:')
ident = Word(alphas+'_', alphanums+'_')
fnumber = Regex(r'[+-]?\d+\.\d*').setParseAction(lambda t:float(t[0]))
inumber = Regex(r'[+-]?\d+').setParseAction(lambda t:int(t[0]))
number = fnumber | inumber
ref_name = Combine("$" + delimitedList(ident, delim=oneOf(". ->"), combine=True))
named_ref = Group(ident("name") + COLON + ref_name("ref"))
unnamed_ref = Group(ref_name("ref"))

IF, ELSE = map(Keyword, "if else".split())

stmt = Forward()

decl = named_ref | unnamed_ref

def setType(typ):
    def parseAction(tokens):
        tokens['type'] = typ
    return parseAction
cond = operatorPrecedence(ref_name | number,
            [
            (oneOf("< == > <= >= !="), 2, opAssoc.LEFT),
            ])
if_else = Group(HASH + IF + LPAR + cond("condition") + RPAR + 
                    LPAR + stmt("then") + RPAR + 
                    Optional(HASH + ELSE + LPAR + stmt("else") + RPAR))

if_else.setParseAction(setType("IF_ELSE"))
decl.setParseAction(setType("DECL"))

stmt << Group(decl | if_else | (HASH + LPAR + delimitedList(stmt) + RPAR))

section = Group(ident("section_name") + LPAR + Group(ZeroOrMore(stmt))("section_body") + RPAR)

parser = OneOrMore(section)


source = """
preview 
( 
    #if ($e.d.stateFlags == 0) ( 
        $e.d 
    ) #else ( 
        #( $e.d->scheme, $e.d->host, $e.d->path ) 
    ) 
) 
children 
( 
    #( 
        scheme: $c.d->scheme, 
        host: $c.d->host, 
        path: $c.d->path, 
        username: $c.d->userName, 
        password: $c.d->password, 
        encodedOriginal: $c.d->encodedOriginal, 
        query: $c.d->query, 
        fragment: $c.d->fragment 
    ) 
)"""


def dump_stmt(tokens, depth=0):
    if 'type' in tokens:
        print tokens.type
        print tokens[0].dump(depth=depth)
    else:
        for stmt in tokens:
            dump_stmt(stmt, depth=depth+1)

for sec in parser.parseString(source):
    print sec.dump()
    print sec.section_name
    for statement in sec.section_body:
        dump_stmt(statement)
    print

使用组在已解析的令牌中创建层次结构。然后,您可以导航组列表并访问其中的命名字段。类似如下:

from pyparsing import *

LPAR,RPAR,COMMA,HASH,COLON = map(Suppress, '(),#:')
ident = Word(alphas+'_', alphanums+'_')
fnumber = Regex(r'[+-]?\d+\.\d*').setParseAction(lambda t:float(t[0]))
inumber = Regex(r'[+-]?\d+').setParseAction(lambda t:int(t[0]))
number = fnumber | inumber
ref_name = Combine("$" + delimitedList(ident, delim=oneOf(". ->"), combine=True))
named_ref = Group(ident("name") + COLON + ref_name("ref"))
unnamed_ref = Group(ref_name("ref"))

IF, ELSE = map(Keyword, "if else".split())

stmt = Forward()

decl = named_ref | unnamed_ref

def setType(typ):
    def parseAction(tokens):
        tokens['type'] = typ
    return parseAction
cond = operatorPrecedence(ref_name | number,
            [
            (oneOf("< == > <= >= !="), 2, opAssoc.LEFT),
            ])
if_else = Group(HASH + IF + LPAR + cond("condition") + RPAR + 
                    LPAR + stmt("then") + RPAR + 
                    Optional(HASH + ELSE + LPAR + stmt("else") + RPAR))

if_else.setParseAction(setType("IF_ELSE"))
decl.setParseAction(setType("DECL"))

stmt << Group(decl | if_else | (HASH + LPAR + delimitedList(stmt) + RPAR))

section = Group(ident("section_name") + LPAR + Group(ZeroOrMore(stmt))("section_body") + RPAR)

parser = OneOrMore(section)


source = """
preview 
( 
    #if ($e.d.stateFlags == 0) ( 
        $e.d 
    ) #else ( 
        #( $e.d->scheme, $e.d->host, $e.d->path ) 
    ) 
) 
children 
( 
    #( 
        scheme: $c.d->scheme, 
        host: $c.d->host, 
        path: $c.d->path, 
        username: $c.d->userName, 
        password: $c.d->password, 
        encodedOriginal: $c.d->encodedOriginal, 
        query: $c.d->query, 
        fragment: $c.d->fragment 
    ) 
)"""


def dump_stmt(tokens, depth=0):
    if 'type' in tokens:
        print tokens.type
        print tokens[0].dump(depth=depth)
    else:
        for stmt in tokens:
            dump_stmt(stmt, depth=depth+1)

for sec in parser.parseString(source):
    print sec.dump()
    print sec.section_name
    for statement in sec.section_body:
        dump_stmt(statement)
    print
['preview', [[['if', ['$e.d.stateFlags', '==', 0], [['$e.d']], 'else', [[['$e.d->scheme']], [['$e.d->host']], [['$e.d->path']]]]]]]
- section_body: [[['if', ['$e.d.stateFlags', '==', 0], [['$e.d']], 'else', [[['$e.d->scheme']], [['$e.d->host']], [['$e.d->path']]]]]]
- section_name: preview
preview
IF_ELSE
['if', ['$e.d.stateFlags', '==', 0], [['$e.d']], 'else', [[['$e.d->scheme']], [['$e.d->host']], [['$e.d->path']]]]
- condition: ['$e.d.stateFlags', '==', 0]
- else: [[['$e.d->scheme']], [['$e.d->host']], [['$e.d->path']]]
- then: [['$e.d']]
  - type: DECL

['children', [[[['scheme', '$c.d->scheme']], [['host', '$c.d->host']], [['path', '$c.d->path']], [['username', '$c.d->userName']], [['password', '$c.d->password']], [['encodedOriginal', '$c.d->encodedOriginal']], [['query', '$c.d->query']], [['fragment', '$c.d->fragment']]]]]
- section_body: [[[['scheme', '$c.d->scheme']], [['host', '$c.d->host']], [['path', '$c.d->path']], [['username', '$c.d->userName']], [['password', '$c.d->password']], [['encodedOriginal', '$c.d->encodedOriginal']], [['query', '$c.d->query']], [['fragment', '$c.d->fragment']]]]
- section_name: children
children
DECL
['scheme', '$c.d->scheme']
  - name: scheme
  - ref: $c.d->scheme
DECL
['host', '$c.d->host']
  - name: host
  - ref: $c.d->host
DECL
['path', '$c.d->path']
  - name: path
  - ref: $c.d->path
DECL
['username', '$c.d->userName']
  - name: username
  - ref: $c.d->userName
DECL
['password', '$c.d->password']
  - name: password
  - ref: $c.d->password
DECL
['encodedOriginal', '$c.d->encodedOriginal']
  - name: encodedOriginal
  - ref: $c.d->encodedOriginal
DECL
['query', '$c.d->query']
  - name: query
  - ref: $c.d->query
DECL
['fragment', '$c.d->fragment']
  - name: fragment
  - ref: $c.d->fragment