2016-08-07 27 views
4

pyparsing verwendet, gibt es eine Möglichkeit, den Kontext, den Sie in bei rekursiven Abstieg ist zu extrahieren. Lass mich erklären, was ich meine. Ich habe den folgenden Code:Erhaltung Textstrukturinformationen - pyparsing

import pyparsing as pp 

openBrace = pp.Suppress(pp.Literal("{")) 
closeBrace = pp.Suppress(pp.Literal("}")) 
ident = pp.Word(pp.alphanums + "_" + ".") 
comment = pp.Literal("//") + pp.restOfLine 
messageName = ident 
messageKw = pp.Suppress(pp.Keyword("msg")) 
text = pp.Word(pp.alphanums + "_" + "." + "-" + "+") 
otherText = ~messageKw + pp.Suppress(text) 
messageExpr = pp.Forward() 
messageExpr << (messageKw + messageName + openBrace + 
       pp.ZeroOrMore(otherText) + pp.ZeroOrMore(messageExpr) + 
       pp.ZeroOrMore(otherText) + closeBrace).ignore(comment) 
testStr = "msg msgName1 { some text msg msgName2 { some text } some text }" 
print messageExpr.parseString(testStr) 

, die diese Ausgabe erzeugt: ['msgName1', 'msgName2']

In der Ausgabe, würde ich den Überblick über die Struktur von eingebetteten Spielen halten mag. Was ich meine ist, dass ich zum Beispiel die folgende Ausgabe mit dem obigen Teststring möchte: ['msgName1', 'msgName1.msgName2'] um die Hierarchie im Text zu verfolgen. Ich bin jedoch neu im Pyapsing und muss noch einen Weg finden, um die Tatsache zu entschlüsseln, dass "msgName2" in die Struktur von "msgName1" eingebettet ist.

Gibt es eine Möglichkeit, die setParseAction()-Methode von ParserElement dazu zu verwenden oder die Benennung von Ergebnissen zu verwenden?

Hilfreiche Beratung würde geschätzt werden.

+1

Bringen Sie eine Parse-Aktion 'messageName' den Namen auf einen externen Stapel zu schieben , und fügen Sie an closeBrace eine Analyseaktion an, um den letzten Namen aus dem Stapel zu entfernen. In der ersten Analyse-Aktion können Sie nach dem Drücken des aktuellen Namens auf den Stack den Namen in den Eingabe-Tokens durch 'Tokens [0] = '.' .join (stack)' ersetzen – PaulMcG

Antwort

2

Dank für seine sagely Beratung Paul McGuire. Hier sind die Ergänzungen/Änderungen, die ich gemacht, was das Problem gelöst:

msgNameStack = [] 

def pushMsgName(str, loc, tokens): 
    msgNameStack.append(tokens[0]) 
    tokens[0] = '.'.join(msgNameStack) 

def popMsgName(str, loc, tokens): 
    msgNameStack.pop() 

closeBrace = pp.Suppress(pp.Literal("}")).setParseAction(popMsgName) 
messageName = ident.setParseAction(pushMsgName) 

Und hier ist der komplette Code:

import pyparsing as pp 

msgNameStack = [] 


def pushMsgName(str, loc, tokens): 
    msgNameStack.append(tokens[0]) 
    tokens[0] = '.'.join(msgNameStack) 


def popMsgName(str, loc, tokens): 
    msgNameStack.pop() 

openBrace = pp.Suppress(pp.Literal("{")) 
closeBrace = pp.Suppress(pp.Literal("}")).setParseAction(popMsgName) 
ident = pp.Word(pp.alphanums + "_" + ".") 
comment = pp.Literal("//") + pp.restOfLine 
messageName = ident.setParseAction(pushMsgName) 
messageKw = pp.Suppress(pp.Keyword("msg")) 
text = pp.Word(pp.alphanums + "_" + "." + "-" + "+") 
otherText = ~messageKw + pp.Suppress(text) 
messageExpr = pp.Forward() 
messageExpr << (messageKw + messageName + openBrace + 
       pp.ZeroOrMore(otherText) + pp.ZeroOrMore(messageExpr) + 
       pp.ZeroOrMore(otherText) + closeBrace).ignore(comment) 

testStr = "msg msgName1 { some text msg msgName2 { some text } some text }" 
print messageExpr.parseString(testStr)