示例#1
0
def make_jinja_parser(config, content):
    jinja_structured_elements_names = (
        DEFAULT_JINJA_STRUCTURED_ELEMENTS_NAMES +
        config.get('jinja_custom_elements_names', []))

    jinja_structured_element = P.alt(*[
        make_jinja_element_parser(
            [P.string(name) for name in names],
            content=content,
        ) for names in jinja_structured_elements_names
    ])

    # These tag names can't begin a Jinja element
    jinja_intermediate_tag_names = [
        n for _, *sublist in jinja_structured_elements_names for n in sublist
    ]

    jinja_intermediate_tag_name = P.alt(
        *(P.string(n) for n in jinja_intermediate_tag_names))

    jinja_element_single = make_jinja_element_parser(
        [
            jinja_intermediate_tag_name.should_fail(
                'not an intermediate Jinja tag name').then(jinja_name)
        ],
        content=content,
    )

    jinja_element = jinja_structured_element | jinja_element_single

    return jinja_variable | jinja_comment | jinja_element
示例#2
0
 def test_alt(self):
     self.assertRaises(ParseError, alt().parse, '')
     self.assertEqual(alt(letter, digit).parse('a'),
                      'a')
     self.assertEqual(alt(letter, digit).parse('1'),
                      '1')
     self.assertRaises(ParseError, alt(letter, digit).parse, '.')
示例#3
0
def make_jinja_parser(config, content):
    # Allow to override elements with the configuration
    jinja_structured_elements_names = dict(
        (names[0], names)
        for names
        in (
            DEFAULT_JINJA_STRUCTURED_ELEMENTS_NAMES +
            config.get('jinja_custom_elements_names', [])
        )
    ).values()

    jinja_structured_element = P.alt(*[
        make_jinja_element_parser(
            [P.string(name) for name in names],
            content=content,
        )
        for names in jinja_structured_elements_names
    ])

    # These tag names can't begin a Jinja element
    jinja_intermediate_tag_names = set(
        n
        for _, *sublist in jinja_structured_elements_names
        for n in sublist
    )

    jinja_intermediate_tag_name = P.alt(*(
        P.string(n) for n in jinja_intermediate_tag_names
    ))

    jinja_element_single = make_jinja_element_parser(
        [
            P.alt(
                # HACK: If we allow `{% if %}`s without `{% endif %}`s here,
                # `make_jinja_optional_container_parser` doesn’t work. It
                # is probably better to reject any structured tag name here.
                P.string('if'),

                jinja_intermediate_tag_name
            )
            .should_fail('not an intermediate Jinja tag name')
            .then(jinja_name)
        ],
        content=content,
    )

    jinja_element = jinja_structured_element | jinja_element_single

    return jinja_variable | jinja_comment | jinja_element
示例#4
0
def op():
    e1 = yield exp
    yield whitespace
    op = yield parsy.alt(*map(parsy.string, ['+', '-', '==', '<']))
    yield whitespace
    e2 = yield exp
    return {'Kind': kind(op), 'Left': e1, 'Right': e2}
示例#5
0
 def varchar_or_char():
     yield p.alt(
         spaceless_string("varchar"), spaceless_string("char")
     ).then(
         lparen.then(p.digit.at_least(1).concat()).skip(rparen).optional()
     )
     return String()
示例#6
0
def dwarfdump():
    import parsy as p

    def dbg(parser):
        return parser.mark().map(lambda x: print(repr(x)))

    newline = p.regex(r'[\r\n]').desc('newline')
    newlines = newline.times(min=1).desc('newlines')
    blank_line = newline.times(min=2).desc('blank line')
    rest_of_line = p.regex(r'.*$', flags=re.MULTILINE)

    quoted_string = p.string('"') >> p.regex(r'[^"]*') << p.string('"')
    hex_number = p.regex(r'0x[0-9a-fA-F]+').map(lambda x: int(x, 0)).desc(
        'hex number')
    decimal_number = p.regex(r'-?[0-9]+').map(lambda x: int(x, 0)).desc(
        'decimal number')
    boolean = (p.string('true')
               | p.string('false')).map(lambda b: b == 'true').desc('boolean')
    dwarf_code = p.string('DW_') >> p.regex(r'\w+')

    null = p.string('NULL')

    attribute_contents = p.alt(
        quoted_string,
        p.seq(hex_number,
              p.whitespace >> quoted_string).combine(_DwarfRawAttributeRef),
        hex_number,
        decimal_number,
        boolean,
        p.seq(
            p.string('DW_') >> p.regex(r'OP_\w+'),
            (p.whitespace >>
             (hex_number
              | decimal_number)).optional()).combine(DwarfAttributeOp),
        dwarf_code.map(DwarfAttributeVal),
    )

    attribute = p.seq(
        p.whitespace >> dwarf_code,
        p.whitespace >> p.string('(') >> attribute_contents << p.string(')'),
    )

    die = p.seq(
        address=hex_number << p.string(': '),
        indent=p.regex('(  )*').map(lambda i: len(i) // 2),
        tag=null | dwarf_code,
        attributes=(p.string('\n') >> attribute).many().map(dict),
    ).combine_dict(_DwarfRawDie)

    compilation_unit = p.seq(
        addr_size=(p.regex(r'.*addr_size = ') >> hex_number <<
                   rest_of_line).desc('compilation unit header'),
        children=blank_line >> die.sep_by(blank_line, min=1),
    ).combine_dict(DwarfCompilationUnit)

    return (yield
            (p.regex(r'.*:\s*file format.*\n\n') >>
             p.regex(r'.*\.debug_info contents:.*\n') >>
             compilation_unit.sep_by(blank_line) << newline.many()).many())
示例#7
0
文件: day19.py 项目: snyke7/aoc2020
 def internal_to_parser(idx):
     rule_def = rule_defs[idx]
     if isinstance(rule_def, str):
         return string(rule_def)
     else:
         return alt(*[
             seq(*list(map(internal_to_parser, to_seq))).map(lambda l: ''.join(l))
             for to_seq in rule_def
         ])
示例#8
0
def single_expression():
    unary = yield unary_operator.optional()

    # ordering below: variable after parens_expression to parse function calls correctly!
    elt = yield P.alt(int_literal, bool_literal, string_literal,
                      parens_expression, variable)
    if unary is not None:
        unary = var_from_op(unary)
        return ast.Application(start=unary.start,
                               end=elt.end,
                               function=unary,
                               args=[elt])
    else:
        return elt
    v = yield ident
    yield dot
    body = yield expr
    yield rparen
    return EQuantified(b, v, body)


@generate
def binop():
    op = yield ident
    if op not in e.bin_ops:
        yield fail("{} is not a binary operator".format(op))
    else:
        return op


@generate
def expr_cont_expr1():
    e1 = yield expr
    p1 = seq(binop, expr <<
             rparen).combine(lambda op, e2: EApply(EApply(EIdent(op), e1), e2))
    p2 = (expr << rparen).map(lambda e2: EApply(e1, e2))
    return (yield (p1 | p2))


expr = alt(ident.map(EIdent), (lparen >>
                               (expr_cont_quantified | expr_cont_expr1)))

thm = seq(expr.sep_by(lexme(string(","))),
          lexme(string("|-")) >> expr).combine(Thm)
示例#10
0
文件: core.py 项目: ibis-project/ibis
def spaceless_string(*strings: str):
    return spaceless(
        p.alt(*(p.string(string, transform=str.lower) for string in strings))
    )
示例#11
0
from basic import Sym, WS, Punc
from parsy import alt, decimal_digit, regex, seq, string

def make_number(sign, int_part, frac_part):
    result = float(int_part + '.' + frac_part) if frac_part else int(int_part)
    return result * -1 if sign else result

number_literal = seq(string('-').optional(), decimal_digit.at_least(1).concat(), string('.').then(decimal_digit.at_least(1).concat()).optional()).combine(make_number)

string_literal = string('"') >> regex(r'[^"]*') << string('"')

operator = regex(r'[]+*^/.\\@d_:!-]').map(Sym)

func = regex(r'sin|cos|tan|asin|acos|atan|deg|rad|pi|e|ln|log').map(Sym)

variable = regex(r'[A-Z]').map(Sym)

punc = regex(r'[\[]').map(Punc)

whitespace = string(' ').at_least(1).map(WS)

stacky_parser = alt(number_literal, operator, punc, func, variable, whitespace).many()
示例#12
0
文件: general.py 项目: quinor/latte
def addpos(p):
    @P.generate
    def addpos_impl():
        beg = yield pos
        obj = yield p
        end = yield pos
        assert isinstance(obj, ast.Node)
        return attr.evolve(obj, start=beg, end=end)

    return addpos_impl


sc = P.alt(
    P.regex(r"\s+", P.re.MULTILINE),
    P.regex(r"/\*.*?\*/", P.re.MULTILINE | P.re.DOTALL),
    P.regex(r"//.*\n"),
    P.regex(r"#.*\n"),
).desc("whitespace").many()


def lexeme(p):
    return p << sc


def symbol(str):
    return lexeme(P.string(str))


def rword(str):
    @lexeme
    @P.generate
示例#13
0
文件: parse.py 项目: jmanuel1/concat
def extension(parsers: ParserDict) -> None:
    # This parses the top level of a file.
    # top level =
    #   ENCODING, (word | statement | NEWLINE)*, [ NEWLINE ],
    #   ENDMARKER ;
    @parsy.generate
    def top_level_parser() -> Generator[parsy.Parser, Any, TopLevelNode]:
        encoding = yield parsers.token('ENCODING')
        newline = parsers.token('NEWLINE')
        statement = parsers['statement']
        word = parsers['word']
        children = yield (word | statement | newline).many()
        children = [
            child
            for child in children
            if not isinstance(child, concat.lex.Token)
        ]
        yield parsers.token('ENDMARKER')
        return TopLevelNode(encoding, children)

    parsers['top-level'] = desc_cumulatively(top_level_parser, 'top level')

    # This parses one of many types of statement.
    # The specific statement node is returned.
    # statement = import statement ;
    parsers['statement'] = parsers.ref_parser('import-statement')

    ImportStatementParserGenerator = Generator[
        parsy.Parser, Any, ImportStatementNode
    ]

    # This parses one of many types of word.
    # The specific word node is returned.
    # word =
    #   push word | literal word | name word | attribute word | quote word ;
    # literal word = number word | string word ;
    parsers['word'] = parsy.alt(
        parsers.ref_parser('push-word'),
        parsers.ref_parser('quote-word'),
        parsers.ref_parser('literal-word'),
        parsers.ref_parser('name-word'),
        parsers.ref_parser('attribute-word'),
    )
    parsers['literal-word'] = parsers.ref_parser(
        'number-word'
    ) | parsers.ref_parser('string-word')

    parsers['name-word'] = parsers.token('NAME').map(NameWordNode)

    parsers['number-word'] = parsers.token('NUMBER').map(NumberWordNode)

    parsers['string-word'] = parsers.token('STRING').map(StringWordNode)

    # This parses a quotation.
    # quote word = LPAR, word*, RPAR ;
    @parsy.generate('quote word')
    def quote_word_parser() -> Generator[parsy.Parser, Any, QuoteWordNode]:
        lpar = yield parsers.token('LPAR')
        if 'type-sequence' in parsers:
            input_stack_type_parser = parsers[
                'type-sequence'
            ] << parsers.token('COLON')
            input_stack_type = yield input_stack_type_parser.optional()
        else:
            input_stack_type = None
        children = yield parsers['word'].many()
        yield parsers.token('RPAR')
        return QuoteWordNode(children, lpar.start, input_stack_type)

    parsers['quote-word'] = quote_word_parser

    # This parses a push word into a node.
    # push word = DOLLARSIGN, word ;
    word = parsers.ref_parser('word')
    dollarSign = parsers.token('DOLLARSIGN')
    parsers['push-word'] = dollarSign >> word.map(PushWordNode)

    # Parsers an attribute word.
    # attribute word = DOT, NAME ;
    dot = parsers.token('DOT')
    name = parsers.token('NAME')
    parsers['attribute-word'] = dot >> name.map(AttributeWordNode)

    parsers['literal-word'] |= parsy.alt(
        parsers.ref_parser('none-word'),
        parsers.ref_parser('not-impl-word'),
        parsers.ref_parser('ellipsis-word'),
        parsers.ref_parser('bytes-word'),
        parsers.ref_parser('tuple-word'),
        parsers.ref_parser('list-word'),
        parsers.ref_parser('set-word'),
        parsers.ref_parser('dict-word'),
    )

    # This parses a none word.
    # none word = NONE ;
    parsers['none-word'] = parsers.token('NONE').map(NoneWordNode)

    # This parses a not-impl word.
    # not-impl word = NOTIMPL ;
    parsers['not-impl-word'] = parsers.token('NOTIMPL').map(NotImplWordNode)

    # This parses an ellipsis word.
    # ellipsis word = ELLIPSIS ;
    parsers['ellipsis-word'] = parsers.token('ELLIPSIS').map(EllipsisWordNode)

    parsers['word'] |= parsy.alt(
        parsers.ref_parser('subscription-word'),
        parsers.ref_parser('slice-word'),
        parsers.ref_parser('operator-word'),
        parsers.ref_parser('yield-word'),
        parsers.ref_parser('await-word'),
        parsers.ref_parser('assert-word'),
        parsers.ref_parser('raise-word'),
        parsers.ref_parser('try-word'),
        parsers.ref_parser('with-word'),
    )

    # This parses a subscription word.
    # subscription word = LSQB, word*, RSQB ;
    parsers['subscription-word'] = (
        parsers.token('LSQB')
        >> parsers.ref_parser('word').many().map(SubscriptionWordNode)
        << parsers.token('RSQB')
    )

    # This parses a slice word.
    # slice word = LSQB, word*, COLON, word*, [ COLON, word* ], RSQB ;
    @parsy.generate('slice word')
    def slice_word_parser():
        yield parsers.token('LSQB')
        start = yield parsers.ref_parser('word').many()
        yield parsers.token('COLON')
        stop = yield parsers.ref_parser('word').many()
        none = concat.lex.Token()
        none.type = 'NONE'
        step = [NoneWordNode(none)]
        if (yield parsers.token('COLON').optional()):
            step = yield parsers['word'].many()
        yield parsers.token('RSQB')
        return SliceWordNode([start, stop, step])

    parsers['slice-word'] = slice_word_parser

    parsers['operator-word'] = parsy.fail('operator')

    from concat.operators import operators

    for operator_name, token_type, node_type, _ in operators:
        parser_name = operator_name + '-word'
        parsers[parser_name] = parsers.token(token_type).map(node_type)
        parsers['operator-word'] |= parsers.ref_parser(parser_name)

    # This parses a bytes word.
    # bytes word = BYTES ;
    parsers['bytes-word'] = parsers.token('BYTES').map(BytesWordNode)

    def iterable_word_parser(
        delimiter: str, cls: Type[IterableWordNode], desc: str
    ) -> 'parsy.Parser[Token, IterableWordNode]':
        @parsy.generate
        def parser() -> Generator:
            location = (yield parsers.token('L' + delimiter)).start
            element_words = yield word_list_parser
            yield parsers.token('R' + delimiter)
            return cls(element_words, location)

        return concat.parser_combinators.desc_cumulatively(parser, desc)

    # This parses a tuple word.
    # tuple word = LPAR, word list, RPAR ;
    parsers['tuple-word'] = iterable_word_parser(
        'PAR', TupleWordNode, 'tuple word'
    )

    # This parses a list word.
    # list word = LSQB, word list, RSQB ;
    parsers['list-word'] = iterable_word_parser(
        'SQB', ListWordNode, 'list word'
    )

    # word list = (COMMA | word+, COMMA | word+, (COMMA, word+)+, [ COMMA ]) ;
    @parsy.generate('word list')
    def word_list_parser() -> Generator:
        empty: 'parsy.Parser[Token, List[Words]]' = parsers.token(
            'COMMA'
        ).result([])
        singleton = parsy.seq(
            parsers['word'].at_least(1) << parsers.token('COMMA')
        )
        multiple_element = (
            parsers['word'].at_least(1).sep_by(parsers.token('COMMA'), min=2)
            << parsers.token('COMMA').optional()
        )
        element_words = yield (multiple_element | singleton | empty)
        return element_words

    # This parses a set word.
    # list word = LBRACE, word list, RBRACE ;
    parsers['set-word'] = iterable_word_parser(
        'BRACE', SetWordNode, 'set word'
    )

    # This parses a dict word.
    # dict word =
    #   LBRACE,
    #   [ key-value pair, (COMMA, key-value pair)* ],
    #   [ COMMA ],
    #   RBRACE ;
    # key-value pair = word*, COLON, word* ;
    @parsy.generate('dict word')
    def dict_word_parser() -> Generator:
        location = (yield parsers.token('LBRACE')).start
        elements = (
            key_value_pair.sep_by(parsers.token('COMMA'), min=0)
            << parsers.token('COMMA').optional()
        )
        element_words = yield elements
        yield parsers.token('RBRACE')
        return DictWordNode(element_words, location)

    parsers['dict-word'] = dict_word_parser

    key_value_pair = parsy.seq(
        parsers.ref_parser('word').many() << parsers.token('COLON'),
        parsers.ref_parser('word').many(),
    )

    parsers['yield-word'] = parsers.token('YIELD').map(YieldWordNode)

    parsers['await-word'] = parsers.token('AWAIT').map(AwaitWordNode)

    parsers['assert-word'] = parsers.token('ASSERT').map(AssertWordNode)

    parsers['raise-word'] = parsers.token('RAISE').map(RaiseWordNode)

    parsers['try-word'] = parsers.token('TRY').map(TryWordNode)

    parsers['with-word'] = parsers.token('WITH').map(WithWordNode)

    parsers['statement'] |= parsy.alt(
        parsers.ref_parser('del-statement'),
        parsers.ref_parser('async-funcdef-statement'),
        parsers.ref_parser('classdef-statement'),
        parsers.ref_parser('funcdef-statement'),
    )

    # Parsers a del statement.
    # del statement = DEL, target words ;
    # target words = target word, (COMMA, target word)*, [ COMMA ] ;
    # target word = name word
    #   | LPAR, target words, RPAR
    #   | LSQB, target words, RQSB
    #   | attribute word
    #   | subscription word
    #   | slice word ;
    parsers['del-statement'] = parsers.token('DEL') >> parsers.ref_parser(
        'target-words'
    ).map(DelStatementNode)

    from concat.astutils import flatten

    parsers['target-words'] = (
        parsers.ref_parser('target-word').sep_by(parsers.token('COMMA'), min=1)
        << parsers.token('COMMA').optional()
    ).map(flatten)

    parsers['target-word'] = parsy.alt(
        parsers.ref_parser('name-word'),
        parsers.token('LPAR')
        >> parsers.ref_parser('target-words')
        << parsers.token('RPAR'),
        parsers.token('LSQB')
        >> parsers.ref_parser('target-words')
        << parsers.token('RSQB'),
        parsers.ref_parser('attribute-word'),
        parsers.ref_parser('subscription-word'),
        parsers.ref_parser('slice-word'),
    )

    # This parses an async function definition.
    # async funcdef statement = ASYNC, funcdef statement ;
    @parsy.generate('async funcdef statement')
    def async_funcdef_statement_parser() -> Generator:
        location = (yield parsers.token('ASYNC')).start
        func: FuncdefStatementNode = (yield parsers['funcdef-statement'])
        name = concat.lex.Token()
        name.value = func.name
        return AsyncFuncdefStatementNode(
            name,
            func.decorators,
            func.annotation,
            func.body,
            location,
            func.stack_effect,
        )

    parsers['async-funcdef-statement'] = async_funcdef_statement_parser

    # This parses a function definition.
    # funcdef statement = DEF, NAME, [ LPAR, stack effect, RPAR ], decorator*,
    #   [ annotation ], COLON, suite ;
    # decorator = AT, word ;
    # annotation = RARROW, word* ;
    # suite = NEWLINE, INDENT, (word | statement, NEWLINE)+, DEDENT | statement
    #    | word+ ;
    # The stack effect syntax is defined within the typecheck module.
    @parsy.generate
    def funcdef_statement_parser() -> Generator:
        location = (yield parsers.token('DEF')).start
        name = yield parsers.token('NAME')
        if (yield parsers.token('LPAR').optional()):
            effect_ast = yield parsers['stack-effect-type']
            yield parsers.token('RPAR')
        else:
            effect_ast = None
        decorators = yield decorator.many()
        annotation = yield annotation_parser.optional()
        yield parsers.token('COLON')
        body = yield suite
        return FuncdefStatementNode(
            name, decorators, annotation, body, location, effect_ast
        )

    parsers['funcdef-statement'] = concat.parser_combinators.desc_cumulatively(
        funcdef_statement_parser, 'funcdef statement'
    )

    decorator = parsers.token('AT') >> parsers.ref_parser('word')

    annotation_parser = (
        parsers.token('RARROW') >> parsers.ref_parser('word').many()
    )

    @parsy.generate
    def suite():
        words = parsers['word'].at_least(1)
        statement = parsy.seq(parsers['statement'])
        block_content = (
            parsers['word'] << parsers.token('NEWLINE').optional()
            | parsers['statement'] << parsers.token('NEWLINE')
        ).at_least(1)
        indented_block = (
            parsers.token('NEWLINE').optional()
            >> parsers.token('INDENT')
            >> block_content
            << parsers.token('DEDENT')
        )
        return (yield indented_block | statement | words)

    suite = concat.parser_combinators.desc_cumulatively(suite, 'suite')

    @parsy.generate('module')
    def module():
        name = parsers.token('NAME').map(operator.attrgetter('value'))
        return '.'.join((yield name.sep_by(parsers.token('DOT'), min=1)))

    # These following parsers parse import statements.
    # import statement = IMPORT, module, [ AS, NAME ]
    #   | FROM, relative module, IMPORT, NAME, [ AS, NAME ]
    #   | FROM, module, IMPORT, STAR;
    # module = NAME, (DOT, NAME)* ;
    # relative module = DOT*, module | DOT+ ;

    @parsy.generate('import statement')
    def import_statement_parser() -> Generator:
        location = (yield parsers.token('IMPORT')).start
        module_name = yield module
        asname_parser = parsers.token('NAME').map(operator.attrgetter('value'))
        asname = None
        if (yield parsers.token('AS').optional()):
            asname = yield asname_parser
        return ImportStatementNode(module_name, asname, location)

    parsers['import-statement'] = import_statement_parser

    @parsy.generate('relative module')
    def relative_module():
        dot = parsers.token('DOT').map(operator.attrgetter('value'))
        return (yield (dot.many().concat() + module) | dot.at_least(1))

    @parsy.generate('from-import statement')
    def from_import_statement_parser() -> Generator:
        location = (yield parsers.token('FROM')).start
        module = yield relative_module
        name_parser = parsers.token('NAME').map(operator.attrgetter('value'))
        imported_name = yield parsers.token('IMPORT') >> name_parser
        asname = None
        if (yield parsers.token('AS').optional()):
            asname = yield name_parser
        return FromImportStatementNode(module, imported_name, asname, location)

    parsers['import-statement'] |= from_import_statement_parser

    @parsy.generate('from-import-star statement')
    def from_import_star_statement_parser() -> Generator:
        location = (yield parsers.token('FROM')).start
        module_name = yield module
        yield parsers.token('IMPORT')
        yield parsers.token('STAR')
        return FromImportStarStatementNode(module_name, location)

    parsers['import-statement'] |= from_import_star_statement_parser

    # This parses a class definition statement.
    # classdef statement = CLASS, NAME, decorator*, [ bases ], keyword arg*,
    #   COLON, suite ;
    # bases = tuple word ;
    # keyword arg = NAME, EQUAL, word ;
    @parsy.generate('classdef statement')
    def classdef_statement_parser():
        location = (yield parsers.token('CLASS')).start
        name_token = yield parsers.token('NAME')
        decorators = yield decorator.many()
        bases_list = yield bases.optional()
        keyword_args = yield keyword_arg.map(tuple).many()
        yield parsers.token('COLON')
        body = yield suite
        return ClassdefStatementNode(
            name_token.value,
            body,
            location,
            decorators,
            bases_list,
            keyword_args,
        )

    parsers['classdef-statement'] = classdef_statement_parser

    bases = parsers.ref_parser('tuple-word').map(
        operator.attrgetter('tuple_children')
    )

    keyword_arg = parsy.seq(
        parsers.token('NAME').map(operator.attrgetter('value'))
        << parsers.token('EQUAL'),
        parsers.ref_parser('word'),
    )

    parsers['word'] |= parsers.ref_parser('cast-word')

    @parsy.generate
    def cast_word_parser() -> Generator:
        location = (yield parsers.token('CAST')).start
        yield parsers.token('LPAR')
        type_ast = yield parsers['type']
        yield parsers.token('RPAR')
        return CastWordNode(type_ast, location)

    # This parses a cast word.
    # none word = LPAR, type, RPAR, CAST ;
    # The grammar of 'type' is defined by the typechecker.
    parsers['cast-word'] = concat.parser_combinators.desc_cumulatively(
        cast_word_parser, 'cast word'
    )
示例#14
0
def typecheck_extension(parsers: concat.parse.ParserDict) -> None:
    @parsy.generate
    def attribute_type_parser() -> Generator:
        location = (yield parsers.token('DOT')).start
        name = (yield parsers.token('NAME')).value
        yield parsers.token('COLON')
        type = yield parsers['type']
        raise NotImplementedError('better think about the syntax of this')

    @parsy.generate
    def named_type_parser() -> Generator:
        name_token = yield parsers.token('NAME')
        return NamedTypeNode(name_token.start, name_token.value)

    @parsy.generate
    def type_sequence_parser() -> Generator:
        name = parsers.token('NAME')
        individual_type_variable = (
            # FIXME: Keep track of individual type variables
            parsers.token('BACKTICK') >> name >> parsy.success(None))
        lpar = parsers.token('LPAR')
        rpar = parsers.token('RPAR')
        nested_stack_effect = lpar >> parsers['stack-effect-type'] << rpar
        type = parsers['type'] | individual_type_variable | nested_stack_effect

        # TODO: Allow type-only items
        item = parsy.seq(
            name, (parsers.token('COLON') >>
                   type).optional()).map(_TypeSequenceIndividualTypeNode)
        items = item.many()

        seq_var = parsers.token('STAR') >> name
        seq_var_parsed, i = yield parsy.seq(seq_var.optional(), items)
        seq_var_value = None

        if seq_var_parsed is None and i:
            location = i[0].location
        elif seq_var_parsed is not None:
            location = seq_var_parsed.start
            seq_var_value = seq_var_parsed.value
        else:
            location = None

        return TypeSequenceNode(location, seq_var_value, i)

    @parsy.generate
    def stack_effect_type_parser() -> Generator:
        separator = parsers.token('MINUS').times(2)

        stack_effect = parsy.seq(  # type: ignore
            parsers['type-sequence'] << separator, parsers['type-sequence'])

        i, o = yield stack_effect

        # FIXME: Get the location
        return StackEffectTypeNode((0, 0), i, o)

    @parsy.generate
    def intersection_type_parser() -> Generator:
        yield parsers.token('AMPER')
        type_1 = yield parsers['type']
        type_2 = yield parsers['type']
        return IntersectionTypeNode(type_1.location, type_1, type_2)

    parsers['stack-effect-type'] = concat.parser_combinators.desc_cumulatively(
        stack_effect_type_parser, 'stack effect type')

    @parsy.generate
    def generic_type_parser() -> Generator:
        type = yield parsers['nonparameterized-type']
        yield parsers.token('LSQB')
        type_arguments = yield parsers['type'].sep_by(parsers.token('COMMA'),
                                                      min=1)
        yield parsers.token('RSQB')
        return _GenericTypeNode(type.location, type, type_arguments)

    parsers['nonparameterized-type'] = parsy.alt(
        concat.parser_combinators.desc_cumulatively(intersection_type_parser,
                                                    'intersection type'),
        concat.parser_combinators.desc_cumulatively(attribute_type_parser,
                                                    'attribute type'),
        concat.parser_combinators.desc_cumulatively(named_type_parser,
                                                    'named type'),
        parsers.ref_parser('stack-effect-type'),
    )

    parsers['type'] = parsy.alt(
        concat.parser_combinators.desc_cumulatively(generic_type_parser,
                                                    'generic type'),
        parsers.ref_parser('nonparameterized-type'),
    )

    parsers['type-sequence'] = concat.parser_combinators.desc_cumulatively(
        type_sequence_parser, 'type sequence')
示例#15
0
            errors.Error(
                start=then_branch.start,
                end=then_branch.end,
                kind=errors.ParseKind.AmbiguousIf,
                message="There is an ambiguous if-if-else construct."))
    return ast.If(cond=cond, then_branch=then_branch, else_branch=else_branch)


@G.addpos
@P.generate
def while_stmt():
    yield G.rword("while")
    cond = yield G.parens(E.expression)
    body = yield statement
    return ast.While(cond=cond, body=body)


raw_statement = P.alt(brace_block, declaration, assignment, plusplus,
                      minusminus, ret, if_stmt, while_stmt, free_expr)


@G.addpos
@P.generate
def statement():
    st = yield raw_statement
    if not isinstance(st, ast.Block):
        bl = ast.Block(statements=[st])
        bl.attrs.generated = True
        return bl
    return st
示例#16
0
文件: day24.py 项目: snyke7/aoc2020
from parsy import string, alt

direction_parse = alt(
    string('sw').result((-1, 1)),
    string('se').result((-1, 0)),
    string('nw').result((1, 0)),
    string('ne').result((1, -1)),
    string('w').result((0, 1)),
    string('e').result((0, -1)))
ordinal_directions = [(1, 0), (1, -1), (-1, 0), (-1, 1), (0, 1), (0, -1)]
directions_parse = direction_parse.many()
directions_list_parse = (directions_parse << string('\n')).many()


def get_destination(dir_list):
    return sum(map(lambda pr: pr[0],
                   dir_list)), sum(map(lambda pr: pr[1], dir_list))


def get_flipped_tiles(dir_list):
    flipped = set()
    for dest in map(get_destination, dir_list):
        if dest not in flipped:
            flipped.add(dest)
        else:
            flipped.remove(dest)
    return flipped


def get_neighbour_tiles(tile_set):
    return {(tx + dx, ty + dy)
示例#17
0
variable = G.addpos(G.identifier.map(lambda v: ast.Variable(var=v)))

int_literal = G.addpos(G.number.map(lambda v: ast.IConstant(val=v)))

bool_literal = G.addpos(
    (G.rword("true").result(True) | G.rword("false").result(False)
     ).map(lambda v: ast.BConstant(val=v)).desc("boolean literal"))

string_literal = G.addpos(
    G.lexeme(
        P.regex(r'".*?"').map(lambda s: ast.SConstant(val=s[1:-1])).desc(
            "string literal")))

unary_operator = G.addpos(
    P.alt(*map(lambda k: G.symbol(k).result(prelude.unary_operator_map[k]),
               prelude.unary_operator_map.keys())).desc("unary operator"))

binary_operator = G.addpos(
    P.alt(*map(lambda k: G.symbol(k).result(prelude.binary_operator_map[k]),
               prelude.binary_operator_map.keys())).desc("binary operator"))


def var_from_op(op: ast.Operator) -> ast.Variable:
    return ast.Variable(start=op.start, end=op.end, var=op.name)


@P.generate
def parens_expression():
    start = yield G.pos
    called_fn = yield variable.optional()
    params = yield G.parens(expression.sep_by(G.symbol(",")))
示例#18
0
            builder.add(start)
            builder.add(poss_range)
            break

        if end < start:
            raise RuntimeError(f"Invalid range: {start}-{end}")
        builder.add(start, end)
        start = yield any_char

    return Lit(builder.min, builder.max)


base = alt(
    char_from(".").result(Lit(CHAR_MIN, CHAR_MAX)),
    char_from("^$"),  # TODO
    string("\\") >> any_char.map(lambda c: Lit(c, c)),
    char_class,
    string("(") >> regex << string(")"),
    test_char(lambda c: c not in "?+*[()|", "").map(lambda c: Lit(c, c)),
)


@attr.s(eq=False)
class Node:
    eps_transitions = attr.ib(factory=list)
    matcher = attr.ib(default=None)
    next = attr.ib(default=None)

    def min_matching(self):
        return self.matcher.min

    def max_matching(self):
示例#19
0
文件: datatypes.py 项目: cpcloud/ibis
def spaceless_string(*strings: str):
    return spaceless(
        p.alt(*[p.string(s, transform=str.lower) for s in strings]))