Initial almost working implementation of pyparsing based string selector

Two test cases are  still failing
This commit is contained in:
adam-urbanczyk 2016-06-21 20:30:36 +02:00
parent f8c377c2f7
commit bde0fddc05

View File

@ -420,6 +420,58 @@ class InverseSelector(Selector):
return SubtractSelector(Selector(), self.selector).filter(objectList) return SubtractSelector(Selector(), self.selector).filter(objectList)
def _makeGrammar():
"""
Define the string selector grammar using PyParsing
"""
#float definition
point = Literal('.')
plusmin = Literal('+') | Literal('-')
number = Word(nums)
integer = Combine(Optional(plusmin) + number)
floatn = Combine(integer + Optional(point + Optional(number)))
#vector definition
lbracket = Literal('(')
rbracket = Literal(')')
comma = Literal(',')
vector = Combine(lbracket + floatn('x') + comma + \
floatn('y') + comma + floatn('z') + rbracket)
#direction definition
simple_dir = oneOf(['X','Y','Z','XY','XZ','YZ'])
direction = simple_dir('simple_dir') | vector('vector_dir')
#CQ type definition
cqtype = oneOf(['Plane','Cylinder','Sphere','Line','Circle','Arc'])
#type operator
type_op = Literal('%')
#direction operator
direction_op = oneOf(['>','<'])
#index definition
ix_number = Optional('-')+Word(nums)
lsqbracket = Literal('[').suppress()
rsqbracket = Literal(']').suppress()
index = lsqbracket + ix_number + rsqbracket
#other operators
other_op = oneOf(['|','#','+','-'])
#named view
named_view = oneOf(['front','back','left','right','top','bottom'])
return (type_op('type_op') + cqtype('cqtype')) | \
(direction_op('dir_op') + direction('dir') + Optional(index('index'))) | \
(other_op('other_op') + direction('dir')) | \
named_view('named_view')
_grammar = _makeGrammar() #make a grammar instance
class StringSyntaxSelector(Selector): class StringSyntaxSelector(Selector):
""" """
Filter lists objects using a simple string syntax. All of the filters available in the string syntax Filter lists objects using a simple string syntax. All of the filters available in the string syntax
@ -458,8 +510,6 @@ class StringSyntaxSelector(Selector):
""" """
def __init__(self,selectorString): def __init__(self,selectorString):
self._expr = self._makeGrammar()
self.axes = { self.axes = {
'X': Vector(1,0,0), 'X': Vector(1,0,0),
'Y': Vector(0,1,0), 'Y': Vector(0,1,0),
@ -469,100 +519,64 @@ class StringSyntaxSelector(Selector):
'XZ': Vector(1,0,1) 'XZ': Vector(1,0,1)
} }
namedViews = { self.namedViews = {
'front': ('>','Z' ), 'front' : (Vector(0,0,1),True),
'back': ('<','Z'), 'back' : (Vector(0,0,1),False),
'left':('<', 'X'), 'left' : (Vector(1,0,0),False),
'right': ('>', 'X'), 'right' : (Vector(1,0,0),True),
'top': ('>','Y'), 'top' : (Vector(0,1,0),True),
'bottom': ('<','Y') 'bottom': (Vector(0,1,0),False)
} }
self.operatorMinMax = {
'>' : True,
'<' : False,
'+' : True,
'-' : False
}
self.operator = {
'+' : DirectionSelector,
'-' : DirectionSelector,
'#' : PerpendicularDirSelector,
'|' : ParallelDirSelector}
self.selectorString = selectorString self.selectorString = selectorString
r = re.compile("\s*([-\+<>\|\%#])*\s*(\w+)\s*",re.IGNORECASE) parsing_result = _grammar.parseString(selectorString)
m = r.match(selectorString) self.mySelector = self._chooseSelector(parsing_result)
if m != None: def _chooseSelector(self,pr):
if namedViews.has_key(selectorString): """
(a,b) = namedViews[selectorString] Sets up the underlying filters accordingly
self.mySelector = self._chooseSelector(a,b ) """
if 'type_op' in pr:
return TypeSelector(pr.cq_type)
elif 'dir_op' in pr:
vec = self._getVector(pr)
minmax = self.operatorMinMax[pr.dir_op]
if 'index' in pr:
return DirectionNthSelector(vec,int(pr.index),minmax)
else: else:
self.mySelector = self._chooseSelector(m.groups()[0],m.groups()[1]) return DirectionMinMaxSelector(vec,minmax)
elif 'other_op' in pr:
vec = self._getVector(pr)
return self.operator[pr.other_op](vec)
else: else:
raise ValueError ("Selector String format must be [-+<>|#%] X|Y|Z ") args = self.namedViews[pr.named_view]
return DirectionMinMaxSelector(*args)
def _makeGrammar(self): def _getVector(self,pr):
''' """
Define the string selector grammar using PyParsing Translate parsed vector string into a CQ Vector
''' """
if 'vector_dir' in pr:
#float definition return Vector(float(pr.x),float(pr.y),float(pr.z))
point = Literal('.')
plusmin = Literal('+') | Literal('-')
number = Word(nums)
integer = Combine(Optional(plusmin) + number)
floatn = Combine(integer + Optional(point + Optional(number)))
#vector definition
lbracket = Literal('(')
rbracket = Literal(')')
comma = Literal(',')
vector = Combine(lbracket + floatn + comma + floatn + comma + floatn + rbracket)
#direction definition
direction = oneOf(['X','Y','Z','XY','XZ','YZ']) | vector
direction = direction.setResultsName('dir')
#CQ type definition
cqtype = oneOf(['Plane','Cylinder','Sphere','Line','Circle','Arc'])
#type operator
type_op = Literal('%')
#direction operator
direction_op = oneOf(['>','<'])
#index definition
ix_number = Optional('-')+Word(nums)
lsqbracket = Literal('[').suppress()
rsqbracket = Literal(']').suppress()
index = lsqbracket + ix_number + rsqbracket
index = index.setResultsName('index')
#other operators
other_op = oneOf(['|','#','+','-'])
return (type_op('op') + cqtype('cqtype')) | (direction_op('op') + direction + Optional(index)) | (other_op('op') + direction)
def _chooseSelector(self,selType,selAxis):
"""Sets up the underlying filters accordingly"""
if selType == "%":
return TypeSelector(selAxis)
#all other types need to select axis as a vector
#get the axis vector first, will throw an except if an unknown axis is used
try:
vec = self.axes[selAxis]
except KeyError:
raise ValueError ("Axis value %s not allowed: must be one of %s" % (selAxis, str(self.axes)))
if selType in (None, "+"):
#use direction filter
return DirectionSelector(vec)
elif selType == '-':
#just use the reverse of the direction vector
return DirectionSelector(vec.multiply(-1.0))
elif selType == "|":
return ParallelDirSelector(vec)
elif selType == ">":
return DirectionMinMaxSelector(vec,True)
elif selType == "<":
return DirectionMinMaxSelector(vec,False)
elif selType == '#':
return PerpendicularDirSelector(vec)
else: else:
raise ValueError ("Selector String format must be [-+<>|] X|Y|Z ") return self.axes[pr.simple_dir]
def filter(self,objectList): def filter(self,objectList):
""" """