Beispiel #1
0
    def add_type(self,
                 name: str,
                 lineno,
                 col_num,
                 storage,
                 eltype=None,
                 check=True):
        """Add a new type definition with the details"""

        if check and self.is_defined(name):
            print_error()
            print(f"Re-declaration of type '{name}' at line {lineno}")
            print_line(lineno)

            pos = col_num - 1
            width = len(name)
            print_marker(pos, width)

            other_type = self.get_type(name)
            print(f"{name} previously declared at line {other_type.lineno}")
            print_line(other_type.lineno)

            pos = other_type.col_num - 1
            print_marker(pos, width)

        new_type = TypeInfo(name, lineno, col_num, storage, eltype)

        self.type_map[name] = new_type
Beispiel #2
0
    def check_unused(self):
        func_type = self.type_table.get_type("FUNCTION")

        for symbol in self.symbols:
            if (symbol.uses == [] and symbol.scope_id != "1"
                    and symbol.type_ != func_type):
                print_error("Unused variable", kind="ERROR")
                print(
                    f"Variable {symbol.name} is defined at line {symbol.lineno} "
                    "but never used.")
                print_line(symbol.lineno)

                pos = symbol.col_num - 1
                width = len(symbol.name)
                print_marker(pos, width)

        if utils.package_name == "main":
            main_fn = self.get_symbol("main")

            if main_fn is None:
                print_error("main is undeclared in package main", kind="ERROR")

                print(
                    "main function is not declared in a file with 'main' package"
                )
Beispiel #3
0
def p_error(p: lex.LexToken):
    print(f"{Fore.RED}SYNTAX ERROR:{Style.RESET_ALL}")
    if p is not None:
        col = find_column(p)
        print(f"at line {p.lineno}, column {col}")
        print_line(p.lineno)
        # print(" " * 10, " \t", " " * (col - 1), "^", sep="")
        print_marker(col - 1, len(p.value))
    else:
        print("Unexpected end of file")
Beispiel #4
0
def t_ANY_error(t):
    print_lexer_error(f"Illegal character {t.value[0]}")
    col = find_column(t)
    print(f"at line {t.lineno}, column {col}")
    print(
        f"{Fore.GREEN}{t.lineno:>10}:\t{Style.RESET_ALL}",
        lines[t.lineno - 1],
        sep="",
    )
    print_marker(col - 1, 1)

    t.lexer.skip(1)
Beispiel #5
0
def t_ANY_UNCLOSED_MULTI_COMMENT(t):
    r"/\*(.|\n)*"

    print_lexer_error("Unclosed Multiline comment")
    col = find_column(t)
    print(f"at line {t.lineno}, column {col}")
    print(
        f"{Fore.GREEN}{t.lineno:>10}:\t{Style.RESET_ALL}",
        lines[t.lineno - 1],
        sep="",
    )
    print_marker(col - 1, 1)
Beispiel #6
0
def p_OperandName(p):
    """OperandName : IDENTIFIER %prec '='
    | QualifiedIdent
    """
    if not isinstance(p[1], syntree.QualifiedIdent):
        ident: Tuple = p[1]
        sym = symtab.get_symbol(ident[1])
        lineno = p.lineno(1)
        if not symtab.is_declared(ident[1]):
            print_error()
            print(f"Undeclared symbol '{ident[1]}' at line {lineno}")
            print_line(lineno)
            line: str = utils.lines[lineno - 1]
            # TODO: get correct position of token rather than searching
            pos = ident[2] - 1
            width = len(ident[1])
            print_marker(pos, width)
        else:
            sym.uses.append(lineno)

    p[0] = p[1]
Beispiel #7
0
def t_STRING_LIT(t):
    r"\"[^\"]*\""

    #  if r"\s*\*/":
    #      print_error("ERROR: Wrong Multiline Comment")
    #      return

    if "\n" in t.value:
        print_lexer_error("string cannot contain line breaks")
        lineno = t.lexer.lineno
        pos = find_column(t)
        splits = list(t.value.split("\n"))
        for i, line_ in enumerate(splits):
            print_line(lineno)
            line_actual = lines[lineno - 1]

            if i == 0:
                print_marker(pos - 1, len(line_actual) - pos + 1)
            elif i == len(splits) - 1:
                print_marker(0, line_actual.find('"') + 1)
            else:
                print_marker(0, len(line_actual))

            lineno += 1
        t.lexer.lineno += t.value.count("\n")

        return

    t.value = ("string", t.value)

    t.lexer.begin("InsertSemi")
    return t
Beispiel #8
0
    def declare_new_variable(
        self,
        symbol: str,
        lineno: int,
        col_num: int,
        type_=None,
        const=False,
        value=None,
    ):
        """Helper function to add symbol to the Symbol Table
        with declaration set to given line number.

        Prints an error if the symbol is already declared at
        current depth.
        """
        if self.is_declared_in_cur_symtab(symbol):
            print_error()
            print(f"Re-declaration of symbol '{symbol}' at line {lineno}")
            print_line(lineno)

            pos = col_num - 1
            width = len(symbol)
            print_marker(pos, width)

            other_sym = self.get_symbol(symbol)
            print(f"{symbol} previously declared at line {other_sym.lineno}")
            print_line(other_sym.lineno)

            pos = other_sym.col_num - 1
            print_marker(pos, width)
        else:
            self.update_info(symbol,
                             lineno,
                             col_num=col_num,
                             type_=type_,
                             const=const,
                             value=value)
Beispiel #9
0
    def update_info(self,
                    symbol: str,
                    lineno,
                    col_num=None,
                    type_=None,
                    const=None,
                    value=None):
        sym = self.get_symbol(symbol)
        sym.lineno = lineno
        sym.type_ = None
        sym.col_num = col_num
        # TODO: infer type from value if not given
        typename = None
        composite_type = False
        eltype = None

        if type_ is not None:
            # sym.storage = self.storage[type_.data]
            valid_type = True
            typename = ""

            # type_ can sometimes be syntree.Type
            if hasattr(type_, "data") and hasattr(type_, "name"):
                if type_.name == "BasicType":
                    typename = type_.data
                elif type_.name == "ARRAY" or type_.name == "SLICE":
                    typename = type_.typename
                    composite_type = True
                    eltype = type_.eltype
                else:
                    print(f"Unknown node {type_}. Could not determine type")
                    valid_type = False
            elif isinstance(type_, str):
                typename = type_
            else:
                print(
                    f"Could not determine type, issue in code. Found {type_}")
                valid_type = False

            if valid_type:

                if not self.type_table.is_defined(typename):
                    print_error()
                    print(f"Type '{typename}' is not defined at line {lineno}")
                    print_line(lineno)

                    line = utils.lines[lineno]
                    pos = line.find(typename)
                    width = len(typename)

                    print_marker(pos, width)
                else:
                    sym.type_ = self.type_table.get_type(typename)

            # elif composite_type:

            #     self.type_table.add_type(f"{typename}_{eltype}")

        if value is not None:
            sym.value = value

        if const is not None:
            sym.const = const