"""
Grammar for selecting regions of a domain.
Regions serve for selection of certain parts of the computational domain (=
selection of nodes and elements of a FE mesh). They are used to define the
boundary conditions, the domains of terms and materials etc.
Notes
-----
History: pre-git versions already from from 13.06.2006.
"""
from pyparsing import Literal, CaselessLiteral, Word, delimitedList,\
Group, Optional, ZeroOrMore, nums, alphas, alphanums,\
Combine, StringStart, StringEnd, Forward, oneOf, ParseException
ParseException # Needed for importing elsewhere.
op_codes = ['OA_SubN', 'OA_SubE', 'OA_AddN', 'OA_AddE',
'OA_IntersectN', 'OA_IntersectE']
eval_codes = ['E_NIR', 'E_NOS', 'E_NBF', 'E_NOG', 'E_ONIR', 'E_NI', 'E_NOSET',
'E_EBF', 'E_EOG', 'E_EI1', 'E_EI2', 'E_EOSET']
kw_codes = ['KW_All', 'KW_Region']
[docs]def to_stack(stack):
def push_first(str, loc, toks):
if toks:
stack.append(toks[0])
return toks
return push_first
[docs]def replace(what, keep=False):
def _replace(str, loc, toks):
ret = {'token' : what, 'orig' : []}
if keep:
ret['orig'] = list(toks[0])
return ret
return _replace
[docs]def replace_with_region(what, r_index):
def _replace(str, loc, toks):
ret = {'token' : what, 'orig' : []}
orig = toks[0]
r_orig = orig[r_index]
if isinstance(r_orig, dict) and (r_orig['token'] == 'KW_Region'):
orig = list(orig[:r_index]) + r_orig['orig']
ret['orig'] = orig
return ret
return _replace
[docs]def join_tokens(str, loc, toks):
return [" ".join(toks[0])]
[docs]def visit_stack(stack, op_visitor, leaf_visitor):
def visit(stack, level):
op = stack.pop()
token = op['token']
if token in op_codes:
res2 = visit(stack, level + 1)
res1 = visit(stack, level + 1)
return op_visitor(level, op, res1, res2)
elif token in eval_codes:
return leaf_visitor(level, op)
elif token in kw_codes:
return leaf_visitor(level, op)
else:
raise ValueError, token
return visit(stack, 0)
[docs]def print_op(level, op, item1, item2):
print level * ' ' + (': %s' % op)
[docs]def print_leaf(level, op):
print level * ' ' + ('< %s' % op)
[docs]def print_stack(stack):
visit_stack(stack, print_op, print_leaf)
[docs]def create_bnf(stack):
point = Literal(".")
comma = Literal(",")
e = CaselessLiteral("E")
inumber = Word(nums)
fnumber = Combine(Word("+-"+nums, nums) +
Optional(point + Optional(Word(nums))) +
Optional(e + Word("+-"+nums, nums)))
_of = Literal('of')
_in = Literal('in')
_by = Literal('by')
_copy = Literal('copy')
_mn = Literal('-n').setParseAction(replace('OA_SubN'))
_me = Literal('-e').setParseAction(replace('OA_SubE'))
_pn = Literal('+n').setParseAction(replace('OA_AddN'))
_pe = Literal('+e').setParseAction(replace('OA_AddE'))
_inn = Literal('*n').setParseAction(replace('OA_IntersectN'))
_ine = Literal('*e').setParseAction(replace('OA_IntersectE'))
regop = (_mn | _me | _pn | _pe | _inn | _ine)
lpar = Literal("(").suppress()
rpar = Literal(")").suppress()
_all = Literal('all').setParseAction(replace('KW_All'))
node = Literal('node')
nodes = Literal('nodes')
element = Literal('element')
elements = Literal('elements')
group = Literal('group')
_set = Literal('set')
surface = Literal('surface')
ident = Word(alphas + '_.', alphanums + '_.')
set_name = Word(nums) | ident
function = Word(alphas + '_', alphanums + '_')
function = Group(function).setParseAction(join_tokens)
region = Combine(Literal('r.') + Word(alphas + '_',
'_' + alphas + nums + '.'))
region = Group(Optional(_copy, default='nocopy') + region)
region.setParseAction(replace('KW_Region', keep=True))
coor = oneOf('x y z')
boolop = oneOf('& |')
relop = oneOf('< > <= >= != ==')
bool_term = (ZeroOrMore('(') + (coor | fnumber) + relop + (coor | fnumber)
+ ZeroOrMore(')'))
relation = Forward()
relation << (ZeroOrMore('(')
+ bool_term + ZeroOrMore(boolop + relation)
+ ZeroOrMore(')'))
relation = Group(relation).setParseAction(join_tokens)
nos = Group(nodes + _of + surface).setParseAction(replace('E_NOS'))
nir = Group(nodes + _in + relation).setParseAction(
replace('E_NIR', keep=True))
nbf = Group(nodes + _by + function).setParseAction(
replace('E_NBF', keep=True))
ebf = Group(elements + _by + function).setParseAction(
replace('E_EBF', keep=True))
eog = Group(elements + _of + group + Word(nums)).setParseAction(
replace('E_EOG', keep=True))
nog = Group(nodes + _of + group + Word(nums)).setParseAction(
replace('E_NOG', keep=True))
onir = Group(node + _in + region).setParseAction(
replace_with_region('E_ONIR', 2))
ni = Group(node + delimitedList(inumber)).setParseAction(
replace('E_NI', keep=True))
ei1 = Group(element + delimitedList(inumber)).setParseAction(
replace('E_EI1', keep=True))
etuple = (lpar.suppress() + inumber + comma.suppress()
+ inumber + rpar.suppress())
ei2 = Group(element + delimitedList(etuple)).setParseAction(
replace('E_EI2', keep=True))
noset = Group(nodes + _of + _set + set_name).setParseAction(
replace('E_NOSET', keep=True))
eoset = Group(elements + _of + _set + set_name).setParseAction(
replace('E_EOSET', keep=True))
region_expression = Forward()
atom1 = (_all | region | ni | onir | nos | nir | nbf
| ei1 | ei2 | ebf | eog | nog | noset | eoset)
atom1.setParseAction(to_stack(stack))
atom2 = (lpar + region_expression.suppress() + rpar)
atom = (atom1 | atom2)
aux = (regop + region_expression)
aux.setParseAction(to_stack(stack))
region_expression << atom + ZeroOrMore(aux)
region_expression = StringStart() + region_expression + StringEnd()
return region_expression
_test_strs = ['nodes of surface -n r.egion_1',
'r.egion_2 +n copy r.egion_1',
'nodes in (y <= 0.00001) & (x < 0.11)',
'nodes in ((y <= 0.00001) & (x < 0.11))',
'nodes in (((y <= 0.00001) & (x < 0.11)))',
'nodes in (((0.00001 < y) & (x < 0.11)))',
'nodes in (y < 1.0)',
'all -n nodes in (y == 0.00001)',
'all -n nodes of surface',
'all -e r.egion_100',
'r.egion_1 -n nodes of surface *e r.egion_8 *n nodes in (y > 0)',
'nodes of surface +n nodes by pokus',
'elements of group 6 +e nodes by fn2_3c',
"""r.egion_1 *n (r.egion_2 +e (nodes in (y > 0) *n r.egion_32))
-n nodes of surface -e r.egion_5""",
'node in r.region_3',
'node 10',
'elements by afun']
if __name__ == "__main__":
test_strs = _test_strs
stack = []
bnf = create_bnf(stack)
n_fail = 0
for test_str in test_strs:
print test_str
stack[:] = []
try:
out = bnf.parseString(test_str)
except:
print '...failed!'
n_fail += 1
continue
print_stack(stack)
print 'failed: %d' % n_fail