Python pyparsing.Group() Examples

The following are 30 code examples of pyparsing.Group(). You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module pyparsing , or try the search function .
Example #1
Source File: interpreter.py    From design-patterns with MIT License 6 votes vote down vote up
def parse(input_string):
        word = Word(alphanums)
        command = Group(OneOrMore(word))
        token = Suppress("->")
        device = Group(OneOrMore(word))
        argument = Group(OneOrMore(word))
        event = command + token + device + Optional(token + argument)
        parse_results = event.parseString(input_string)
        cmd = parse_results[0]
        dev = parse_results[1]
        cmd_str = "_".join(cmd)
        dev_str = "_".join(dev)
        try:
            val = parse_results[2]
        except IndexError:
            val_str = None
        else:
            val_str = "_".join(val)
        return cmd_str, dev_str, val_str 
Example #2
Source File: ldap3mock.py    From privacyidea with GNU Affero General Public License v3.0 6 votes vote down vote up
def _parse_filter():
        op = pyparsing.oneOf('! & |')
        lpar  = pyparsing.Literal('(').suppress()
        rpar  = pyparsing.Literal(')').suppress()

        k = pyparsing.Word(pyparsing.alphanums)
        # NOTE: We may need to expand on this list, but as this is not a real
        # LDAP server we should be OK.
        # Value to contain:
        #   numbers, upper/lower case letters, astrisk, at symbol, minus, full
        #   stop, backslash or a space
        v = pyparsing.Word(pyparsing.alphanums + "-*@.\\ äöü")
        rel = pyparsing.oneOf("= ~= >= <=")

        expr = pyparsing.Forward()
        atom = pyparsing.Group(lpar + op + expr + rpar) \
                            | pyparsing.Combine(lpar + k + rel + v + rpar)
        expr << atom + pyparsing.ZeroOrMore( expr )

        return expr 
Example #3
Source File: httpServerLogParser.py    From phpsploit with GNU General Public License v3.0 6 votes vote down vote up
def getLogLineBNF():
    global logLineBNF
    
    if logLineBNF is None:
        integer = Word( nums )
        ipAddress = delimitedList( integer, ".", combine=True )
        
        timeZoneOffset = Word("+-",nums)
        month = Word(string.uppercase, string.lowercase, exact=3)
        serverDateTime = Group( Suppress("[") + 
                                Combine( integer + "/" + month + "/" + integer +
                                        ":" + integer + ":" + integer + ":" + integer ) +
                                timeZoneOffset + 
                                Suppress("]") )
                         
        logLineBNF = ( ipAddress.setResultsName("ipAddr") + 
                       Suppress("-") +
                       ("-" | Word( alphas+nums+"@._" )).setResultsName("auth") +
                       serverDateTime.setResultsName("timestamp") + 
                       dblQuotedString.setResultsName("cmd").setParseAction(getCmdFields) +
                       (integer | "-").setResultsName("statusCode") + 
                       (integer | "-").setResultsName("numBytesSent")  + 
                       dblQuotedString.setResultsName("referrer").setParseAction(removeQuotes) +
                       dblQuotedString.setResultsName("clientSfw").setParseAction(removeQuotes) )
    return logLineBNF 
Example #4
Source File: macro_expander.py    From rekall with GNU General Public License v2.0 6 votes vote down vote up
def expression(self):
        expression = pyparsing.Forward()

        # (1 + (2 + 3))
        nested_expression = pyparsing.nestedExpr(
            "(", ")", expression).setParseAction(self._combine_lists)

        # FOO(2 , 3)
        function_call = (
            _TOKEN().setResultsName("function")
            + _OPEN_PARENTHESIS()
            + pyparsing.delimitedList(
                pyparsing.Combine(expression, adjacent=False, joinString=" "),
                delim=",").setResultsName("func_args")
            + _CLOSE_PARENTHESIS()
        )

        expression << pyparsing.OneOrMore(
            function_call.setParseAction(self._is_known_function)
            | pyparsing.Group(nested_expression)
            | _TOKEN()
            | _NOT_TOKEN()
        )

        return pyparsing.Combine(expression, adjacent=False, joinString=" ") 
Example #5
Source File: parser.py    From pdblp with MIT License 6 votes vote down vote up
def _parse(mystr):

    LBRACE, RBRACE, EQUAL = map(pp.Suppress, "{}=")
    field = pp.Word(pp.printables + ' ', excludeChars='[]=')
    field.addParseAction(pp.tokenMap(str.rstrip))
    string = pp.dblQuotedString().setParseAction(pp.removeQuotes)
    number = pp.pyparsing_common.number()
    date_expr = pp.Regex(r'\d\d\d\d-\d\d-\d\d')
    time_expr = pp.Regex(r'\d\d:\d\d:\d\d\.\d\d\d')
    nan = pp.Keyword('nan')
    scalar_value = (string | date_expr | time_expr | number | nan)

    list_marker = pp.Suppress("[]")
    value_list = pp.Forward()
    jobject = pp.Forward()

    memberDef1 = pp.Group(field + EQUAL + scalar_value)
    memberDef2 = pp.Group(field + EQUAL + jobject)
    memberDef3 = pp.Group(field + list_marker + EQUAL + LBRACE + value_list +
                          RBRACE)
    memberDef = memberDef1 | memberDef2 | memberDef3

    value_list <<= (pp.delimitedList(scalar_value, ",") |
                    pp.ZeroOrMore(pp.Group(pp.Dict(memberDef2))))
    value_list.setParseAction(lambda t: [pp.ParseResults(t[:])])

    members = pp.OneOrMore(memberDef)
    jobject <<= pp.Dict(LBRACE + pp.ZeroOrMore(memberDef) + RBRACE)
    # force empty jobject to be a dict
    jobject.setParseAction(lambda t: t or {})

    parser = members
    parser = pp.OneOrMore(pp.Group(pp.Dict(memberDef)))

    return parser.parseString(mystr) 
Example #6
Source File: rule.py    From CWR-DataApi with MIT License 6 votes vote down vote up
def _apply_modifiers(rule, modifiers):
        if 'grouped' in modifiers:
            rule = pp.Group(rule)

        if 'optional' in modifiers:
            rule = pp.Optional(rule)
        else:
            for modifier in modifiers:
                if modifier.startswith('at_least'):
                    times = rule_at_least.parseString(modifier)[0]
                    if times > 0:
                        rule_multiple = rule
                        for _ in range(1, times):
                            rule_multiple = rule_multiple + rule
                        rule = rule_multiple + pp.ZeroOrMore(rule)
                    else:
                        rule = pp.Optional(pp.ZeroOrMore(rule))

        return rule 
Example #7
Source File: special.py    From CWR-DataApi with MIT License 5 votes vote down vote up
def audio_visual_key(name=None):
    """
    Creates the grammar for an Audio Visual Key code.

    This is a variation on the ISAN (International Standard Audiovisual Number)

    :param name: name for the field
    :return: grammar for an ISRC field
    """

    if name is None:
        name = 'AVI Field'

    society_code = basic.numeric(3)
    society_code = society_code.setName('Society Code') \
        .setResultsName('society_code')

    av_number = basic.alphanum(15, extended=True, isLast=True)
    field_empty = pp.Regex('[ ]{15}')
    field_empty.setParseAction(pp.replaceWith(''))
    av_number = av_number | field_empty
    av_number = av_number.setName('Audio-Visual Number') \
        .setResultsName('av_number')

    field = pp.Group(society_code + pp.Optional(av_number))

    field.setParseAction(lambda v: _to_avi(v[0]))

    field = field.setName(name)

    return field.setResultsName('audio_visual_key') 
Example #8
Source File: modulefilter.py    From wfuzz with GNU General Public License v2.0 5 votes vote down vote up
def __init__(self):
        if PYPARSING:
            category = Word(alphas + "_-*", alphanums + "_-*")
            operator = oneOf("and or ,")
            neg_operator = "not"
            elementRef = category
            definition = elementRef + ZeroOrMore(operator + elementRef)
            nestedformula = Group(Suppress(Optional(Literal("("))) + definition + Suppress(Optional(Literal(")"))))
            neg_nestedformula = Optional(neg_operator) + nestedformula
            self.finalformula = neg_nestedformula + ZeroOrMore(operator + neg_nestedformula)

            elementRef.setParseAction(self.__compute_element)
            neg_nestedformula.setParseAction(self.__compute_neg_formula)
            nestedformula.setParseAction(self.__compute_formula)
            self.finalformula.setParseAction(self.__myreduce) 
Example #9
Source File: parser.py    From holoviews with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def todict(cls, parseresult, mode='parens', ns={}):
        """
        Helper function to return dictionary given the parse results
        from a pyparsing.nestedExpr object (containing keywords).

        The ns is a dynamic namespace (typically the IPython Notebook
        namespace) used to update the class-level namespace.
        """
        grouped, kwargs = [], {}
        tokens = cls.collect_tokens(parseresult, mode)
        # Group tokens without '=' and append to last token containing '='
        for group in groupby(tokens, lambda el: '=' in el):
            (val, items) = group
            if val is True:
                grouped += list(items)
            if val is False:
                elements =list(items)
                # Assume anything before ) or } can be joined with commas
                # (e.g tuples with spaces in them)
                joiner=',' if any(((')' in el) or ('}' in el))
                                  for el in elements) else ''
                grouped[-1] += joiner + joiner.join(elements)

        for keyword in grouped:
            # Tuple ('a', 3) becomes (,'a',3) and '(,' is never valid
            # Same for some of the other joining errors corrected here
            for (fst,snd) in [('(,', '('), ('{,', '{'), ('=,','='),
                              (',:',':'), (':,', ':'), (',,', ','),
                              (',.', '.')]:
                keyword = keyword.replace(fst, snd)
            try:
                kwargs.update(eval('dict(%s)' % keyword,
                                   dict(cls.namespace, **ns)))
            except:
                if cls.abort_on_eval_failure:
                    raise SyntaxError("Could not evaluate keyword: %r"
                                      % keyword)
                msg = "Ignoring keyword pair that fails to evaluate: '%s'"
                parsewarning.warning(msg % keyword)

        return kwargs 
Example #10
Source File: __init__.py    From pyparsing with MIT License 5 votes vote down vote up
def extract_into_diagram(self, el_id: int):
        """
        Used when we encounter the same token twice in the same tree. When this happens, we replace all instances of that
        token with a terminal, and create a new subdiagram for the token
        """
        position = self.first[el_id]

        # Replace the original definition of this element with a regular block
        if position.parent:
            ret = EditablePartial.from_call(railroad.NonTerminal, text=position.name)
            if "item" in position.parent.kwargs:
                position.parent.kwargs["item"] = ret
            else:
                position.parent.kwargs["items"][position.parent_index] = ret

        # If the element we're extracting is a group, skip to its content but keep the title
        if position.converted.func == railroad.Group:
            content = position.converted.kwargs["item"]
        else:
            content = position.converted

        self.diagrams[el_id] = EditablePartial.from_call(
            NamedDiagram,
            name=position.name,
            diagram=EditablePartial.from_call(
                railroad.Diagram, content, **self.diagram_kwargs
            ),
            index=position.number,
        )
        del self.first[el_id] 
Example #11
Source File: htmlTableParser.py    From pyparsing with MIT License 5 votes vote down vote up
def table_row(start_tag, end_tag):
    body = start_tag.tag_body
    body.addParseAction(pp.tokenMap(str.strip), pp.tokenMap(strip_html))
    row = pp.Group(
        tr.suppress()
        + pp.ZeroOrMore(start_tag.suppress() + body + end_tag.suppress())
        + tr_end.suppress()
    )
    return row 
Example #12
Source File: expression_parser.py    From rekall with GNU General Public License v2.0 5 votes vote down vote up
def _base_or_array_expression(self):
        array_indices = pyparsing.ZeroOrMore(
            _OPEN_BRACKETS
            + self.expression
            + _CLOSE_BRACKETS
        )
        return (
            self._base_expression()
            + pyparsing.Group(array_indices)
        ).setParseAction(self._create_base_or_array_expression) 
Example #13
Source File: special.py    From CWR-DataApi with MIT License 5 votes vote down vote up
def date_time(name=None):
    """
    Creates the grammar for a date and time field, which is a combination of
    the Date (D) and Time or Duration field (T).

    This field requires first a Date, and then a Time, without any space in
    between.

    :param name: name for the field
    :return: grammar for a Date and Time field
    """
    if name is None:
        name = 'Date and Time Field'

    date = basic.date('Date')
    time = basic.time('Time')

    date = date.setResultsName('date')
    time = time.setResultsName('time')

    field = pp.Group(date + time)

    field.setParseAction(lambda d: _combine_date_time(d[0]))

    field.setName(name)

    return field.setResultsName('date_time') 
Example #14
Source File: header_parsing.py    From dm_control with Apache License 2.0 5 votes vote down vote up
def _nested_scopes(opening, closing, body):
  """Constructs a parser for (possibly nested) scopes."""
  scope = pp.Forward()
  scope << pp.Group(  # pylint: disable=expression-not-assigned
      opening +
      pp.ZeroOrMore(body | scope)("members") +
      closing)
  return scope 
Example #15
Source File: header_parsing.py    From dm_control with Apache License 2.0 5 votes vote down vote up
def _nested_if_else(if_, pred, else_, endif, match_if_true, match_if_false):
  """Constructs a parser for (possibly nested) if...(else)...endif blocks."""
  ifelse = pp.Forward()
  ifelse << pp.Group(  # pylint: disable=expression-not-assigned
      if_ +
      pred("predicate") +
      pp.ZeroOrMore(match_if_true | ifelse)("if_true") +
      pp.Optional(else_ +
                  pp.ZeroOrMore(match_if_false | ifelse)("if_false")) +
      endif)
  return ifelse


# Some common string patterns to suppress.
# ------------------------------------------------------------------------------ 
Example #16
Source File: utilities.py    From pyactr with GNU General Public License v3.0 5 votes vote down vote up
def getchunk():
    """
    Using pyparsing, create chunk reader for chunk strings.
    """
    slot = pp.Word("".join([pp.alphas, "_"]), "".join([pp.alphanums, "_"]))
    special_value = pp.Group(pp.oneOf([ACTRVARIABLE, "".join([ACTRNEG, ACTRVARIABLE]), ACTRNEG, VISIONGREATER, VISIONSMALLER, "".join([VISIONGREATER, ACTRVARIABLE]), "".join([VISIONSMALLER, ACTRVARIABLE])])\
            + pp.Word("".join([pp.alphanums, "_", '"', "'"])))
    strvalue = pp.QuotedString('"', unquoteResults=False)
    strvalue2 = pp.QuotedString("'", unquoteResults=False)
    varvalue = pp.Word("".join([pp.alphanums, "_"]))
    value = varvalue | special_value | strvalue | strvalue2
    chunk_reader = pp.OneOrMore(pp.Group(slot + value))
    return chunk_reader 
Example #17
Source File: utilities.py    From pyactr with GNU General Public License v3.0 5 votes vote down vote up
def getrule():
    """
    Using pyparsing, get rule out of a string.
    """
    arrow = pp.Literal("==>")
    buff = pp.Word(pp.alphas, "".join([pp.alphanums, "_"]))
    special_valueLHS = pp.oneOf([x for x in _LHSCONVENTIONS.keys()])
    end_buffer = pp.Literal(">")
    special_valueRHS = pp.oneOf([x for x in _RHSCONVENTIONS.keys()])
    chunk = getchunk()
    rule_reader = pp.Group(pp.OneOrMore(pp.Group(special_valueLHS + buff + end_buffer + pp.Group(pp.Optional(chunk))))) + arrow + pp.Group(pp.OneOrMore(pp.Group(special_valueRHS + buff + end_buffer + pp.Group(pp.Optional(chunk)))))
    return rule_reader 
Example #18
Source File: dsl_parser.py    From ibis with Apache License 2.0 5 votes vote down vote up
def __init__(self, cfg_mgr, pre_defined_actions, scripts_dir):
        """init
        Args:
            cfg_mgr: Instance of ibis.utilities.config_manager.ConfigManager
            pre_defined_actions: list of default action ids
        """
        self.cfg_mgr = cfg_mgr
        self.logger = get_logger(self.cfg_mgr)
        self.pre_defined_actions = pre_defined_actions
        header_pattern = pp.Keyword('action').setResultsName('action_header')
        body_pattern = pp.Word(pp.alphanums + '._/')
        body_pattern = body_pattern.setResultsName('action_id')
        self.pattern = header_pattern + \
            pp.Group(body_pattern).setResultsName('action_body')
        self.scripts_dir = scripts_dir 
Example #19
Source File: case_parser.py    From psst with MIT License 5 votes vote down vote up
def parse_table(attribute, string):
    Line = OneOrMore(Float)('data') + Literal(';') + Optional(Comments, default='')('name')
    Grammar = Suppress(Keyword('mpc.{}'.format(attribute)) + Keyword('=') + Keyword('[') + Optional(Comments)) + OneOrMore(Group(Line)) + Suppress(Keyword(']') + Optional(Comments))

    result, i, j = Grammar.scanString(string).next()

    _list = list()
    for r in result:
        _list.append([int_else_float_except_string(s) for s in r['data'].asList()])

    return _list 
Example #20
Source File: expression_parser.py    From rekall with GNU General Public License v2.0 5 votes vote down vote up
def _arguments(self):
        return pyparsing.Group(
            pyparsing.Optional(pyparsing.delimitedList(self._argument()))
        ) 
Example #21
Source File: expression_parser.py    From rekall with GNU General Public License v2.0 5 votes vote down vote up
def _multiword_argument(self):
        return pyparsing.Group(
            self._variable()
            + pyparsing.OneOrMore(self._variable())
        ).setParseAction(util.action(pre_ast.CompositeBlock)) 
Example #22
Source File: location.py    From pybel with MIT License 5 votes vote down vote up
def get_location_language(identifier: ParserElement) -> ParserElement:
    """Build a location parser."""
    return Group(location_tag + nest(identifier))(LOCATION) 
Example #23
Source File: c_parser.py    From rekall with GNU General Public License v2.0 5 votes vote down vote up
def _enum_definition(self):
        """Detect an enum definition.

        e.g.
             enum foo {
                OPTION_1: 1 + 2,
                OPTION_2
             }
        """
        return (
            _ENUM
            + pyparsing.Optional(self._identifier())("enum_name")
            + _OPEN_CURLY
            + pyparsing.ZeroOrMore(
                pyparsing.Group(
                    self._identifier()("name")
                    + pyparsing.Optional(
                        _EQUALS
                        # This allows us to get even invalid expressions.
                        + pyparsing.SkipTo(pyparsing.Word(",}"))("expression")
                    )
                    + pyparsing.Optional(_COMMA)
                )
            )("fields")
            + _CLOSE_CURLY
            + self._maybe_attributes()("attributes")
        ).setParseAction(self._process_enum_definition) 
Example #24
Source File: macro_expander.py    From rekall with GNU General Public License v2.0 5 votes vote down vote up
def _arguments(self):
        return pyparsing.Group(
            pyparsing.Optional(
                pyparsing.delimitedList(self.expression()))) 
Example #25
Source File: gene_modification.py    From pybel with MIT License 5 votes vote down vote up
def get_gene_modification_language(concept_qualified: ParserElement) -> ParserElement:
    """Build a gene modification parser."""
    concept = MatchFirst([
        concept_qualified,
        gmod_default_ns,
    ])
    return gmod_tag + nest(Group(concept)(CONCEPT)) 
Example #26
Source File: yara_support.py    From rekall with GNU General Public License v2.0 5 votes vote down vote up
def meta_section():
    return pyparsing.Group(
        pyparsing.Literal("meta") +
        _COLON +
        pyparsing.OneOrMore(
            statement()
        ).setResultsName("statements")
    ).setResultsName("meta") 
Example #27
Source File: yara_support.py    From rekall with GNU General Public License v2.0 5 votes vote down vote up
def statement():
    return pyparsing.Group(
        _IDENTIFIER.setResultsName("lhs") + _EQUALS +
        pyparsing.Combine(
            (anything_in_curly() |
             pyparsing.QuotedString("'", escChar="\\", unquoteResults=False) |
             pyparsing.QuotedString("\"", escChar="\\", unquoteResults=False) |
             _REGEX) +
            pyparsing.ZeroOrMore(_KEYWORD),
            adjacent=False,
            joinString=" ",
        ).setResultsName("rhs")
    ) 
Example #28
Source File: yara_support.py    From rekall with GNU General Public License v2.0 5 votes vote down vote up
def strings_section():
    return pyparsing.Group(
        pyparsing.Literal("strings") +
        _COLON +
        pyparsing.OneOrMore(statement()).setResultsName("statements")
    ).setResultsName("strings") 
Example #29
Source File: jsLiteralParse.py    From ReadableWebProxy with BSD 3-Clause "New" or "Revised" License 4 votes vote down vote up
def jsParse(inStr):
	# This disaster is a context-free grammar parser for parsing javascript object literals.
	# It needs to be able to handle a lot of the definitional messes you find in in-the-wild
	# javascript object literals.
	# Unfortunately, Javascript is /way/ more tolerant then JSON when it comes to object literals
	# so we can't just parse objects using python's `json` library.

	TRUE = pp.Keyword("true").setParseAction( pp.replaceWith(True) )
	FALSE = pp.Keyword("false").setParseAction( pp.replaceWith(False) )
	NULL = pp.Keyword("null").setParseAction( pp.replaceWith(None) )

	jsonString = pp.quotedString.setParseAction( pp.removeQuotes )
	jsonNumber = pp.Combine( pp.Optional('-') + ( '0' | pp.Word('123456789',pp.nums) ) +
											pp.Optional( '.' + pp.Word(pp.nums) ) +
											pp.Optional( pp.Word('eE',exact=1) + pp.Word(pp.nums+'+-',pp.nums) ) )

	jsonObject   = pp.Forward()
	jsonValue    = pp.Forward()
	jsonDict     = pp.Forward()
	jsonArray    = pp.Forward()
	jsonElements = pp.Forward()

	rawText      = pp.Regex('[a-zA-Z_$][0-9a-zA-Z_$]*')

	commaToNull = pp.Word(',,', exact=1).setParseAction(pp.replaceWith(None))
	jsonElements << pp.ZeroOrMore(commaToNull) + pp.Optional(jsonObject) + pp.ZeroOrMore((pp.Suppress(',') + jsonObject) | commaToNull)

	jsonValue << ( jsonString | jsonNumber | TRUE | FALSE | NULL )


	dictMembers = pp.delimitedList( pp.Group( (rawText | jsonString) + pp.Suppress(':') + (jsonValue | jsonDict | jsonArray)))
	jsonDict << ( pp.Dict( pp.Suppress('{') + pp.Optional(dictMembers) + pp.ZeroOrMore(pp.Suppress(',')) + pp.Suppress('}') ) )
	jsonArray << ( pp.Group(pp.Suppress('[') + pp.Optional(jsonElements) + pp.Suppress(']') ) )
	jsonObject << (jsonValue | jsonDict | jsonArray)

	jsonComment = pp.cppStyleComment
	jsonObject.ignore( jsonComment )

	def convertDict(s, l, toks):

		return dict(toks.asList())

	def convertNumbers(s,l,toks):
		n = toks[0]
		try:
			return int(n)
		except ValueError:
			return float(n)

	jsonNumber.setParseAction(convertNumbers)
	jsonDict.setParseAction(convertDict)

	# jsonObject.setDebug()
	jsonObject.parseString('"inStr"').pop()
	return jsonObject.parseString(inStr).pop()


# Stolen from http://stackoverflow.com/a/12017573/268006 
Example #30
Source File: c_parser.py    From rekall with GNU General Public License v2.0 4 votes vote down vote up
def _type_instance(self):
        """A type declaration.

        The modifiers of a typedef:
                struct s *P[];
                         ^^^^<-    The type instance.
        """
        type_instance = (
            # Function pointer     (*f)(int foobar)
            pyparsing.ZeroOrMore(_STAR)
            + _OPEN_PARENTHESIS
            + pyparsing.Optional(_STAR("function_pointer"))
            + self._identifier()("type_instance_name")
            + _CLOSE_PARENTHESIS
            + parsers.anything_in_parentheses()("function_args")
        ) | (
            # Function object  f(foo bar *)
            pyparsing.ZeroOrMore(_STAR)
            + self._identifier()("type_instance_name")
            + parsers.anything_in_parentheses()("function_args")
        ) | (
            # Simple form: *foo[10];
            pyparsing.ZeroOrMore(_STAR)("type_pointer")
            + self._identifier()("type_instance_name")

            # Possibly array: [] , [][]
            + pyparsing.ZeroOrMore(
                _OPEN_BRACKET
                + pyparsing.SkipTo(_CLOSE_BRACKET)(
                    "brackets_with_expression_inside*")
                + _CLOSE_BRACKET)

            # Bitfields:    int x: 7;
            + pyparsing.Optional(
                _COLON
                + pyparsing.SkipTo(
                    _SEMICOLON | _COMMA)("bitfield")
            )
        )

        return pyparsing.Group(
            type_instance
            + self._maybe_attributes()
        )