示例#1
0
    def reduce_NodeName_LPAREN_OptFuncArgList_RPAREN(self, *kids):
        module = kids[0].val.module
        func_name = kids[0].val.name
        name = func_name if not module else (module, func_name)

        last_named_seen = None
        args = []
        kwargs = {}
        for argname, argname_ctx, arg in kids[2].val:
            if argname is not None:
                if argname in kwargs:
                    raise EdgeQLSyntaxError(
                        f"duplicate named argument `{argname}`",
                        context=argname_ctx)

                last_named_seen = argname
                kwargs[argname] = arg

            else:
                if last_named_seen is not None:
                    raise EdgeQLSyntaxError(
                        f"positional argument after named "
                        f"argument `{last_named_seen}`",
                        context=arg.context)
                args.append(arg)

        self.val = qlast.FunctionCall(func=name, args=args, kwargs=kwargs)
示例#2
0
 def reduce_ARGUMENT(self, dp):
     if dp.val[1].isdigit():
         raise EdgeQLSyntaxError(f'numeric parameters are not supported',
                                 context=dp.context)
     else:
         raise EdgeQLSyntaxError(
             f"function parameters do not need a $ prefix, "
             f"rewrite as '{dp.val[1:]}'",
             context=dp.context)
示例#3
0
 def reduce_ARGUMENT_ASSIGN_Expr(self, *kids):
     if kids[0].val[1].isdigit():
         raise EdgeQLSyntaxError(
             f"numeric named arguments are not supported",
             context=kids[0].context)
     else:
         raise EdgeQLSyntaxError(
             f"named arguments do not need a '$' prefix, "
             f"rewrite as '{kids[0].val[1:]} := ...'",
             context=kids[0].context)
示例#4
0
    def _process_function_body(self, block):
        props = {}

        commands = []
        code = None
        language = qlast.Language.SQL
        from_expr = False
        from_function = None

        for node in block.val:
            if isinstance(node, qlast.FunctionCode):
                if node.from_function:
                    if from_function is not None:
                        raise EdgeQLSyntaxError(
                            'more than one FROM FUNCTION clause',
                            context=node.context)
                    from_function = node.from_function

                elif node.code:
                    if code is not None:
                        raise EdgeQLSyntaxError(
                            'more than one FROM <code> clause',
                            context=node.context)
                    code = node.code
                    language = node.language

                else:
                    # FROM SQL EXPRESSION
                    from_expr = True
            else:
                commands.append(node)

        if (code is None and from_function is None and not from_expr):
            raise EdgeQLSyntaxError(
                'CREATE FUNCTION requires at least one FROM clause',
                context=block.context)

        else:
            if from_expr and (from_function or code):
                raise EdgeQLSyntaxError(
                    'FROM SQL EXPRESSION is mutually exclusive with other '
                    'FROM variants',
                    context=block.context)

            props['code'] = qlast.FunctionCode(
                language=language,
                from_function=from_function,
                from_expr=from_expr,
                code=code,
            )

        if commands:
            props['commands'] = commands

        return props
示例#5
0
    def reduce_Insert(self, *kids):
        r'%reduce INSERT OptionallyAliasedExpr OptUnlessConflictClause'

        subj = kids[1].val.expr
        subj_alias = kids[1].val.alias

        # check that the insert subject is either a path or a shape
        if isinstance(subj, qlast.Shape):
            objtype = subj.expr
            shape = subj.elements
        else:
            objtype = subj
            shape = []

        unless_conflict = kids[2].val

        if not isinstance(objtype, qlast.Path):
            raise EdgeQLSyntaxError(
                "insert expression must be an object type reference",
                context=subj.context)

        self.val = qlast.InsertQuery(
            subject=objtype,
            subject_alias=subj_alias,
            shape=shape,
            unless_conflict=unless_conflict,
        )
示例#6
0
    def _float_to_path(self, token, context):
        from edb.schema import pointers as s_pointers

        # make sure that the float is of the type 0.1
        parts = token.val.split('.')
        if not (len(parts) == 2 and parts[0].isdigit() and parts[1].isdigit()):
            raise EdgeQLSyntaxError(f"Unexpected {token.val!r}",
                                    context=token.context)

        # context for the AST is established manually here
        return [
            qlast.Ptr(
                ptr=qlast.ObjectRef(
                    name=parts[0],
                    context=token.context,
                ),
                direction=s_pointers.PointerDirection.Outbound,
                context=context,
            ),
            qlast.Ptr(
                ptr=qlast.ObjectRef(
                    name=parts[1],
                    context=token.context,
                ),
                direction=s_pointers.PointerDirection.Outbound,
                context=token.context,
            )
        ]
示例#7
0
文件: commondl.py 项目: fantix/edgedb
def _parse_language(node):
    try:
        return qlast.Language(node.val.upper())
    except ValueError:
        raise EdgeQLSyntaxError(
            f'{node.val} is not a valid language',
            context=node.context) from None
示例#8
0
    def parse(self, input):
        try:
            self.reset_parser(input)
            mod = self.get_parser_spec_module()

            tok = self.lexer.token()

            while tok:
                token = self.process_lex_token(mod, tok)
                if token is not None:
                    self.parser.token(token)

                tok = self.lexer.token()

            self.parser.eoi()

        except TokenizerError as e:
            message, position = e.args
            hint = _derive_hint(input, message, position)
            raise EdgeQLSyntaxError(message,
                                    context=self.context(pos=position),
                                    hint=hint) from e

        except parsing.SyntaxError as e:
            raise self.get_exception(e, context=self.context(tok),
                                     token=tok) from e

        except ParserError as e:
            raise self.get_exception(e, context=e.context) from e

        except lexer.LexError as e:
            raise self.get_exception(e, context=self.context(None)) from e

        return self.parser.start[0].val
示例#9
0
文件: ddl.py 项目: alipqb/edgedb
    def reduce_FROM_Identifier_CAST(self, *kids):
        lang = commondl._parse_language(kids[1])
        if lang != qlast.Language.SQL:
            raise EdgeQLSyntaxError(
                f'{lang} language is not supported in FROM CAST clause',
                context=kids[1].context) from None

        self.val = qlast.CastCode(language=lang, from_cast=True)
示例#10
0
    def reduce_FROM_Identifier_EXPRESSION(self, *kids):
        lang = _parse_language(kids[1])
        if lang != qlast.Language.SQL:
            raise EdgeQLSyntaxError(
                f'{lang} language is not supported in FROM clause',
                context=kids[1].context) from None

        self.val = qlast.FunctionCode(language=lang)
示例#11
0
    def reduce_LPAREN_FuncDeclArgList_RPAREN(self, *kids):
        args = kids[1].val

        last_pos_default_arg = None
        last_named_arg = None
        variadic_arg = None
        names = set()
        for arg in args:
            if arg.name in names:
                raise EdgeQLSyntaxError(
                    f'duplicate parameter name `{arg.name}`',
                    context=arg.context)
            names.add(arg.name)

            if arg.kind is qltypes.ParameterKind.VARIADIC:
                if variadic_arg is not None:
                    raise EdgeQLSyntaxError('more than one variadic argument',
                                            context=arg.context)
                elif last_named_arg is not None:
                    raise EdgeQLSyntaxError(
                        f'NAMED ONLY argument `{last_named_arg.name}` '
                        f'before VARIADIC argument `{arg.name}`',
                        context=last_named_arg.context)
                else:
                    variadic_arg = arg

                if arg.default is not None:
                    raise EdgeQLSyntaxError(
                        f'VARIADIC argument `{arg.name}` '
                        f'cannot have a default value',
                        context=arg.context)

            elif arg.kind is qltypes.ParameterKind.NAMED_ONLY:
                last_named_arg = arg

            else:
                if last_named_arg is not None:
                    raise EdgeQLSyntaxError(
                        f'positional argument `{arg.name}` '
                        f'follows NAMED ONLY argument `{last_named_arg.name}`',
                        context=arg.context)

                if variadic_arg is not None:
                    raise EdgeQLSyntaxError(
                        f'positional argument `{arg.name}` '
                        f'follows VARIADIC argument `{variadic_arg.name}`',
                        context=arg.context)

            if arg.kind is qltypes.ParameterKind.POSITIONAL:
                if arg.default is None:
                    if last_pos_default_arg is not None:
                        raise EdgeQLSyntaxError(
                            f'positional argument `{arg.name}` without '
                            f'default follows positional argument '
                            f'`{last_pos_default_arg.name}` with default',
                            context=arg.context)
                else:
                    last_pos_default_arg = arg

        self.val = args
示例#12
0
文件: ddl.py 项目: alipqb/edgedb
    def reduce_FROM_Identifier_BaseStringConstant(self, *kids):
        lang = commondl._parse_language(kids[1])
        if lang not in {qlast.Language.SQL, qlast.Language.EdgeQL}:
            raise EdgeQLSyntaxError(
                f'{lang} language is not supported in FROM clause',
                context=kids[1].context) from None

        self.val = qlast.CastCode(language=lang,
                                  code=kids[2].val.value)
示例#13
0
    def reduce_FROM_Identifier_FUNCTION_BaseStringConstant(self, *kids):
        lang = _parse_language(kids[1])
        if lang != qlast.Language.SQL:
            raise EdgeQLSyntaxError(
                f'{lang} language is not supported in FROM FUNCTION clause',
                context=kids[1].context) from None

        self.val = qlast.FunctionCode(language=lang,
                                      from_function=kids[3].val.value)
示例#14
0
    def reduce_RSCONST(self, str_tok):
        match = lexutils.VALID_RAW_STRING_RE.match(str_tok.val)
        if not match:
            raise EdgeQLSyntaxError(
                f"invalid raw string literal", context=str_tok.context)

        quote = match.group('Q')
        val = match.group('body')

        self.val = qlast.RawStringConstant(value=val, quote=quote)
示例#15
0
    def reduce_SCONST(self, str_tok):
        match = lexutils.VALID_STRING_RE.match(str_tok.val)

        if not match:
            raise EdgeQLSyntaxError(
                f"invalid string literal", context=str_tok.context)
        if match.group('err_esc'):
            raise EdgeQLSyntaxError(
                f"invalid string literal: invalid escape sequence "
                f"'{match.group('err_esc')}'",
                context=str_tok.context)

        quote = match.group('Q')
        val = match.group('body')

        # handle line continuations
        val = re.sub(r'\\\n', '', val)

        self.val = qlast.StringConstant(value=val, quote=quote)
示例#16
0
文件: sdl.py 项目: xing0713/edgedb
    def _process_function_body(self, block):
        props = _process_commands(block.val)
        function_code = props.get('function_code')

        if (not function_code or
            (function_code.code is None and function_code.from_function is None
             and not function_code.from_expr)):
            raise EdgeQLSyntaxError(
                'CREATE FUNCTION requires at least one FROM clause',
                context=block.context)

        else:
            if function_code.from_expr and (function_code.from_function
                                            or function_code.code):
                raise EdgeQLSyntaxError(
                    'FROM SQL EXPRESSION is mutually exclusive with other '
                    'FROM variants',
                    context=block.context)

        return props
示例#17
0
    def reduce_BCONST(self, bytes_tok):
        val = bytes_tok.val
        match = lexutils.VALID_BYTES_RE.match(val)

        if not match:
            raise EdgeQLSyntaxError(f"invalid bytes literal",
                                    context=bytes_tok.context)
        if match.group('err_esc'):
            raise EdgeQLSyntaxError(
                f"invalid bytes literal: invalid escape sequence "
                f"'{match.group('err_esc')}'",
                context=bytes_tok.context)
        if match.group('err'):
            raise EdgeQLSyntaxError(
                f"invalid bytes literal: character '{match.group('err')}' "
                f"is outside of the ASCII range",
                context=bytes_tok.context)

        self.val = qlast.BytesConstant(value=match.group('body'),
                                       quote=match.group('BQ'))
示例#18
0
def _validate_declarations(
    declarations: Sequence[Union[qlast.ModuleDeclaration, qlast.DDLCommand]]
) -> None:
    # Check that top-level declarations either use fully-qualified
    # names or are module blocks.
    for decl in declarations:
        if (not isinstance(decl, qlast.ModuleDeclaration)
                and decl.name.module is None):
            raise EdgeQLSyntaxError(
                "only fully-qualified name is allowed in "
                "top-level declaration",
                context=decl.name.context)
示例#19
0
文件: ddl.py 项目: alipqb/edgedb
    def reduce_FROM_Identifier_OPERATOR_BaseStringConstant(self, *kids):
        lang = commondl._parse_language(kids[1])
        if lang != qlast.Language.SQL:
            raise EdgeQLSyntaxError(
                f'{lang} language is not supported in FROM OPERATOR clause',
                context=kids[1].context) from None

        sql_operator = kids[3].val.value
        m = re.match(r'([^(]+)(?:\((\w*(?:,\s*\w*)*)\))?', sql_operator)
        if not m:
            raise EdgeQLSyntaxError(
                f'invalid syntax for FROM OPERATOR clause',
                context=kids[3].context) from None

        sql_operator = (m.group(1),)
        if m.group(2):
            operands = tuple(op.strip() for op in m.group(2).split(','))
            sql_operator += operands

        self.val = qlast.OperatorCode(
            language=lang, from_operator=sql_operator)
示例#20
0
    def reduce_ReservedKeyword(self, *kids):
        name = kids[0].val
        if name[:2] == '__' and name[-2:] == '__':
            # There are a few reserved keywords like __std__ and __subject__
            # that can be used in paths but are prohibited to be used
            # anywhere else. So just as the tokenizer prohibits using
            # __names__ in general, we enforce the rule here for the
            # few remaining reserved __keywords__.
            raise EdgeQLSyntaxError(
                "identifiers surrounded by double underscores are forbidden",
                context=kids[0].context)

        self.val = name
示例#21
0
文件: commondl.py 项目: fantix/edgedb
    def reduce_VERSION_BaseStringConstant(self, *kids):
        version = kids[1].val

        try:
            verutils.parse_version(version.value)
        except ValueError:
            raise EdgeQLSyntaxError(
                'invalid extension version format',
                details='Expected a SemVer-compatible format.',
                context=version.context,
            ) from None

        self.val = version
示例#22
0
    def validate_subtype_list(self, lst):
        has_nonstrval = has_strval = has_items = False
        for el in lst.val:
            if isinstance(el, qlast.TypeExprLiteral):
                has_strval = True
            elif isinstance(el, qlast.TypeName):
                if el.name:
                    has_items = True
                else:
                    has_nonstrval = True

        if (has_nonstrval or has_items) and has_strval:
            # Prohibit cases like `tuple<a: int64, 'aaaa'>` and
            # `enum<bbbb, 'aaaa'>`
            raise EdgeQLSyntaxError(
                "mixing string type literals and type names is not supported",
                context=lst.context)

        if has_items and has_nonstrval:
            # Prohibit cases like `tuple<a: int64, int32>`
            raise EdgeQLSyntaxError(
                "mixing named and unnamed subtype declarations "
                "is not supported",
                context=lst.context)
示例#23
0
    def reduce_SCONST(self, str_tok):
        match = lexutils.VALID_STRING_RE.match(str_tok.val)

        if not match:
            raise EdgeQLSyntaxError(f"invalid string literal",
                                    context=str_tok.context)
        if match.group('err_esc'):
            raise EdgeQLSyntaxError(
                f"invalid string literal: invalid escape sequence "
                f"'{match.group('err_esc')}'",
                context=str_tok.context)
        elif match.group('err_cont'):
            raise EdgeQLSyntaxError(
                f"invalid string literal: invalid line continuation",
                hint="newline has to immediately follow '\\'",
                context=str_tok.context)

        quote = match.group('Q')
        val = match.group('body')

        # collapse the whitespace after a line continuation
        val = lexutils.collapse_newline_whitespace(val)

        self.val = qlast.StringConstant(value=val, quote=quote)
示例#24
0
 def reduce_OptParameterKind_FuncDeclArgName_OptDefault(self, *kids):
     raise EdgeQLSyntaxError(
         f'missing type declaration for the `{kids[1].val}` parameter',
         context=kids[1].context)
示例#25
0
 def reduce_DOLLAR_ICONST(self, dk, di):
     raise EdgeQLSyntaxError(f'numeric parameters are not supported',
                             context=dk.context)
示例#26
0
 def reduce_DOLLAR_AnyIdentifier(self, dk, dp):
     raise EdgeQLSyntaxError(
         f"function parameters do not need a $ prefix, "
         f"rewrite as '{dp.val}'",
         context=dk.context)
示例#27
0
 def reduce_Shape(self, *kids):
     raise EdgeQLSyntaxError(f"Missing ':' before '{{' in a sub-shape",
                             context=kids[0].context)
示例#28
0
    def _process_function_body(self, block, *, optional_using: bool = False):
        props: typing.Dict[str, typing.Any] = {}

        commands = []
        code = None
        nativecode = None
        language = qlast.Language.EdgeQL
        from_expr = False
        from_function = None

        for node in block.val:
            if isinstance(node, qlast.FunctionCode):
                if node.from_function:
                    if from_function is not None:
                        raise EdgeQLSyntaxError(
                            'more than one USING FUNCTION clause',
                            context=node.context)
                    from_function = node.from_function
                    language = qlast.Language.SQL

                elif node.nativecode:
                    if code is not None or nativecode is not None:
                        raise EdgeQLSyntaxError(
                            'more than one USING <code> clause',
                            context=node.context)
                    nativecode = node.nativecode
                    language = node.language

                elif node.code:
                    if code is not None or nativecode is not None:
                        raise EdgeQLSyntaxError(
                            'more than one USING <code> clause',
                            context=node.context)
                    code = node.code
                    language = node.language

                else:
                    # USING SQL EXPRESSION
                    from_expr = True
                    language = qlast.Language.SQL
            else:
                commands.append(node)

        if (nativecode is None and code is None and from_function is None
                and not from_expr and not optional_using):
            raise EdgeQLSyntaxError('missing a USING clause',
                                    context=block.context)

        else:
            if from_expr and (from_function or code):
                raise EdgeQLSyntaxError(
                    'USING SQL EXPRESSION is mutually exclusive with other '
                    'USING variants',
                    context=block.context)

            props['code'] = qlast.FunctionCode(
                language=language,
                from_function=from_function,
                from_expr=from_expr,
                code=code,
            )

            props['nativecode'] = nativecode

        if commands:
            props['commands'] = commands

        return props
示例#29
0
 def reduce_DOLLAR_ICONST_ASSIGN_Expr(self, *kids):
     raise EdgeQLSyntaxError(
         f"numeric named arguments are not supported",
         context=kids[0].context)
示例#30
0
 def reduce_DOLLAR_AnyIdentifier_ASSIGN_Expr(self, *kids):
     raise EdgeQLSyntaxError(
         f"named arguments do not need a '$' prefix: "
         f"rewrite as '{kids[1].val} := ...'",
         context=kids[0].context)