def make_parser(self): self.constant = pp.MatchFirst([constant['token'].setParseAction(constant.get('action', ConstantAction)) for constant in self.constants]) if self.variables: self.variable = pp.MatchFirst([variable['token'].setParseAction(variable.get('action', VariableAction)) for variable in self.variables]) baseExpr = self.constant | self.variable else: self.variable = None baseExpr = self.constant EXP = pp.Forward() funcExpr = [] for function in self.functions: if isinstance(function['token'], tuple) and len(function['token'])==2: # bifixNotation left = pp.Literal(function['token'][0]) if isinstance(function['token'][0], str) else function['token'][0] right = pp.Literal(function['token'][1]) if isinstance(function['token'][1], str) else function['token'][0] if 'arity' in function: if function['arity'] == 1: funcExpr.append((left('left') + EXP('arg') +right('right')).setParseAction(function['action'])) else: funcExpr.append((left('left') + ((EXP + COMMA) * (function['arity']-1) + EXP)('args') + right('right')).setParseAction(function['action'])) else: funcExpr.append((left('left') + pp.delimitedList(EXP)('args') +right('right')).setParseAction(function['action'])) else: if isinstance(function['token'], str): function['token'] = pp.Literal(function['token']) if 'arity' in function: if function['arity'] == 1: funcExpr.append((function['token']('function') + LPAREN + EXP('arg') + RPAREN).setParseAction(function['action'])) else: funcExpr.append((function['token']('function') + LPAREN + ((EXP + COMMA) * (function['arity']-1) + EXP)('args') + RPAREN).setParseAction(function['action'])) else: funcExpr.append((function['token']('function') + LPAREN+ pp.delimitedList(EXP)('args') + RPAREN).setParseAction(function['action'])) funcExpr = pp.MatchFirst(funcExpr) tupleExpr = LPAREN + (pp.Group(pp.Optional(EXP + COMMA)) | (EXP + COMMA + pp.delimitedList(EXP) + pp.Optional(COMMA)))('items') + RPAREN tupleExpr.setParseAction(TupleAction) M = funcExpr | tupleExpr | baseExpr | LPAREN + EXP + RPAREN indexExpr = M('variable') + pp.OneOrMore(pp.Suppress('[') + EXP + pp.Suppress(']'))('index') indexExpr.setParseAction(IndexAction) EXP <<= pp.infixNotation(indexExpr | M, optable2oplist(self.operators)) self.expression = EXP
def _make_parser(): word = pp.CharsNotIn(''.join(whitespace)) word.skipWhitespace = True value = pp.MatchFirst([ pp.dblQuotedString.copy().setParseAction(pp.removeQuotes), pp.sglQuotedString.copy().setParseAction(pp.removeQuotes), pp.Empty() + pp.CharsNotIn(''.join(whitespace)), ]) expressions = [] for field in named_fields: exp = pp.Suppress(pp.CaselessLiteral(field) + ':') + \ value.copy().setParseAction(_decorate_match(field)) expressions.append(exp) any_ = value.copy().setParseAction(_decorate_match('any')) expressions.append(any_) return pp.ZeroOrMore(pp.MatchFirst(expressions))
def expr(cls): parts = [i.expr() for i in cls.components] atom = pp.MatchFirst(parts) resp = pp.And( [ WF.expr(), base.Sep, pp.ZeroOrMore(base.Sep + atom) ] ) resp = resp.setParseAction(cls) return resp
def __set_name__(self, owner, name): self.owner = owner self.name = name string_parsers = [self.parser_for_string(s) for s in self.definitions] parser = pp.MatchFirst(string_parsers) parser.setName(name) # TODO THIS BIT IS NOT GENERAL PURPOSE metavar = pp.Regex(r'\{[^\{\}\s]+\}') metavar.setName('metavar') parser |= metavar self.parser <<= parser
def _make_parser(): word = pp.CharsNotIn("".join(whitespace)) word.skipWhitespace = True value = pp.MatchFirst([ pp.dbl_quoted_string.copy().set_parse_action(pp.remove_quotes), pp.sgl_quoted_string.copy().set_parse_action(pp.remove_quotes), pp.Empty() + pp.CharsNotIn("".join(whitespace)), ]) expressions = [] for field in named_fields: exp = pp.Suppress(pp.CaselessLiteral(field) + ":") + value.copy().set_parse_action( _decorate_match(field)) expressions.append(exp) any_ = value.copy().set_parse_action(_decorate_match("any")) expressions.append(any_) return pp.ZeroOrMore(pp.MatchFirst(expressions))
def _make(): # Order is important - multi-char expressions need to come before narrow # ones. parts = [] for cls in filter_unary: f = pp.Literal(f"~{cls.code}") + pp.WordEnd() f.setParseAction(cls.make) parts.append(f) # This is a bit of a hack to simulate Word(pyparsing_unicode.printables), # which has a horrible performance with len(pyparsing.pyparsing_unicode.printables) == 1114060 unicode_words = pp.CharsNotIn("()~'\"" + pp.ParserElement.DEFAULT_WHITE_CHARS) unicode_words.skipWhitespace = True regex = ( unicode_words | pp.QuotedString('"', escChar='\\') | pp.QuotedString("'", escChar='\\') ) for cls in filter_rex: f = pp.Literal(f"~{cls.code}") + pp.WordEnd() + regex.copy() f.setParseAction(cls.make) parts.append(f) for cls in filter_int: f = pp.Literal(f"~{cls.code}") + pp.WordEnd() + pp.Word(pp.nums) f.setParseAction(cls.make) parts.append(f) # A naked rex is a URL rex: f = regex.copy() f.setParseAction(FUrl.make) parts.append(f) atom = pp.MatchFirst(parts) expr = pp.infixNotation( atom, [(pp.Literal("!").suppress(), 1, pp.opAssoc.RIGHT, lambda x: FNot(*x)), (pp.Literal("&").suppress(), 2, pp.opAssoc.LEFT, lambda x: FAnd(*x)), (pp.Literal("|").suppress(), 2, pp.opAssoc.LEFT, lambda x: FOr(*x)), ]) expr = pp.OneOrMore(expr) return expr.setParseAction(lambda x: FAnd(x) if len(x) != 1 else x)
def get_parser_extension(parser_extensions, parse_actions=False): """Get parser extension parser element. :param list parser_extensions: parser extensions parser_extension = opening tag, { any Unicode character }, closing tag; :returns: parser extension parser element :rtype: ParserElement """ parser_extensions.sort(key=len, reverse=True) parser_extension = (pyparsing.MatchFirst( pyparsing.Regex("<{0}(.*?)>(.*?)</{0}>".format(tag), re.DOTALL) for tag in parser_extensions) | pyparsing.MatchFirst( pyparsing.Regex("<{}(.*?)/>".format(tag)) for tag in parser_extensions)) parser_extension.setName("parser_extension") parser_extension.parseWithTabs() if parse_actions: parser_extension.setParseAction( src.wpmarkupparser.parse_actions.tags.sub_parser_extension) return parser_extension
def _get_parser(): double_escape = pp.Combine(pp.Literal(_DOUBLE_ESCAPE) + pp.MatchFirst([pp.FollowedBy(_REF_OPEN), pp.FollowedBy(_REF_CLOSE), pp.FollowedBy(_INV_OPEN), pp.FollowedBy(_INV_CLOSE)])).setParseAction(pp.replaceWith(_ESCAPE)) ref_open = pp.Literal(_REF_OPEN).suppress() ref_close = pp.Literal(_REF_CLOSE).suppress() ref_not_open = ~pp.Literal(_REF_OPEN) + ~pp.Literal(_REF_ESCAPE_OPEN) + ~pp.Literal(_REF_DOUBLE_ESCAPE_OPEN) ref_not_close = ~pp.Literal(_REF_CLOSE) + ~pp.Literal(_REF_ESCAPE_CLOSE) + ~pp.Literal(_REF_DOUBLE_ESCAPE_CLOSE) ref_escape_open = pp.Literal(_REF_ESCAPE_OPEN).setParseAction(pp.replaceWith(_REF_OPEN)) ref_escape_close = pp.Literal(_REF_ESCAPE_CLOSE).setParseAction(pp.replaceWith(_REF_CLOSE)) ref_text = pp.CharsNotIn(_REF_EXCLUDES) | pp.CharsNotIn(_REF_CLOSE_FIRST, exact=1) ref_content = pp.Combine(pp.OneOrMore(ref_not_open + ref_not_close + ref_text)) ref_string = pp.MatchFirst([double_escape, ref_escape_open, ref_escape_close, ref_content]).setParseAction(_string) ref_item = pp.Forward() ref_items = pp.OneOrMore(ref_item) reference = (ref_open + pp.Group(ref_items) + ref_close).setParseAction(_reference) ref_item << (reference | ref_string) inv_open = pp.Literal(_INV_OPEN).suppress() inv_close = pp.Literal(_INV_CLOSE).suppress() inv_not_open = ~pp.Literal(_INV_OPEN) + ~pp.Literal(_INV_ESCAPE_OPEN) + ~pp.Literal(_INV_DOUBLE_ESCAPE_OPEN) inv_not_close = ~pp.Literal(_INV_CLOSE) + ~pp.Literal(_INV_ESCAPE_CLOSE) + ~pp.Literal(_INV_DOUBLE_ESCAPE_CLOSE) inv_escape_open = pp.Literal(_INV_ESCAPE_OPEN).setParseAction(pp.replaceWith(_INV_OPEN)) inv_escape_close = pp.Literal(_INV_ESCAPE_CLOSE).setParseAction(pp.replaceWith(_INV_CLOSE)) inv_text = pp.CharsNotIn(_INV_CLOSE_FIRST) inv_content = pp.Combine(pp.OneOrMore(inv_not_close + inv_text)) inv_string = pp.MatchFirst([double_escape, inv_escape_open, inv_escape_close, inv_content]).setParseAction(_string) inv_items = pp.OneOrMore(inv_string) export = (inv_open + pp.Group(inv_items) + inv_close).setParseAction(_invquery) text = pp.CharsNotIn(_EXCLUDES) | pp.CharsNotIn('', exact=1) content = pp.Combine(pp.OneOrMore(ref_not_open + inv_not_open + text)) string = pp.MatchFirst([double_escape, ref_escape_open, inv_escape_open, content]).setParseAction(_string) item = reference | export | string line = pp.OneOrMore(item) + pp.StringEnd() return line
def build_element(self): """ A helper function to assemble the command parser's top level element. """ command_elements = [] for command in self.commands.values(): command_elements.append(command.build_element()) # Enforce command at string start element = pp.StringStart() # Attempt to match command name only first using lookahead commands_element = pp.MatchFirst(pp.Keyword(c) for c in self.commands) element -= pp.FollowedBy(commands_element) # If the above lookahead element matches, the parser will then look for # one of the full command string. Otherwise, it will stop immediately. element -= pp.MatchFirst(command_elements).setParseAction(self.on_match) # Enforce no extra arguments. element -= pp.StringEnd() return element
def define_numeric_word_range(names: str, from_: int, to_: int, step: int = 1) -> pp.MatchFirst: """ Compose a MatchFirst of CaselessKeywords, given their names and values, which when parsed, are converted to their value """ def define_numeric_word(nm: str, val: int): return pp.CaselessKeyword(nm).add_parse_action(lambda: val) names = names.split() values = range(from_, to_ + 1, step) return pp.MatchFirst( define_numeric_word(name, value) for name, value in zip(names, values))
def build_clause(cls, clauses=None): ''' Build a single clause from a list of clauses using pp.MatchFirst Merges a list of clauses into a single clause using :py:class:`pyparsing.MatchFirst`. This is equivalent to "clause = clause1 | clause2 | clause3`. The clause precedence the Parser uses will be the order they appear in the list. The default is to use the attached Parser._clauses list. Parameters: clauses: list A list of clauses to merge into a single clause ''' clauses = clauses or cls._clauses assert isinstance(clauses, list), 'clauses must be a list' clauses = pp.MatchFirst(clauses) cls._clause = clauses
class Profile(Node): """ Description of a pulseaudio profile. """ __fragments__ = { 'name': 'profile-name', 'label': 'profile-label', 'sink_cnt': 'profile-sink-count', 'source_cnt': 'profile-source-count', 'priority': 'profile-priority', } __syntax__ = ( p.Word(p.alphanums + "+-:").setParseAction( lambda t: t[0].rstrip(':') ).setResultsName("profile-name") + p.delimitedList( p.Literal("(HDMI)") | p.Literal("(IEC958)") | p.Regex('[^ (\n]+'), ' ', combine=True ).setResultsName('profile-label') + p.Suppress('(') + p.Keyword('sinks').suppress() + p.Suppress(':') + p.Word(p.nums).setParseAction( lambda t: int(t[0]) ).setResultsName('profile-sink-count') + p.Suppress(',') + p.Keyword('sources').suppress() + p.Suppress(':') + p.Word(p.nums).setParseAction( lambda t: int(t[0]) ).setResultsName('profile-source-count') + p.Suppress(',') + p.Keyword('priority').suppress() + p.MatchFirst([ p.Suppress('.'), # Merged on 2013-06-03 (YYYY-MM-DD) # http://cgit.freedesktop.org/pulseaudio/pulseaudio/commit/src/utils/pactl.c?id=83c3cf0a65fb05900f81bd2dbb38e6956eb23935 p.Suppress(':'), ]) + p.Word(p.nums).setParseAction( lambda t: int(t[0]) ).setResultsName('profile-priority') + p.Suppress(')') ).setResultsName("profile")
def _get_modifier(modifiers, parse_actions=False): """Get modifier parser element. :param list modifiers: modifiers modifier = any modifier; :returns: modifier parser element :rtype: ParserElement """ modifiers.sort(key=len, reverse=True) modifiers = [pyparsing.CaselessKeyword(modifier) for modifier in modifiers] modifier = pyparsing.MatchFirst(modifiers).setResultsName("modifier") modifier.parseWithTabs() if parse_actions: pass return modifier
def _get_variable(variables, parse_actions=False): """Get variable parser element. :param list variables: variables variable = any variable; :returns: variable parser element :rtype: ParserElement """ variables.sort(key=len, reverse=True) variable = pyparsing.MatchFirst(variables).setResultsName("variable") variable.setName("variable") variable.parseWithTabs() if parse_actions: pass return variable
def _create_optional_argument(self, name_list: list, arg_name: str, value_parser: pp.ParserElement, help_text=None, optional=True): arg = pp.MatchFirst([pp.CaselessKeyword(i) for i in name_list ]).setParseAction(lambda x: arg_name) # It is important that the ParseAction is inside the Optional! Otherwise we will get errors if it does not # match. complete = (arg + value_parser.copy()).setName( arg_name).setParseAction(lambda x: {x[0]: x[1]})(arg_name) if optional: complete = pp.Optional(complete) return self._arg_info(complete, arg_name, name_list, help_text)
def _make(): # Order is important - multi-char expressions need to come before narrow # ones. parts = [] for klass in filt_unary: f = pp.Literal("~%s" % klass.code) + pp.WordEnd() f.setParseAction(klass.make) parts.append(f) simplerex = "".join(c for c in pp.printables if c not in "()~'\"") rex = pp.Word(simplerex) |\ pp.QuotedString("\"", escChar='\\') |\ pp.QuotedString("'", escChar='\\') for klass in filt_rex: f = pp.Literal("~%s" % klass.code) + pp.WordEnd() + rex.copy() f.setParseAction(klass.make) parts.append(f) for klass in filt_int: f = pp.Literal("~%s" % klass.code) + pp.WordEnd() + pp.Word(pp.nums) f.setParseAction(klass.make) parts.append(f) # A naked rex is a URL rex: f = rex.copy() f.setParseAction(FUrl.make) parts.append(f) atom = pp.MatchFirst(parts) expr = pp.operatorPrecedence(atom, [(pp.Literal("!").suppress(), 1, pp.opAssoc.RIGHT, lambda x: FNot(*x)), (pp.Literal("&").suppress(), 2, pp.opAssoc.LEFT, lambda x: FAnd(*x)), (pp.Literal("|").suppress(), 2, pp.opAssoc.LEFT, lambda x: FOr(*x)), ]) expr = pp.OneOrMore(expr) return expr.setParseAction(lambda x: FAnd(x) if len(x) != 1 else x)
def _get_parser_function(parser_functions, parse_actions=False): """Get parser function parser element. :param list parser_functions: parser functions parser_function = any parser function; :returns: parser function parser element :rtype: ParserElement """ parser_functions.sort(key=len, reverse=True) parser_function = pyparsing.MatchFirst(parser_functions).setResultsName( "parser_function") parser_function.setName("parser_function") parser_function.parseWithTabs() if parse_actions: pass return parser_function
def get_behaviour_switch(behavior_switches, parse_actions=False): """Get behavior switch parser element. :param list behavior_switches: behavior switches behavior_switch = any behavior switch; :returns: behavior switch parser element :rtype: ParserElement """ behavior_switches.sort(key=len, reverse=True) behavior_switch = pyparsing.MatchFirst(behavior_switches).setResultsName( "behavior_switch") behavior_switch.setName("behavior_switch") behavior_switch.parseWithTabs() if parse_actions: behavior_switch.setParseAction( src.wpmarkupparser.parse_actions.magic_words.sub_behavior_switch) return behavior_switch
class EnvRefCommand(DockerfileCommand): class EnvReference(Stanza): def __init__(self, tokens): self.reference = tokens['ref'] def __str__(self): return '${' + self.reference + '}' def expand(self, environ): return environ[self.reference] class EnvStaticString(Stanza): def __init__(self, tokens): self.string = tokens[0] def __str__(self): return self.string.replace('\\', '\\\\').replace('$', '\\') # noinspection PyUnusedLocal def expand(self, environ): return self.string env_var = p.Word(p.alphas + '_', bodyChars=p.alphanums + '_') env_ref = \ p.Combine(ch('$') + env_var('ref')) | \ p.Combine(ch('${') + env_var('ref') + ch('}').suppress()) env_value = p.OneOrMore( p.MatchFirst( (p.Combine(escaped_char).setParseAction(EnvStaticString), env_ref.leaveWhitespace().setParseAction(EnvReference), p.Word(p.printables + ' \t', excludeChars='$\\').leaveWhitespace().setParseAction( EnvStaticString)))) env_word_value = p.Group( (p.QuotedString('"', escChar='\\', multiline=True) | p.QuotedString("'", escChar='\\', multiline=True) | p.Combine( p.OneOrMore( p.Word(p.printables, excludeChars='\\') | escaped_char)) ).leaveWhitespace().setParseAction(env_quoted_string))
def _get_project(projects, parse_actions=False): """Get project parser element. :param list projects: projects project = any project; :returns: project parser element :rtype: ParserElement """ keywords = ([ pyparsing.CaselessKeyword(project) for project in projects if project != "wikipedia" ] + [pyparsing.Keyword("wikipedia")]) project = pyparsing.MatchFirst(keywords).setResultsName("project") project.setName("project") project.parseWithTabs() if parse_actions: pass return project
def _get_namespace(namespaces, parse_actions=False): """Get namespace parser element. :param list namespaces: namespaces namespace = any namespace; :returns: namespace parser element :rtype: ParserElement """ namespaces.sort(key=len, reverse=True) namespaces = [ pyparsing.CaselessKeyword(namespace) for namespace in namespaces ] namespace = pyparsing.MatchFirst(namespaces).setResultsName("namespace") namespace.setName("namespace") namespace.parseWithTabs() if parse_actions: pass return namespace
class Port(Node): """ Description of a port on a sink """ __fragments__ = { 'name': 'port-name', 'label': 'port-label', 'priority': 'port-priority', 'availability': 'port-availability' } __syntax__ = ( p.Optional('[Out] ').suppress() + p.Optional('[In] ').suppress() + p.Word(p.alphanums + " -;").setResultsName('port-name') + p.Suppress(':') # This part was very tricky to write. The label is basically # arbitrary localized Unicode text. We want to grab all of it in # one go but without consuming the upcoming '(' character or the # space that comes immediately before. # # The syntax here combines a sequence of words, as defined by # anything other than a space and '(', delimited by a single # whitespace. + p.delimitedList( p.Regex('[^ (\n]+'), ' ', combine=True ).setResultsName('port-label') + p.Suppress('(') + p.Keyword('priority').suppress() + p.Suppress(':') + p.Word(p.nums).setParseAction( lambda t: int(t[0]) ).setResultsName('port-priority') + p.MatchFirst([ p.Suppress(',') + p.Literal('not available'), p.Suppress(',') + p.Literal('available'), p.Empty().setParseAction(lambda t: '') ]).setResultsName('port-availability') + p.Suppress(')') ).setResultsName("port")
def _get_language_code(language_codes, parse_actions=False): """Get language code parser element. :param list language_codes: language codes language_code = any language code; :returns: language code parser element :rtype: ParserElement """ language_codes.sort(key=len, reverse=True) caseless_keywords = [ pyparsing.CaselessKeyword(language_code) for language_code in language_codes ] language_code = (pyparsing.MatchFirst(caseless_keywords).setResultsName( "language_code")) language_code.setName("language_code") language_code.parseWithTabs() if parse_actions: pass return language_code
def define_numeric_word_range(names: str, from_: int, to_: int = None, step: int = 1) -> pp.MatchFirst: """ Compose a MatchFirst of CaselessKeywords, given their names and values, which when parsed, are converted to their value """ def define_numeric_word(nm: str, val: int): return pp.CaselessKeyword(nm).add_parse_action(lambda: val) names = names.split() if to_ is None: to_ = from_ values = range(from_, to_ + 1, step) ret = pp.MatchFirst( define_numeric_word(name, value) for name, value in zip(names, values)) if len(names) == 1: ret.setName(names[0]) else: ret.setName("{}-{}".format(names[0], names[-1])) return ret
def expand(pe, aslist=False): pe.streamline() if isinstance(pe, (pp.And, pp.Each)): if pe.exprs: x = expand(pe.exprs[0], True) for expr in pe.exprs[1:]: x = [xi + a for xi in x for a in expand(expr, True)] elif isinstance(pe, (pp.Or, pp.MatchFirst)): x = [] for expr in pe.exprs: x.extend(expand(expr, True)) elif isinstance(pe, _Enhance): x = expand(pe.expr, True) else: # x is monomal x = [pe] x = [xi.streamline() for xi in x] if aslist: return x else: if len(x) == 1: return x[0] else: return pp.MatchFirst(x)
def __init__(self, progress_callback=None): """Constructor. Args: progress_callback: If specified, called with the character location of the end of the last-yielded statement. """ # Get all the class variables that matches _*_TOKEN keywords = list(SQLParser.__dict__[k] for k in SQLParser.__dict__ if re.match(r'^_([_\w])+_TOKEN$', k)) # Fill the grammar rule _KEYWORDS with all the keywords possible SQLParser.__dict__['_KEYWORDS'] << pyp.MatchFirst(keywords) self._loc = 0 # Last yielded line end self._base_loc = 0 # Start of this statement self._callback = progress_callback for key in dir(self): grammar_rule = getattr(self, key) if isinstance(grammar_rule, pyp.ParserElement): grammar_rule.setName(key) grammar_rule.setDebugActions( self._LogStart, self._LogSuccess, self._LogFailure)
def make_parser(self, enablePackrat=True): self.constant = pp.MatchFirst([ constant['token'].setParseAction( constant.get('action', ConstantAction)) for constant in self.constants ]) if self.variables: self.variable = pp.MatchFirst([ variable['token'].setParseAction( variable.get('action', VariableAction)) for variable in self.variables ]) baseExpr = self.constant | self.variable else: self.variable = None baseExpr = self.constant EXP = pp.Forward() funcExpr = [] unpackExpr = pp.Suppress('*') + EXP('content') unpackExpr.setParseAction(UnpackAction) for function in self.functions: if isinstance(function['token'], tuple) and len( function['token']) == 2: # bifixNotation left = pp.Literal(function['token'][0]) if isinstance( function['token'][0], str) else function['token'][0] right = pp.Literal(function['token'][1]) if isinstance( function['token'][1], str) else function['token'][0] if 'arity' in function: if function['arity'] == 1: funcExpr.append((left('left') + EXP('arg') + right('right')).setParseAction( function['action'])) else: funcExpr.append( (left('left') + ((EXP + COMMA) * (function['arity'] - 1) + EXP)('args') + right('right')).setParseAction( function['action'])) else: funcExpr.append( (left('left') + pp.delimitedList(EXP)('args') + right('right')).setParseAction(function['action'])) else: if isinstance(function['token'], str): function['token'] = pp.Literal(function['token']) if 'arity' in function: if function['arity'] == 1: funcExpr.append( (function['token']('function') + LPAREN + EXP('arg') + RPAREN).setParseAction( function['action'])) else: funcExpr.append( (function['token']('function') + LPAREN + ((EXP + COMMA) * (function['arity'] - 1) + EXP)('args') + RPAREN).setParseAction(function['action'])) else: funcExpr.append( (function['token']('function') + LPAREN + pp.delimitedList(EXP)('args') + RPAREN).setParseAction(function['action'])) funcExpr = pp.MatchFirst(funcExpr) tupleExpr = tupleExpression(EXP)('args') tupleExpr.setParseAction(TupleAction) # dictExpr = LBRACE + pp.ZeroOrMore(EXP('key') + COLON + EXP('value')) + RBRACE # dictExpr.setParseAction(DictAction) M = funcExpr | tupleExpr | baseExpr | LPAREN + EXP + RPAREN indexExpr = M('variable') + pp.OneOrMore(LBRACK + EXP + RBRACK)('index') indexExpr.setParseAction(IndexAction) EXP <<= pp.infixNotation(indexExpr | M, optable2oplist(self.operators)) self.expression = EXP self.tupleExpr = tupleExpr # self.dictExpr = dictExpr if enablePackrat: self.expression.enablePackrat()
primary = Identifier | Integer | '(' expr ')' | ('+' | '-' | '!') primary ; """ import pyparsing as pp pp.ParserElement.enablePackrat() LBRACE, RBRACE, LPAR, RPAR, SEMI = map(pp.Suppress, "{}();") EQ = pp.Literal('=') keywords = (WHILE, IF, PRINT, PUTC, ELSE) = map(pp.Keyword, "while if print putc else".split()) identifier = ~(pp.MatchFirst(keywords)) + pp.pyparsing_common.identifier integer = pp.pyparsing_common.integer string = pp.QuotedString( '"', convertWhitespaceEscapes=False).setName("quoted string") char = pp.Regex(r"'\\?.'") expr = pp.infixNotation(identifier | integer | char, [ ( pp.oneOf("+ - !"), 1, pp.opAssoc.RIGHT, ), ( pp.oneOf("* / %"), 2, pp.opAssoc.LEFT,
ENDIF = pp.Keyword("#endif").suppress() # Variable names, types, literals etc. # ------------------------------------------------------------------------------ NAME = pp.Word(pp.alphanums + "_") INT = pp.Word(pp.nums + "UuLl") FLOAT = pp.Word(pp.nums + ".+-EeFf") NUMBER = FLOAT | INT # Dimensions can be of the form `[3]`, `[constant_name]` or `[2*constant_name]` ARRAY_DIM = pp.Combine(LBRACK + (INT | NAME) + pp.Optional(pp.Literal("*")) + pp.Optional(INT | NAME) + RBRACK) PTR = pp.Literal("*") EXTERN = pp.Keyword("extern") NATIVE_TYPENAME = pp.MatchFirst([pp.Keyword(n) for n in C_TO_CTYPES.keys()]) # Macros. # ------------------------------------------------------------------------------ HDR_GUARD = DEFINE + "THIRD_PARTY_MUJOCO_HDRS_" # e.g. "#define mjUSEDOUBLE" DEF_FLAG = pp.Group(DEFINE + NAME("name") + (COMMENT("comment") | EOL)).ignore(HDR_GUARD) # e.g. "#define mjMINVAL 1E-14 // minimum value in any denominator" DEF_CONST = pp.Group(DEFINE + NAME("name") + (NUMBER | NAME)("value") + (COMMENT("comment") | EOL)) # e.g. "X( mjtNum*, name_textadr, ntext, 1 )"
("seven", 7), ("eight", 8), ("nine", 9), ("ten", 10), ("eleven", 11), ("twelve", 12), ("thirteen", 13), ("fourteen", 14), ("fifteen", 15), ("sixteen", 16), ("seventeen", 17), ("eighteen", 18), ("nineteen", 19), ] units = pp.MatchFirst( makeLit(s, v) for s, v in sorted(unitDefinitions, key=lambda d: -len(d[0]))) tensDefinitions = [ ("ten", 10), ("twenty", 20), ("thirty", 30), ("forty", 40), ("fourty", 40), # for the spelling-challenged... ("fifty", 50), ("sixty", 60), ("seventy", 70), ("eighty", 80), ("ninety", 90), ] tens = pp.MatchFirst(makeLit(s, v) for s, v in tensDefinitions)