como - Pyrarsing, analizar los contenidos de los bloques de comentarios de la función php usando analizadores anidados
php agregar comentario (1)
En primer lugar, estoy enamorado. PyParser tiene que ser una de las mejores librerías que he usado. En segundo lugar, la solución fue realmente, realmente, fácil.
Así es como lo arreglé:
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
La última sección:
print commentedFuncDef.parseString(
"""
/**
* @vo{$bow=BowVo}
* @vo{$sddfs=UserAccount}
*/
private function doggyWithCustomComment($bow,$sddfs){ $dog="dave" }"""
)
El resultado:
[[''$bow'', ''='', ''BowVo''], [''$sddfs'', ''='', ''UserAccount''], [''private'', ''function'', ''doggyWithCustomComment''], ''('', [''$bow'', ''$sddfs''], '')'', [''{'', '' $dog="dave" '', ''}'']]
AKA "Agregar nodos construidos a partir de los resultados de una Parser.parseAction al árbol de análisis primario"
Estoy tratando de analizar archivos PHP utilizando PyParsing (que rige en mi humilde opinión) por el cual las definiciones de funciones se han anotado con anotaciones de estilo JavaDoc. La razón es que quiero almacenar información de tipo de una manera que pueda usarse para generar código de código auxiliar de cliente.
Por ejemplo:
/*
* @vo{$user=UserAccount}
*/
public function blah($user){ ......
Ahora, he podido escribir un analizador, es muy fácil usar PyParser. Pero, PyParser viene con un token javaStyleComment incorporado, que quería volver a utilizar. Así que analicé el código y luego traté de adjuntar un parseAction que eliminaría la suciedad y ejecutaría un sub-analizador (lo siento, no estoy seguro de la terminología) y adjuntará el resultado al árbol de análisis primario.
No puedo entender cómo hacerlo. El código se adjunta a continuación. Por cierto, podría escribir fácilmente mi propio javaStyleComment, pero me pregunto, en general, ¿es posible encadenar resultados de análisis?
De nuevo, disculpe si mi pregunta no es concisa, solo soy un novato en esta materia.
#@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)""")
=== Actualización
Descubrí que ParseResults, por ejemplo, tiene una insert
método que le permite aumentar el árbol de análisis sintáctico, pero todavía no puede encontrar la manera de hacerlo dinámicamente.
Por ejemplo:
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], {})