Esempio n. 1
0
def _match(f, c):
    global _nchar
    _skip_white(f)
    if _nchar == c:
        _nchar = f.read(1).decode("utf-8")
    else:
        error._expected(c)
Esempio n. 2
0
def _a_expression(f):
    _a_term(f)
    op = scanner._get_operator(f)
    while op != "":
        if op not in scanner._add_ops:
            # Unget the op chars and reset scanner._nchar
            f.seek(-len(op) - 1, 1)
            scanner._nchar = f.read(1).decode("utf-8")
            # Break out of the loop - not our operator
            break
        # TODO Handle unary ++ and --
        codegen._push_primary()
        _a_term(f)
        codegen._pop_secondary()
        # Flip order of primary and secondary for - b/c second argument is
        # the one in primary. + is commutative so it doesn't matter for that
        # case
        regs = (codegen.PRIMARY, codegen.SECONDARY, codegen.PRIMARY)
        if op == '+':
            codegen._add(*regs)
        elif op == '-':
            codegen._sub(*regs)
        else:
            error._expected('+ or -')
        op = scanner._get_operator(f)
Esempio n. 3
0
def _get_name(f):
    global _nchar
    _skip_white(f)
    if _nchar == '':
        return ''
    if not _is_valid_identifier_start(_nchar):
        # Eventually calls sys.exit()
        error._expected(("Identifier beginning [alpha or _], got {} on " +
                         "line {}").format(_nchar, _line))
    id = ""
    while _is_valid_identifier(_nchar):
        id += _nchar
        _nchar = f.read(1).decode("utf-8")
    return id
Esempio n. 4
0
def _get_num(f):
    """Returns the next number as a str
    """
    global _nchar
    _skip_white(f)
    if _nchar == '':
        return ''
    if not _is_num(_nchar):
        # Eventually calls sys.exit()
        error._expected("Number")
    n = ""
    while _is_num(_nchar):
        n += _nchar
        _nchar = f.read(1).decode("utf-8")
    return n
Esempio n. 5
0
def _block(f):
    _symtab.append({})
    scanner._skip_white(f)
    local_allocations = 0
    dealloc = True
    while scanner._nchar != '}':
        if scanner._is_valid_identifier_start(scanner._nchar):
            identifier = scanner._get_name(f)
            if identifier == 'if':
                _if(f)
            elif identifier == 'while':
                _while(f)
            elif identifier == 'var':
                local_allocations += 1
                _local_var(f)
            elif identifier == 'break':
                pass
            elif identifier == 'return':
                dealloc = False
                # Dealloc local vars - special case because the code will exit
                # the block before the "end"
                codegen._dealloc_stack(local_allocations
                                       * codegen.WORD // codegen.BYTE)
                _return(f)
            else:
                # Either an assignment or a function call
                # Look in symbol table to tell which is which
                entry = _lookup(identifier)
                if entry is not None:
                    if entry['type'] == 'local_var' or entry['type'] == \
                            'global_var':
                        _assignment(f, entry)
                    elif entry['type'] == 'function':
                        _function_call(f, entry)
                else:
                    error._error("Undeclared identifier: " + str(identifier))
        elif scanner._nchar == '@':
            scanner._match(f, '@')
            _p_assignment(f)
        else:
            error._expected("Identifier or '@', got {}".format(scanner._nchar))
        scanner._skip_white(f)
    if dealloc:
        # Dealloc local vars to get back to return address
        codegen._dealloc_stack(local_allocations
                               * codegen.WORD // codegen.BYTE)
    _symtab.pop()
Esempio n. 6
0
def _term(f):
    _factor(f)
    op = scanner._get_operator(f)
    while op != "":
        if op not in scanner._and_ops:
            # Unget the op chars and reset scanner._nchar
            f.seek(-len(op) - 1, 1)
            scanner._nchar = f.read(1).decode("utf-8")
            # Break out of the loop - not our operator
            break
        codegen._push_primary()
        _factor(f)
        codegen._pop_secondary()
        regs = (codegen.PRIMARY, codegen.PRIMARY, codegen.SECONDARY)
        if op == '&':
            codegen._bitwise_and(*regs)
        elif op == '&&':
            codegen._logical_and(*regs)
        else:
            error._expected('& or &&')
        op = scanner._get_operator(f)
Esempio n. 7
0
def _a_term(f):
    _a_factor(f)
    op = scanner._get_operator(f)
    while op != "":
        if op not in scanner._mul_ops:
            # Unget the op chars and reset scanner._nchar
            f.seek(-len(op) - 1, 1)
            scanner._nchar = f.read(1).decode("utf-8")
            # Break out of the loop - not our operator
            break
        codegen._push_primary()
        _a_factor(f)
        codegen._pop_secondary()
        # Flip order for / for same reason as -. * is comm so doesn't matter
        regs = (codegen.PRIMARY, codegen.SECONDARY, codegen.PRIMARY)
        if op == '*':
            codegen._mul(*regs)
        elif op == '/':
            codegen._div(*regs)
        else:
            error._expected('* or /')
        op = scanner._get_operator(f)
Esempio n. 8
0
def _expression(f):
    _term(f)
    op = scanner._get_operator(f)
    while op != "":
        if op not in scanner._or_ops:
            # Unget the op chars and reset scanner._nchar
            f.seek(-len(op) - 1, 1)
            scanner._nchar = f.read(1).decode("utf-8")
            # Break out of the loop - not our operator
            break
        codegen._push_primary()
        _term(f)
        codegen._pop_secondary()
        # Both branches use the same arguments
        regs = (codegen.PRIMARY, codegen.PRIMARY, codegen.SECONDARY)
        if op == '|':
            # Unpack the regs tuple as args
            codegen._bitwise_or(*regs)
        elif op == '||':
            codegen._logical_or(*regs)
        else:
            error._expected('| or ||')
        op = scanner._get_operator(f)