diff --git a/requirements.txt b/requirements.txt index 9eb0cad1..8cf0ffb8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ +ply pytest pytest-ordering diff --git a/src/compiler/__init__.py b/src/compiler/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/compiler/components/__init__.py b/src/compiler/components/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/compiler/components/abstract_component.py b/src/compiler/components/abstract_component.py new file mode 100644 index 00000000..a5c09476 --- /dev/null +++ b/src/compiler/components/abstract_component.py @@ -0,0 +1,20 @@ + +class Component: + def __init__(self, + input_info, + component_name, + debug_session = False, + error_log_file = None, + build_after_initialize = True): + self.input_info = input_info + self.component_name = component_name + self.debug_session = debug_session + self.error_log_file = error_log_file + + if build_after_initialize: self.build_component() + + + def build_component (self): + if self.debug_session: + print('Building %s component' %self.component_name) + diff --git a/src/compiler/components/dummy_component.py b/src/compiler/components/dummy_component.py new file mode 100644 index 00000000..d462f321 --- /dev/null +++ b/src/compiler/components/dummy_component.py @@ -0,0 +1,14 @@ +from .abstract_component import Component + + +class dummy_component (Component): + def __init__(self, component_name, *args, **kwargs): + component_name = "dummy_" + component_name + super().__init__(*args, component_name = "dummy_" + component_name, **kwargs) + + + + def build_component(self): + super().build_component() + return "Sorry, this is just a %s component" %(self.component_name) + diff --git a/src/compiler/components/lexer_analyzer.py b/src/compiler/components/lexer_analyzer.py new file mode 100644 index 00000000..4353af2e --- /dev/null +++ b/src/compiler/components/lexer_analyzer.py @@ -0,0 +1,228 @@ +import ply.lex as lex +from ply.lex import Token +from ply.lex import TOKEN +from ..utils.errors import error + +tokens = [ + # Identifiers + "ID", "TYPE", + + # Primitive Types + "INTEGER", "STRING", "BOOLEAN", + + # Literals + "LPAREN", "RPAREN", "LBRACE", "RBRACE", "COLON", "COMMA", "DOT", "SEMICOLON", "AT", + + # Operators + "PLUS", "MINUS", "MULTIPLY", "DIVIDE", "EQ", "LT", "LTEQ", "ASSIGN", "INT_COMP", + + # Special Operators + "ARROW" +] + +reserved = { + 'new':'NEW', + 'of':'OF', + 'if' : 'IF', + 'let':'LET', + 'in' : 'IN', + 'fi':'FI', + 'else' : 'ELSE', + 'while':'WHILE', + 'case':'CASE', + 'then' : 'THEN', + 'esac':'ESAC', + 'pool':'POOL', + 'class':'CLASS', + 'loop':'LOOP', + 'inherits':'INHERITS', + 'isvoid':'ISVOID', + "self": "SELF", + "not": "NOT" +} + +tokens += list(reserved.values()) + +#Simple rules +t_PLUS = r'\+' +t_MINUS = r'\-' +t_MULTIPLY = r'\*' +t_DIVIDE = r'\/' +t_LPAREN = r'\(' +t_RPAREN = r'\)' +t_EQ = r'\=' +t_LT = r'\<' +t_LTEQ = r'\<\=' +t_ASSIGN = r'\<\-' +t_INT_COMP = r'~' +t_LBRACE = r'\{' +t_RBRACE = r'\}' +t_COLON = r'\:' +t_COMMA = r'\,' +t_DOT = r'\.' +t_SEMICOLON = r'\;' +t_AT = r'\@' +t_ARROW = r'\=\>' +#complex rules + +@TOKEN(r"(t[R|r][U|u][e|E]|f[a|A][l|L][s|S][e|E])") +def t_BOOLEAN(token): + token.value = token.value.lower() + return token + +@TOKEN(r"\d+") +def t_INTEGER(token): + token.value = int(token.value) + return token + +@TOKEN(r"[A-Z][A-Za-z0-9_]*") +def t_TYPE(token): + token.type = reserved.get(token.value.lower(), 'TYPE') + return token + +@TOKEN(r"[a-z][A-Za-z0-9_]*") +def t_ID(token): + token.type = reserved.get(token.value.lower(), "ID") + return token + +# Utility definitions +@TOKEN(r'\n+') +def t_newline(t): + global readjust_col + readjust_col = t.lexpos + len(t.value) + t.lexer.lineno += len(t.value) + +def t_error(token): + global readjust_col + errors.append(error(error_type="LexicographicError", row_and_col= (token.lineno, token.lexpos - readjust_col + 1), message='ERROR "%s"' % (token.value[:1]))) + token.lexer.skip(1) + +t_ignore = ' \t' +t_ignore_COMMENTLINE = r"\-\-[^\n]*" + + +#Global states +states = ( + ("STRING", "exclusive"), + ("COMMENT", "exclusive") +) + +#The string states +@TOKEN(r'\"') +def t_start_string(token): + token.lexer.push_state("STRING") + token.lexer.string_backslashed = False + token.lexer.stringbuf = "" + +@TOKEN(r'\n') +def t_STRING_newline(token): + global readjust_col + token.lexer.lineno += 1 + if not token.lexer.string_backslashed: + errors.append(error(error_type="LexicographicError", row_and_col= (token.lineno, token.lexpos - readjust_col + 1), + message= "Unterminated string constant")) + token.lexer.pop_state() + else: + token.lexer.string_backslashed = False + readjust_col = token.lexpos + len(token.value) + +@TOKEN('\0') +def t_STRING_null(token): + errors.append(error(error_type="LexicographicError", row_and_col= (token.lineno, token.lexpos - readjust_col + 1), message='Null character in string')) + token.lexer.skip(1) + +@TOKEN(r'\"') +def t_STRING_end(token): + if not token.lexer.string_backslashed: + token.lexer.pop_state() + token.value = token.lexer.stringbuf + token.type = "STRING" + return token + else: + token.lexer.stringbuf += '"' + token.lexer.string_backslashed = False + +@TOKEN(r"[^\n]") +def t_STRING_anything(token): + if token.lexer.string_backslashed: + if token.value == 'b': + token.lexer.stringbuf += '\b' + elif token.value == 't': + token.lexer.stringbuf += '\t' + elif token.value == 'n': + token.lexer.stringbuf += '\n' + elif token.value == 'f': + token.lexer.stringbuf += '\f' + elif token.value == '\\': + token.lexer.stringbuf += '\\' + else: + token.lexer.stringbuf += token.value + token.lexer.string_backslashed = False + else: + if token.value != '\\': + token.lexer.stringbuf += token.value + else: + token.lexer.string_backslashed = True + +def t_STRING_error(token): + token.lexer.skip(1) + errors.append(error(error_type="LexicographicError", + row_and_col= (token.lineno, token.lexpos - readjust_col + 1), + message= 'ERROR at or near ')) + +def t_STRING_eof(token): + errors.append(error(error_type="LexicographicError", row_and_col= (token.lineno, token.lexpos - readjust_col + 1), message='EOF in string constant')) + token.lexer.pop_state() + +t_STRING_ignore = '' + +# The comment state + +@TOKEN(r"\(\*") +def t_start_comment(token): + token.lexer.push_state("COMMENT") + token.lexer.comment_count = 0 + +@TOKEN(r"\(\*") +def t_COMMENT_startanother(token): + token.lexer.comment_count += 1 + +@TOKEN(r"\n+") +def t_COMMENT_newline(token): + global readjust_col + readjust_col = token.lexpos + len(token.value) + token.lexer.lineno += len(token.value) + +@TOKEN(r"\*\)") +def t_COMMENT_end(token): + if token.lexer.comment_count == 0: + token.lexer.pop_state() + else: + token.lexer.comment_count -= 1 + + +def t_COMMENT_error(token): + token.lexer.skip(1) + +def t_COMMENT_eof(token): + global readjust_col + errors.append(error(error_type="LexicographicError", row_and_col= (token.lineno, token.lexpos - readjust_col + 1), message= "EOF in comment")) + token.lexer.pop_state() + +t_COMMENT_ignore = '' +errors = [] + + +lexer = lex.lex() +def tokenizer(stream_input): + global readjust_col + readjust_col = 0 + lexer.input(stream_input) + token_list = [] + real_col = {} + for tok in lexer: + real_col.update({ str(tok): tok.lexpos - readjust_col + 1 }) + token_list.append(tok) + + return errors, token_list, real_col + diff --git a/src/compiler/components/syntax_analyzer.py b/src/compiler/components/syntax_analyzer.py new file mode 100644 index 00000000..ae22da5e --- /dev/null +++ b/src/compiler/components/syntax_analyzer.py @@ -0,0 +1,303 @@ +import ply.yacc as yacc +from ply.yacc import YaccProduction, YaccSymbol +from ..utils.errors import error +from ..components.lexer_analyzer import lexer + +class pyCoolParser: + def __init__(self, tokens, real_col): + self.tokens = tokens + self.errors_parser = [] + self.parser = yacc.yacc(module=self) + self.row_tracker = 0 + self.column_corrector = 0 + self.real_col = real_col + + # precedence rules + precedence = ( + ('right', 'ASSIGN'), + ('right', 'NOT'), + ('nonassoc', 'LTEQ', 'LT', 'EQ'), + ('left', 'PLUS', 'MINUS'), + ('left', 'MULTIPLY', 'DIVIDE'), + ('right', 'ISVOID'), + ('right', 'INT_COMP'), + ('left', 'AT'), + ('left', 'DOT') + ) + + def p_program(self, p): + """ + program : class_list + """ + + + def p_class_list(self, p): + """ + class_list : class_list class SEMICOLON + | class SEMICOLON + """ + + def p_class(self, p): + """ + class : CLASS TYPE LBRACE features_list_opt RBRACE + """ + + def p_class_inherits(self, p): + """ + class : CLASS TYPE INHERITS TYPE LBRACE features_list_opt RBRACE + """ + + def p_feature_list_opt(self, p): + """ + features_list_opt : features_list + | empty + """ + + def p_feature_list(self, p): + """ + features_list : features_list feature SEMICOLON + | feature SEMICOLON + """ + + def p_feature_method(self, p): + """ + feature : ID LPAREN formal_params_list RPAREN COLON TYPE LBRACE expression RBRACE + """ + + def p_feature_method_no_formals(self, p): + """ + feature : ID LPAREN RPAREN COLON TYPE LBRACE expression RBRACE + """ + + def p_feature_attr_initialized(self, p): + """ + feature : ID COLON TYPE ASSIGN expression + """ + + def p_feature_attr(self, p): + """ + feature : ID COLON TYPE + """ + + def p_formal_list_many(self, p): + """ + formal_params_list : formal_params_list COMMA formal_param + | formal_param + """ + + def p_formal(self, p): + """ + formal_param : ID COLON TYPE + """ + + def p_expression_object_identifier(self, p): + """ + expression : ID + """ + + def p_expression_integer_constant(self, p): + """ + expression : INTEGER + """ + + def p_expression_boolean_constant(self, p): + """ + expression : BOOLEAN + """ + + def p_expression_string_constant(self, p): + """ + expression : STRING + """ + + def p_expr_self(self, p): + """ + expression : SELF + """ + + def p_expression_block(self, p): + """ + expression : LBRACE block_list RBRACE + """ + + def p_block_list(self, p): + """ + block_list : block_list expression SEMICOLON + | expression SEMICOLON + """ + + def p_expression_assignment(self, p): + """ + expression : ID ASSIGN expression + """ + +# ######################### UNARY OPERATIONS ####################################### + + def p_expression_new(self, p): + """ + expression : NEW TYPE + """ + + def p_expression_isvoid(self, p): + """ + expression : ISVOID expression + """ + + def p_expression_integer_complement(self, p): + """ + expression : INT_COMP expression + """ + + def p_expression_boolean_complement(self, p): + """ + expression : NOT expression + """ + + # ######################### PARENTHESIZED, MATH & COMPARISONS ##################### + + def p_expression_math_operations(self, p): + """ + expression : expression PLUS expression + | expression MINUS expression + | expression MULTIPLY expression + | expression DIVIDE expression + """ + + def p_expression_math_comparisons(self, p): + """ + expression : expression LT expression + | expression LTEQ expression + | expression EQ expression + """ + + def p_expression_with_parenthesis(self, p): + """ + expression : LPAREN expression RPAREN + """ + + # ######################### CONTROL FLOW EXPRESSIONS ############################## + + def p_expression_if_conditional(self, p): + """ + expression : IF expression THEN expression ELSE expression FI + """ + + def p_expression_while_loop(self, p): + """ + expression : WHILE expression LOOP expression POOL + """ + + ## ######################### LET EXPRESSIONS ######################################## + def p_expression_let(self, p): + """ + expression : let_expression + """ + + def p_expression_let_simple(self, p): + """ + let_expression : LET nested_lets IN expression + """ + + def p_nested_lets_simple(self, p): + """ + nested_lets : ID COLON TYPE + | nested_lets COMMA ID COLON TYPE + """ + + def p_nested_lets_initialize(self, p): + """ + nested_lets : ID COLON TYPE ASSIGN expression + | nested_lets COMMA ID COLON TYPE ASSIGN expression + """ + + # ######################### CASE EXPRESSION ######################################## + + def p_expression_case(self, p): + """ + expression : CASE expression OF actions_list ESAC + """ + + def p_actions_list(self, p): + """ + actions_list : actions_list action + | action + """ + + def p_action_expr(self, p): + """ + action : ID COLON TYPE ARROW expression SEMICOLON + """ + + + # ######################### METHODS DISPATCH ###################################### + + def p_expression_dispatch(self, p): + """ + expression : expression DOT ID LPAREN arguments_list_opt RPAREN + """ + + def p_arguments_list_opt(self, p): + """ + arguments_list_opt : arguments_list + | empty + """ + + + def p_arguments_list(self, p): + """ + arguments_list : arguments_list COMMA expression + | expression + """ + + def p_expression_static_dispatch(self, p): + """ + expression : expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + """ + + + def p_expression_self_dispatch(self, p): + """ + expression : ID LPAREN arguments_list_opt RPAREN + """ + + + + # ######################### ################## ################################### + + def p_empty(self, p): + """ + empty : + """ + + def findColumn(self, trackedRow): + for i in range(len(self.parser.symstack) -1, 1, -1): + if self.parser.symstack[i].lineno != trackedRow: + return self.parser.symstack[i].lexpos + return 0 + + def p_error(self, p): + """ + Error rule for Syntax Errors handling and reporting. + """ + if p: + self.errors_parser.append( + error(message= "Error at or near %s" %p.value, + error_type="SyntacticError", + row_and_col= (p.lineno, self.real_col[str(p)] ))) + + else: + self.errors_parser.append( + error(message= "EOF in string", + error_type="SyntacticError", + row_and_col= (0, 0 ))) + + + + +def run_parser(tokens, source_program, real_col): + #print(source_program) + parserCool = pyCoolParser(tokens, real_col) + lexer.lineno = 1 + parserCool.parser.parse(source_program, lexer=lexer) + return parserCool.errors_parser + diff --git a/src/compiler/initialize.py b/src/compiler/initialize.py new file mode 100644 index 00000000..7ebf2a62 --- /dev/null +++ b/src/compiler/initialize.py @@ -0,0 +1,8 @@ +from utils import compiler_containers + +class compiler: + def __init__(self, lexer, parser): + self.symbolTable = {} + self.lexer = lexer + self.parser = parser + pass \ No newline at end of file diff --git a/src/compiler/utils/__init__.py b/src/compiler/utils/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/compiler/utils/compiler_containers.py b/src/compiler/utils/compiler_containers.py new file mode 100644 index 00000000..9484d1a7 --- /dev/null +++ b/src/compiler/utils/compiler_containers.py @@ -0,0 +1,21 @@ +from dependency_injector import containers, providers +from ..components import dummy_component, lexer_analyzer +from ..utils import lexer_definitions + +component_injector = { + 'lexer_options': { 'dummy': dummy_component, + 'cool' : lexer_analyzer }, + 'parser_options': {'dummy' : dummy_component} + } + +params_for_component = { + 'lexer' : { + 'cool' : { + 'basic_keywords': lexer_definitions.basic_keywords, + 'simple_rules' : lexer_definitions.simple_rules, + 'complex_rules' : lexer_definitions.complex_rules, + 'tokens_collection' : lexer_definitions.tokens_collection, + 'error_handlers' : lexer_definitions.error_handlers + } + } +} \ No newline at end of file diff --git a/src/compiler/utils/errors.py b/src/compiler/utils/errors.py new file mode 100644 index 00000000..fcb6af92 --- /dev/null +++ b/src/compiler/utils/errors.py @@ -0,0 +1,10 @@ +class error: + def __init__(self, error_type, row_and_col, message): + self.error_type = error_type + self.row_and_col = row_and_col + self.message = message + + def __str__(self): + return '(%d, %d) - %s: %s' %(self.row_and_col[0], self.row_and_col[1], self.error_type, self.message) + + __repr__ = __str__ \ No newline at end of file diff --git a/src/compiler/utils/lexer_definitions.py b/src/compiler/utils/lexer_definitions.py new file mode 100644 index 00000000..77c27e4e --- /dev/null +++ b/src/compiler/utils/lexer_definitions.py @@ -0,0 +1,267 @@ +from ply.lex import TOKEN + +tokens_collection = ( + # Identifiers + "ID", "TYPE", + + # Primitive Types + "INTEGER", "STRING", "BOOLEAN", + + # Literals + "LPAREN", "RPAREN", "LBRACE", "RBRACE", "COLON", "COMMA", "DOT", "SEMICOLON", "AT", + + # Operators + "PLUS", "MINUS", "MULTIPLY", "DIVIDE", "EQ", "LT", "LTEQ", "ASSIGN", "INT_COMP", "NOT", + + # Special Operators + "ARROW" +) + +class keyword(str): + def __eq__(self, other: str): + val = str(self) + if val != 'true' and val != 'false': + return val == other.lower() + return val[0] == other[0] and val[1:] == other.lower()[1:] + def __hash__(self): + return super().__hash__() + +basic_keywords = { + "case": keyword("case"), + "class": keyword("class"), + "else": keyword("else"), + "esac": keyword("esac"), + "fi": keyword("fi"), + "if": keyword("if"), + "in": keyword("in"), + "inherits": keyword("inherits"), + "isvoid": keyword("isvoid"), + "let": keyword("let"), + "loop": keyword("loop"), + "new": keyword("new"), + "of": keyword("of"), + "pool": keyword("pool"), + "self": keyword("self"), + "then": keyword("then"), + "while": keyword("while"), + "true": keyword("true"), + "false": keyword("false"), + 'not' : keyword('not') +} + +#Simple rules for cool +t_LPAREN = r'\(' # ( +t_RPAREN = r'\)' # ) +t_LBRACE = r'\{' # { +t_RBRACE = r'\}' # } +t_COLON = r'\:' # : +t_COMMA = r'\,' # , +t_DOT = r'\.' # . +t_SEMICOLON = r'\;' # ; +t_AT = r'\@' # @ +t_PLUS = r'\+' # + +t_MINUS = r'\-' # - +t_MULTIPLY = r'\*' # * +t_DIVIDE = r'\/' # / +t_EQ = r'\=' # = +t_LT = r'\<' # < +t_LTEQ = r'\<\=' # <= +t_ASSIGN = r'\<\-' # <- +t_INT_COMP = r'~' # ~ +t_NOT = r'not' # not + +#ignore spaces +t_ignore = ' \t\r\f' + +simple_rules = { + 't_LPAREN': t_LPAREN, + 't_RPAREN': t_RPAREN, + 't_LBRACE': t_LBRACE, + 't_RBRACE': t_RBRACE, + 't_COLON': t_COLON, + 't_COMMA': t_COMMA, + 't_DOT': t_DOT, + 't_SEMICOLON': t_SEMICOLON, + 't_AT': t_AT, + 't_PLUS': t_PLUS, + 't_MINUS': t_MINUS, + 't_MULTIPLY': t_MULTIPLY, + 't_DIVIDE': t_DIVIDE, + 't_EQ': t_EQ, + 't_LT': t_LT, + 't_LTEQ': t_LTEQ, + 't_ASSIGN': t_ASSIGN, + 't_INT_COMP': t_INT_COMP, + 't_NOT': t_NOT, + 't_ignore' : t_ignore +} + + +#Complex rules for cool + +@TOKEN(r"(true|false)") +def t_BOOLEAN (token): + token.value = True if token.value == basic_keywords['true'] else False + return token + +@TOKEN(r"\d+") +def t_INTEGER(token): + token.value = int(token.value) + return token + +@TOKEN(r"[A-Z][a-zA-Z_0-9]*") +def t_TYPE(token): + token.type = basic_keywords.get(token.value, 'TYPE') + return token + +@TOKEN(r"\n+") +def t_newline(token): + token.lexer.lineno += len(token.value) + + +@TOKEN(r"[a-z][a-zA-Z_0-9]*") +def t_ID(token): + token.type = basic_keywords.get(token.value, 'ID') + return token + + + +#Lexer states +def states(): + return ( + ("STRING", "exclusive"), + ("COMMENT", "exclusive") + ) + +# The string states + +@TOKEN(r"\"") +def t_STRING_start(token): + token.lexer.push_state("STRING") + token.lexer.string_backslashed = False + token.lexer.stringbuf = "" + + +@TOKEN(r"\n") +def t_STRING_newline(token): + token.lexer.lineno += 1 + if not token.lexer.string_backslashed: + print("String newline not escaped") + token.lexer.skip(1) + else: + token.lexer.string_backslashed = False + + +@TOKEN(r"\"") +def t_STRING_end(token): + if not token.lexer.string_backslashed: + token.lexer.pop_state() + token.value = token.lexer.stringbuf + token.type = "STRING" + return token + else: + token.lexer.stringbuf += '"' + token.lexer.string_backslashed = False + +@TOKEN(r"[^\n]") +def t_STRING_anything( token): + if token.lexer.string_backslashed: + if token.value == 'b': + token.lexer.stringbuf += '\b' + elif token.value == 't': + token.lexer.stringbuf += '\t' + elif token.value == 'n': + token.lexer.stringbuf += '\n' + elif token.value == 'f': + token.lexer.stringbuf += '\f' + elif token.value == '\\': + token.lexer.stringbuf += '\\' + else: + token.lexer.stringbuf += token.value + token.lexer.string_backslashed = False + else: + if token.value != '\\': + token.lexer.stringbuf += token.value + else: + token.lexer.string_backslashed = True + + +# STRING ignored characters +t_STRING_ignore = '' + + + + + + +# The comment states +@TOKEN(r"\(\*") +def t_COMMENT_start(token): + token.lexer.push_state("COMMENT") + token.lexer.comment_count = 0 + +#Comments can be recursive +@TOKEN(r"\(\*") +def t_COMMENT_startanother(t): + t.lexer.comment_count += 1 + +@TOKEN(r"\*\)") +def t_COMMENT_end(token): + if token.lexer.comment_count == 0: + token.lexer.pop_state() + else: + token.lexer.comment_count -= 1 + + +t_ignore_SINGLE_LINE_COMMENT = r"\-\-[^\n]*" + + + + + +#Error handlers +#(4, 2) - LexicographicError: ERROR "!" +# STRING error handler +def t_STRING_error( token): + print('({0}, {1}) - LexicographicError: ERROR "{2}"'.format(token.lineno, token.lexpos, token.value[0])) + token.lexer.skip(1) + +#(55, 46) - LexicographicError: EOF in comment +# COMMENT error handler +def t_COMMENT_error( token): + print("({0}, {1}) - LexicographicError: EOF in comment".format(token.lineno, token.lexpos)) + token.lexer.skip(1) + + +def t_error( token): + print('({0}, {1}) - LexicographicError: ERROR "{2}"'.format(token.lineno, token.lexpos, token.value[0])) + token.lexer.skip(1) + + + +#Complex rules list +complex_rules = { + 't_BOOLEAN': t_BOOLEAN, + 't_INTEGER': t_INTEGER, + 't_TYPE': t_TYPE, + 't_newline': t_newline, + 't_ID': t_ID, + #---------- + #String states rules + 't_STRING_start': t_STRING_start, + 't_STRING_newline': t_STRING_newline, + 't_STRING_anything': t_STRING_anything, + 't_STRING_end': t_STRING_end, + #---------- + #Comment states rules + 't_COMMENT_start': t_COMMENT_start, + 't_COMMENT_startanother': t_COMMENT_startanother, + 't_COMMENT_end': t_COMMENT_end, +} +#Error handlers +error_handlers = { + 't_STRING_error': t_STRING_error, + 't_COMMENT_error': t_COMMENT_error, + 't_error': t_error +} + diff --git a/src/coolc.sh b/src/coolc.sh index 3088de4f..002ce0cb 100755 --- a/src/coolc.sh +++ b/src/coolc.sh @@ -1,11 +1,17 @@ -# Incluya aquí las instrucciones necesarias para ejecutar su compilador - INPUT_FILE=$1 OUTPUT_FILE=${INPUT_FILE:0: -2}mips + +#El compilador va a ser un py. +#Aquí llamamos al compilador con los valores de la entrada estándar. + + + # Si su compilador no lo hace ya, aquí puede imprimir la información de contacto -echo "LINEA_CON_NOMBRE_Y_VERSION_DEL_COMPILADOR" # TODO: Recuerde cambiar estas -echo "Copyright (c) 2019: Nombre1, Nombre2, Nombre3" # TODO: líneas a los valores correctos +echo "DiazRock Compiler" # TODO: Recuerde cambiar estas +echo "CopyLeft (L) 2020: Alejandro Díaz Roque" # Llamar al compilador -echo "Compiling $INPUT_FILE into $OUTPUT_FILE" +python3 main.py "$@" +#echo "Compiling $INPUT_FILE into $OUTPUT_FILE" + diff --git a/src/main.py b/src/main.py new file mode 100644 index 00000000..48bc0652 --- /dev/null +++ b/src/main.py @@ -0,0 +1,36 @@ +import sys, fileinput +from argparse import ArgumentParser +from compiler.components.lexer_analyzer import tokenizer, tokens +from compiler.components.syntax_analyzer import run_parser + +parser_input = ArgumentParser(description= 'This is the Diaz-Horrach cool compiler, an school project.\nRead this help and see the ofitial repo') +parser_input.add_argument('files_for_compile', help = 'The file(s) to be compiled', nargs= '+') +""" parser_input.add_argument("--lexer", help = 'Select the lexer that you could use from avialable options', choices = component_injector['lexer_options'].keys(), + default='cool') +parser_input.add_argument("--parser", help = 'Select the lexer that you could use from avialable options', choices = component_injector['parser_options'].keys()) +parser_input.add_argument("--output", help = 'Put the info of the selected components in the standard output.', choices = ['l','p','t']) + """ +args = parser_input.parse_args() +#print(args.files_for_compile) +file = open(args.files_for_compile[0]) +working_input = file.read() + +all_errors = [] +token_errors, tokens_for_input, real_col = tokenizer(working_input) +if token_errors: + print(token_errors[0]) + exit(1) +#print(tokens_for_input) + +parser_errors = run_parser(tokens, working_input, real_col) + +""" print('tokens for _input \n') +print(tokens_for_input) +print('---------------') """ +if parser_errors: + print(parser_errors[0]) + exit(1) + + +exit(0) +