Source code for sfepy.fem.parseEq

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