LBRA = Literal('{').suppress()
RBRA = Literal('}').suppress()
EOL = lineEnd.suppress()
tmshString = Word(alphanums + '!#$%&()*+,-./:;<=>?@[\\]^_`|~')
tmshValue = Combine(tmshString | dblQuotedString.setParseAction(removeQuotes))
tmshKey = tmshString

def toSet(s, loc, t):
    return set(t[0])
tmshSet = LBRA + Group(ZeroOrMore(tmshValue.setWhitespaceChars(' '))
    ).setParseAction(toSet) + RBRA

def toDict(d, l):
    if not l[0] in d:
        d[l[0]] = {}
for v in l[1:]:
    if type(v) == list:
        toDict(d[l[0]], v)
else:
    d[l[0]] = v

def trueDefault(s, loc, t):
    return len(t) and t or True
singleKeyValue = Forward()
singleKeyValue << Group(tmshKey + (EOL.setParseAction(trueDefault) |
    tmshSet | Optional(tmshValue | LBRA + ZeroOrMore(singleKeyValue) + RBRA
    ).setParseAction(trueDefault)))
multiKeysOneValue = Forward()
multiKeysOneValue << Group(tmshKey + (multiKeysOneValue | tmshSet | LBRA +
    ZeroOrMore(singleKeyValue) + RBRA))
toplevel = OneOrMore(multiKeysOneValue)
data = toplevel.parseString(testData)
h = {}
map(lambda x: toDict(h, x), data.asList())
pprint(h)
Разбор TCL-подобного текста