Example #1
0
def func_declarations(
        start: int, tokens: List[Token],
        func_symtable: FunctionSymbolTable) -> Tuple[int, DeclarationsNode]:
    i = start
    declarations_tree = []
    while tokens[i].symbol.kind in DATA_TYPES:
        dtype = check_token_type(tokens[i], data_types)
        check_id(tokens[i + 1], dtype)
        func_symtable.put(tokens[i + 1])
        declarations_tree.append(DeclarationNode(dtype, tokens[i + 1]))
        check_token(tokens[i + 2], SEMMI)
        if tokens[i + 3].symbol.kind not in DATA_TYPES:
            return i + 3, DeclarationsNode(declarations_tree)
        i += 3
    return i, DeclarationsNode(declarations_tree)
Example #2
0
def arg_def(
        start: int, tokens: list,
        func_symtable: FunctionSymbolTable) -> Tuple[int, DeclarationsNode]:
    i = start
    args_tree = []
    while tokens[i].symbol.kind is not RIGHT_PAR:
        dtype = check_token_type(tokens[i], data_types)
        check_id(tokens[i + 1], dtype)
        func_symtable.put(tokens[i + 1])
        args_tree.append(DeclarationNode(dtype, tokens[i + 1]))
        if tokens[i + 2].symbol.kind is RIGHT_PAR:
            return i + 2, DeclarationsNode(args_tree)
        check_token(tokens[i + 2], COMMA)
        check_token_type(tokens[i + 3], data_types)
        i += 3
    return i, DeclarationsNode(args_tree)
Example #3
0
def ass_statement(start: int, tokens: List[Token],
                  func_symtable: FunctionSymbolTable) -> Tuple[int, AssNode]:
    # Check assignment syntax
    check_token(tokens[start], ID)
    left = func_symtable.get_token(tokens[start + 4])
    l_dtype = None if left is None else left.dtype
    id_node = IdNode(l_dtype, tokens[start].symbol.value)
    check_token(tokens[start + 1], ASS)
    # first check for negation, only identifiers, no function calls
    if tokens[start + 2].symbol.kind is NOT:
        check_token(tokens[start + 3], ID)
        check_token(tokens[start + 4], SEMMI)
        token = func_symtable.get_token(tokens[start + 3])
        dtype = None if token is None else token.dtype
        rightNode = IdNode(dtype, tokens[start + 3].symbol.value)
        return start + 4, AssNode(id_node,
                                  UnaryExpressionNode(LOGICO, NOT, rightNode))

    i, expression_node = expression(start + 2, tokens, func_symtable)
    return i, AssNode(id_node, expression_node)
Example #4
0
def func_def(start: int,
             tokens: list) -> Tuple[int, FunctionSymbolTable, FuncNode]:
    # Check and put function datatype
    dtype = check_token_type(tokens[start], data_types)
    check_id(tokens[start + 1], dtype)
    func_symtable = FunctionSymbolTable(tokens[start + 1].symbol.value, dtype)

    # Check function args
    check_token(tokens[start + 2], LEFT_PAR)
    end_args, args_node = arg_def(start + 3, tokens, func_symtable)
    check_token(tokens[end_args], RIGHT_PAR)

    # Check declarations
    check_token(tokens[end_args + 1], LEFT_CURL)
    end_declarations, declarations_node = func_declarations(
        end_args + 2, tokens, func_symtable)

    # Check function body
    end_body, body_node = func_body(end_declarations, tokens, func_symtable)

    # return statement
    check_token(tokens[end_body], REGRESA)
    check_token(tokens[end_body + 1], ID)
    id_name = tokens[end_body + 1].symbol.value
    token = func_symtable.get_token(id_name)
    dtype = None if token is None else token.dtype
    return_node = ReturnNode(dtype, id_name)

    # This is semantic!
    # inTable = func_symtable.contains(tokens[end_body + 2].symbol.value)
    # match_dtype = tokens[end_body + 2].dtype == func_symtable.dtype
    # if not inTable:
    # throwSyntaxError('variable no definida: ' + tokens[end_body + 2].symbol.vale)
    # if  not match_dtype:
    #     throwSyntaxError('el tipo de la funcion ' + func_symtable.name + ' y el tipo de la variable de retorno ' + tokens[end_body + 2].symbol.vale) + ' no coinciden'
    check_token(tokens[end_body + 2], SEMMI)
    check_token(tokens[end_body + 3], RIGHT_CURL)
    return end_body + 4, func_symtable, FuncNode(args_node, declarations_node,
                                                 body_node, return_node)
Example #5
0
def principal_def(start: int, tokens: list,
                  tables: Dict[str, FunctionSymbolTable]) -> MainNode:
    check_token(tokens[start], PRINCIPAL)
    check_token(tokens[start + 1], LEFT_PAR)
    check_token(tokens[start + 2], RIGHT_PAR)
    check_token(tokens[start + 3], LEFT_CURL)
    principal_symtable = FunctionSymbolTable('principal', None)
    declarations_end, declarations_node = func_declarations(
        start + 4, tokens, principal_symtable)
    body_end, body_node = func_body(declarations_end, tokens,
                                    principal_symtable)
    check_token(tokens[body_end], RIGHT_CURL)
    if body_end + 1 != len(tokens):
        throwSyntaxError('principal debe ser el último bloque de código')
Example #6
0
def parameters(
        start: int, tokens: List[Token],
        func_symtable: FunctionSymbolTable) -> Tuple[int, ParametersNode]:
    i = start
    parameters_tree = []
    while tokens[i].symbol.kind is not RIGHT_PAR:
        check_id(tokens[i], ID)
        token = func_symtable.get_token(tokens[i].symbol.value)
        dtype = None if token is None else token.dtype
        parameters_tree.append(IdNode(dtype, token.symbol.value))
        if tokens[i + 1].symbol.kind is RIGHT_PAR:
            return i + 1, ParametersNode(parameters_tree)
        check_token(tokens[i + 1], COMMA)
        check_token(tokens[i + 2], ID)
        i += 2
    return i, ParametersNode(parameters_tree)
Example #7
0
def if_statement(start: int, tokens: List[Token],
                 func_symtable: FunctionSymbolTable) -> Tuple[int, IfNode]:
    # Check si syntax
    check_token(tokens[start], SI)
    check_token(tokens[start + 1], LEFT_PAR)
    check_token(tokens[start + 2], ID)
    # put if boolean datatype, leave this for later semantic check.
    token = func_symtable.get_token(tokens[start + 2])
    id_node = IdNode(None if token is None else token.dtype,
                     tokens[start + 2].symbol.value)
    check_token(tokens[start + 3], RIGHT_PAR)
    check_token(tokens[start + 4], LEFT_CURL)
    i = start + 5
    statement_nodes = []
    while tokens[i].symbol.kind is not RIGHT_CURL:
        i, statement_node = statement(i, tokens, func_symtable)
        statement_nodes.append(statement_node)
        i += 1
    return i, IfNode(id_node, statement_nodes)
Example #8
0
def expression(
        start: int, tokens: List[Token],
        func_symtable: FunctionSymbolTable) -> Tuple[int, ExpressionNode]:
    i = start
    previous = None
    stack = []
    while tokens[i] is not SEMMI:
        # first construct literals, ids and function call tokens
        sym = tokens[i].symbol
        if sym.kind in LITERALS:
            # Check previous node is ok
            if previous is not None and (previous is not LEFT_PAR
                                         and previous not in OPERATORS):
                throwSyntaxError(
                    'Sintaxis invalida en linea {}, columna {}'.format(
                        tokens[i].line, tokens[i].col))
            stack.append(tokens[i])
        elif sym.kind is ID:
            nextKind = tokens[i + 1].symbol.kind
            if previous is not None and (previous is not LEFT_PAR
                                         and previous not in OPERATORS):
                throwSyntaxError(
                    'Sintaxis invalida en linea {}, columna {}'.format(
                        tokens[i].line, tokens[i].col))
            if nextKind is LEFT_PAR:
                # Create function call node with parameters
                i, parameters_node = parameters(i + 2, tokens, func_symtable)
                check_token(tokens[i], RIGHT_PAR)
                stack.append(FuncCallNode(sym.value, parameters_node))
            else:
                token = func_symtable.get_token(sym.value)
                dtype = None if token is None else token.dtype
                stack.append(IdNode(dtype, sym.value))
        elif sym.kind in OPERATORS:
            if previous is None or (previous not in LITERALS
                                    and previous is not ID
                                    and previous is not RIGHT_PAR):
                throwSyntaxError(
                    'Sintaxis invalida en linea {}, columna {}'.format(
                        tokens[i].line, tokens[i].col))
            stack.append(tokens[i])
        elif sym.kind is LEFT_PAR:
            if previous is not None and (previous is not LEFT_PAR
                                         and previous not in OPERATORS):
                throwSyntaxError(
                    'Sintaxis invalida en linea {}, columna {}'.format(
                        tokens[i].line, tokens[i].col))
            stack.append(tokens[i])
        elif sym.kind is RIGHT_PAR:
            if previous is None or (previous not in LITERALS
                                    and previous is not ID
                                    and previous is not RIGHT_PAR):
                throwSyntaxError(
                    'Sintaxis invalida en linea {}, columna {}'.format(
                        tokens[i].line, tokens[i].col))
            nested_expr = []
            x = stack.pop()
            while x.symbol.kind is not LEFT_PAR if type(x) is Token else True:
                nested_expr.append(x)
                if len(stack) == 0:
                    throwSyntaxError(
                        'Sintaxis invalida: falta parentesis izquierdo')
                x = stack.pop()
            stack.append(nested_expr)
        elif sym.kind is SEMMI:
            break
        else:
            throwSyntaxError(
                'Sintaxis invalida: {} en linea {}, columna {}'.format(
                    tokens[i].symbol.value, tokens[i].line, tokens[i].col))
        previous = sym.kind
        i += 1

    # Check balanced parenthesis
    for item in stack:
        if type(item) is Token and item.symbol.kind is LEFT_PAR:
            throwSyntaxError(
                'Sintaxis invalida: parentesis no balanceados en linea {}, columna {}'
                .format(item.symbol.value, item.line, item.col))

    # TODO: parse intermediate stack to prefix expression
    expression_node = stack
    check_token(tokens[i], SEMMI)
    return i, expression_node