Example #1
0
    def parser(self):
        join_type = (pp.Literal("LEFT") | pp.Literal("RIGHT")
                     | pp.Literal("INNER") | pp.Literal("OUTER"))
        node_name = pp.Word(pp.alphas, pp.alphanums + "_$")

        col_name = pp.Word(pp.alphas, pp.alphanums + "_$")
        col_name_list = pp.Group(pp.delimitedList(col_name, delim=","))

        l_brac = pp.Suppress("[")
        r_brac = pp.Suppress("]")

        single_join = (join_type + pp.Suppress("(") + node_name + l_brac +
                       col_name_list + r_brac + pp.Suppress("==>") +
                       node_name + l_brac + col_name_list + r_brac +
                       pp.Suppress(")"))

        single_join.addParseAction(
            lambda x: self._add_join(join_type=x[0],
                                     child_node_name=x[1],
                                     child_cols=x[2],
                                     parent_node_name=x[3],
                                     parent_cols=x[4]))
        join_block = pp.OneOrMore(single_join)
        return join_block
Example #2
0
class TestResultsModifyingParseAction(PyparsingExpressionTestCase):
    def compute_stats_parse_action(t):
        # by the time this parse action is called, parsed numeric words
        # have been converted to ints by a previous parse action, so
        # they can be treated as ints
        t['sum'] = sum(t)
        t['ave'] = sum(t) / len(t)
        t['min'] = min(t)
        t['max'] = max(t)

    tests = [
        PpTestSpec(desc="A parse action that adds new key-values",
                   expr=pp.OneOrMore(
                       pp.pyparsing_common.integer).addParseAction(
                           compute_stats_parse_action),
                   text="27 1 14 22 89",
                   expected_list=[27, 1, 14, 22, 89],
                   expected_dict={
                       'ave': 30.6,
                       'max': 89,
                       'min': 1,
                       'sum': 153
                   }),
    ]
Example #3
0
def _make():
    # Order is important - multi-char expressions need to come before narrow
    # ones.
    parts = []
    for klass in filter_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 filter_rex:
        f = pp.Literal("~%s" % klass.code) + pp.WordEnd() + rex.copy()
        f.setParseAction(klass.make)
        parts.append(f)

    for klass in filter_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)
Example #4
0
    def create_py_parsing_grammar(self):
        # Keep around all whitespace.
        pp.ParserElement.setDefaultWhitespaceChars("")

        def add_element(name: str, value: pp.ParserElement):
            nonlocal self
            if self.debug:
                value.setName(name)
                value.setDebug()
            return value

        # Our grammar is pretty simple. We want to remove all newlines
        # inside quoted strings, to make the quoted strings JSON
        # compliant. So our grammar should skip to the first quote while
        # keeping everything before it as-is, process the quoted string
        # skip to the next quote, and repeat that until the end of the
        # file.

        EOF = add_element("EOF", pp.StringEnd())
        SkipToQuote = add_element("SkipToQuote", pp.SkipTo('"'))
        SkipToEOF = add_element("SkipToEOF", pp.SkipTo(EOF))

        def remove_newlines_and_whitespace_in_quoted_string(tokens):
            first_string = tokens[0]
            replaced_string = re.sub(r"\n[ ]*", " ", first_string)
            return replaced_string

        QuotedString = add_element(
            "QuotedString", pp.QuotedString(quoteChar='"', multiline=True, unquoteResults=False)
        )
        QuotedString.setParseAction(remove_newlines_and_whitespace_in_quoted_string)

        QuotedTerm = add_element("QuotedTerm", pp.Optional(SkipToQuote) + QuotedString)
        Grammar = add_element("Grammar", pp.OneOrMore(QuotedTerm) + SkipToEOF)

        return Grammar
Example #5
0
class Identifiers:
    """
    This class static variables can be used when defining regex view. For ex:
    _PFENotificationStatsTable:
      title: PFE Notification statistics
      key: name
      view: _PFENotificationStatsView

    _PFENotificationStatsView:
      regex:
        value: numbers
        name: words
    """
    printables = pp.OneOrMore(pp.Word(pp.printables))
    numbers = (pp.Word(pp.nums) + pp.Optional(pp.Literal('.') + pp.Word(
        pp.nums))).setParseAction(lambda i: ''.join(i))
    hex_numbers = pp.OneOrMore(pp.Word(pp.nums, min=1)) & pp.OneOrMore(
        pp.Word('abcdefABCDEF', min=1))
    word = pp.Word(pp.alphanums) | pp.Word(pp.alphas)
    words = (pp.OneOrMore(word)).setParseAction(lambda i: ' '.join(i))
    percentage = pp.Word(pp.nums) + pp.Literal('%')
    header_bar = (pp.OneOrMore(pp.Word('-')) | pp.OneOrMore(pp.Word('='))) + \
        pp.StringEnd()
Example #6
0
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
Example #7
0
                               "&" + "*" + "+" + "<" + ">")
pp_digits = "0123456789"
pp_plusorminus = pyparsing.Literal('+') | pyparsing.Literal('-')
pp_int = pyparsing.Combine(
    pyparsing.Optional(pp_plusorminus) + pyparsing.Word(pp_digits))
pp_float = pyparsing.Combine(
    pyparsing.Optional(pp_plusorminus) + pyparsing.Optional(pp_int) + "." +
    pp_int)
pp_eorE = pyparsing.Literal('e') | pyparsing.Literal('E')
pp_floatorint = pp_float | pp_int
pp_e_notation = pyparsing.Combine(pp_floatorint + pp_eorE + pp_int)
pp_number = pp_e_notation | pp_float | pp_int
pp_numberorname = pp_number | pp_param_name
pp_il = pyparsing.Word("il")
pp_choices = pp_param_name + pyparsing.Optional(
    pyparsing.OneOrMore("," + pp_param_name))

pp_cont_param = pp_param_name + "[" + pp_number + "," + pp_number + "]" + \
    "[" + pp_number + "]" + pyparsing.Optional(pp_il)
pp_cat_param = pp_param_name + "{" + pp_choices + "}" + "[" + pp_param_name + "]"
pp_condition = pp_param_name + "|" + pp_param_name + "in" + "{" + pp_choices + "}"
pp_forbidden_clause = "{" + pp_param_name + "=" + pp_numberorname + \
    pyparsing.Optional(pyparsing.OneOrMore("," + pp_param_name + "=" + pp_numberorname)) + "}"


def build_categorical(param):
    cat_template = "%s {%s} [%s]"
    return cat_template % (param.name, ", ".join(
        [str(value) for value in param.choices]), str(param.default_value))

Example #8
0
print '--------------'
ni = pp.CaselessLiteral('Ni')
print ni.parseString('Ni')
print ni.parseString('NI')
print ni.parseString('nI')
print ni.parseString('ni')

# OneOrMore
print '--------------'
name = pp.Word(pp.alphas)
number = pp.Word(pp.nums)
nameNoOrBang = pp.Or([name, number, pp.Literal('!')])
print nameNoOrBang.parseString('Brian')
print nameNoOrBang.parseString('73')
print nameNoOrBang.parseString('!')
several = pp.OneOrMore(nameNoOrBang)
print several.parseString('18 years of total silence!')
print several.parseString('18 years of total silence?')

# body exat exclude
print '--------------'
name = pp.Word('abcdef')
print name.parseString('fadedglory')
pyName = pp.Word(pp.alphas + '_', bodyChars=pp.alphanums + '_')
print pyName.parseString('_crunchyFrog13')
name4 = pp.Word(pp.alphas, exact=4)
print name4.parseString('Whizzo')
noXY = pp.Word(pp.alphas, excludeChars='xy')
print noXY.parseString('Sussex')

# Optional is like OneOrMore
    ("1d6h3l3", P.ParseException),
    ("d6h+1", P.ParseException),
]

# temporary modifier
# temporary modifier
temp_modifier = dice_bonus.setResultsName('temp_modifier')

# verb phrases
# verb phrases
o = L('[')
t = L(']')
wordchars = P.alphanums + string.punctuation.replace(']', '')

v_word = P.Word(wordchars)
v_words = P.OneOrMore(v_word).setResultsName('verbs')

v_word_nonterminal = v_word + P.NotAny(t)
v_words_nonterminal = P.OneOrMore(v_word_nonterminal).setResultsName('verbs')

# FIXME - [d20 1d10] should be an error
v_content = P.Optional(v_words_nonterminal) + (temp_modifier | dice) | v_words
verb_phrase = Sup(o) + v_content + Sup(t)
verb_phrase = verb_phrase.setResultsName('verb_phrase')

_test_verb_phrases = [
    ("[]", P.ParseException),
    ("[star]", "['star']"),
    ("[rock star]", "['rock', 'star']"),
    ("[woo 1d20+1]", "['woo', 1, 20, 1]"),
    ("[woo +2]", "['woo', 2]"),
Example #10
0
# It creates a couple of the form ('DEFFACTS_CONSTRUCT', list of the elements of the fact).
DEFFACTS_CONSTRUCT.setParseAction(lambda s, l, t: ('DEFFACTS_CONSTRUCT', [x for x in t]))

# --- Definition of the constructs for the declaration of the rules.

# Defines the name of a rule.
RULE_NAME = SYMBOL.copy()

# Defines an integer expression.
INTEGER_EXPRESSION = EXPRESSION

# Defines the declaration of the salience of a rule.
RULE_PROPERTY = OB + pp.Keyword('salience') + INTEGER_EXPRESSION + CB

# Defines the declaration of a rule.
DECLARATION = OB + pp.Group(pp.Keyword('declare').suppress() + pp.OneOrMore(RULE_PROPERTY)) + CB

# Initializes a condition in the left part of a rule.
CONDITIONAL_ELEMENT = pp.Forward()

# Defines a term for a constraint in the right part of a rule.
RHS_TERM = CONSTANT | VARIABLE | FUNCTION_CALL

# Defines a term for a constraint in the left part of a rule.
LHS_TERM = CONSTANT | GLOBAL_VARIABLE | SINGLEFIELD_VARIABLE

# Defines a constraint in the right part of a rule.
RHS_CONSTRAINT = RHS_TERM

# Defines a constraint in the left part of a rule.
LHS_CONSTRAINT = LHS_TERM
Example #11
0
def parse_file(file_name):

    number = pp.Word(pp.nums)
    identifier = pp.Word(pp.alphas + "_", pp.alphanums + "_")

    lbrace = pp.Literal('{').suppress()
    rbrace = pp.Literal('}').suppress()
    cls = pp.Keyword('class')
    colon = pp.Literal(":")
    semi = pp.Literal(";").suppress()
    langle = pp.Literal("<")
    rangle = pp.Literal(">")
    equals = pp.Literal("=")
    comma = pp.Literal(",")
    lparen = pp.Literal("(")
    rparen = pp.Literal(")")
    lbrack = pp.Literal("[")
    rbrack = pp.Literal("]")
    mins = pp.Literal("-")
    struct = pp.Keyword('struct')
    template = pp.Keyword('template')
    final = pp.Keyword('final')("final")
    stub = pp.Keyword('stub')("stub")
    with_colon = pp.Word(pp.alphanums + "_" + ":")
    btype = with_colon
    type = pp.Forward()
    nestedParens = pp.nestedExpr('<', '>')

    tmpl = pp.Group(
        btype("template_name") + langle.suppress() +
        pp.Group(pp.delimitedList(type)) + rangle.suppress())
    type << (tmpl | btype)
    enum_lit = pp.Keyword('enum')
    enum_class = pp.Group(enum_lit + cls)
    ns = pp.Keyword("namespace")

    enum_init = equals.suppress() + pp.Optional(mins) + number
    enum_value = pp.Group(identifier + pp.Optional(enum_init))
    enum_values = pp.Group(lbrace + pp.delimitedList(enum_value) +
                           pp.Optional(comma) + rbrace)
    content = pp.Forward()

    member_name = pp.Combine(
        pp.Group(identifier + pp.Optional(lparen + rparen)))
    attrib = pp.Group(lbrack.suppress() + lbrack.suppress() + pp.SkipTo(']') +
                      rbrack.suppress() + rbrack.suppress())
    opt_attribute = pp.Optional(attrib)("attribute")
    namespace = pp.Group(
        ns("type") + identifier("name") + lbrace +
        pp.Group(pp.OneOrMore(content))("content") + rbrace)
    enum = pp.Group(
        enum_class("type") + identifier("name") + colon.suppress() +
        identifier("underline_type") + enum_values("enum_values") +
        pp.Optional(semi).suppress())
    default_value = equals.suppress() + pp.SkipTo(';')
    class_member = pp.Group(
        type("type") + member_name("name") + opt_attribute +
        pp.Optional(default_value)("default") + semi.suppress())("member")
    template_param = pp.Group(identifier("type") + identifier("name"))
    template_def = pp.Group(template + langle +
                            pp.Group(pp.delimitedList(template_param))
                            ("params") + rangle)
    class_content = pp.Forward()
    class_def = pp.Group(
        pp.Optional(template_def)("template") + (cls | struct)("type") +
        with_colon("name") + pp.Optional(final) + pp.Optional(stub) +
        opt_attribute + lbrace +
        pp.Group(pp.ZeroOrMore(class_content))("members") + rbrace +
        pp.Optional(semi))
    content << (enum | class_def | namespace)
    class_content << (enum | class_def | class_member)
    for varname in "enum class_def class_member content namespace template_def".split(
    ):
        locals()[varname].setName(varname)
    rt = pp.OneOrMore(content)
    singleLineComment = "//" + pp.restOfLine
    rt.ignore(singleLineComment)
    rt.ignore(pp.cStyleComment)
    return rt.parseFile(file_name, parseAll=True)
Example #12
0
    Group(Optional(PARENS(pp.delimitedList(tname))))('bases') -
    DOCSTR_BLOCK(nested_decl))
constdef = G(K('const') - _cnamedef)
enumdef = G(K('enum') - cname + Optional(S('with') - BLOCK(crename)))
capsule_def = G(K('capsule') - cname)
stmeth_stmt = G(K('staticmethods') - S('from') + ASTRING - BLOCK(funcdef))

_decl = classdef | enumdef | constdef
global_decl = (K('pass') | funcdef | capsule_def | _decl | interface_stmt
               | stmeth_stmt)
nested_decl <<= vardef | methoddef | _decl | K('pass') | implementsdef

import_stmt = G(S('from') + pp.WordEnd() + dotted_name - K('import') + NAME)
# Put 'import' first.
import_stmt.setParseAction(lambda t: [t[1], t[2], t[0], t[3]])
ns_stmt = G(K('namespace') - ASTRING + BLOCK(global_decl))
from_stmt = G(K('from') + QSTRING + BLOCK(global_decl | ns_stmt))
include_stmt = G(
    Tag('include') + S('from') + QSTRING + S('import') - S('*') +
    Optional(S('as') - NAME))
typedef_stmt = G(K('type') - NAME + S('=') + type)
use_stmt = G(K('use') - crename)

stmt = Group(NEWLINE | from_stmt | import_stmt | include_stmt | typedef_stmt
             | use_stmt | interface_stmt)

# Top-level parser.
Clif = pp.OneOrMore(stmt)  # pylint: disable=invalid-name
Clif.ignore(pp.pythonStyleComment)
Clif.validate()
Example #13
0
    def parse_components(self):
        EOL = pp.LineEnd().suppress()
        linebreak = pp.Suppress(";" + pp.LineEnd())
        identifier = pp.Word(
            pp.alphanums +
            '._“!<>/[]$#$%&‘*+,/:<=>?@[\]^_`{|}~')  # CONFLICT with '();'
        number = pp.pyparsing_common.number
        word = pp.Word(pp.alphas)
        LPAR = pp.Suppress('(')
        RPAR = pp.Suppress(')')
        ORIENT = (pp.Keyword('N')
                  | pp.Keyword('S')
                  | pp.Keyword('E')
                  | pp.Keyword('W')
                  | pp.Keyword('FN')
                  | pp.Keyword('FS')
                  | pp.Keyword('FE')
                  | pp.Keyword('FW'))
        pt = LPAR + pp.OneOrMore(number
                                 | pp.Keyword('*')) + RPAR  # pair of x,y
        self.events[0].wait()  # Wait for event[0] to finish
        components_id = pp.Keyword('COMPONENTS')
        end_components_id = pp.Keyword("END COMPONENTS").suppress()
        begin_comp = pp.Suppress(pp.Keyword('-'))
        ws_comp = pp.Suppress(
            pp.Keyword('+'))  # parameter division in components

        # compName
        compName = (identifier('comp_name') +
                    identifier('cell')).setResultsName('compName')

        # EEQMASTER
        EEQMASTER = (ws_comp + identifier + identifier('EEQMASTER'))

        # SOURCE
        SOURCE = (ws_comp + pp.Suppress(pp.Keyword('SOURCE')) +
                  identifier('source_type')).setResultsName('SOURCE')

        # PLACEMENT
        PLACEMENT_ids = (pp.Keyword('FIXED')
                         | pp.Keyword('COVER')
                         | pp.Keyword('PLACED')
                         | pp.Keyword('UNPLACED'))
        PLACEMENT_coord = (LPAR + number('placement_x') +
                           number('placement_y') + RPAR)
        PLACEMENT = (ws_comp + PLACEMENT_ids +
                     pp.Optional(PLACEMENT_coord + ORIENT('orientation'))
                     ).setResultsName('PLACEMENT')

        # MASKSHIFT
        MASKSHIFT = (ws_comp + pp.Suppress(pp.Keyword('MASKSHIFT')) +
                     number('shiftLayerMasks')).setResultsName('MASKSHIFT')

        # HALO
        HALO = (ws_comp + pp.Keyword('HALO') +
                pp.Optional(pp.Keyword('SOFT')) + number('haloL') +
                number('haloB') + number('haloR') +
                number('haloT')).setResultsName('HALO')

        # ROUTEHALO
        ROUTEHALO = (ws_comp + pp.Keyword('ROUTEHALO') + number('rhaloDist') +
                     identifier('rhaloMinLayer') +
                     identifier('rhaloMaxLayer')).setResultsName('ROUTEHALO')

        # WEIGHT
        WEIGHT = (ws_comp + pp.Keyword('WEIGHT') +
                  number('weight')).setResultsName('WEIGHT')

        # REGION
        REGION = (ws_comp + pp.Keyword('REGION') +
                  identifier('region')).setResultsName('REGION')

        # PROPERTY
        PROPERTY = (ws_comp + pp.Keyword('PROPERTY') + identifier('propName') +
                    identifier('propVal')).setResultsName('PROPERTY')

        subcomponent = pp.Group(begin_comp + compName +
                                pp.Optional(EEQMASTER) + pp.Optional(SOURCE) +
                                pp.Optional(PLACEMENT) +
                                pp.Optional(MASKSHIFT) + pp.Optional(HALO) +
                                pp.Optional(ROUTEHALO) + pp.Optional(WEIGHT) +
                                pp.Optional(REGION) + pp.ZeroOrMore(PROPERTY) +
                                linebreak).setResultsName('subcomponents',
                                                          listAllMatches=True)

        components = pp.Group(
            pp.Suppress(components_id) + number('numComps') + linebreak +
            pp.OneOrMore(subcomponent) +
            pp.Suppress(end_components_id)).setResultsName('COMPONENTS')

        return components
Example #14
0
 def _makeSVGGrammar(self):
     """
     Creates an SVG path parsing grammar
     """
  
     # pyparsing grammar
     comma = PYP.Literal(",").suppress() # supress removes the ',' when captured
     dot = PYP.Literal(".")
     coord = PYP.Regex(r"-?\d+(\.\d*)?([Ee][+-]?\d+)?") 
     one_coord = PYP.Group(coord)
     xycoords = PYP.Group(coord + PYP.Optional(comma) + coord)
     two_xycoords = xycoords + PYP.Optional(comma) + xycoords
     three_xycoords = xycoords + PYP.Optional(comma) + xycoords + PYP.Optional(comma)+xycoords
     
     # TODO optimise this; there has to be a more efficient way to describe this
     c_M = PYP.Literal('M') + PYP.OneOrMore(xycoords)
     c_m = PYP.Literal('m') + PYP.OneOrMore(xycoords)
  
     c_C = PYP.Literal('C') + PYP.OneOrMore(three_xycoords)
     c_c = PYP.Literal('c') + PYP.OneOrMore(three_xycoords)
  
     c_Q = PYP.Literal('Q') + PYP.OneOrMore(two_xycoords)
     c_q = PYP.Literal('q') + PYP.OneOrMore(two_xycoords)
  
     c_T = PYP.Literal('T') + PYP.OneOrMore(xycoords)
     c_t = PYP.Literal('t') + PYP.OneOrMore(xycoords)
  
     c_L = PYP.Literal('L') + PYP.OneOrMore(xycoords)
     c_l = PYP.Literal('l') + PYP.OneOrMore(xycoords)
  
     c_V = PYP.Literal('V') + PYP.OneOrMore(one_coord)
     c_v = PYP.Literal('v') + PYP.OneOrMore(one_coord)
  
     c_H = PYP.Literal('H') + PYP.OneOrMore(one_coord)
     c_h = PYP.Literal('h') + PYP.OneOrMore(one_coord)
  
     c_S = PYP.Literal('S') + PYP.OneOrMore(two_xycoords)
     c_s = PYP.Literal('s') + PYP.OneOrMore(two_xycoords)
  
     c_z = PYP.Literal('z')
     c_Z = PYP.Literal('Z')
     
     path_cmd = c_M | c_m | c_C | c_c | c_Q | c_q | c_T | c_t | c_L | c_l | c_V | c_v | c_H | c_h | c_S | c_s | c_Z | c_z
  
     return PYP.OneOrMore(PYP.Group(path_cmd))
Example #15
0
    "thirty-four":34, "thirty-five":35, "thirty-six":36, "thirty-seven":37,
    "thirty-eight":38, "thirty-nine":39, "forty":50, "forty-one":41,
    "forty-two":42, "forty-three":43, "forty-four":44, "forty-five":45,
    "forty-six":46, "forty-seven":47, "forty-eight":48, "forty-nine":49,
    "fifty":50 }

# Parser primitives.
# We define them up here because they'll be re-used over and over.
help_command = pp.CaselessLiteral("help")
get_command = pp.Optional(pp.CaselessLiteral("get"))
top_command = pp.CaselessLiteral("top")
results_count = (pp.Word(pp.nums) |
                 pp.Word(pp.alphas + "-")).setResultsName("count")
hitsfor_command = pp.CaselessLiteral("hits for")
search_term = pp.Word(pp.alphanums + "_,'-")
search_terms = pp.OneOrMore(search_term)
send_command = (pp.CaselessLiteral("send") | pp.CaselessLiteral("e-mail") |
                pp.CaselessLiteral("email") | pp.CaselessLiteral("mail"))
me = pp.CaselessLiteral("me")
email = pp.Regex(r"(?P<user>[A-Za-z0-9._%+-]+)@(?P<hostname>[A-Za-z0-9.-]+)\.(?P<domain>[A-Za-z]{2,4})")
destination = pp.Optional(me) + pp.Optional(email).setResultsName("dest")

# search <engine or shortcut> (for) <search terms>
search_command = pp.CaselessLiteral("search")
shortcut_command = "!" + pp.Word(pp.alphanums).setResultsName("shortcode")
for_command = pp.Optional(pp.CaselessLiteral("for"))

# (list) (search) engines
list_command = pp.CaselessLiteral("list")
engines_command = pp.CaselessLiteral("engines")
Example #16
0
    def __repr__(self):
        print(self.devices)
        return ''


# 构造ebnf解析器
integer = pp.Word(pp.nums)
hex = pp.Word(pp.nums + 'abcdef')
path = pp.Word(pp.alphanums + '/')
key = pp.Word(pp.alphanums)

info_name = pp.Suppress('name:') + pp.QuotedString('"')
info_value = pp.Suppress('(') + hex + pp.Suppress(')')

info_event_key = 'KEY' + info_value + pp.Suppress(':') + pp.Group(
    pp.OneOrMore(hex))
info_event_sw = 'SW' + info_value + pp.Suppress(':') + pp.OneOrMore(hex)
info_event_abs_value = key + integer + pp.Suppress(pp.Optional(','))
info_event_abs_values = hex + pp.Suppress(':') + pp.Group(
    pp.OneOrMore(pp.Group(info_event_abs_value)))
info_event_abs = 'ABS' + info_value + pp.Suppress(':') + pp.Group(
    pp.OneOrMore(pp.Group(info_event_abs_values)))
info_event = info_event_key | info_event_sw | info_event_abs
info_events = pp.Suppress('events:') + pp.Group(
    pp.OneOrMore(pp.Group(info_event)))

input_prop_value = '<none>' | pp.Word(pp.string.ascii_uppercase + '_')
input_props = 'input props:' + input_prop_value

infos = info_name + info_events + pp.Group(input_props)
device = pp.Suppress('add device') + integer + pp.Suppress(':') + path + infos
Example #17
0
number.setParseAction(lambda r: int(r[0]))
unklen = pp.Literal('*')
length = number | unklen
unkbit = pp.oneOf(['-'])
fixbyte = pp.Regex(r'{[0-9a-fA-F][0-9a-fA-F]}').setParseAction(
    lambda r: Bits(int(r[0][1:3], 16), 8))
fixed = fixbyte | fixbit | unkbit
option = pp.oneOf(['.', '~', '#', '='])
symbol = pp.Regex(r'[A-Za-z_][A-Za-z0-9_]*')
location = pp.Suppress('(') + length + pp.Suppress(')')
directive = pp.Group(
    pp.Optional(option, default='') + symbol +
    pp.Optional(location, default=1))
speclen = pp.Group(length + pp.Optional(indxdir, default='<'))
specformat = pp.Group(
    pp.Suppress('[') + pp.OneOrMore(directive | fixed) + pp.Suppress(']'))
specoption = pp.Optional(pp.Literal('+').setParseAction(lambda r: True),
                         default=False)
specdecode = speclen + specformat + specoption


def ispec_register(x, module):
    F = []
    try:
        S = module.ISPECS
    except AttributeError:
        logger.error(
            "spec modules must declare ISPECS=[] before @ispec decorators")
        raise AttributeError
    logger.progress(len(S), pfx='loading %s instructions ' % module.__name__)
    f = x.fixed()
Example #18
0
    def parse_pins(self):
        EOL = pp.LineEnd().suppress()
        linebreak = pp.Suppress(";" + pp.LineEnd())
        identifier = pp.Word(
            pp.alphanums +
            '._“!<>/[]$#$%&‘*+,/:<=>?@[\]^_`{|}~')  # CONFLICT with '();'
        number = pp.pyparsing_common.number
        word = pp.Word(pp.alphas)
        LPAR = pp.Suppress('(')
        RPAR = pp.Suppress(')')
        ORIENT = (pp.Keyword('N')
                  | pp.Keyword('S')
                  | pp.Keyword('E')
                  | pp.Keyword('W')
                  | pp.Keyword('FN')
                  | pp.Keyword('FS')
                  | pp.Keyword('FE')
                  | pp.Keyword('FW'))
        pt = LPAR + pp.OneOrMore(number
                                 | pp.Keyword('*')) + RPAR  # pair of x,y
        pins_id = pp.Keyword('PINS')
        end_pins_id = pp.Keyword("END PINS").suppress()
        begin_pin = pp.Keyword('-')
        ws_pin = pp.Suppress(pp.Keyword('+'))  # parameter division in pins

        # pinName
        pinName = (identifier('pin_name') + ws_pin + pp.Keyword('NET') +
                   identifier('netName'))

        # SPECIAL
        SPECIAL = (ws_pin + pp.Keyword('SPECIAL')('SPECIAL'))

        # DIRECTION
        DIRECTION_ids = (pp.Keyword('INPUT')
                         | pp.Keyword('OUTPUT')
                         | pp.Keyword('INOUT')
                         | pp.Keyword('FEEDTHRU'))

        DIRECTION = (ws_pin + pp.Keyword('DIRECTION') +
                     pp.OneOrMore(DIRECTION_ids('DIRECTION')))

        # NETEXPR
        NETEXPR = pp.Group(ws_pin + pp.Keyword('NETEXPR') + pp.OneOrMore(word)
                           ('net_expr')).setResultsName('NETEXPR')

        # SUPPLYSENSITIVITY
        SUPPLYSENSITIVITY = pp.Group(ws_pin + pp.Keyword('SUPPLYSENSITIVITY') +
                                     identifier('supply_sensitivity')
                                     ).setResultsName('SUPPLYSENSITIVITY')

        # GROUNDSENSITIVITY
        GROUNDSENSITIVITY = pp.Group(ws_pin + pp.Keyword('GROUNDSENSITIVITY') +
                                     identifier('ground_sensitivity')
                                     ).setResultsName('GROUNDSENSITIVITY')

        # USE
        USE_ids = (pp.Keyword('SIGNAL')
                   | pp.Keyword('POWER')
                   | pp.Keyword('GROUND')
                   | pp.Keyword('CLOCK')
                   | pp.Keyword('TIEOFF')
                   | pp.Keyword('ANALOG')
                   | pp.Keyword('SCAN')
                   | pp.Keyword('RESET'))

        USE = (ws_pin + pp.Keyword('USE') + pp.OneOrMore(USE_ids('USE')))

        # Common element to be used in the following subsections
        LAYER_layerName = pp.Keyword('LAYER') + identifier('layerName')

        # ANTENNAPINPARTIALMETALAREA
        ANTENNAPINPARTIALMETALAREA = pp.Group(
            ws_pin + pp.Keyword('ANTENNAPINPARTIALMETALAREA') + number +
            pp.Optional(LAYER_layerName)).setResultsName(
                'ANTENNAPINPARTIALMETALAREA')

        # ANTENNAPINPARTIALMETALSIDEAREA
        ANTENNAPINPARTIALMETALSIDEAREA = pp.Group(
            ws_pin + pp.Keyword('ANTENNAPINPARTIALMETALSIDEAREA') + number +
            pp.Optional(LAYER_layerName)).setResultsName(
                'ANTENNAPINPARTIALMETALSIDEAREA')

        # ANTENNAPINPARTIALCUTAREA
        ANTENNAPINPARTIALCUTAREA = pp.Group(
            ws_pin + pp.Keyword('ANTENNAPINPARTIALCUTAREA') + number +
            pp.Optional(LAYER_layerName)).setResultsName(
                'ANTENNAPINPARTIALCUTAREA')

        # ANTENNAPINDIFFAREA
        ANTENNAPINDIFFAREA = pp.Group(
            ws_pin + pp.Keyword('ANTENNAPINDIFFAREA') + number +
            pp.Optional(LAYER_layerName)).setResultsName('ANTENNAPINDIFFAREA')

        # ANTENNAMODEL
        ANTENNAMODEL_ids = (pp.Keyword('OXIDE1')
                            | pp.Keyword('OXIDE2')
                            | pp.Keyword('OXIDE3')
                            | pp.Keyword('OXIDE4'))

        ANTENNAMODEL = pp.Group(ws_pin + pp.Keyword('ANTENNAMODEL') +
                                ANTENNAMODEL_ids).setResultsName(
                                    'ANTENNAMODEL')

        # ANTENNAPINGATEAREA
        ANTENNAPINGATEAREA = pp.Group(
            ws_pin + pp.Keyword('ANTENNAPINGATEAREA') + number +
            pp.Optional(LAYER_layerName)).setResultsName('ANTENNAPINGATEAREA')

        # ANTENNAPINMAXAREACAR
        ANTENNAPINMAXAREACAR = pp.Group(
            ws_pin + pp.Keyword('ANTENNAPINMAXAREACAR') + number +
            LAYER_layerName).setResultsName('ANTENNAPINMAXAREACAR')

        # ANTENNAPINMAXSIDEAREACAR
        ANTENNAPINMAXSIDEAREACAR = pp.Group(
            ws_pin + pp.Keyword('ANTENNAPINMAXSIDEAREACAR') + number +
            LAYER_layerName).setResultsName('ANTENNAPINMAXSIDEAREACAR')

        # ANTENNAPINMAXCUTCAR
        ANTENNAPINMAXCUTCAR = pp.Group(
            ws_pin + pp.Keyword('ANTENNAPINMAXCUTCAR') + number +
            LAYER_layerName).setResultsName('ANTENNAPINMAXCUTCAR')

        # PLACEMENT_PINS
        PORT = (ws_pin + pp.Keyword('PORT')('PORT'))

        MASK = pp.Group(pp.Suppress(pp.Keyword('MASK')) +
                        number('maskNum')).setResultsName('MASK')

        SPACING = pp.Group(
            pp.Suppress(pp.Keyword('SPACING')) +
            number('minSpacing')).setResultsName('SPACING')

        DESIGNRULEWIDTH = pp.Group(
            pp.Suppress(pp.Keyword('DESIGNRULEWIDTH')) +
            number('effectiveWidth')).setResultsName('DESIGNRULEWIDTH')

        LAYER = pp.Group(ws_pin + pp.Suppress(pp.Keyword('LAYER')) +
                         identifier('layerName') + pp.Optional(MASK) +
                         pp.Optional(SPACING | DESIGNRULEWIDTH) +
                         pp.OneOrMore(pp.Group(pt))('coord')).setResultsName(
                             'LAYER')

        POLYGON = pp.Group(ws_pin + pp.Suppress(pp.Keyword('POLYGON')) +
                           identifier('layerName') + pp.Optional(MASK) +
                           pp.Optional(SPACING | DESIGNRULEWIDTH) +
                           pp.OneOrMore(pp.Group(pt))('coord')).setResultsName(
                               'POLYGON')

        VIA = pp.Group(ws_pin + pp.Suppress(pp.Keyword('VIA')) +
                       identifier('viaName') + pp.Optional(MASK) +
                       pp.Group(pt)('coord')).setResultsName('VIA')

        COVER = pp.Group(ws_pin + pp.Suppress(pp.Keyword('COVER')) +
                         pp.Group(pt)('coord') +
                         ORIENT('orient')).setResultsName('COVER')

        FIXED = pp.Group(ws_pin + pp.Suppress(pp.Keyword('FIXED')) +
                         pp.Group(pt)('coord') +
                         ORIENT('orient')).setResultsName('FIXED')

        PLACED = pp.Group(ws_pin + pp.Suppress(pp.Keyword('PLACED')) +
                          pp.Group(pt)('coord') +
                          ORIENT('orient')).setResultsName('PLACED')

        PLACEMENT_PINS = (PORT
                          | pp.Group(LAYER | POLYGON | VIA)
                          | pp.Group(COVER | FIXED | PLACED))

        pin = pp.Group(
            pp.Suppress(begin_pin) + pinName + pp.Optional(SPECIAL) +
            pp.Optional(DIRECTION) + pp.Optional(NETEXPR) +
            pp.Optional(SUPPLYSENSITIVITY) + pp.Optional(GROUNDSENSITIVITY) +
            pp.Optional(USE) + pp.ZeroOrMore(ANTENNAPINPARTIALMETALAREA) +
            pp.ZeroOrMore(ANTENNAPINPARTIALMETALSIDEAREA) +
            pp.ZeroOrMore(ANTENNAPINPARTIALCUTAREA) +
            pp.ZeroOrMore(ANTENNAPINDIFFAREA) + pp.ZeroOrMore(ANTENNAMODEL) +
            pp.ZeroOrMore(ANTENNAPINGATEAREA) +
            pp.ZeroOrMore(ANTENNAPINMAXAREACAR) +
            pp.ZeroOrMore(ANTENNAPINMAXSIDEAREACAR) +
            pp.ZeroOrMore(ANTENNAPINMAXCUTCAR) +
            pp.ZeroOrMore(PLACEMENT_PINS)('PLACEMENT') +
            linebreak).setResultsName('pin', listAllMatches=True)

        pins = pp.Group(
            pp.Suppress(pins_id) + number('numPins') + linebreak +
            pp.OneOrMore(pin) +
            pp.Suppress(end_pins_id)).setResultsName('PINS')

        return pins
Example #19
0
# subject pyparsing definition
#
# Copyright (C) 2016 Intel Corporation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

# NOTE:This is an oversimplified syntax of the mbox's summary

import pyparsing
import common

target = pyparsing.OneOrMore(
    pyparsing.Word(pyparsing.printables.replace(':', '')))
summary = pyparsing.OneOrMore(pyparsing.Word(pyparsing.printables))
shortlog = common.start + target + common.colon + summary + common.end
Example #20
0
    def parse_nets(self):
        EOL = pp.LineEnd().suppress()
        linebreak = pp.Suppress(";" + pp.LineEnd())
        identifier = pp.Word(
            pp.alphanums +
            '._“!<>/[]$#$%&‘*+,/:<=>?@[\]^_`{|}~')  # CONFLICT with '();'
        number = pp.pyparsing_common.number
        word = pp.Word(pp.alphas)
        LPAR = pp.Suppress('(')
        RPAR = pp.Suppress(')')
        ORIENT = (pp.Keyword('N')
                  | pp.Keyword('S')
                  | pp.Keyword('E')
                  | pp.Keyword('W')
                  | pp.Keyword('FN')
                  | pp.Keyword('FS')
                  | pp.Keyword('FE')
                  | pp.Keyword('FW'))
        pt = LPAR + pp.OneOrMore(number
                                 | pp.Keyword('*')) + RPAR  # pair of x,y
        nets_id = pp.Keyword('NETS')
        end_nets_id = pp.Keyword("END NETS").suppress()
        begin_net = pp.Keyword('-')
        ws_net = pp.Suppress(pp.Keyword('+'))  # parameter division in NETS

        # netName
        netName_1 = pp.Group(
            LPAR + identifier('compName') + identifier('pinName') +
            pp.Optional(ws_net + pp.Keyword('SYNTHESIZED'))('SYNTHESIZED') +
            RPAR).setResultsName('netName')

        netName_2 = pp.Group(
            pp.Keyword('MUSTJOIN') + LPAR + identifier('compName') +
            identifier('pinName') + RPAR).setResultsName('MUSTJOIN')

        netName = (
            identifier('netName') +
            pp.OneOrMore(netName_1 | netName_2)).setResultsName('netName')

        # SHIELDNET
        SHIELDNET = pp.Group(ws_net + pp.Keyword('SHIELDNET') +
                             identifier('shieldNetName')).setResultsName(
                                 'SHIELDNET')

        # VPIN
        VPIN_PLACEMENT_ids = (pp.Keyword('PLACED')
                              | pp.Keyword('FIXED')
                              | pp.Keyword('COVER'))

        VPIN_PLACEMENT = (VPIN_PLACEMENT_ids('PLACEMENT') +
                          pp.Group(pt)('pt') + pp.ZeroOrMore(word('orient')))

        VPIN_LAYER = pp.Keyword('LAYER') + identifier('layerName')

        VPIN = pp.Group(ws_net + pp.Keyword('VPIN') + identifier('vpinName') +
                        pp.Optional(VPIN_LAYER) + pp.Group(pt)('pt1') +
                        pp.Group(pt)('pt2') +
                        pp.Optional(pp.Group(VPIN_PLACEMENT)('PLACEMENT')))(
                            'VPIN')

        # routingPoints (used by regularWiring)
        MASK_id = pp.Keyword('MASK')('MASK')
        RECT_id = pp.Keyword('RECT')('RECT')
        VIRTUAL_id = pp.Keyword('VIRTUAL')('VIRTUAL')

        routingPoints_1 = (pp.Optional(MASK_id + number('maskNum')) +
                           pp.Group(pt))

        routingPoints_2 = (pp.Optional(MASK_id + number('viaMaskNum')) +
                           pp.NotAny(pp.Keyword('NEW') | pp.Keyword('RECT')) +
                           identifier('viaName') +
                           pp.Optional(ORIENT('orient')))

        routingPoints_3 = (pp.Optional(MASK_id + number('maskNum')) + RECT_id +
                           pp.Group(pt))

        routingPoints_4 = (VIRTUAL_id + pp.Group(pt))

        routingPoints = (pp.Group(pt) + pp.OneOrMore(routingPoints_1
                                                     | routingPoints_2
                                                     | routingPoints_3
                                                     | routingPoints_4))

        # regularWiring
        regularWiring_ids = (pp.Keyword('COVER')
                             | pp.Keyword('FIXED')
                             | pp.Keyword('ROUTED')
                             | pp.Keyword('NOSHIELD'))

        TAPER_RULE = ((pp.Keyword('TAPER') | pp.Keyword('TAPERRULE')) +
                      identifier('ruleName'))

        STYLE = (pp.Keyword('STYLE') + identifier('layerName') +
                 pp.OneOrMore(pt))

        regularWiring_Head = pp.Group(
            regularWiring_ids('WIRING_id') + identifier('layerName') +
            pp.Optional(TAPER_RULE)('TAPER_RULE') +
            pp.Optional(STYLE)('STYLE') +
            pp.OneOrMore(routingPoints)('routingPoints'))

        NEW_WIRING = pp.Group(
            pp.Keyword('NEW')('WIRING_id') + identifier('layerName') +
            pp.Optional(TAPER_RULE)('TAPER_RULE') +
            pp.Optional(STYLE)('STYLE') +
            pp.OneOrMore(routingPoints)('routingPoints'))

        regularWiring = pp.Group(
            ws_net + pp.Group(regularWiring_Head)('WIRING_Head') +
            pp.Group(pp.ZeroOrMore(NEW_WIRING))('NEW_WIRING'))('WIRING')

        # SUBNET
        SUBNET_regularWiring = pp.Group(
            pp.Group(regularWiring_Head)('WIRING_Head') +
            pp.Group(pp.ZeroOrMore(NEW_WIRING))('NEW_WIRING'))('WIRING')

        SUBNET_NONDEFAULTRULE = (pp.Keyword('NONDEFAULTRULE') +
                                 identifier('NONDEFAULTRULE_ruleName'))

        SUBNET_pin_type = (pp.Keyword('VPIN')('VPIN')
                           | pp.Keyword('PIN')('PIN')
                           | identifier('compName'))

        SUBNET = pp.Group(ws_net + pp.Keyword('SUBNET') +
                          identifier('subnetName') +
                          pp.ZeroOrMore(LPAR + SUBNET_pin_type +
                                        identifier('pinName') + RPAR) +
                          pp.Optional(SUBNET_NONDEFAULTRULE) +
                          pp.ZeroOrMore(SUBNET_regularWiring))('SUBNET')

        # XTALK
        XTALK = (ws_net + pp.Keyword('XTALK') + number('XTALK_class'))

        # NONDEFAULTRULE
        NONDEFAULTRULE = (ws_net + pp.Keyword('NONDEFAULTRULE') +
                          identifier('NONDEFAULTRULE_ruleName'))

        # SOURCE
        SOURCE = (ws_net + pp.Keyword('SOURCE') +
                  (pp.Keyword('DIST')
                   | pp.Keyword('NETLIST')
                   | pp.Keyword('TEST')
                   | pp.Keyword('TIMING')
                   | pp.Keyword('USER'))('SOURCE'))

        # FIXEDBUMP
        FIXEDBUMP = (ws_net + pp.Keyword('FIXEDBUMP')('FIXEDBUMP'))

        # FREQUENCY
        FREQUENCY = (ws_net + pp.Keyword('FREQUENCY') + number('FREQUENCY'))

        # ORIGINAL
        ORIGINAL = (ws_net + pp.Keyword('ORIGINAL') +
                    identifier('ORIGINAL_netName'))

        # USE > USE_ids
        USE_ids = (pp.Keyword('ANALOG')
                   | pp.Keyword('CLOCK')
                   | pp.Keyword('GROUND')
                   | pp.Keyword('POWER')
                   | pp.Keyword('RESET')
                   | pp.Keyword('SCAN')
                   | pp.Keyword('SIGNAL')
                   | pp.Keyword('TIEOFF'))

        # USE
        USE = ws_net + pp.Keyword('USE') + USE_ids('USE')

        # PATTERN
        PATTERN_ids = (pp.Keyword('BALANCED')
                       | pp.Keyword('STEINER')
                       | pp.Keyword('TRUNK')
                       | pp.Keyword('WIREDLOGIC'))

        PATTERN = (ws_net + pp.Keyword('PATTERN') + PATTERN_ids('PATTERN'))

        # ESTCAP
        ESTCAP = (ws_net + pp.Keyword('ESTCAP') + number('ESTCAP_wireCap'))

        # WEIGHT
        WEIGHT = (ws_net + pp.Keyword('WEIGHT') + number('WEIGHT'))

        # PROPERTY
        PROPERTY = pp.Group(ws_net + pp.Keyword('PROPERTY') + pp.OneOrMore(
            identifier('propName') + number('propVal')))('PROPERTY')

        # Refactor this!?
        if self.ignore_nets_route:
            regularWiring = pp.SkipTo((EOL + ws_net) | linebreak)

        net = pp.Group(
            pp.Suppress(begin_net) + netName + pp.Optional(SHIELDNET) +
            pp.ZeroOrMore(VPIN) + pp.ZeroOrMore(SUBNET) + pp.Optional(XTALK) +
            pp.Optional(NONDEFAULTRULE) + pp.ZeroOrMore(regularWiring) +
            pp.Optional(SOURCE) + pp.Optional(FIXEDBUMP) +
            pp.Optional(FREQUENCY) + pp.Optional(ORIGINAL) + pp.Optional(USE) +
            pp.Optional(PATTERN) + pp.Optional(ESTCAP) + pp.Optional(WEIGHT) +
            pp.ZeroOrMore(PROPERTY) + linebreak).setResultsName(
                'net', listAllMatches=True)

        nets = pp.Group(
            pp.Suppress(nets_id) + number('numNets') + linebreak +
            pp.ZeroOrMore(net) +
            pp.Suppress(end_nets_id)).setResultsName('NETS')

        return nets
Example #21
0
argument = number | variable

# arguments are a delimited list of 'argument' surrounded by parenthesis
arguments = (pp.Suppress('(') + pp.delimitedList(argument) +
             pp.Suppress(')')).setResultsName('arguments', listAllMatches=True)

# a fact is composed of a relationship and it's arguments
# (I'm aware it's actually more complicated than this
# it's just a simplifying assumption)
fact = (relationship + arguments).setResultsName('facts', listAllMatches=True)

# a sentence is a fact plus a period
sentence = fact + pp.Suppress('.')

# self explanatory
prolog_sentences = pp.OneOrMore(sentence)


def process_file(filename):
    atoms = []
    predicates = set()
    constants = set()
    with open(filename) as f:
        data = f.read().replace('\n', '')
        result = prolog_sentences.parseString(data)
        for idx in range(len(result['facts'])):
            fact = result['facts'][idx]
            predicate = result['relationship'][idx]
            terms = [Term(False, term) for term in result['arguments'][idx]]
            term_var = [Term(True, f'X_{i}') for i in range(len(terms))]
Example #22
0
    def parse_specialnets(self):
        EOL = pp.LineEnd().suppress()
        linebreak = pp.Suppress(";" + pp.LineEnd())
        identifier = pp.Word(
            pp.alphanums +
            '._“!<>/[]$#$%&‘*+,/:<=>?@[\]^_`{|}~')  # CONFLICT with '();'
        number = pp.pyparsing_common.number
        word = pp.Word(pp.alphas)
        LPAR = pp.Suppress('(')
        RPAR = pp.Suppress(')')
        ORIENT = (pp.Keyword('N')
                  | pp.Keyword('S')
                  | pp.Keyword('E')
                  | pp.Keyword('W')
                  | pp.Keyword('FN')
                  | pp.Keyword('FS')
                  | pp.Keyword('FE')
                  | pp.Keyword('FW'))
        pt = LPAR + pp.OneOrMore(number
                                 | pp.Keyword('*')) + RPAR  # pair of x,y
        specialnets_id = pp.Suppress(pp.Keyword('SPECIALNETS'))
        end_specialnets_id = pp.Keyword("END SPECIALNETS").suppress()
        begin_specialnet = pp.Suppress(pp.Keyword('-'))
        ws_snet = pp.Suppress(pp.Keyword('+'))  # parameter division in NETS

        # netName
        netName_1 = pp.Group(
            LPAR + identifier('compName') + identifier('pinName') +
            pp.Optional(ws_snet + pp.Keyword('SYNTHESIZED'))('SYNTHESIZED') +
            RPAR)
        netName = identifier('netName') + pp.ZeroOrMore(
            netName_1).setResultsName('nets')

        # MASK
        MASK = pp.Group(pp.Keyword('MASK') +
                        number('maskNum')).setResultsName('MASK')

        MASK_id = pp.Keyword('MASK')
        RECT_id = pp.Keyword('RECT')
        VIRTUAL_id = pp.Keyword('VIRTUAL')
        routingPoints_1 = pp.Optional(MASK('MASK') +
                                      number('maskNum')) + pp.Group(pt)
        routingPoints_2 = pp.Optional(MASK_id('MASK') + number('viaMaskNum')) + pp.NotAny(pp.Keyword('NEW') | pp.Keyword('RECT')) \
                                    + identifier('viaName') + pp.Optional(ORIENT('orient')) \
                        + pp.Optional(pp.Suppress(pp.Keyword('DO')) + number('numX') + pp.Suppress(pp.Keyword('BY')) + number('numY')
                                    + pp.Suppress(pp.Keyword('STEP')) + number('stepX') + number('stepY'))
        routingPoints = (pp.Group(pt) +
                         pp.OneOrMore(routingPoints_1 | routingPoints_2))

        specialWiring_placement = (ws_snet + (
            (pp.Keyword('COVER')('PLACEMENT'))
            | (pp.Keyword('FIXED')('PLACEMENT'))
            | (pp.Keyword('ROUTED')('PLACEMENT'))
            |
            (pp.Keyword('SHIELD')('PLACEMENT') + identifier('shieldNetName'))))

        specialWiring_1 = (
            pp.Optional(specialWiring_placement) +
            pp.Optional(ws_snet + pp.Keyword('SHAPE') +
                        identifier('shapeType')) +
            pp.Optional(ws_snet + pp.Keyword('MASK') + number('maskNum')) +
            ((ws_snet + pp.Keyword('POLYGON') + identifier('layerName') +
              pp.OneOrMore(pt))
             |
             (ws_snet + pp.Keyword('RECT') + identifier('layerName') + pt + pt)
             | (ws_snet + pp.Keyword('VIA') + identifier('viaName') +
                pp.Optional(ORIENT('orient')) + pp.OneOrMore(pt))))

        SHAPE_elems = (pp.Keyword('RING') | pp.Keyword('PADRING')
                       | pp.Keyword('BLOCKRING')
                       | pp.Keyword('STRIPE') | pp.Keyword('FOLLOWPIN')
                       | pp.Keyword('IOWIRE')
                       | pp.Keyword('COREWIRE') | pp.Keyword('BLOCKWIRE')
                       | pp.Keyword('BLOCKAGEWIRE')
                       | pp.Keyword('FILLWIRE') | pp.Keyword('FILLWIREOPC')
                       | pp.Keyword('DRCFILL'))

        specialWiring_2 = (
            specialWiring_placement + identifier('layerName') +
            number('routeWidth') +
            pp.Optional(ws_snet + pp.Keyword('SHAPE') + SHAPE_elems('SHAPE')) +
            pp.Optional(ws_snet + pp.Keyword('STYLE') + number('styleNum')) +
            routingPoints('routingPoints') + pp.Group(
                pp.ZeroOrMore(
                    pp.Group(
                        pp.Keyword('NEW') + identifier('layerName') +
                        number('routeWidth') +
                        pp.Optional(ws_snet + pp.Keyword('SHAPE') +
                                    SHAPE_elems('SHAPE')) +
                        pp.Optional(ws_snet + pp.Keyword('STYLE') +
                                    identifier('styleNum')) +
                        routingPoints('routingPoints')))))('NEW')

        specialWiring = pp.Group(
            pp.OneOrMore(specialWiring_1 | specialWiring_2))('specialWiring')

        VOLTAGE = ws_snet + pp.Keyword('VOLTAGE') + number('VOLTAGE')

        SOURCE = ws_snet + pp.Keyword('SOURCE') + (
            pp.Keyword('DIST') | pp.Keyword('NETLIST') | pp.Keyword('TIMING')
            | pp.Keyword('USER'))

        FIXEDBUMP = ws_snet + pp.Keyword('FIXEDBUMP')('FIXEDBUMP')

        ORIGINAL = ws_snet + pp.Keyword('ORIGINAL') + identifier(
            'ORIGINAL_netName')

        USE_ids = (pp.Keyword('ANALOG') | pp.Keyword('CLOCK')
                   | pp.Keyword('GROUND') | pp.Keyword('POWER')
                   | pp.Keyword('RESET') | pp.Keyword('SCAN')
                   | pp.Keyword('SIGNAL') | pp.Keyword('TIEOFF'))
        USE = ws_snet + pp.Keyword('USE') + USE_ids('USE')

        PATTERN_ids = (pp.Keyword('BALANCED') | pp.Keyword('STEINER')
                       | pp.Keyword('TRUNK') | pp.Keyword('WIREDLOGIC'))
        PATTERN = ws_snet + pp.Keyword('PATTERN') + PATTERN_ids('PATTERN')

        ESTCAP = ws_snet + pp.Keyword('ESTCAP') + number(
            'ESTCAP_wireCapacitance')

        WEIGHT = ws_snet + pp.Keyword('WEIGHT') + number('WEIGHT')

        PROPERTY = pp.Group(ws_snet + pp.Keyword('PROPERTY') + pp.OneOrMore(
            identifier('propName') + number('propVal')))('PROPERTY')

        specialnet = pp.Group(begin_specialnet + netName +
                              pp.Optional(VOLTAGE) +
                              pp.ZeroOrMore(specialWiring) +
                              pp.Optional(SOURCE) + pp.Optional(FIXEDBUMP) +
                              pp.Optional(ORIGINAL) + pp.Optional(USE) +
                              pp.Optional(PATTERN) + pp.Optional(ESTCAP) +
                              pp.Optional(WEIGHT) + pp.ZeroOrMore(PROPERTY) +
                              linebreak).setResultsName('specialnets',
                                                        listAllMatches=True)

        specialnets = pp.Group(specialnets_id + number('numNets') + linebreak +
                               pp.ZeroOrMore(specialnet) +
                               pp.Suppress(end_specialnets_id)).setResultsName(
                                   'SPECIALNETS')

        return specialnets
Example #23
0
    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()
Example #24
0
import pyparsing as pp
import re

number = pp.Word(pp.nums, max=2)
plusOrMinus = pp.Word("+-/", max=1)
transposition = pp.Optional(pp.Combine(plusOrMinus + number))
lpar = pp.Literal('{').suppress()
rpar = pp.Literal('}').suppress()
startend = pp.Optional(pp.Combine(number + "-" + number))
whitespace = pp.ZeroOrMore(" ")
space = pp.Optional(pp.OneOrMore(" "))
pattern = pp.Combine(lpar + number + space + transposition + space + startend +
                     rpar)
repeatCount = pp.Combine("*" + number)
patterns = pp.OneOrMore(pattern | repeatCount)

# shorthand = patterns.parseString("{1 +0 1-32}*4 {1 +5 1-32}*2 {1}*2 {1 +7 1-32} {1 +5 1-32} {1 +0 1-32} {1 +0 1-16} {1 +7 17-32}")
# longhand = []
# for i in range(len(shorthand)):
#     s = shorthand[i]
#     if s[0]=='*':
#         repeat = int(s[1:])-1
#         for j in range(repeat):
#             longhand.append(shorthand[i-1])
#     else:
#         longhand.append(shorthand[i])
#
# print longhand

# lsqbracket  = pp.Literal( '[' ).suppress()
# rsqbracket = pp.Literal( ']' ).suppress()
Example #25
0
    def getSequenceArray(self, inputString):
        testPattern = "{0 +0 1-32}*4 {0 +5 1-32}*2 {0}*2 {0 +7 1-32} {0 +5 1-32} {0 +0 1-32} {0 +0 1-16} {0 +7 17-32}"
        if inputString == "":
            inputString = testPattern
        print "INPUT STRING IS " + inputString
        inputString = inputString.replace("\n", "")
        inputString = inputString.replace("\r", "")

        sections = inputString.split('[')
        sections = filter(None, sections)
        for i in range(len(sections)):
            # if len(sections[i])==0: continue

            partplustimes = sections[i].split(']*')
            if len(partplustimes) > 1:
                sections[i] = partplustimes[0] * int(partplustimes[1])

        inputString = str()
        inputString = inputString.join(sections)
        number = pp.Word(pp.nums, max=2)
        plusOrMinus = pp.Word("+-/", max=1)
        transposition = pp.Optional(pp.Combine(plusOrMinus + number))
        lpar = pp.Literal('{').suppress()
        rpar = pp.Literal('}').suppress()
        startend = pp.Optional(pp.Combine(number + "-" + number))
        whitespace = pp.ZeroOrMore(" ")
        space = pp.Optional(pp.OneOrMore(" "))
        pattern = pp.Combine(lpar + number + space + transposition + space +
                             startend + rpar)
        repeatCount = pp.Combine("*" + number)
        patterns = pp.OneOrMore(pattern | repeatCount)
        print "~~~~~~" + inputString
        #there is s problem here I dont know what it is
        #if inputstring is pasted into the textbox it works
        #but if its done directly from parsing the square bracketed text
        #it fails
        try:
            shorthand = patterns.parseString(inputString)
        except pp.ParseException as pe:
            print("Exception Here")
            print(pe)
            print("column: {}".format(pe.col))
            return

        longhand = []
        for i in range(len(shorthand)):
            s = shorthand[i]
            print "S is :", s
            if s[0] == '*':
                repeat = int(s[1:]) - 1
                for j in range(repeat):
                    longhand.append(shorthand[i - 1])
            else:
                longhand.append(shorthand[i])

        listOfBreaks = []
        for i in range(len(longhand)):
            b = Break()
            b.setBreak(longhand[i])
            listOfBreaks.append(b)
        print listOfBreaks
        return listOfBreaks
Example #26
0
def parse_request(s):
    """
    Parses any request string, including parenthesised form, and merging (pipe operator).
    @return (base_pkgs, subshells). base_pkgs is a list of packages in the 'master' shell, ie 
        outside of any parenthesised subshell. 'subshells' is a dict of subshells, keyed on the
        subshell name.
    """

    global base_pkgs
    global subshells
    global curr_ss
    global merged_base_pkgs
    global merged_subshells

    base_pkgs = []
    subshells = {}
    merged_base_pkgs = []
    merged_subshells = {}
    curr_ss = None

    def _parse_pkg(s, loc, toks):
        global curr_ss
        pkg_str = str('').join(toks)
        if curr_ss is None:
            base_pkgs.append(pkg_str)
        else:
            curr_ss["pkgs"].append(pkg_str)

    def _parse_ss_label(s, loc, toks):
        curr_ss["label"] = toks[0]

    def _parse_ss_prefix(s, loc, toks):
        global curr_ss
        curr_ss = {
            "pkgs": [],
            "prefix": '',
            "suffix": ''
        }
        prefix_str = toks[0][:-1]
        if prefix_str:
            curr_ss["prefix"] = prefix_str

    def _parse_ss_suffix(s, loc, toks):
        global curr_ss
        suffix_str = toks[0][1:]
        if suffix_str:
            curr_ss["suffix"] = suffix_str
        if "label" not in curr_ss:
            pkg_fam = curr_ss["pkgs"][0].split('-')[0]
            label_str = curr_ss["prefix"] + pkg_fam + curr_ss["suffix"]
            curr_ss["label"] = label_str

        subshell_name = curr_ss["label"]
        if subshell_name in subshells:
            print >> sys.stderr, "Error: subshell '%s' is defined more than once!" % subshell_name
            sys.exit(1)

        subshells[subshell_name] = curr_ss
        curr_ss = None

    def _parse_ss_request(s, loc, toks):
        global base_pkgs
        global subshells
        global merged_base_pkgs
        global merged_subshells
        merged_base_pkgs = _merge_pkgs(merged_base_pkgs, base_pkgs)
        merged_subshells = _merge_subshells(merged_subshells, subshells)
        base_pkgs = []
        subshells = {}        

    _pkg = pp.Regex("[a-zA-Z_0-9~<=^\\.\\-\\!\\+]+").setParseAction(_parse_pkg)

    _subshell_label = pp.Regex("[a-zA-Z0-9_]+")
    _subshell_label_decl = (_subshell_label + ':').setParseAction(_parse_ss_label)
    _subshell_body = (_subshell_label_decl * (0,1)) + pp.OneOrMore(_pkg)
    _subshell_prefix = (pp.Regex("[a-zA-Z0-9_]+\\(") ^ '(').setParseAction(_parse_ss_prefix)
    _subshell_suffix = (pp.Regex("\\)[a-zA-Z0-9_]+") ^ ')').setParseAction(_parse_ss_suffix)
    _subshell = _subshell_prefix + _subshell_body + _subshell_suffix

    _request = pp.OneOrMore(_pkg ^ _subshell).setParseAction(_parse_ss_request)
    _expr = _request + pp.ZeroOrMore('|' + _request)

    pr = _expr.parseString(s, parseAll=True)
    return (merged_base_pkgs, merged_subshells)
        return True


apache = parse.SkipTo(parse.CaselessLiteral(u'<a href='),
                      include=True).suppress() + parse.quotedString.setParseAction(
    parse.removeQuotes).setResultsName(u'url') + parse.SkipTo(u'</a>',
                                                              include=True).suppress()\
         + parse.Optional(
    parse.Literal(u'</td><td align="right">')).suppress() + parse.Optional(parse.Combine(
    parse.Word(parse.alphanums + u'-') +
    parse.Word(parse.alphanums + u':')
    , adjacent=False, joinString=u' ').setResultsName(u'date')
                                                                           )

iis = parse.SkipTo(u'<br>').suppress() + parse.OneOrMore(
    u'<br>').suppress() + parse.Optional(parse.Combine(
    parse.Word(parse.alphanums + '/') +
    parse.Word(parse.alphanums + u':') +
    parse.Word(parse.alphas)
    , adjacent=False, joinString=u' ').setResultsName(u'date')
                                         ) + parse.Word(
    parse.nums).suppress() + parse.Literal(
    u'<A HREF=').suppress() + parse.quotedString.setParseAction(
    parse.removeQuotes).setResultsName(u'url')

other = parse.SkipTo(parse.CaselessLiteral(u'<a href='),
                     include=True).suppress() + parse.quotedString.setParseAction(
    parse.removeQuotes).setResultsName(u'url')

scrapers = {
    u'apache': parse.OneOrMore(parse.Group(apache)),
Example #28
0
forstm = PP.Suppress(forwd) + identifier + PP.Suppress(inwd) + expr + block
forstm.setParseAction(lambda x: For(x[0], x[1], x[2]))
forstm("for statement")

whilestm = PP.Suppress(whilewd) + expr + block
whilestm("while statement")
whilestm.setParseAction(lambda x: While(x[0], x[1]))

statement << (ifstm | forstm | whilestm | assignstm)

program = identifier + PP.Suppress(readwd) + identifier + block + PP.Suppress(
    writewd) + identifier
program.setParseAction(lambda x: Program(x[0], x[1], x[3], x[2]))

file = PP.OneOrMore(program)


def asList(*exprs):
    return reduce(lambda x, y: ConsExp(y, x), reversed(exprs), NilExp())


def toBinaryCons(integer):
    assert integer >= 0
    binary_digits = []
    while True:
        digit = integer % 2
        integer = integer // 2
        binary_digits.append(
            ConsExp(NilExp(), NilExp()) if digit else NilExp())
        if integer == 0:
Example #29
0
def parse(schema):
    result = {}

    # constants
    LPAR, RPAR, LBRACK, RBRACK, LBRACE, RBRACE, LABRACK, RABRACK, COLON, SEMI, COMMA, EQ = map(pa.Suppress, "()[]{}<>:;,=")

    # keywords
    _typedef, _const, _enum, _struct, _exception, _service = map(pa.Keyword, ("typedef", "const", "enum", "struct", "exception", "service"))

    # comment match
    single_line_comment = (pa.Suppress("//") | pa.Suppress("#")) + pa.restOfLine

    # general tokens
    identifier = pa.Word(pa.alphanums + '_')

    # general value
    value = pa.Forward()
    nums_ = pa.Word(pa.nums)
    integer_ = nums_.setParseAction(lambda s, l, t: [int(t[0])])
    double_ = pa.Combine(nums_ + '.' + nums_).setParseAction(lambda s, l, t: [float(t[0])])
    string_ = pa.quotedString.setParseAction(pa.removeQuotes)
    list_ = pa.Group(LBRACK + pa.delimitedList(value) + RBRACK).setParseAction(lambda s, l, t: t.asList())
    value << _or(double_, integer_, string_, list_)

    # scan for possible user defined types
    _typedef_prefix = _typedef + identifier + pa.Optional(pa.nestedExpr(opener='<', closer='>'))
    scan_utypes = _or(_typedef_prefix, _enum, _struct, _exception) + identifier
    utypes = map(pa.Keyword, (t[-1] for t, _, _ in scan_utypes.scanString(schema)))

    # ttypes
    ttype = pa.Forward()
    t_list = pa.Group(pa.Keyword("list")("ttype") + LABRACK + ttype('v') + RABRACK)
    t_map = pa.Group(pa.Keyword("map")("ttype") + LABRACK + ttype('k') + COMMA + ttype('v') + RABRACK)
    orig_types = _or(t_list, t_map, *map(pa.Keyword, ("bool", "byte", "i16", "i32", "i64", "double", "string")))
    ttype << _or(orig_types, *utypes)

    # typedef parser
    typedef = _typedef + orig_types("ttype") + identifier("name")
    result["typedefs"] = {t.name: t.ttype for t, _, _ in typedef.scanString(schema)}

    # const parser
    const = _const + ttype("ttype") + identifier("name") + EQ + value("value")
    result["consts"] = {c.name: c.value for c, _, _ in const.scanString(schema)}

    # enum parser
    enum_value = pa.Group(identifier('name') + pa.Optional(EQ + integer_('value')) + pa.Optional(COMMA))
    enum_list = pa.Group(pa.OneOrMore(enum_value))("members")
    enum = _enum + identifier("name") + LBRACE + enum_list + RBRACE
    enum.ignore(single_line_comment)
    result["enums"] = {e.name: e for e, _, _ in enum.scanString(schema)}

    # struct parser
    category = _or(*map(pa.Literal, ("required", "optional")))
    struct_field = pa.Group(integer_("id") + COLON + pa.Optional(category) + ttype("ttype") + identifier("name") + pa.Optional(EQ + value("value")) + pa.Optional(COMMA))
    struct_members = pa.Group(pa.OneOrMore(struct_field))("members")
    struct = _struct + identifier("name") + LBRACE + struct_members + RBRACE
    struct.ignore(single_line_comment)
    # struct defines is ordered
    result["structs"] = [s for s, _, _ in struct.scanString(schema)]

    # exception parser
    exception = _exception + identifier("name") + LBRACE + struct_members + RBRACE
    exception.ignore(single_line_comment)
    result["exceptions"] = [s for s, _, _ in exception.scanString(schema)]

    # service parser
    ftype = _or(ttype, pa.Keyword("void"))
    api_param = pa.Group(integer_("id") + COLON + ttype("ttype") + identifier("name") + pa.Optional(COMMA))
    api_params = pa.Group(pa.ZeroOrMore(api_param))
    service_api = pa.Group(ftype("ttype") + identifier("name") + LPAR + api_params("params") + RPAR + pa.Optional(pa.Keyword("throws") + LPAR + api_params("throws") + RPAR) + pa.Optional(SEMI | COMMA))
    service_apis = pa.Group(pa.OneOrMore(service_api))("apis")
    service = _service + identifier("name") + LBRACE + service_apis + RBRACE
    service.ignore(single_line_comment)
    service.ignore(pa.cStyleComment)
    result["services"] = [s for s, _, _ in service.scanString(schema)]

    return result
# Declarations inside (possibly nested) #if(n)def... #else... #endif... blocks.
COND_DECL = _nested_if_else(IFDEF, NAME, ELSE, ENDIF, UNCOND_DECL, UNCOND_DECL)
# Note: this doesn't work for '#if defined(FLAG)' blocks

# e.g. "mjtNum gravity[3];              // gravitational acceleration"
STRUCT_MEMBER = pp.Group(
    pp.Optional(STRUCT("struct")) + (NATIVE_TYPENAME | NAME)("typename") +
    pp.Optional(PTR("ptr")) + NAME("name") + pp.ZeroOrMore(ARRAY_DIM)("size") +
    SEMI + pp.Optional(COMMENT("comment")))

# Struct declaration within a union (non-nested).
UNION_STRUCT_DECL = pp.Group(
    STRUCT("struct") + pp.Optional(NAME("typename")) +
    pp.Optional(COMMENT("comment")) + LBRACE +
    pp.OneOrMore(STRUCT_MEMBER)("members") + RBRACE +
    pp.Optional(NAME("name")) + SEMI)

ANONYMOUS_UNION_DECL = pp.Group(
    pp.Optional(MULTILINE_COMMENT("comment")) + UNION("anonymous_union") +
    LBRACE + pp.OneOrMore(UNION_STRUCT_DECL | STRUCT_MEMBER
                          | COMMENT.suppress())("members") + RBRACE + SEMI)

# Multiple (possibly nested) struct declarations.
NESTED_STRUCTS = _nested_scopes(
    opening=(STRUCT + pp.Optional(NAME("typename")) +
             pp.Optional(COMMENT("comment")) + LBRACE),
    closing=(RBRACE + pp.Optional(NAME("name")) + SEMI),
    body=pp.OneOrMore(STRUCT_MEMBER | ANONYMOUS_UNION_DECL
                      | COMMENT.suppress())("members"))