Pyparsing, analizzando il contenuto dei blocchi di commenti della funzione PHP usando parser nidificati

StackOverflow https://stackoverflow.com/questions/9399873

Domanda

AKA "Aggiungi sotto-nodi costruiti dai risultati di un parser.

Sto cercando di analizzare i file PHP usando pyparsing (che regole IMHO) per cui le definizioni delle funzioni sono state annotate con annotazioni in stile Javadoc. Il motivo è che voglio archiviare le informazioni del tipo in un modo che può essere utilizzato per generare codice di stub client.

Per esempio:

/*
*  @vo{$user=UserAccount}
*/
public function blah($user){ ......

Ora, sono stato in grado di scrivere un parser, è super facile usare Pyparser. Ma Pyparser viene fornito con un token JavastyleComment incorporato, che volevo riutilizzare. Così ho analizzato il codice e poi ho provato ad allegare una parseazione che avrebbe spogliato il gunk ed eseguire un sottosuolo (scusate, non certo della terminologia) e collegare il risultato all'albero di analisi genitore.

Non riesco a capire come farlo. Il codice è allegato di seguito. Per inciso, potrei facilmente scrivere la mia javastyleComment, ma in generale mi chiedo che sia possibile fare incazzare i risultati di analisi?

Ancora una volta, scusa se la mia domanda non è succinta, sono solo un novizio di questa roba.

#@PydevCodeAnalysisIgnore
from pyparsing import delimitedList,Literal,Keyword,Regex,ZeroOrMore,Suppress,Optional,QuotedString,Word,hexnums,alphas,\
    dblQuotedString,FollowedBy, sglQuotedString,oneOf,Group
import pyparsing

digits = "0123456789"
colon = Literal(':')
semi = Literal(';')
period = Literal('.')
comma = Literal(',')
lparen = Literal('{')
rparen = Literal('}')
lbracket = Literal('(')
rbracket = Literal(')')
number = Word(digits)
hexint = Word(hexnums,exact=2)
text = Word(alphas)

php = Literal("<?php") + Literal("echo") + Literal("?>")
print php.parseString("""<?php echo ?>""")

funcPerm = oneOf("public private protected")

print funcPerm.parseString("""public""")
print funcPerm.parseString("""private""")
print funcPerm.parseString("""protected""")

stdParam = Regex(r"\$[a-z][a-zA-Z0-9]*")
print stdParam.parseString("""$dog""")

dblQuotedString.setParseAction(lambda t:t[0][1:-1])
sglQuotedString.setParseAction(lambda t:t[0][1:-1])
defaultParam = Group(stdParam + Literal("=") + ( dblQuotedString | sglQuotedString | number))  
print defaultParam.parseString(""" $dave = 'dog' """)

param = ( defaultParam | stdParam )
print param.parseString("""$dave""")

#print param.parseString("""dave""")
print param.parseString(""" $dave = 'dog' """)
print param.parseString(""" $dave = "dog" """)

csl = Optional(param  + ZeroOrMore( Suppress( "," ) + param))
print csl.parseString("""$dog,$cat,$moose     """)
print csl.parseString("""$dog,$cat,$moose = "denny"     """)
print csl.parseString("""""")
#
funcIdent = Regex(r"[a-z][_a-zA-Z0-9]*")
funcIdent.parseString("farb_asdfdfsDDDDDDD")
#
funcStart = Group(funcPerm + Literal("function") + funcIdent)
print funcStart.parseString("private function dave")
#
#
litWordlit = Literal("(") +  csl + Literal(")")
print litWordlit.parseString("""( )""")

funcDef = funcStart + Literal("(") + Group(csl)  + Literal(")")
#funcDef.Name = "FUNCTION"
#funcDef.ParseAction = lambda t: (("found %s") % t)
print funcDef.parseString("""private function doggy($bow,$sddfs)""")

funcDefPopulated = funcStart + Literal("(") + Group(csl)  + Literal(")") + Group(Literal("{")  +  ZeroOrMore(pyparsing.CharsNotIn("}"))  +Literal("}")) 
#funcDef.Name = "FUNCTION"
#funcDef.ParseAction = lambda t: (("found %s") % t)
print funcDefPopulated.parseString("""private function doggy($bow,$sddfs){ $dog="dave" }""")

#" @vo{$bow=BowVo}"
docAnnotations = ZeroOrMore( Group( Literal("@") + text + Suppress(lparen) + param + Literal("=") + text  + Suppress(rparen ) ))
print docAnnotations.parseString(""" @vo{$bow=BowVo}""")

def extractDoco(s,l,t):
    """ Helper parse action for parsing the content of a comment block
    """
    ret = t[0]
    ret = ret.replace('/**','')
    ret = ret.replace('*\n','')
    ret = ret.replace('*\n','\n')
    ret = ret.replace('*/','')
    t = docAnnotations.parseString(ret)
    return  t

phpCustomComment = pyparsing.javaStyleComment

#Can't figure out what to do here. Help !!!!!
phpCustomComment.addParseAction(extractDoco)

commentedFuncDef  =  phpCustomComment + funcDefPopulated
print commentedFuncDef.parseString(
                                   """
                                   /**
                                   * @vo{$bow=BowVo}
                                   * @vo{$sddfs=UserAccount}
                                   */
                                   private function doggy($bow,$sddfs){ $dog="dave" }"""
                                   )


*emphasized text*





#example = open("./example.php","r")
#funcDef.parseFile(example)
#f4.parseString("""private function dave ( $bow )""")
#funcDef = funcPerm + Keyword("function") + funcName + Literal("(")  +  csl  + Literal(")")  
#print funcDef.parseString(""" private function doggy($bow)""")

=== Aggiornamento

Ho scoperto che i parseresults, ad esempio, ha un metodo insert che ti consente di aumentare l'albero di analisi, ma non riesco ancora a capire come farlo in modo dinamico.

Per esempio:

title = oneOf("Mr Miss Sir Dr Madame")
aname = title + Group(Word(alphas) + Word(alphas))
res=aname.parseString("Mr Dave Young")
res
(['Mr', (['Dave', 'Young'], {})], {})

res.insert(3,3)

res
(['Mr', (['Dave', 'Young'], {}), 3], {})
È stato utile?

Soluzione

In primo luogo, sono innamorato. Pyparser deve essere uno dei libri più belli che abbia mai usato. In secondo luogo, la soluzione era davvero, davvero, facile.

Ecco come l'ho risolto:

docAnnotations = ZeroOrMore( Group( ZeroOrMore(Suppress("*")) +   Suppress(Literal("@")) + Suppress(Literal("vo")) + Suppress(lparen) + param + Literal("=") + text  + Suppress(rparen ) ))
print docAnnotations.parseString(""" @vo{$bow=BowVo}""")

def extractDoco(t):
    """ Helper parse action for parsing the content of a comment block
    """
    ret = t[0]
    ret = ret.replace('/**','')
    ret = ret.replace('*\n','')
    ret = ret.replace('*\n','\n')
    ret = ret.replace('*/','')
    print ret
    return docAnnotations.parseString(ret)  

phpCustomComment = pyparsing.javaStyleComment

L'ultima sezione:

print commentedFuncDef.parseString(
                                   """
                                   /**
                                   * @vo{$bow=BowVo}
                                   * @vo{$sddfs=UserAccount}
                                   */
                                   private function doggyWithCustomComment($bow,$sddfs){ $dog="dave" }"""
                                   )

Il risultato:

[['$bow', '=', 'BowVo'], ['$sddfs', '=', 'UserAccount'], ['private', 'function', 'doggyWithCustomComment'], '(', ['$bow', '$sddfs'], ')', ['{', ' $dog="dave" ', '}']]
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top