Exemplo n.º 1
0
def parse_map(fields, text, index, *cwd):
    # #MAPvalue(default[,k1:v1,k2:v2...])
    try:
        args_index, value = parse_ints(text, index, 1, fields=fields)
    except MissingParameterError:
        raise MacroParsingError("No valid expression found: '#MAP{}'".format(
            text[index:]))
    try:
        end, args = parse_strings(text, args_index)
    except NoParametersError:
        raise NoParametersError("No mappings provided: {}".format(
            text[index:args_index]))
    map_id = text[args_index:end]
    if map_id in _map_cache:
        return end, _map_cache[map_id][value]
    default = args.pop(0)
    m = defaultdict(lambda: default)
    if args:
        for pair in args:
            if ':' in pair:
                k, v = pair.split(':', 1)
            else:
                k = v = pair
            try:
                m[evaluate(k)] = v
            except ValueError:
                raise MacroParsingError("Invalid key ({}): {}".format(
                    k, text[args_index:end]))
    _map_cache[map_id] = m
    return end, m[value]
Exemplo n.º 2
0
def parse_call(writer, text, index, *cwd):
    # #CALL:methodName(args)
    macro = '#CALL'
    if index >= len(text):
        raise MacroParsingError("No parameters")
    if text[index] != ':':
        raise MacroParsingError("Malformed macro: {}{}...".format(
            macro, text[index]))

    end = index + 1
    match = RE_METHOD_NAME.match(text, end)
    if match:
        method_name = match.group()
        end += len(method_name)
    else:
        raise MacroParsingError("No method name")
    end, m_args = parse_brackets(text, end)

    if not hasattr(writer, method_name):
        writer.warn("Unknown method name in {} macro: {}".format(
            macro, method_name))
        return end, ''
    method = getattr(writer, method_name)
    if not inspect.ismethod(method):
        raise MacroParsingError(
            "Uncallable method name: {}".format(method_name))

    if m_args is None:
        raise MacroParsingError("No argument list specified: {}{}".format(
            macro, text[index:end]))
    args = list(cwd)
    kwargs = {}
    if m_args:
        for arg in _format_params(writer.expand(m_args), m_args,
                                  **writer.fields).split(','):
            a1, sep, a2 = arg.partition('=')
            if sep:
                v = a2
            else:
                v = a1
            try:
                value = evaluate(v)
            except ValueError:
                if v:
                    value = v
                else:
                    value = None
            if sep:
                kwargs[a1] = value
            else:
                args.append(value)

    try:
        retval = method(*args, **kwargs)
    except Exception as e:
        raise MacroParsingError("Method call {} failed: {}".format(
            text[index + 1:end], e))
    if retval is None:
        retval = ''
    return end, retval
Exemplo n.º 3
0
def parse_foreach(entry_holder, text, index, *cwd):
    # #FOREACH([v1,v2,...])(var,string[,sep,fsep])
    try:
        end, values = parse_strings(text, index)
    except NoParametersError:
        raise NoParametersError("No values")
    try:
        end, (var, s, sep, fsep) = parse_strings(text, end, 4, ('', None))
    except (NoParametersError, MissingParameterError) as e:
        raise MacroParsingError("No variable name: {}".format(text[index:e.args[1]]))
    if len(values) == 1:
        value = values[0]
        if value.startswith(('EREF', 'REF')):
            addr_str, getter, desc = {
                'E': (value[4:], entry_holder.get_instruction, 'instruction'),
                'R': (value[3:], entry_holder.get_entry, 'entry')
            }[value[0]]
            try:
                address = evaluate(addr_str)
                entity = getter(address)
                if not entity:
                    raise MacroParsingError('No {} at {}: {}'.format(desc, address, value))
                values = [str(r.address) for r in sorted(entity.referrers, key=lambda e: e.address)]
            except ValueError:
                pass
        elif value.startswith('ENTRY'):
            types = value[5:]
            values = [str(e.address) for e in entry_holder.memory_map if e.ctl != 'i' and (not types or e.ctl in types)]
    if not values:
        return end, ''
    if fsep is None:
        fsep = sep
    if len(values) == 1:
        return end, s.replace(var, values[0])
    return end, fsep.join((sep.join([s.replace(var, v) for v in values[:-1]]), s.replace(var, values[-1])))
Exemplo n.º 4
0
def parse_def(writer, text, index, *cwd):
    # #DEF(#MACRO[(ia[=i0],ib[=i1]...)[(sa[=s0],sb[=s1]...)]] body)
    end, definition = parse_strings(text, index, 1)
    definition = definition.strip()
    match = RE_MACRO.match(definition, 0)
    if match:
        name = match.group()
        dindex = match.end()
    else:
        raise MacroParsingError("Invalid macro name: #DEF{}".format(
            text[index:]))
    dindex, iparams = parse_brackets(definition, dindex)
    if iparams is None:
        sparams = None
    else:
        dindex, sparams = parse_brackets(definition, dindex)
    body = definition[dindex:].strip()

    inames, idefaults = [], []
    if iparams:
        for ispec in _format_params(iparams, iparams,
                                    **writer.fields).split(','):
            iname, sep, ival = [s.strip() for s in ispec.partition('=')]
            match = re.match(PARAM_NAME, iname)
            if match and iname == match.group():
                inames.append(iname)
            else:
                raise MacroParsingError(
                    f'Invalid macro argument name: {iname}')
            if sep:
                try:
                    idefaults.append(evaluate(ival))
                except ValueError:
                    raise InvalidParameterError(
                        f"Cannot parse integer argument value: '{ispec}'")
            elif idefaults:
                idefaults.append(0)

    snames, sdefaults = [], []
    if sparams:
        for sspec in _split_unbracketed(sparams):
            sname, sep, sval = [s.strip() for s in sspec.partition('=')]
            snames.append(sname)
            if sep:
                sdefaults.append(Template(sval))
            elif sdefaults:
                sdefaults.append(Template(''))

    writer.macros[name] = partial(_expand_def_macro, writer, inames, idefaults,
                                  snames, sdefaults, Template(body))
    return end, ''
Exemplo n.º 5
0
def get_params(param_string, num=0, defaults=(), names=(), safe=True):
    params = []
    named_params = {}
    index = 0
    has_named_param = False
    if names:
        num = len(names)
    if param_string:
        for p in param_string.split(','):
            if index < len(names):
                name = names[index]
            else:
                name = index
            if p and names:
                match = RE_PARAM_NAME.match(p)
                if match:
                    name = match.group()[:-1].strip()
                    if name in names:
                        value = p[match.end():]
                        index = names.index(name)
                        has_named_param = True
                    else:
                        raise MacroParsingError(
                            "Unknown keyword argument: '{}'".format(p))
                else:
                    if has_named_param:
                        raise MacroParsingError(
                            "Non-keyword argument after keyword argument: '{}'"
                            .format(p))
                    value = p
            else:
                value = p
            if value:
                try:
                    param = evaluate(value, safe)
                except ValueError:
                    raise InvalidParameterError(
                        "Cannot parse integer '{}' in parameter string: '{}'".
                        format(value, param_string))
                if names and name:
                    named_params[name] = param
                else:
                    params.append(param)
            elif not names:
                params.append(None)
            index += 1

    req = num - len(defaults)
    if named_params:
        for i in range(req):
            req_name = names[i]
            if req_name not in named_params:
                raise MissingParameterError(
                    "Missing required argument '{}': '{}'".format(
                        req_name, param_string))
    elif index < req:
        if params:
            raise MissingParameterError(
                "Not enough parameters (expected {}): '{}'".format(
                    req, param_string))
        raise MissingParameterError("No parameters (expected {})".format(req))
    elif None in params:
        missing_index = params.index(None)
        if missing_index < req:
            raise MissingParameterError(
                "Missing required parameter in position {}/{}: '{}'".format(
                    missing_index + 1, req, param_string))
    if index > num > 0:
        raise TooManyParametersError(
            "Too many parameters (expected {}): '{}'".format(
                num, param_string), param_string)

    if names:
        for i in range(req, num):
            name = names[i]
            if name not in named_params:
                named_params[name] = defaults[i - req]
        return [named_params[name] for name in names]

    params += [None] * (num - len(params))
    for i in range(req, num):
        if params[i] is None:
            params[i] = defaults[i - req]
    return params