from pyparsing import Combine, Literal, Word, delimitedList, Group, Optional,\
ZeroOrMore, OneOrMore, nums, alphas, alphanums,\
StringStart, StringEnd, CaselessLiteral, Forward, oneOf
[docs]class TermParse( object ):
def __str__( self ):
ss = "%s\n" % self.__class__
for key, val in self.__dict__.iteritems():
ss += " %s:\n %s\n" % (key, self.__dict__[key])
return ss
[docs]def collect_term(term_descs, lc):
signs = {'+' : 1.0, '-': -1.0}
def append( str, loc, toks ):
sign = signs[toks.sign] * signs[lc[0]]
## print toks, lc
tp = TermParse()
tp.integral = toks.term_desc.integral
if not tp.integral:
tp.integral = 'a'
tp.region = toks.term_desc.region
tp.flag = toks.term_desc.flag
tp.sign = sign * eval(''.join( toks.mul ))
tp.name = toks.term_desc.name
tp.args = ', '.join(toks.args[0])
## print tp
term_descs.append( tp )
return append
[docs]def rhs( lc ):
def aux( str, loc, toks ):
if toks:
# print toks
lc[0] = '-'
return aux
[docs]def create_bnf(term_descs):
"""term_descs .. list of TermParse objects
(sign, term_name, term_arg_names), where sign can be real or complex
multiplier"""
lc = ['+'] # Linear combination context.
equal = Literal( "=" ).setParseAction( rhs( lc ) )
zero = Literal( "0" ).suppress()
point = Literal( "." )
e = CaselessLiteral( "E" )
inumber = Word( "+-"+nums, nums )
fnumber = Combine( Word( "+-"+nums, nums ) +
Optional( point + Optional( Word( nums ) ) ) +
Optional( e + Word( "+-"+nums, nums ) ) )
number = fnumber + Optional( Literal( 'j' ), default = '' )
add_op = oneOf('+ -')
number_expr = Forward()
number_expr << ZeroOrMore('(') + number \
+ ZeroOrMore(add_op + number_expr) \
+ ZeroOrMore(')')
ident = Word( alphas, alphanums + "_")
integral = Combine((Literal('i') + Word(alphanums)) | Literal('a')
| Word(nums))("integral")
history = Optional('[' + inumber + ']', default='')("history")
variable = Combine(Word(alphas, alphanums + '._') + history)
derivative = Combine(Literal('d') + variable\
+ Literal('/') + Literal('dt'))
trace = Combine(Literal('tr') + '(' + variable + ')')
generalized_var = derivative | trace | variable
args = Group(delimitedList(generalized_var))
flag = Literal( 'a' )
term = Optional( Literal( '+' ) | Literal( '-' ), default = '+' )( "sign" )\
+ Optional( number_expr + Literal( '*' ).suppress(),
default = ['1.0', ''] )( "mul" ) \
+ Combine( ident( "name" )\
+ Optional( "." + (integral + "."
+ ident( "region" ) + "." + flag( "flag" ) |
integral + "." + ident( "region" ) |
ident( "region" )
)))( "term_desc" ) + "("\
+ Optional(args, default=[''])( "args" ) + ")"
term.setParseAction(collect_term(term_descs, lc))
rhs1 = equal + OneOrMore( term )
rhs2 = equal + zero
equation = StringStart() + OneOrMore( term )\
+ Optional( rhs1 | rhs2 ) + StringEnd()
## term.setDebug()
return equation
if __name__ == "__main__":
test_str = """d_term1.Y( fluid, u, w, Nu, dcf, mode )
+ 5.0 * d_term2.Omega( u, w, Nu, dcf, mode )
- d_another_term.Elsewhere( w, p[-1], Nu, dcf, mode )
= - dw_rhs.a.Y3( u, q, Nu, dcf, mode )"""
term_descs = []
bnf = create_bnf(term_descs)
out = bnf.parseString( test_str )
print 'out:', out, '\n'
for tp in term_descs:
print tp