Ejemplo n.º 1
0
def message_type_definition() -> Token:
    first_aspect = Keyword("First") - Keyword("=>") - mathematical_expression()
    first_aspect.setParseAction(parse_aspect)
    length_aspect = Keyword("Length") - Keyword(
        "=>") - mathematical_expression()
    length_aspect.setParseAction(parse_aspect)
    component_aspects = Keyword("with") - delimitedList(first_aspect
                                                        | length_aspect)
    component_aspects.setParseAction(parse_aspects)

    then = locatedExpr(
        Keyword("then") - (Keyword("null") | unqualified_identifier()) -
        Group(Optional(component_aspects)) -
        Group(Optional(value_constraint())))
    then.setParseAction(parse_then)
    then_list = then + ZeroOrMore(comma() - then)
    then_list.setParseAction(lambda t: [t.asList()])
    component_item = (~Keyword("end") + ~CaselessKeyword("Message") -
                      unqualified_identifier() + Literal(":") -
                      qualified_identifier() - Optional(then_list) -
                      semicolon())
    component_item.setParseAction(lambda t: Component(t[0], t[2], t[3])
                                  if len(t) >= 4 else Component(t[0], t[2]))
    component_item.setName("Component")
    null_component_item = Keyword("null") - then - semicolon()
    null_component_item.setParseAction(lambda t: Component(None, None, [t[1]]))
    null_component_item.setName("NullComponent")
    component_list = Group(
        Optional(null_component_item) - component_item -
        ZeroOrMore(component_item))
    component_list.setParseAction(lambda t: t.asList())

    return (Keyword("message") - component_list - Keyword("end message")
            | Keyword("null message")).setName("Message")
Ejemplo n.º 2
0
def integer_type_definition() -> Token:
    range_type_aspects = Keyword("with") - size_aspect()
    range_type_aspects.setParseAction(parse_aspects)

    range_type_definition = (Keyword("range") - mathematical_expression() -
                             Suppress(Literal("..")) -
                             mathematical_expression() - range_type_aspects)
    range_type_definition.setName("RangeInteger")
    modular_type_definition = Keyword("mod") - mathematical_expression()
    modular_type_definition.setName("ModularInteger")

    return range_type_definition | modular_type_definition
Ejemplo n.º 3
0
    def __init__(self, basedir: str = '.') -> None:
        self.__basedir = basedir
        self.__specifications: Dict[str, Specification] = {}
        self.__pdus: Dict[str, PDU] = {}
        self.__refinements: Dict[str, Refinement] = {}

        # Generic
        comma = Suppress(Literal(','))
        comma.setName('","')
        semicolon = Suppress(Literal(';'))
        semicolon.setName('";"')

        # Comments
        comment = Regex(r'--.*')

        # Names
        identifier = WordStart(alphanums) + Word(alphanums +
                                                 '_') + WordEnd(alphanums +
                                                                '_')
        identifier.setParseAction(verify_identifier)
        identifier.setName('Identifier')
        qualified_identifier = Optional(identifier + Literal('.')) - identifier
        qualified_identifier.setParseAction(lambda t: ''.join(t.asList()))
        attribute_designator = Keyword('First') | Keyword('Last') | Keyword(
            'Length')
        attribute_reference = identifier + Literal('\'') - attribute_designator
        attribute_reference.setParseAction(parse_attribute)
        attribute_reference.setName('Attribute')
        name = attribute_reference | identifier
        name.setName('Name')

        # Literals
        numeral = Word(nums) + ZeroOrMore(Optional(Word('_')) + Word(nums))
        numeral.setParseAction(
            lambda t: int(''.join(t.asList()).replace('_', '')))
        extended_digit = Word(nums + 'ABCDEF')
        based_numeral = extended_digit + ZeroOrMore(
            Optional('_') + extended_digit)
        based_literal = numeral + Literal('#') - based_numeral - Literal('#')
        based_literal.setParseAction(
            lambda t: int(t[2].replace('_', ''), int(t[0])))
        numeric_literal = based_literal | numeral
        numeric_literal.setParseAction(lambda t: Number(t[0]))
        numeric_literal.setName('Number')
        literal = numeric_literal

        # Operators
        mathematical_operator = (Literal('**') | Literal('+') | Literal('-')
                                 | Literal('*')
                                 | Literal('/'))
        relational_operator = (Keyword('<=') | Keyword('>=') | Keyword('=')
                               | Keyword('/=')
                               | Keyword('<') | Keyword('>'))
        logical_operator = Keyword('and') | Keyword('or')

        # Expressions
        mathematical_expression = Forward()
        relation = mathematical_expression + relational_operator - mathematical_expression
        relation.setParseAction(parse_relation)
        relation.setName('Relation')
        logical_expression = infixNotation(
            relation,
            [(logical_operator, 2, opAssoc.LEFT, parse_logical_expression)])
        logical_expression.setName('LogicalExpression')
        term = Keyword('null') | literal | name
        term.setParseAction(parse_term)
        mathematical_expression << infixNotation(
            term, [(mathematical_operator, 2, opAssoc.LEFT,
                    parse_mathematical_expression)])
        mathematical_expression.setName('MathematicalExpression')

        # Type Refinement
        value_constraint = Keyword('if') - logical_expression
        value_constraint.setParseAction(lambda t: t[1])
        type_refinement_definition = (
            Keyword('new') - qualified_identifier - Suppress(Literal('(')) -
            identifier - Suppress(Literal('=>')) -
            (Keyword('null') | qualified_identifier) - Suppress(Literal(')')) -
            Optional(value_constraint))
        type_refinement_definition.setName('Refinement')

        # Integer Types
        size_aspect = Keyword('Size') - Keyword('=>') - mathematical_expression
        size_aspect.setParseAction(parse_aspect)
        range_type_aspects = Keyword('with') - size_aspect
        range_type_aspects.setParseAction(parse_aspects)

        range_type_definition = (Keyword('range') - mathematical_expression -
                                 Suppress(Literal('..')) -
                                 mathematical_expression - range_type_aspects)
        range_type_definition.setName('RangeInteger')
        modular_type_definition = Keyword('mod') - mathematical_expression
        modular_type_definition.setName('ModularInteger')
        integer_type_definition = range_type_definition | modular_type_definition

        # Enumeration Types
        enumeration_literal = name
        positional_enumeration = enumeration_literal + ZeroOrMore(
            comma - enumeration_literal)
        positional_enumeration.setParseAction(
            lambda t: [(k, Number(v)) for v, k in enumerate(t.asList())])
        element_value_association = enumeration_literal + Keyword(
            '=>') - numeric_literal
        element_value_association.setParseAction(lambda t: (t[0], t[2]))
        named_enumeration = (element_value_association +
                             ZeroOrMore(comma - element_value_association))

        boolean_literal = Keyword('True') | Keyword('False')
        boolean_literal.setParseAction(lambda t: t[0] == 'True')
        boolean_aspect_definition = Optional(Keyword('=>') - boolean_literal)
        boolean_aspect_definition.setParseAction(lambda t:
                                                 (t if t else ['=>', True]))
        always_valid_aspect = Literal(
            'Always_Valid') - boolean_aspect_definition
        always_valid_aspect.setParseAction(parse_aspect)
        enumeration_aspects = Keyword('with') - delimitedList(
            size_aspect | always_valid_aspect)
        enumeration_aspects.setParseAction(parse_aspects)

        enumeration_type_definition = (
            Literal('(') - (named_enumeration | positional_enumeration) -
            Literal(')') - enumeration_aspects)
        enumeration_type_definition.setName('Enumeration')

        # Array Type
        unconstrained_array_definition = Keyword('array of') + name
        array_type_definition = unconstrained_array_definition
        array_type_definition.setName('Array')

        # Message Type
        first_aspect = Keyword('First') - Keyword(
            '=>') - mathematical_expression
        first_aspect.setParseAction(parse_aspect)
        length_aspect = Keyword('Length') - Keyword(
            '=>') - mathematical_expression
        length_aspect.setParseAction(parse_aspect)
        component_aspects = Keyword('with') - delimitedList(first_aspect
                                                            | length_aspect)
        component_aspects.setParseAction(parse_aspects)

        then = (Keyword('then') - (Keyword('null') | identifier) -
                Group(Optional(component_aspects)) -
                Group(Optional(value_constraint)))
        then.setParseAction(parse_then)
        then_list = then + ZeroOrMore(comma - then)
        then_list.setParseAction(lambda t: [t.asList()])
        component_list = Forward()
        message_type_definition = Keyword(
            'message') - component_list - Keyword('end message')
        message_type_definition.setName('Message')
        component_item = (~Keyword('end') + ~CaselessKeyword('Message') -
                          identifier + Literal(':') - name -
                          Optional(then_list) - semicolon)
        component_item.setParseAction(lambda t: Component(t[0], t[2], t[3]) if
                                      len(t) >= 4 else Component(t[0], t[2]))
        component_item.setName('Component')
        null_component_item = Keyword('null') - then - semicolon
        null_component_item.setParseAction(
            lambda t: Component(t[0], '', [t[1]]))
        null_component_item.setName('NullComponent')
        component_list << (Group(
            Optional(null_component_item) - component_item -
            ZeroOrMore(component_item)))
        component_list.setParseAction(lambda t: t.asList())

        # Types
        type_definition = (enumeration_type_definition
                           | integer_type_definition
                           | message_type_definition
                           | type_refinement_definition
                           | array_type_definition)
        type_declaration = (Keyword('type') - identifier - Keyword('is') -
                            type_definition - semicolon)
        type_declaration.setParseAction(parse_type)

        # Package
        basic_declaration = type_declaration
        package_declaration = (Keyword('package') - identifier -
                               Keyword('is') -
                               Group(ZeroOrMore(basic_declaration)) -
                               Keyword('end') - name - semicolon)
        package_declaration.setParseAction(
            lambda t: Package(t[1], t[3].asList()))

        # Context
        context_item = Keyword('with') - identifier - semicolon
        context_item.setParseAction(lambda t: t[1])
        context_clause = ZeroOrMore(context_item)
        context_clause.setParseAction(lambda t: Context(t.asList()))

        # Specification
        specification = Optional(context_clause + package_declaration)
        specification.setParseAction(lambda t: Specification(t[0], t[1])
                                     if len(t) == 2 else None)

        # Grammar
        self.__grammar = specification + StringEnd()
        self.__grammar.setParseAction(self.__evaluate_specification)
        self.__grammar.ignore(comment)
Ejemplo n.º 4
0
def model_grammar():
    """
    Construct a parser for winBugs/openBugs/JAGS models.

    Returns *parser*, which is a *pyaparsing.ParserElement, with the
    *parser.parserString()* method.

    Be sure to strip comments from the string prior to parsing, so that the
    grammar can be a little simpler.
    """
    ###factor = Forward().setName('factor') # for right-to-left parsing
    expression = Forward().setName('expr')
    group = Forward().setName('group')

    # start:stop used for indexing and for loops
    inner_range = Optional (expression + Optional(Literal(":") + expression))
    paren_range = Literal("(").suppress() + inner_range + Literal(")").suppress()
    slice =  inner_range | paren_range

    paren_range.setName('(slice)')
    inner_range.setName('slice').setParseAction(
        lambda s,l,t: [(SLICE,(NONE,),(NONE,)) if len(t)==0 else (SLICE,t[0],t[2]) if len(t)>1 else t[0]])

    # indexing
    subscripts = slice + ZeroOrMore(Literal(',').suppress() + slice)
    index = Literal('[').suppress() + subscripts + Literal(']').suppress()
    indexed_variable = variable + Optional(index)

    subscripts.setName('subs')
    index.setName('index')
    indexed_variable.setName('deref').setParseAction(
        lambda s,l,t: [(DEREF,t[0],t[1:])])

    # arithmetic
    muldiv = Literal('*') | Literal('/')
    addsub = Literal('+') | Literal('-')
    ###exponent = Literal('^')

    pars = expression + ZeroOrMore(Literal(',').suppress() + expression)
    function = variable + Literal('(') + Optional(pars) + Literal(')')
    paren = Literal('(') + expression + Literal(')')
    value = constant + Empty()
    atom = Optional("-") + (function | indexed_variable | value | paren )
    ###factor << (atom | ZeroOrMore (exponent + factor))
    ###term = factor + ZeroOrMore(muldiv + factor)
    term = atom + ZeroOrMore(muldiv + atom)
    expression << (term + ZeroOrMore(addsub + term))

    paren.setName('paren').setParseAction(
        lambda s,l,t: [t[1]])
    value.setName('value').setParseAction(
        lambda s,l,t: [(CONST, t[0])])
    function.setName('apply').setParseAction(
        lambda s,l,t: [(APPLY, t[0], t[2:-1])])
    atom.setName('atom').setParseAction(
        lambda s,l,t: [(UNARY, t[0], t[1]) if len(t)>1 else t[0]])
    ###factor.setName('factor').setParseAction(lambda s,l,t: [_binop(t)])
    term.setName('term').setParseAction(
        lambda s,l,t: [_binop(t)])
    expression.setName('expr').setParseAction(
        lambda s,l,t: [_binop(t)])

    # priors look like dname(p1,p2,...) with optional qualifier T(left,right)
    # to set the bounds on the prior.   Since left/right are optional, the
    # function parser can't be used, and we need a special bounds term to
    # parse this form.
    bounds_limit = expression | Empty()
    bounds_function = (variable + Literal('(') + bounds_limit
                           + Literal(',') + bounds_limit + Literal(')'))
    bounds = bounds_function | Empty()
    bounds_limit.setName('limit').setParseAction(
        lambda s,l,t: [(t[0] if len(t) else (NONE,))])
    bounds.setName('trunc').setParseAction(
        lambda s,l,t: [(APPLY,t[0],[t[2],t[4]]) if len(t) else (NONE,)])

    # Funky assignment lhs functions, such as:
    #    logit(t) <- alpha; D(C[5],t) <- PER1 * C[7] - R*kT1*C[1]
    lhs_function = variable + Literal('(') + indexed_variable \
                   + ZeroOrMore(Literal(',') + indexed_variable) + Literal(')')
    lhs_function.setName('f(lhs)').setParseAction(
        lambda s,l,t: [(APPLY, t[0], t[2::2])])

    # statements
    assignment = (lhs_function | indexed_variable) + Literal("<-") + expression
    prior = indexed_variable + Literal("~") + function + bounds
    loop = (Keyword("for")  + Literal("(") + variable + Keyword("in")
            + expression + Literal(":") + expression + Literal(")") + group)

    assignment.setName('assign').setParseAction(
        lambda s,l,t: [(ASSIGN, t[0], t[2])])
    prior.setName('prior').setParseAction(
        lambda s,l,t: [(PRIOR, t[0], t[2], t[3])])
    loop.setName('loop').setParseAction(
        lambda s,l,t: [(LOOP, t[2], t[4], t[6], t[8:])])

    # Note: line breaks are ignored.  That means the following are valid:
    #     statement\n
    #     statement;\n
    #     statement; statement\n
    #     statement statement\n
    #     partial statement\n statement completion
    # Indeed, all of these forms exist in the openBugs example models.
    #comment = Literal("#[^\n]*")
    statement = (loop | assignment | prior) + Optional(Literal(';')).suppress()
    body = ZeroOrMore(statement)
    group << (Literal("{").suppress() + body + Literal("}").suppress())
    model = Keyword("model") + group + StringEnd()

    model.setName('model').setParseAction(
        lambda s,l,t: [(MODEL, t[1:])])

    if 0: # Debug
        all_terms = (
            model, group, body, statement, loop, prior, assignment,
            expression, term, atom, muldiv, addsub,
            value, constant, paren, function, pars,
            indexed_variable, variable, index, subscripts,
            slice, inner_range, paren_range,
        )
        for s in all_terms: s.setDebug(True)
    return model