# in some rare cases (color table declarations), control has ' ;' suffix BASE_CTRL = Combine(BASE_CTRL + SEP) | BASE_CTRL BASE_CTRL.setName("BaseControl") #\*\html93394 HTM_CTRL = Combine(Literal('\\*\\') + CTRL_LABEL) HTM_CTRL.setName("HtmlControl") RTF_CTRL = BASE_CTRL | HTM_CTRL RTF_CTRL.setName("Control") RTFCODE = OneOrMore(RTF_CTRL | BRCKT) # handle "{\*\htmltag4 \par }"" HTM_CTRL_NEWLINE = HTM_CTRL.suppress() + Literal("\\par").setParseAction(replaceWith("\n")) HTM_CTRL_NEWLINE.suppress() # handle "{\*\htmltag84 }" HTM_CTRL_EMPTY = HTM_CTRL.suppress() + Word(" ").leaveWhitespace() HTM_TXT = OneOrMore(Word(htmchars)) HTM_CTRL_CONTENT = HTM_CTRL.suppress() + Optional(BRCKT_R).suppress() + HTM_TXT # Both opening and closing tags and their contents HTM_TAG = Combine(Literal("<") + Word(htmchars) + Literal(">")) HTM_TAG.leaveWhitespace() HTM_TAG.setName("HtmlTag") #HTM_TAG_EMPTYCONTENT = Word(" ") + BRCKT_R.suppress() HTM_TAG_PLUS_CONTENT = HTM_TAG + Optional(BRCKT_R.suppress() + HTM_TXT)
return int(n) except ValueError: return float(n) integer = Word(nums).setParseAction(numeric) floatnum = Combine(Optional('-') + ('0' | Word('123456789',nums)) + Optional('.' + Word(nums)) + Optional(Word('eE',exact=1) + Word(nums+'+-',nums))) floatnum.setParseAction(numeric) end = Keyword('end').suppress() point2d = floatnum + floatnum # Note: Since we're just doing 2D, we ignore the z term of 3D points. point3d = floatnum + floatnum + floatnum.suppress() # Obstacle position = Group((Keyword('pos') | Keyword('position')) + point3d) size = Group(Keyword('size') + point3d) rotation = Group((Keyword('rot') | Keyword('rotation')) + floatnum) obstacle_items = [position, Optional(size), Optional(rotation)] class Box(object): """A basic obstacle type.""" def __init__(self, pos=None, position=None, rot=None, rotation=None, size=None): self.pos = pos or position self.rot = rot or rotation
class ObfuscateBNF(object): __metaclass__ = abc.ABCMeta def __init__(self, get_obfuscated): """BNF grammar for source statements. Parameters ---------- get_obfuscated : function Function to return the obfuscated name for an identifier. """ self.get_obfuscated = get_obfuscated self.directive = oneOf("#:") self.comment = ~self.directive + pythonStyleComment self.separator = Word("~!@$%^&*()+`-={}|[]:;<>?,/.", max=2) self.string = \ QuotedString(quoteChar='"', escChar='\\', multiline=False, unquoteResults=False) |\ QuotedString(quoteChar="'", escChar='\\', multiline=False, unquoteResults=False) self.doc_string = \ QuotedString(quoteChar='"""', escChar='\\', multiline=True, unquoteResults=False) |\ QuotedString(quoteChar="'''", escChar='\\', multiline=True, unquoteResults=False) self.string_or_doc = self.doc_string | self.string self.triple_quote = Literal("'''") | Literal('"""') self.e = Literal('E') | Literal('e') self.point = Literal('.') self.plusorminus = Literal('+') | Literal('-') self.number = Word(nums) self.integer = Combine(Optional(self.plusorminus) + self.number) self.fnumber = Combine(self.integer + Optional(self.point + Optional(self.number)) + Optional(self.e + self.integer)) self.tab = Literal(' ') self.ident = Word(alphas + '_', alphanums + '_') self.conseq_idents_numbs = OneOrMore(self.ident | self.fnumber) self.attrib = self.ident + OneOrMore('.' + self.ident) self.statement = (ZeroOrMore( (self.directive | self.tab | self.conseq_idents_numbs | self.separator | self.string_or_doc | self.triple_quote)) + Optional(self.comment).suppress()) self.attribs = (ZeroOrMore( (self.directive.suppress() | self.tab.suppress() | self.attrib | self.ident.suppress() | self.separator.suppress() | self.fnumber.suppress() | self.string_or_doc.suppress() | self.triple_quote.suppress())) + Optional(self.comment).suppress()) self.conseq_idents = (ZeroOrMore( (self.directive.suppress() | self.tab.suppress() | self.ident | self.separator.suppress() | self.fnumber.suppress() | self.string.suppress())) + Optional(self.comment).suppress()) self.conseq_idents_no_obfuscate = (ZeroOrMore( (self.directive.suppress() | self.tab.suppress() | self.ident | self.separator.suppress() | self.fnumber.suppress() | self.string_or_doc.suppress() | self.triple_quote.suppress())) + Optional(self.comment).suppress()) self.attribs.setParseAction(self.add_attribs_reserveds) self.conseq_idents.setParseAction(self.add_conseq_idents) self.conseq_idents_no_obfuscate.setParseAction( self.add_conseq_idents_no_obfuscate) self.conseq_idents_numbs.setParseAction( self.transform_conseq_ident_numbs) self.directive.setParseAction(self.transform_directive) ############### # Parse actions ############### def add_conseq_idents(self, conseq_idents_list): """Add names to obfuscate to identifiers table. Parameters ---------- conseq_idents_list : list """ if 'import' not in conseq_idents_list[:] and \ 'except' not in conseq_idents_list[:]: add_identifiers(set(conseq_idents_list)) def add_conseq_idents_no_obfuscate(self, conseq_idents_no_obfuscate_list): """Add names that are not obfuscated to identifiers table. Parameters ---------- conseq_idents_no_obfuscate_list : list """ # If an except error was not added to reserved list, don't obfuscate it if 'import' not in conseq_idents_no_obfuscate_list[:] and \ 'except' not in conseq_idents_no_obfuscate_list[:]: add_identifiers(set(conseq_idents_no_obfuscate_list), do_obfuscate=False) def add_attribs_reserveds(self, attribs_list): """Add attributes of reserved names to reserved list. Take a list of attributes strings from a source statement, break it into lists of objects with their attributes, and add attributes that follow a reserved name to the reserved list. Example ------ If r is reserved, then a.r.c + d.r.e would add c and e to reserveds. Parameters ---------- attribs_list : list """ if attribs_list: # Create an ordered list of attribute parents # Ex. a.b.c => [a, b] _attrib_list = [attribs_list[0]] is_last_token_an_attrib = True for token in attribs_list[1:]: if is_last_token_an_attrib and token != '.': # End of attrib list reached. Process list. add_attribs_reserveds_list(_attrib_list) # Start new attrib list _attrib_list = [token] is_last_token_an_attrib = True elif is_last_token_an_attrib and token == '.': is_last_token_an_attrib = False elif not is_last_token_an_attrib and token == '.': continue # Multiple dots, continue attrib list elif not is_last_token_an_attrib and token != '.': _attrib_list.append(token) is_last_token_an_attrib = True else: # Process last list if _attrib_list: add_attribs_reserveds_list(_attrib_list) def transform_conseq_ident_numbs(self, conseq_ident_list): """Allow for non-name tokens in a statement. Names start with an alpha or underscore. Obfuscate these name tokens and simply copy unchanged other tokens. Parameters ---------- conseq_ident_list : list Returns ------- statement : str """ return ' '.join([ self.get_obfuscated(ident) if (ident[0].isalpha() or ident[0] == '_') else ident for ident in conseq_ident_list ]) def transform_directive(self, directive_list): """Create a directive statement.""" return ''.join([directive_list[0], ' '])
class ObfuscateBNF(object): __metaclass__ = abc.ABCMeta def __init__(self, get_obfuscated): """BNF grammar for source statements. Parameters ---------- get_obfuscated : function Function to return the obfuscated name for an identifier. """ self.get_obfuscated = get_obfuscated self.directive = oneOf("#:") self.comment = ~self.directive + pythonStyleComment self.separator = Word("~!@$%^&*()+`-={}|[]:;<>?,/.", max=2) self.string = \ QuotedString(quoteChar='"', escChar='\\', multiline=False, unquoteResults=False) |\ QuotedString(quoteChar="'", escChar='\\', multiline=False, unquoteResults=False) self.doc_string = \ QuotedString(quoteChar='"""', escChar='\\', multiline=True, unquoteResults=False) |\ QuotedString(quoteChar="'''", escChar='\\', multiline=True, unquoteResults=False) self.string_or_doc = self.doc_string | self.string self.triple_quote = Literal("'''") | Literal('"""') self.e = Literal('E') | Literal('e') self.point = Literal('.') self.plusorminus = Literal('+') | Literal('-') self.number = Word(nums) self.integer = Combine(Optional(self.plusorminus) + self.number) self.fnumber = Combine( self.integer + Optional(self.point + Optional(self.number)) + Optional(self.e + self.integer)) self.tab = Literal(' ') self.ident = Word(alphas+'_', alphanums+'_') self.conseq_idents_numbs = OneOrMore(self.ident | self.fnumber) self.attrib = self.ident + OneOrMore('.'+self.ident) self.statement = ( ZeroOrMore( (self.directive | self.tab | self.conseq_idents_numbs | self.separator | self.string_or_doc | self.triple_quote) ) + Optional(self.comment).suppress() ) self.attribs = ( ZeroOrMore( (self.directive.suppress() | self.tab.suppress() | self.attrib | self.ident.suppress() | self.separator.suppress() | self.fnumber.suppress() | self.string_or_doc.suppress() | self.triple_quote.suppress()) ) + Optional(self.comment).suppress() ) self.conseq_idents = ( ZeroOrMore( (self.directive.suppress() | self.tab.suppress() | self.ident | self.separator.suppress() | self.fnumber.suppress() | self.string.suppress()) ) + Optional(self.comment).suppress() ) self.conseq_idents_no_obfuscate = ( ZeroOrMore( (self.directive.suppress() | self.tab.suppress() | self.ident | self.separator.suppress() | self.fnumber.suppress() | self.string_or_doc.suppress() | self.triple_quote.suppress()) ) + Optional(self.comment).suppress() ) self.attribs.setParseAction(self.add_attribs_reserveds) self.conseq_idents.setParseAction(self.add_conseq_idents) self.conseq_idents_no_obfuscate.setParseAction( self.add_conseq_idents_no_obfuscate) self.conseq_idents_numbs.setParseAction( self.transform_conseq_ident_numbs) self.directive.setParseAction(self.transform_directive) ############### # Parse actions ############### def add_conseq_idents(self, conseq_idents_list): """Add names to obfuscate to identifiers table. Parameters ---------- conseq_idents_list : list """ if 'import' not in conseq_idents_list[:] and \ 'except' not in conseq_idents_list[:]: add_identifiers(set(conseq_idents_list)) def add_conseq_idents_no_obfuscate( self, conseq_idents_no_obfuscate_list): """Add names that are not obfuscated to identifiers table. Parameters ---------- conseq_idents_no_obfuscate_list : list """ # If an except error was not added to reserved list, don't obfuscate it if 'import' not in conseq_idents_no_obfuscate_list[:] and \ 'except' not in conseq_idents_no_obfuscate_list[:]: add_identifiers(set(conseq_idents_no_obfuscate_list), do_obfuscate=False) def add_attribs_reserveds(self, attribs_list): """Add attributes of reserved names to reserved list. Take a list of attributes strings from a source statement, break it into lists of objects with their attributes, and add attributes that follow a reserved name to the reserved list. Example ------ If r is reserved, then a.r.c + d.r.e would add c and e to reserveds. Parameters ---------- attribs_list : list """ if attribs_list: # Create an ordered list of attribute parents # Ex. a.b.c => [a, b] _attrib_list = [attribs_list[0]] is_last_token_an_attrib = True for token in attribs_list[1:]: if is_last_token_an_attrib and token != '.': # End of attrib list reached. Process list. add_attribs_reserveds_list(_attrib_list) # Start new attrib list _attrib_list = [token] is_last_token_an_attrib = True elif is_last_token_an_attrib and token == '.': is_last_token_an_attrib = False elif not is_last_token_an_attrib and token == '.': continue # Multiple dots, continue attrib list elif not is_last_token_an_attrib and token != '.': _attrib_list.append(token) is_last_token_an_attrib = True else: # Process last list if _attrib_list: add_attribs_reserveds_list(_attrib_list) def transform_conseq_ident_numbs(self, conseq_ident_list): """Allow for non-name tokens in a statement. Names start with an alpha or underscore. Obfuscate these name tokens and simply copy unchanged other tokens. Parameters ---------- conseq_ident_list : list Returns ------- statement : str """ return ' '.join([ self.get_obfuscated(ident) if (ident[0].isalpha() or ident[0] == '_') else ident for ident in conseq_ident_list ]) def transform_directive(self, directive_list): """Create a directive statement.""" return ''.join([directive_list[0], ' '])
return float(n) integer = Word(nums).setParseAction(numeric) floatnum = Combine( Optional('-') + ('0' | Word('123456789', nums)) + Optional('.' + Word(nums)) + Optional(Word('eE', exact=1) + Word(nums + '+-', nums))) floatnum.setParseAction(numeric) end = Keyword('end').suppress() point2d = floatnum + floatnum # Note: Since we're just doing 2D, we ignore the z term of 3D points. point3d = floatnum + floatnum + floatnum.suppress() # Obstacle position = Group((Keyword('pos') | Keyword('position')) + point3d) size = Group(Keyword('size') + point3d) rotation = Group((Keyword('rot') | Keyword('rotation')) + floatnum) obstacle_items = [position, Optional(size), Optional(rotation)] class Box(object): """A basic obstacle type.""" def __init__(self, pos=None, position=None, rot=None, rotation=None,