Пример #1
0
    def funcargs(self, kids, meta):
        '''
        A list of function parameters (as part of a function definition)
        '''
        newkids = []

        names = set()
        kwfound = False

        for kid in kids:
            kid = self._convert_child(kid)
            newkids.append(kid)

            if isinstance(kid, s_ast.CallKwarg):
                name = kid.kids[0].valu
                kwfound = True
                # Make sure no repeated kwarg
            else:
                name = kid.valu
                # Make sure no positional follows a kwarg
                if kwfound:
                    mesg = f"Positional parameter '{name}' follows keyword parameter in definition"
                    raise s_exc.BadSyntax(mesg=mesg, at=meta.start_pos)

            if name in names:
                mesg = f"Duplicate parameter '{name}' in function definition"
                raise s_exc.BadSyntax(mesg=mesg, at=meta.start_pos)

            names.add(name)

        return s_ast.FuncArgs(newkids)
Пример #2
0
def parse_float(text, off):
    match = floatre.match(text[off:])
    if match is None:
        raise s_exc.BadSyntax(at=off, mesg='Invalid float')

    s = match.group(0)

    return float(s), len(s) + off
Пример #3
0
 def raiseOnBadStorm(q):
     ''' Just enough storm parsing for this test '''
     # TODO: Async this and use AsyncMock when Python 3.8+ only
     f = asyncio.Future()
     if (q[0] == '[') != (q[-1] == ']'):
         f.set_exception(s_exc.BadSyntax(mesg='mismatched braces'))
     else:
         f.set_result('all good')
     return f
Пример #4
0
 def exit(self, status=0, message=None):
     '''
     Argparse expects exit() to be a terminal function and not return.
     As such, this function must raise an exception which will be caught
     by Cmd.hasValidOpts.
     '''
     self.exited = True
     if message is not None:
         self.mesgs.extend(message.split('\n'))
     raise s_exc.BadSyntax(mesg=message, prog=self.prog, status=status)
Пример #5
0
    def _larkToSynExc(self, e):
        '''
        Convert lark exception to synapse BadSyntax exception
        '''
        mesg = regex.split('[\n!]', str(e))[0]
        at = len(self.text)
        if isinstance(e, lark.exceptions.UnexpectedCharacters):
            expected = sorted(terminalEnglishMap[t] for t in e.allowed)
            mesg += f'.  Expecting one of: {", ".join(expected)}'
            at = e.pos_in_stream
        elif isinstance(e, lark.exceptions.UnexpectedEOF):
            expected = sorted(terminalEnglishMap[t] for t in set(e.expected))
            mesg += ' ' + ', '.join(expected)
        elif isinstance(e, lark.exceptions.VisitError):
            # Lark unhelpfully wraps an exception raised from AstConverter in a VisitError.  Unwrap it.
            origexc = e.orig_exc
            if not isinstance(origexc, s_exc.SynErr):
                raise  # pragma: no cover
            origexc.errinfo['text'] = self.text
            return s_exc.BadSyntax(**origexc.errinfo)

        return s_exc.BadSyntax(at=at, text=self.text, mesg=mesg)
Пример #6
0
    def getStormEval(self, runt, name):
        '''
        Construct an evaluator function that takes a path and returns a value.
        This allows relative / absolute props and variables.
        '''
        if name.startswith('$'):
            varn = name[1:]

            def func(path):
                return path.getVar(varn, defv=None)

            return func

        if name.startswith(':'):
            prop = name[1:]

            def func(path):
                return path.node.get(prop)

            return func

        if name.startswith('.'):

            def func(path):
                return path.node.get(name)

            return func

        form = runt.snap.core.model.form(name)
        if form is not None:

            def func(path):
                if path.node.form != form:
                    return None
                return path.node.ndef[1]

            return func

        prop = runt.snap.core.model.prop(name)
        if prop is not None:

            def func(path):
                if path.node.form != prop.form:
                    return None
                return path.node.get(prop.name)

            return func

        mesg = 'Unknown prop/variable syntax'
        raise s_exc.BadSyntax(mesg=mesg, valu=name)
Пример #7
0
    def _larkToSynExc(self, e):
        '''
        Convert lark exception to synapse badGrammar exception
        '''
        mesg = regex.split('[\n!]', e.args[0])[0]
        at = len(self.text)
        if isinstance(e, lark.exceptions.UnexpectedCharacters):
            mesg += f'.  Expecting one of: {", ".join(terminalEnglishMap[t] for t in sorted(set(e.allowed)))}'
            at = e.pos_in_stream
        elif isinstance(e, lark.exceptions.ParseError):
            if mesg == 'Unexpected end of input':
                mesg += f'.  Expecting one of: {", ".join(terminalEnglishMap[t] for t in self._eofParse(e.args[0]))}'

        return s_exc.BadSyntax(at=at, text=self.text, mesg=mesg)
Пример #8
0
    def funccall(self, kids, meta):
        kids = self._convert_children(kids)
        argkids = []
        kwargkids = []
        kwnames = set()

        for kid in kids[1:]:
            if isinstance(kid, s_ast.CallKwarg):
                name = kid.kids[0].valu
                if name in kwnames:
                    mesg = f"Duplicate keyword argument '{name}' in function call"
                    raise s_exc.BadSyntax(mesg=mesg, at=meta.start_pos)

                kwnames.add(name)
                kwargkids.append(kid)
            else:
                if kwargkids:
                    mesg = 'Positional argument follows keyword argument in function call'
                    raise s_exc.BadSyntax(mesg=mesg, at=meta.start_pos)
                argkids.append(kid)

        args = s_ast.CallArgs(kids=argkids)
        kwargs = s_ast.CallKwargs(kids=kwargkids)
        return s_ast.FuncCall(kids=[kids[0], args, kwargs])
Пример #9
0
    def cmdrargs(self, kids):
        argv = []

        for kid in kids:

            if isinstance(kid, s_ast.SubQuery):
                argv.append(kid.text)
                continue

            # this one should never happen, but is here in case
            if isinstance(kid, s_ast.Const):  # pragma: no cover
                argv.append(kid.valu)
                continue

            if isinstance(kid, lark.lexer.Token):
                argv.append(str(kid))
                continue

            # pragma: no cover
            mesg = f'Unhandled AST node type in cmdrargs: {kid!r}'
            raise s_exc.BadSyntax(mesg=mesg)

        return argv
Пример #10
0
 def raiseOnBadStorm(q):
     ''' Just enough storm parsing for this test '''
     if (q[0] == '[') != (q[-1] == ']'):
         raise s_exc.BadSyntax(mesg='mismatched braces')
Пример #11
0
    def getCmdOpts(self, text):
        '''
        Use the _cmd_syntax def to split/parse/normalize the cmd line.

        Args:
            text (str): Command to process.

        Notes:
            This is implemented independent of argparse (et al) due to the
            need for syntax aware argument splitting. Also, allows different
            split per command type

        Returns:
            dict: An opts dictionary.
        '''
        off = 0

        _, off = s_grammar.nom(text, off, s_grammar.whites)

        name, off = s_grammar.meh(text, off, s_grammar.whites)

        _, off = s_grammar.nom(text, off, s_grammar.whites)

        opts = {}

        args = collections.deque(
            [synt for synt in self._cmd_syntax if not synt[0].startswith('-')])
        switches = {
            synt[0]: synt
            for synt in self._cmd_syntax if synt[0].startswith('-')
        }

        # populate defaults and lists
        for synt in self._cmd_syntax:
            snam = synt[0].strip('-')

            defval = synt[1].get('defval')
            if defval is not None:
                opts[snam] = defval

            if synt[1].get('type') == 'list':
                opts[snam] = []

        def atswitch(t, o):
            # check if we are at a recognized switch.  if not
            # assume the data is part of regular arguments.
            if not text.startswith('-', o):
                return None, o

            name, x = s_grammar.meh(t, o, s_grammar.whites)
            swit = switches.get(name)
            if swit is None:
                return None, o

            return swit, x

        while off < len(text):

            _, off = s_grammar.nom(text, off, s_grammar.whites)

            swit, off = atswitch(text, off)
            if swit is not None:

                styp = swit[1].get('type', 'flag')
                snam = swit[0].strip('-')

                if styp == 'valu':
                    valu, off = s_parser.parse_cmd_string(text, off)
                    opts[snam] = valu

                elif styp == 'list':
                    valu, off = s_parser.parse_cmd_string(text, off)
                    if not isinstance(valu, list):
                        valu = valu.split(',')
                    opts[snam].extend(valu)

                elif styp == 'enum':
                    vals = swit[1].get('enum:vals')
                    valu, off = s_parser.parse_cmd_string(text, off)
                    if valu not in vals:
                        raise s_exc.BadSyntax(mesg='%s (%s)' %
                                              (swit[0], '|'.join(vals)),
                                              text=text)

                    opts[snam] = valu

                else:
                    opts[snam] = True

                continue

            if not args:
                raise s_exc.BadSyntax(mesg='trailing text: [%s]' %
                                      (text[off:], ),
                                      text=text)

            synt = args.popleft()
            styp = synt[1].get('type', 'valu')

            # a glob type eats the remainder of the string
            if styp == 'glob':
                opts[synt[0]] = text[off:]
                break

            # eat the remainder of the string as separate vals
            if styp == 'list':
                valu = []

                while off < len(text):
                    item, off = s_parser.parse_cmd_string(text, off)
                    valu.append(item)

                opts[synt[0]] = valu
                break

            valu, off = s_parser.parse_cmd_string(text, off)
            opts[synt[0]] = valu

        return opts