diff --git a/jcematcom - Entrega.pdf b/jcematcom - Entrega.pdf new file mode 100644 index 000000000..9aabf1075 Binary files /dev/null and b/jcematcom - Entrega.pdf differ diff --git a/requirements.txt b/requirements.txt index 9eb0cad1a..cba16ee2f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ pytest pytest-ordering +ply diff --git a/src/Compiler/CodeGen/Assembler/Generator.py b/src/Compiler/CodeGen/Assembler/Generator.py new file mode 100644 index 000000000..6e0147f22 --- /dev/null +++ b/src/Compiler/CodeGen/Assembler/Generator.py @@ -0,0 +1,565 @@ +from CodeGen.Assembler.mips_data import * +from CodeGen.Intermediate import cil +from Semantic import visitor + + +class CILToSPIMVisitor: + + def __init__(self): + self.dotdata = list() + self.dottext = list() + self.current_function = None + self.defined_types = None + self.args_for_call = list() + + def add_data(self, data): + self.dotdata.append(data) + + def add_instruction(self, instruction): + self.dottext.append(instruction) + + def get_addr(self, offset, register): + return f'{offset}({register})' + + def get_stack_addr(self, name, offset = 0): + for i in range(len(self.current_function.params)): + if name == self.current_function.params[i].name: + return self.get_addr(4 * (i + 1 + len(self.current_function.localvars) + offset), sp_REGISTER) + + for i in range(len(self.current_function.localvars)): + if name == self.current_function.localvars[i].name: + return self.get_addr(4 * (i + 1 + offset), sp_REGISTER) + + + @visitor.on('node') + def visit(self, node): + pass + + + @visitor.when(cil.ProgramNode) + def visit(self, node): + self.defined_types = node.dottypes + self.add_data(Asciiz('abort_message', 'Abort called from class ').__mips__()) + self.add_data(Asciiz('eol', '\\n').__mips__()) + self.add_data(Asciiz('empty_string', "").__mips__()) + + for _data in node.dotdata: + self.visit(_data) + for _type in node.dottypes: + self.visit(_type) + for _code in node.dotcode: + self.visit(_code) + + return (self.dotdata, self.dottext) + + + @visitor.when(cil.TypeNode) + def visit(self, node): + """ + node.name -> DataNode + node.parent -> str + node.attributes -> [ str ... ] + node.methods = [ (str, str) ... ] + """ + self.add_data(Type(node.name, node.parent, node.attributes, node.methods).__mips__()) + + + @visitor.when(cil.DataNode) + def visit(self, node): + """ + node.name -> str + node.value -> str + """ + self.add_data(Asciiz(node.name, node.value).__mips__()) + + + @visitor.when(cil.FunctionNode) + def visit(self, node): + """ + node.name -> str + node.params -> [ ParamNode ... ] + node.localvars -> [ LocalNode ... ] + node.instructions -> [ Node ... ] + """ + self.current_function = node + instructions = list() + instructions.append(Addi(sp_REGISTER, sp_REGISTER, -4 * (len(self.current_function.localvars)+1)).__mips__()) + instructions.append(Sw(ra_REGISTER, self.get_addr(0, sp_REGISTER)).__mips__()) + + for instr in node.instructions: + instructions += self.visit(instr) + + self.add_instruction(Function(node.name, instructions).__mips__()) + self.current_function = None + + + @visitor.when(cil.ParamNode) + def visit(self, node): + """ + node.name -> str + """ + return [] + + + @visitor.when(cil.LocalNode) + def visit(self, node): + """ + node.name -> str + """ + return [] + + + @visitor.when(cil.AssignNode) + def visit(self, node): + """ + node.dest -> str + node.source -> str + """ + instructions = list() + + source = self.get_stack_addr(node.source) + dest = self.get_stack_addr(node.dest) + + instructions.append(Lw(a_REGISTERS[0], source).__mips__()) + instructions.append(Lw(t_REGISTERS[0], self.get_addr(0, a_REGISTERS[0])).__mips__()) + instructions.append(Lw(t_REGISTERS[0], self.get_addr(12, t_REGISTERS[0])).__mips__()) + instructions.append(Jalr(ra_REGISTER, t_REGISTERS[0]).__mips__()) + + instructions.append(Sw(v_REGISTERS[0], dest).__mips__()) + return instructions + + + @visitor.when(cil.IntComplementNode) + def visit(self, node): + """ + node.dest -> str + node.source -> str + """ + instructions = list() + + source = self.get_stack_addr(node.source) + dest = self.get_stack_addr(node.dest) + + instructions.append(La(a_REGISTERS[0], "type_Int").__mips__()) + instructions.append(Jal('create_instance').__mips__()) + + instructions.append(Lw(t_REGISTERS[1], source).__mips__()) + instructions.append(Lw(t_REGISTERS[1], self.get_addr(4, t_REGISTERS[1])).__mips__()) + + instructions.append(Sub(t_REGISTERS[1], zero_REGISTER, t_REGISTERS[1]).__mips__()) + instructions.append(Sw(t_REGISTERS[1], self.get_addr(4, v_REGISTERS[0])).__mips__()) + instructions.append(Sw(v_REGISTERS[0], dest).__mips__()) + return instructions + + + @visitor.when(cil.BoolComplementNode) + def visit(self, node): + """ + node.dest -> str + node.source -> str + """ + instructions = list() + + source = self.get_stack_addr(node.source) + dest = self.get_stack_addr(node.dest) + + instructions.append(La(a_REGISTERS[0], "type_Bool").__mips__()) + instructions.append(Jal('create_instance').__mips__()) + + instructions.append(Lw(t_REGISTERS[1], source).__mips__()) + instructions.append(Lw(t_REGISTERS[1], self.get_addr(4, t_REGISTERS[1])).__mips__()) + + instructions.append(Li(t_REGISTERS[2], 1).__mips__()) + instructions.append(Sub(t_REGISTERS[1], t_REGISTERS[2], t_REGISTERS[1]).__mips__()) + instructions.append(Sw(t_REGISTERS[1], self.get_addr(4, v_REGISTERS[0])).__mips__()) + instructions.append(Sw(v_REGISTERS[0], dest).__mips__()) + return instructions + + + @visitor.when(cil.PlusNode) + def visit(self, node): + """ + node.dest -> str + node.left -> str + node.right -> str + """ + instructions = list() + + dest = self.get_stack_addr(node.dest) + left = self.get_stack_addr(node.left) + right = self.get_stack_addr(node.right) + + instructions.append(La(a_REGISTERS[0], "type_Int").__mips__()) + instructions.append(Jal('create_instance').__mips__()) + + instructions.append(Lw(t_REGISTERS[1], left).__mips__()) + instructions.append(Lw(t_REGISTERS[1], self.get_addr(4, t_REGISTERS[1])).__mips__()) + instructions.append(Lw(t_REGISTERS[2], right).__mips__()) + instructions.append(Lw(t_REGISTERS[2], self.get_addr(4, t_REGISTERS[2])).__mips__()) + + instructions.append(Add(t_REGISTERS[3], t_REGISTERS[1], t_REGISTERS[2]).__mips__()) + instructions.append(Sw(t_REGISTERS[3], self.get_addr(4, v_REGISTERS[0])).__mips__()) + instructions.append(Sw(v_REGISTERS[0], dest).__mips__()) + return instructions + + + @visitor.when(cil.MinusNode) + def visit(self, node): + """ + node.dest -> str + node.left -> str + node.right -> str + """ + instructions = list() + + dest = self.get_stack_addr(node.dest) + left = self.get_stack_addr(node.left) + right = self.get_stack_addr(node.right) + + instructions.append(La(a_REGISTERS[0], "type_Int").__mips__()) + instructions.append(Jal('create_instance').__mips__()) + + instructions.append(Lw(t_REGISTERS[1], left).__mips__()) + instructions.append(Lw(t_REGISTERS[1], self.get_addr(4, t_REGISTERS[1])).__mips__()) + instructions.append(Lw(t_REGISTERS[2], right).__mips__()) + instructions.append(Lw(t_REGISTERS[2], self.get_addr(4, t_REGISTERS[2])).__mips__()) + + instructions.append(Sub(t_REGISTERS[3], t_REGISTERS[1], t_REGISTERS[2]).__mips__()) + instructions.append(Sw(t_REGISTERS[3], self.get_addr(4, v_REGISTERS[0])).__mips__()) + instructions.append(Sw(v_REGISTERS[0], dest).__mips__()) + return instructions + + + @visitor.when(cil.StarNode) + def visit(self, node): + """ + node.dest -> str + node.left -> str + node.right -> str + """ + instructions = list() + + dest = self.get_stack_addr(node.dest) + left = self.get_stack_addr(node.left) + right = self.get_stack_addr(node.right) + + instructions.append(La(a_REGISTERS[0], "type_Int").__mips__()) + instructions.append(Jal('create_instance').__mips__()) + + instructions.append(Lw(t_REGISTERS[1], left).__mips__()) + instructions.append(Lw(t_REGISTERS[1], self.get_addr(4, t_REGISTERS[1])).__mips__()) + instructions.append(Lw(t_REGISTERS[2], right).__mips__()) + instructions.append(Lw(t_REGISTERS[2], self.get_addr(4, t_REGISTERS[2])).__mips__()) + + instructions.append(Mult(t_REGISTERS[1], t_REGISTERS[2]).__mips__()) + instructions.append(Mflo(t_REGISTERS[3]).__mips__()) + instructions.append(Sw(t_REGISTERS[3], self.get_addr(4, v_REGISTERS[0])).__mips__()) + instructions.append(Sw(v_REGISTERS[0], dest).__mips__()) + return instructions + + + @visitor.when(cil.DivNode) + def visit(self, node): + """ + node.dest -> str + node.left -> str + node.right -> str + """ + instructions = list() + + dest = self.get_stack_addr(node.dest) + left = self.get_stack_addr(node.left) + right = self.get_stack_addr(node.right) + + instructions.append(La(a_REGISTERS[0], "type_Int").__mips__()) + instructions.append(Jal('create_instance').__mips__()) + + instructions.append(Lw(t_REGISTERS[1], left).__mips__()) + instructions.append(Lw(t_REGISTERS[1], self.get_addr(4, t_REGISTERS[1])).__mips__()) + instructions.append(Lw(t_REGISTERS[2], right).__mips__()) + instructions.append(Lw(t_REGISTERS[2], self.get_addr(4, t_REGISTERS[2])).__mips__()) + + instructions.append(Div(t_REGISTERS[1], t_REGISTERS[2]).__mips__()) + instructions.append(Mflo(t_REGISTERS[3]).__mips__()) + instructions.append(Sw(t_REGISTERS[3], self.get_addr(4, v_REGISTERS[0])).__mips__()) + instructions.append(Sw(v_REGISTERS[0], dest).__mips__()) + return instructions + + + @visitor.when(cil.GetAttribNode) + def visit(self, node): + """ + node.dest -> str / Variable de destino + node.instance -> str / Variable instancia + node.pos -> int / Numero del atributo + """ + instructions = list() + + dest = self.get_stack_addr(node.dest) + instance = self.get_stack_addr(node.instance) + + instructions.append(Lw(t_REGISTERS[0], instance).__mips__()) + instructions.append(Lw(a_REGISTERS[0], self.get_addr(4 * (1 + node.pos), t_REGISTERS[0])).__mips__()) + instructions.append(Lw(t_REGISTERS[0], self.get_addr(0, a_REGISTERS[0])).__mips__()) + instructions.append(Lw(t_REGISTERS[0], self.get_addr(12, t_REGISTERS[0])).__mips__()) + instructions.append(Jalr(ra_REGISTER, t_REGISTERS[0]).__mips__()) + instructions.append(Sw(v_REGISTERS[0], dest).__mips__()) + + return instructions + + + @visitor.when(cil.SetAttribNode) + def visit(self, node): + """ + node.source -> str / Variable de origen + node.instance -> str / Variable instancia + node.pos -> int / Numero del Atributo + """ + instructions = list() + + source = self.get_stack_addr(node.source) + instance = self.get_stack_addr(node.instance) + + instructions.append(Lw(a_REGISTERS[0], source).__mips__()) + instructions.append(Lw(t_REGISTERS[0], self.get_addr(0, a_REGISTERS[0])).__mips__()) + instructions.append(Lw(t_REGISTERS[0], self.get_addr(12, t_REGISTERS[0])).__mips__()) + instructions.append(Jalr(ra_REGISTER, t_REGISTERS[0]).__mips__()) + + instructions.append(Lw(t_REGISTERS[1], instance).__mips__()) + instructions.append(Sw(v_REGISTERS[0], self.get_addr(4 * (1 + node.pos), t_REGISTERS[1])).__mips__()) + instructions.append(Sw(t_REGISTERS[1], instance).__mips__()) + + return instructions + + + @visitor.when(cil.AllocateNode) + def visit(self, node): + """ + node.type -> str / Direccion del Tipo + node.dest -> str / Variable a la que se le asignara la direccion del espacio en memoria + """ + instructions = list() + + dest = self.get_stack_addr(node.dest) + + instructions.append(La(a_REGISTERS[0], node.type).__mips__()) + instructions.append(Jal('create_instance').__mips__()) + + if not node.value is None: + if node.type == 'type_String': + instructions.append(La(t_REGISTERS[0], node.value).__mips__()) + else: + instructions.append(Li(t_REGISTERS[0], node.value).__mips__()) + instructions.append(Sw(t_REGISTERS[0], self.get_addr(4, v_REGISTERS[0])).__mips__()) + + instructions.append(Sw(v_REGISTERS[0], dest).__mips__()) + return instructions + + + @visitor.when(cil.TypeOfNode) + def visit(self, node): + """ + node.obj -> str / Variable de Tipo T + node.dest -> str / Variable donde se almacenara la direccion al tipo T + """ + instructions = list() + + dest = self.get_stack_addr(node.dest) + obj = self.get_stack_addr(node.obj) + + + instructions.append(Lw(a_REGISTERS[0], obj).__mips__()) + instructions.append(Lw(a_REGISTERS[0], self.get_addr(0, a_REGISTERS[0])).__mips__()) + instructions.append(Lw(a_REGISTERS[0], self.get_addr(8, a_REGISTERS[0])).__mips__()) + instructions.append(Jal('str_assigment_from_str').__mips__()) + instructions.append(Sw(v_REGISTERS[0], dest).__mips__()) + return instructions + + + @visitor.when(cil.LabelNode) + def visit(self, node): + """ + node.name -> str / Nombre de la etiqueta + """ + return [Label(node.name).__mips__()] + + + @visitor.when(cil.GotoNode) + def visit(self, node): + """ + node.label -> str / Nombre de la etiqueta + """ + return [J(node.label).__mips__()] + + + @visitor.when(cil.GotoIfNode) + def visit(self, node): + """ + node.vname -> str / Variable de tipo Bool + node.goto_label -> str / Nombre de la etiqueta + """ + instructions = list() + + vname = self.get_stack_addr(node.vname) + + instructions.append(Lw(t_REGISTERS[0], vname).__mips__()) + instructions.append(Lw(t_REGISTERS[0], self.get_addr(4, t_REGISTERS[0])).__mips__()) + instructions.append(Li(t_REGISTERS[1], 1).__mips__()) + instructions.append(Beq(t_REGISTERS[0], t_REGISTERS[1], node.goto_label).__mips__()) + + return instructions + + + @visitor.when(cil.StaticCallNode) + def visit(self, node): + """ + node.function -> str / Nombre de la funcion (en formato `function__at_`) + node.dest -> str / Variable que almacenara el valor de retorno + """ + instructions = list() + + dest = self.get_stack_addr(node.dest) + + instructions.append(Addi(sp_REGISTER, sp_REGISTER, -4 * len(self.args_for_call)).__mips__()) + + for i in range(len(self.args_for_call)): + instance = self.get_stack_addr(self.args_for_call[i].name, len(self.args_for_call)) + instructions.append(Lw(t_REGISTERS[0], instance).__mips__()) + instructions.append(Sw(t_REGISTERS[0], self.get_addr(4 * i, sp_REGISTER)).__mips__()) + + instructions.append(Jal(node.function).__mips__()) + instructions.append(Lw(t_REGISTERS[0], self.get_addr(0, sp_REGISTER)).__mips__()) + instance0 = self.get_stack_addr(self.args_for_call[0].name, len(self.args_for_call)) + instructions.append(Sw(t_REGISTERS[0], instance0).__mips__()) + instructions.append(Addi(sp_REGISTER, sp_REGISTER, 4 * len(self.args_for_call)).__mips__()) + instructions.append(Sw(v_REGISTERS[0], dest).__mips__()) + self.args_for_call = list() + return instructions + + + @visitor.when(cil.DynamicCallNode) + def visit(self, node): + """ + node.xtype -> str / Variable que contiene la direccion al nombre de su tipo dinamico + node.function -> str / Nombre de la funcion (Solo el nombre, no esta en formato `function__at_`) + node.dest -> str / Variable que almacenara el valor de retorno + """ + pass + + + @visitor.when(cil.ArgNode) + def visit(self, node): + """ + node.name -> str / Variable cuyo valor se pasara como argumento + """ + self.args_for_call.append(node) + return [] + + + @visitor.when(cil.ReturnNode) + def visit(self, node): + """ + node.ret -> str / Variable que contiene el valor de retorno + """ + instructions = list() + ret = self.get_stack_addr(node.ret) + instructions.append(Lw(v_REGISTERS[0], ret).__mips__()) + instructions.append(Lw(ra_REGISTER, self.get_addr(0, sp_REGISTER)).__mips__()) + instructions.append(Addi(sp_REGISTER, sp_REGISTER, 4 * (len(self.current_function.localvars)+1)).__mips__()) + instructions.append(Jr(ra_REGISTER).__mips__()) + return instructions + + + @visitor.when(cil.RunTimeNode) + def visit(self, node): + instructions = list() + instructions.append(La(a_REGISTERS[0], node.error).__mips__()) + instructions.append(Jal('runtime_error').__mips__()) + return instructions + + + @visitor.when(cil.EndProgramNode) + def visit(self, node): + instructions = list() + instructions.append(Li(v_REGISTERS[0], 10).__mips__()) + instructions.append(Syscall().__mips__()) + return instructions + + + @visitor.when(cil.LoadNode) + def visit(self, node): + """ + node.dest -> dest / Variable destino + node.msg -> msg / Variable de la seccion .data + """ + instructions = list() + + dest = self.get_stack_addr(node.dest) + + instructions.append(La(a_REGISTERS[0], node.msg).__mips__()) + instructions.append(Jal('str_assigment_from_str').__mips__()) + instructions.append(Sw(v_REGISTERS[0], dest).__mips__()) + return instructions + + + @visitor.when(cil.BranchEqualNode) + def visit(self, node): + """ + node.left -> str / Variable con el valor izquierdo + node.right -> str / Variable con el valor derecho + node.label -> str / Etiqueta de salto + """ + instructions = list() + + left = self.get_stack_addr(node.left) + right = self.get_stack_addr(node.right) + + instructions.append(Lw(a_REGISTERS[0], left).__mips__()) + instructions.append(Lw(a_REGISTERS[1], right).__mips__()) + instructions.append(Lw(t_REGISTERS[0], self.get_addr(0, a_REGISTERS[0])).__mips__()) + instructions.append(Lw(t_REGISTERS[0], self.get_addr(16, t_REGISTERS[0])).__mips__()) + instructions.append(Jalr(ra_REGISTER, t_REGISTERS[0]).__mips__()) + instructions.append(Lw(t_REGISTERS[0], self.get_addr(4, v_REGISTERS[0])).__mips__()) + instructions.append(Li(t_REGISTERS[1], 1).__mips__()) + instructions.append(Beq(t_REGISTERS[0], t_REGISTERS[1], node.label).__mips__()) + return instructions + + + @visitor.when(cil.BranchLTNode) + def visit(self, node): + """ + node.left -> str / Variable con el valor izquierdo + node.right -> str / Variable con el valor derecho + node.label -> str / Etiqueta de salto + """ + instructions = list() + + left = self.get_stack_addr(node.left) + right = self.get_stack_addr(node.right) + + instructions.append(Lw(t_REGISTERS[0], left).__mips__()) + instructions.append(Lw(t_REGISTERS[1], right).__mips__()) + instructions.append(Lw(t_REGISTERS[0], self.get_addr(4, t_REGISTERS[0])).__mips__()) + instructions.append(Lw(t_REGISTERS[1], self.get_addr(4, t_REGISTERS[1])).__mips__()) + instructions.append(Blt(t_REGISTERS[0], t_REGISTERS[1], node.label).__mips__()) + return instructions + + + @visitor.when(cil.BranchLENode) + def visit(self, node): + """ + node.left -> str / Variable con el valor izquierdo + node.right -> str / Variable con el valor derecho + node.label -> str / Etiqueta de salto + """ + instructions = list() + + left = self.get_stack_addr(node.left) + right = self.get_stack_addr(node.right) + + instructions.append(Lw(t_REGISTERS[0], left).__mips__()) + instructions.append(Lw(t_REGISTERS[1], right).__mips__()) + instructions.append(Lw(t_REGISTERS[0], self.get_addr(4, t_REGISTERS[0])).__mips__()) + instructions.append(Lw(t_REGISTERS[1], self.get_addr(4, t_REGISTERS[1])).__mips__()) + instructions.append(Ble(t_REGISTERS[0], t_REGISTERS[1], node.label).__mips__()) + return instructions \ No newline at end of file diff --git a/src/Compiler/CodeGen/Assembler/mips_data.py b/src/Compiler/CodeGen/Assembler/mips_data.py new file mode 100644 index 000000000..ffdd2159b --- /dev/null +++ b/src/Compiler/CodeGen/Assembler/mips_data.py @@ -0,0 +1,91 @@ +from CodeGen.Assembler.mips_instructions import * + +# Registers +t_REGISTERS = ['$t0', '$t1', '$t2', '$t3', '$t4', '$t5', '$t6', '$t7', '$t8', '$t9'] #temporary (not preserved across call) +s_REGISTERS = ['$s0', '$s1', '$s2', '$s3', '$s4', '$s5', '$s6', '$s7'] #saved temporary (preserved across call) +a_REGISTERS = ['$a0', '$a1', '$a2', '$a3'] # arguments +v_REGISTERS = ['$v0', '$v1'] #expression evaluation and results of a function +zero_REGISTER = '$zero' #constant 0 +fp_REGISTER = '$fp' #frame pointer +sp_REGISTER = '$sp' #stack pointer +ra_REGISTER = '$ra' #return address (used by function call) +gp_REGISTER = '$gp' #pointer to global area + +INTERNAL = "_INTERNAL" +INTERNAL_METHOD = "_INTERNAL_METHOD_" +INTERNAL_TYPE = "_INTERNAL_TYPE" + +class Node: + pass + +class Label(Node): + def __init__(self, label): + self.label = label + def __mips__(self): + return '{}:'.format(self.label) + +class Asciiz(Node): + def __init__(self, name, string): + self.name = name + self.string = string + def __mips__(self) -> str: + return '\n{}: .asciiz "{}"'.format(self.name, self.string) + +class Word(Node): + def __init__(self, name, value): + self.name = name + self.value = value + def __mips__(self) -> str: + return '\n{}: .word {}'.format(self.name, self.string) + + +class Type(Node): + def __init__(self, name, parent, attributes, methods): + self.data = name + self.parent = parent + self.methods = methods + self.attributes = attributes + + def __mips__(self): + output = f'\n\ntype_{self.data.value}_methods:' + + for meth in self.methods: + output += f'\n\t.word {meth[1]}' + + assigment = 'ref_assigment' + equal = 'ref_equal' + + if self.data.value in ['Int', 'Bool']: + assigment = 'val_assigment' + equal = 'val_equal' + elif self.data.value == 'String': + assigment = 'str_assigment' + equal = 'str_equal' + + output += f'\n\ntype_{self.data.value}:' + output += f'\n\t.word {4 * (len(self.attributes)+1)}' + output += f'\n\t.word type_{self.data.value}_methods' + output += f'\n\t.word {self.data.name}' + output += f'\n\t.word {assigment}' + output += f'\n\t.word {equal}' + + if self.parent is None: + output += f'\n\t.word 0' + else: + output += f'\n\t.word type_{self.parent}' + + return output + +class Function(Node): + def __init__(self, name, instructions): + self.name = name + self.instructions = instructions + + def __mips__(self): + output = f'\n\n{self.name}:' + + for instr in self.instructions: + output += f'\n\t{instr}' + + return output + diff --git a/src/Compiler/CodeGen/Assembler/mips_instructions.py b/src/Compiler/CodeGen/Assembler/mips_instructions.py new file mode 100644 index 000000000..a63bbc7d2 --- /dev/null +++ b/src/Compiler/CodeGen/Assembler/mips_instructions.py @@ -0,0 +1,874 @@ +class Node: + pass + + +class IType(Node): + def __init__(self, op = None, first = None, second = None, third = None): + self.op = op + self.first = first + self.second = second + self.third = third + + def __mips__(self): + if self.first is None: + return '{}'.format(self.op) + + elif self.second is None: # instruction with 1 factor + return '{} {}'.format(self.op, self.first,) + + elif self.third is None: # instruction with 2 factors + return '{} {}, {}'.format(self.op, self.first, self.second) + + else: # instruction with 3 factors + return '{} {}, {}, {}'.format(self.op, self.first, self.second, self.third) + + +############################### INMEDIATE TYPE INSTRUCTIONS ############################## + +####### ARITHMETIC AND LOGIC ####### + +class Addi(IType): + """ + Addition inmediate with overflow + """ + def __init__(self, rt, rs, inmediate): + super(Addi, self).__init__('addi', rt, rs, inmediate) + + +class Addiu(IType): + """ + Addition inmediate without overflow + """ + def __init__(self, rt, rs, inmediate): + super(Addiu, self).__init__('addiu', rt, rs, inmediate) + + +class Andi(IType): + """ + AND inmediate: Put the logical AND of register rs and the zero-extended immediate into register rt + """ + def __init__(self, rt, rs, inmediate): + super(Andi, self).__init__('andi', rt, rs, inmediate) + + +class Ori(IType): + """ + OR inmediate: Put the logical OR of register rs and the zero-extended immediate into register rt + """ + def __init__(self, rt, rs, inmediate): + super(Ori, self).__init__('ori', rt, rs, inmediate) + + +class Xori(IType): + """ + XOR inmediate: Put the logical XOR of register rs and the zero-extended immediate into register rt + """ + def __init__(self, rt, rs, inmediate): + super(Xori, self).__init__('xori', rt, rs, inmediate) + + +####### COMPARISON ####### + +class Slti(IType): + """ + Set less than immediate signed: Set register rt to 1 if register rs is less than the sign-extended immediate, and to 0 otherwise. Signed. + """ + def __init__(self, rt, rs, inmediate): + super(Slti, self).__init__('slti', rt, rs, inmediate) + + +class Sltiu(IType): + """ + Set less than immediate unsigned: Set register rt to 1 if register rs is less than the sign-extended immediate, and to 0 otherwise. Unigned. + """ + def __init__(self, rt, rs, inmediate): + super(Sltiu, self).__init__('sltiu', rt, rs, inmediate) + + +class Lui(IType): + """ + Load upper immediate: Load the lower halfword of the immediate imm into the upper halfword of register rt. + """ + def __init__(self, rt, inmediate): + super(Lui, self).__init__('lui', rt, inmediate) + + +class Li(IType): + """ + Load immediate: Move the immediate imm into register rdest. + """ + def __init__(self, rdest, inm): + super(Li, self).__init__('li', rdest, inm) + + +class Slti(IType): + """ + Set less than immediate signed: Set register rd to 1 if register rs is less than the immediate, and to 0 otherwise. Signed. + """ + def __init__(self, rt, rs, inmediate): + super(Slti, self).__init__('slti', rt, rs, inmediate) + + +class Sltiu(IType): + """ + Set less than immediate unsigned: Set register rd to 1 if register rs is less than the immediate, and to 0 otherwise. Unigned. + """ + def __init__(self, rt, rs, inmediate): + super(Sltiu, self).__init__('sltiu', rt, rs, inmediate) + + + +####### BRANCH INSTRUCTIONS ####### + +class B(IType): + """ + Unconditionally branch to the instruction at the label. + """ + def __init__(self, label): + super(B, self).__init__('b', label) + + +class Beq(IType): + """ + Branch on equal: Conditionally branch the number of instructions specified by the offset if register rs equals rt. + """ + def __init__(self, rs, rt, label): + super(Beq, self).__init__('beq', rs, rt, label) + + +class Bgez(IType): + """ + Branch on greater than equal zero: Conditionally branch the number of instructions specified by the offset if register rs is greater than or equal to 0. + """ + def __init__(self, rs, label): + super(Bgez, self).__init__('bgez', rs, label) + + +class Bgezal(IType): + """ + Branch on greater than equal zero and link: Conditionally branch the number of instructions specified by the offset if register rs is greater than or equal to 0, then save the address of the next instruction in register 31. + """ + def __init__(self, rs, label): + super(Bgezal, self).__init__('bgezal', rs, label) + + +class Bgtz(IType): + """ + Branch on greater than zero: Conditionally branch the number of instructions specified by the offset if register rs is greater than 0. + """ + def __init__(self, rs, label): + super(Bgtz, self).__init__('bgtz', rs, label) + + +class Blez(IType): + """ + Branch on less than equal zero: Conditionally branch the number of instructions specified by the offset if register rs is less than or equal to 0. + """ + def __init__(self, rs, label): + super(Blez, self).__init__('blez', rs, label) + + +class Bltz(IType): + """ + Branch on less than zero: Conditionally branch the number of instructions specified by the offset if register rs is less than 0. + """ + def __init__(self, rs, label): + super(Bltz, self).__init__('bltz', rs, label) + + +class Bltzal(IType): + """ + Branch on less than zero and link: Conditionally branch the number of instructions specified by the offset if register rs is less than 0. Save the address of the next instruction in register 31. + """ + def __init__(self, rs, label): + super(Bltzal, self).__init__('bltzal', rs, label) + + +class Bne(IType): + """ + Branch on not equal: Conditionally branch the number of instructions specified by the offset if register rs is not equal to rt. + """ + def __init__(self, rs, label): + super(Bne, self).__init__('bne', rs, label) + + +class Beqz(IType): + def __init__(self, rs, label): + """ + Branch on equal zero: Conditionally branch to the instruction at the label if rs equals 0. + """ + super(Beqz, self).__init__('beqz', rs, label) + + +class Bnez(IType): + """ + Branch on not equal zero: Conditionally branch to the instruction at the label if register rs is not equal to 0. + """ + def __init__(self, rs, label): + super(Bnez, self).__init__('bnez', rs, label) + + +class Bge(IType): + """ + Branch on greater than equal signed: Conditionally branch to the instruction at the label if register rs1 is greater than or equal to rs2. Signed. + """ + def __init__(self, rs1, rs2, label): + super(Bge, self).__init__('bge', rs1, rs2, label) + + +class Bgeu(IType): + """ + Branch on greater than equal unsigned: Conditionally branch to the instruction at the label if register rs1 is greater than or equal to rs2. Unsigned. + """ + def __init__(self, rs1, rs2, label): + super(Bgeu, self).__init__('bgeu', rs1, rs2, label) + + +class Bgt(IType): + """ + Branch on greater than signed: Conditionally branch to the instruction at the label if register rs1 is greater than rs2. Signed. + """ + def __init__(self, rs1, rs2, label): + super(Bgt, self).__init__('bgt', rs1, rs2, label) + + +class Bgtu(IType): + """ + Branch on greater than unsigned: Conditionally branch to the instruction at the label if register rs1 is greater than rs2. Unsigned. + """ + def __init__(self, rs1, rs2, label): + super(Bgtu, self).__init__('bgtu', rs1, rs2, label) + + +class Ble(IType): + """ + Branch on less than equal signed: Conditionally branch to the instruction at the label if register rs1 is less than or equal to rs2. Signed. + """ + def __init__(self, rs1, rs2, label): + super(Ble, self).__init__('ble', rs1, rs2, label) + + +class Bleu(IType): + """ + Branch on less than equal unsigned: Conditionally branch to the instruction at the label if register rs1 is less than or equal to rs2. Unsigned. + """ + def __init__(self, rs1, rs2, label): + super(Bleu, self).__init__('bleu', rs1, rs2, label) + + +class Blt(IType): + """ + Branch on less than signed: Conditionally branch to the instruction at the label if register rs1 is less than rs2. Signed. + """ + def __init__(self, rs1, rs2, label): + super(Blt, self).__init__('blt', rs1, rs2, label) + + +class Bltu(IType): + """ + Branch on less than unsigned: Conditionally branch to the instruction at the label if register rs1 is less than rs2. Unsigned. + """ + def __init__(self, rs1, rs2, label): + super(Bltu, self).__init__('bltu', rs1, rs2, label) + + + +####### LOAD INSTRUCTIONS ####### + +class La(IType): + """ + Load address: Load computed address (not the contents of the location) into register rdest. + """ + def __init__(self, rdest, address): + super(La, self).__init__('la', rdest, address) + + +class Lb(IType): + """ + Load byte signed: Load the byte at address into register rt. Signed. + """ + def __init__(self, rt, address): + super(Lb, self).__init__('lb', rt, address) + + +class Lbu(IType): + """ + Load byte unsigned: Load the byte at address into register rt. Unsigned. + """ + def __init__(self, rt, address): + super(Lbu, self).__init__('lbu', rt, address) + + +class Lh(IType): + """ + Load halfword signed: Load the 16-bit quantity (halfword) at address into register rt. Signed. + """ + def __init__(self, rt, address): + super(Lh, self).__init__('lh', rt, address) + + +class Lhu(IType): + """ + Load halfword unsigned: Load the 16-bit quantity (halfword) at address into register rt. Unsigned. + """ + def __init__(self, rt, address): + super(Lhu, self).__init__('lhu', rt, address) + + +class Lw(IType): + """ + Load word: Load the 32-bit quantity (word) at address into register rt. + """ + def __init__(self, rt, address): + super(Lw, self).__init__('lw', rt, address) + + +class Lwl(IType): + """ + Load word: Load the left bytes from the word at the possibly unaligned address into register rt. + """ + def __init__(self, rt, address): + super(Lwl, self).__init__('lwl', rt, address) + + +class Lwr(IType): + """ + Load word: Load the right bytes from the word at the possibly unaligned address into register rt. + """ + def __init__(self, rt, address): + super(Lwr, self).__init__('lwr', rt, address) + + +class Ld(IType): + """ + Load doubleword: Load the 64-bit quantity at address into registers rdest and rdest + 1. + """ + def __init__(self, rdest, address): + super(Ld, self).__init__('ld', rdest, address) + + +class Ulh(IType): + """ + Unaligned load halfword signed: Load the 16-bit quantity (halfword) at the possibly unaligned address into register rdest. Signed. + """ + def __init__(self, rdest, address): + super(Ulh, self).__init__('ulh', rdest, address) + + +class Ulhu(IType): + """ + Unaligned load halfword unsigned: Load the 16-bit quantity (halfword) at the possibly unaligned address into register rdest. Unsigned. + """ + def __init__(self, rdest, address): + super(Ulhu, self).__init__('ulhu', rdest, address) + + +class Ulw(IType): + """ + Load the 32-bit quantity (word) at the possibly unaligned address into register rdest. + """ + def __init__(self, rdest, address): + super(Ulw, self).__init__('ulw', rdest, address) + + + +####### STORE INSTRUCTIONS ####### + +class Sb(IType): + """ + Store byte: Store the low byte from register rt at address. + """ + def __init__(self, rt, address): + super(Sb, self).__init__('sb', rt, address) + + +class Sh(IType): + """ + Store halfword: Store the low halfword from register rt at address. + """ + def __init__(self, rt, address): + super(Sh, self).__init__('sh', rt, address) + + +class Sw(IType): + """ + Store word: Store the word from register rt at address. + """ + def __init__(self, rt, address): + super(Sw, self).__init__('sw', rt, address) + + +class Swl(IType): + """ + Store word: Store the left bytes from register rt at the possibly unaligned address. + """ + def __init__(self, rt, address): + super(Swl, self).__init__('swl', rt, address) + + +class Swr(IType): + """ + Store word: Store the right bytes from register rt at the possibly unaligned address. + """ + def __init__(self, rt, address): + super(Swr, self).__init__('swr', rt, address) + + +class Sd(IType): + """ + Store doubleword: Store the 64-bit quantity in registers rs and rs + 1 at address. + """ + def __init__(self, rs, address): + super(Sd, self).__init__('sd', rs, address) + + +class Ush(IType): + """ + Unaligned store halfword: Store the low halfword from register rs at the possibly unaligned address. + """ + def __init__(self, rs, address): + super(Ush, self).__init__('ush', rs, address) + + +class Usw(IType): + """ + Unaligned store word: Store the word from register rs at the possibly unaligned address. + """ + def __init__(self, rs, address): + super(Usw, self).__init__('usw', rs, address) + + + +############################### JUMP TYPE INSTRUCTIONS ############################## + + +class J(IType): + """ + Jump: Unconditionally jump to the instruction at target. + """ + def __init__(self, target): + super(J, self).__init__('j', target) + + +class Jal(IType): + """ + Jump: Same as before and save the address of the next instruction in register rd (defaults to 31). + """ + def __init__(self, target): + super(Jal, self).__init__('jal', target) + + +class Jr(IType): + """ + Jump register: Unconditionally jump to the instruction whose address is in register rs. + """ + def __init__(self, rs): + super(Jr, self).__init__('jr', rs) + + +class Jalr(IType): + """ + Jump and link register: Unconditionally jump to the instruction whose address is in register rs. Save the address of the next instruction in register rd. + """ + def __init__(self, rs, rd): + super(Jalr, self).__init__('jalr', rs, rd) + + + +############################### REGISTER TYPE INSTRUCTIONS ############################## + +####### ARITHMETIC AND LOGIC ####### + +class Abs(IType): + """ + Absolute value: Put the absolute value of register rs in register rd. + """ + def __init__(self, rd, rs): + super(Abs, self).__init__('abs', rd, rs) + + + +class Mult(IType): + """ + Multiply signed: Multiply registers rs and rt. Leave the low-order word of the product in register lo and the high-order word in register hi. Signed. + """ + def __init__(self, rs, rt): + super(Mult, self).__init__('mult', rs, rt) + + +class Multu(IType): + """ + Multiply unsigned: Multiply registers rs and rt. Leave the low-order word of the product in register lo and the high-order word in register hi. Unsigned. + """ + def __init__(self, rs, rt): + super(Multu, self).__init__('multu', rs, rt) + + +#Multiply: Put the product of register rs and rt into register rd +class Mul(IType): + """ + Multiply: Put the product of register rs and rt into register rd. Signed multiply without overflow. + """ + def __init__(self, rd, rs, rt): + super(Mul, self).__init__('mul', rd, rs, rt) + + +class Mulo(IType): + """ + Multiply: Put the product of register rs and rt into register rd. Signed multiply with overflow. + """ + def __init__(self, rd, rs, rt): + super(Mulo, self).__init__('mulo', rd, rs, rt) + + +class Mulou(IType): + """ + Multiply: Put the product of register rs and rt into register rd. Unsigned multiply with overflow. + """ + def __init__(self, rd, rs, rt): + super(Mulou, self).__init__('mulou', rd, rs, rt) + + +class Neg(IType): # with overflow + """ + Negate: Put the negative of register rs into register rd. With overflow. + """ + def __init__(self, rd, rs): + super(Neg, self).__init__('neg', rd, rs) + + +class Negu(IType): + """ + Negate: Put the negative of register rs into register rd. Without overflow. + """ + def __init__(self, rd, rs): + super(Negu, self).__init__('negu', rd, rs) + + +class Add(IType): + """ + Addition: Put the sum of registers rs and rt into register rd. With overflow. + """ + def __init__(self, rd, rs, rt): + super(Add, self).__init__('add', rd, rs, rt) + + +class Addu(IType): + """ + Addition: Put the sum of registers rs and rt into register rd. Without overflow. + """ + def __init__(self, rd, rs, rt): + super(Addu, self).__init__('addu', rd, rs, rt) + + +class Sub(IType): + """ + Substraction: Put the difference of registers rs and rt into register rd. With overflow. + """ + def __init__(self, rd, rs, rt): + super(Sub, self).__init__('sub', rd, rs, rt) + + +class Subu(IType): + """ + Substraction: Put the difference of registers rs and rt into register rd. Without overflow. + """ + def __init__(self, rd, rs, rt): + super(Subu, self).__init__('subu', rd, rs, rt) + + +class Not(IType): + """ + Put the bitwise logical negation of register rs into register rd. + """ + def __init__(self, rd, rs): + super(Not, self).__init__('not', rd, rs) + + +class And(IType): + """ + Put the logical AND of registers rs and rt into register rd + """ + def __init__(self, rd, rs, rt): + super(And, self).__init__('and', rd, rs, rt) + + +class Or(IType): + """ + Put the logical OR of registers rs and rt into register rd + """ + def __init__(self, rd, rs, rt): + super(Or, self).__init__('or', rd, rs, rt) + + +class Nor(IType): + """ + Put the logical NOR of registers rs and rt into register rd + """ + def __init__(self, rd, rs, rt): + super(Nor, self).__init__('nor', rd, rs, rt) + + +class Xor(IType): + """ + Put the logical XOR of registers rs and rt into register rd + """ + def __init__(self, rd, rs, rt): + super(Xor, self).__init__('xor', rd, rs, rt) + + +class Div(IType): + """ + Divide (2 parameters): Divide register rs by register rt. Leave the quotient in register lo and the remainder in register hi. With overflow. + Divide (3 parameters): Put the quotient of register nd and rd into register rs. With overflow. + """ + def __init__(self, rs, nd, rd = None): + super(Div, self).__init__('div', rs, nd, rd) + + +class Divu(IType): + """ + Divide (2 parameters): Divide register rs by register rt. Leave the quotient in register lo and the remainder in register hi. Without overflow. + Divide (3 parameters): Put the quotient of register nd and rd into register rs. Without overflow. + """ + def __init__(self, rs, nd, rd = None): + super(Divu, self).__init__('divu', rs, nd, rd) + + +class Rem(IType): + """ + Remainder: Put the remainder of register rsrc1 divided by register rsrc2 into register rdest. Signed. + """ + def __init__(self, rdest, rsrc1, rsrc2): + super(Rem, self).__init__('rem', rdest, rsrc1, rsrc2) + + +class Remu(IType): + """ + Remainder: Put the remainder of register rsrc1 divided by register rsrc2 into register rdest. Unsigned. + """ + def __init__(self, rdest, rsrc1, rsrc2): + super(Remu, self).__init__('remu', rdest, rsrc1, rsrc2) + + +class Sll(IType): + """ + Shift left logical: Shift register rt left by the distance indicated by immediate shamt and put the result in register rd. + """ + def __init__(self, rd, rt, shamt): + super(Sll, self).__init__('sll', rd, rt, shamt) + + +class Sllv(IType): + """ + Shift left logical: Shift register rt left by the distance indicated by the register rs and put the result in register rd. + """ + def __init__(self, rd, rt, rs): + super(Sllv, self).__init__('sllv', rd, rt, rs) + + +class Sra(IType): + """ + Shift right aritmethic: Shift register rt right by the distance indicated by immediate shamt and put the result in register rd. + """ + def __init__(self, rd, rt, shamt): + super(Sra, self).__init__('sra', rd, rt, shamt) + + +class Srav(IType): + """ + Shift right aritmethic: Shift register rt right by the distance indicated by the register rs and put the result in register rd. + """ + def __init__(self, rd, rt, rs): + super(Srav, self).__init__('srav', rd, rt, rs) + + +class Srl(IType): + """ + Shift right logical: Shift register rt right by the distance indicated by immediate shamt and put the result in register rd. + """ + def __init__(self, rd, rt, shamt): + super(Srl, self).__init__('srl', rd, rt, shamt) + + +class Srlv(IType): + """ + Shift right logical: Shift register rt right by the distance indicated by the register rs and put the result in register rd. + """ + def __init__(self, rd, rt, rs): + super(Srlv, self).__init__('srlv', rd, rt, rs) + + +class Rol(IType): + """ + Rotate: Rotate register rsrc1 left by the distance indicated by rsrc2 and put the result in register rdest. + """ + def __init__(self, rdest, rsrc1, rsrc2): + super(Rol, self).__init__('rol', rdest, rsrc1, rsrc2) + + +class Ror(IType): + """ + Rotate: Rotate register rsrc1 right by the distance indicated by rsrc2 and put the result in register rdest. + """ + def __init__(self, rdest, rsrc1, rsrc2): + super(Ror, self).__init__('ror', rdest, rsrc1, rsrc2) + + +####### COMPARISON ####### + +class Slt(IType): + """ + Set less than: Set register rd to 1 if register rs is less than rt , and to 0 otherwise. Signed. + """ + def __init__(self, rd, rs, rt): + super(Slt, self).__init__('slt', rd, rs, rt) + + +class Sltu(IType): + """ + Set less than: Set register rd to 1 if register rs is less than rt , and to 0 otherwise. Unsigned. + """ + def __init__(self, rd, rs, rt): + super(Sltu, self).__init__('sltu', rd, rs, rt) + + +class Seq(IType): + """ + Set equal: Set register rdest to 1 if register rsrc1 equals rsrc2, and to 0 otherwise. + """ + def __init__(self, rdest, rsrc1, rsrc2 ): + super(Seq, self).__init__('seq', rdest, rsrc1, rsrc2) + + +class Sne(IType): + """ + Set not equal: Set register rdest to 1 if register rsrc1 is not equal to rsrc2, and to 0 otherwise. + """ + def __init__(self, rdest, rsrc1, rsrc2 ): + super(Sne, self).__init__('sne', rdest, rsrc1, rsrc2) + + +class Sge(IType): + """ + Set greater than equal: Set register rdest to 1 if register rsrc1 is greater than or equal to rsrc2, and to 0 otherwise. Signed. + """ + def __init__(self, rdest, rsrc1, rsrc2 ): + super(Sge, self).__init__('sge', rdest, rsrc1, rsrc2) + + +class Sgeu(IType): + """ + Set greater than equal: Set register rdest to 1 if register rsrc1 is greater than or equal to rsrc2, and to 0 otherwise. Unsigned. + """ + def __init__(self, rdest, rsrc1, rsrc2 ): + super(Sgeu, self).__init__('sgeu', rdest, rsrc1, rsrc2) + + +class Sgt(IType): + """ + Set greater than: Set register rdest to 1 if register rsrc1 is greater than rsrc2, and to 0 otherwise. Signed. + """ + def __init__(self, rdest, rsrc1, rsrc2 ): + super(Sgt, self).__init__('sgt', rdest, rsrc1, rsrc2) + + +class Sgtu(IType): + """ + Set greater than: Set register rdest to 1 if register rsrc1 is greater than rsrc2, and to 0 otherwise. Unsigned. + """ + def __init__(self, rdest, rsrc1, rsrc2 ): + super(Sgtu, self).__init__('sgtu', rdest, rsrc1, rsrc2) + + +class Sle(IType): + """ + Set less than equal: Set register rdest to 1 if register rsrc1 is less than or equal to rsrc2, and to 0 otherwise. Signed. + """ + def __init__(self, rdest, rsrc1, rsrc2 ): + super(Sle, self).__init__('sle', rdest, rsrc1, rsrc2) + + +class Sleu(IType): + """ + Set less than equal: Set register rdest to 1 if register rsrc1 is less than or equal to rsrc2, and to 0 otherwise. Unsigned. + """ + def __init__(self, rdest, rsrc1, rsrc2 ): + super(Sleu, self).__init__('sleu', rdest, rsrc1, rsrc2) + + +####### MOVE INSTRUCTIONS ####### + +class Move(IType): + """ + Move register rsrc to rdest. + """ + def __init__(self, rdest, rsrc): + super(Move, self).__init__('move', rdest, rsrc) + + +class Mfhi(IType): + """ + Move from the register hi to the rd register. + """ + def __init__(self, rd): + super(Mfhi, self).__init__('mfhi', rd) + + +class Mflo(IType): + """ + Move from the register lo to the rd register. + """ + def __init__(self, rd): + super(Mflo, self).__init__('mflo' , rd) + + +class Mthi(IType): + """ + Move register rs to the hi register. + """ + def __init__(self): + super(Mthi, self).__init__('mthi') + + +class Mtlo(IType): + """ + Move register rs to the lo register. + """ + def __init__(self): + super(Mtlo, self).__init__('mtlo') + + + +############################### EXCEPTION AND INTERRUPT INSTRUCTIONS ############################## + +class Rfe(IType): + """ + Return from exception: Restore the Status register. + """ + def __init__(self): + super(Rfe, self).__init__('rfe') + + +class Syscall(IType): + """ + System call: Register $v0 contains the number of the system call (see Figure A.17) provided by SPIM. + """ + def __init__(self): + super(Syscall, self).__init__('syscall') + + +class Break(IType): + """ + Break: Cause exception code. Exception 1 is reserved for the debugger. + """ + def __init__(self): + super(Break, self).__init__('break') + + +class Nop(IType): + """ + No operation: Do nothing. + """ + def __init__(self): + super(Nop, self).__init__('nop') \ No newline at end of file diff --git a/src/Compiler/CodeGen/Intermediate/Generator.py b/src/Compiler/CodeGen/Intermediate/Generator.py new file mode 100644 index 000000000..dea695a38 --- /dev/null +++ b/src/Compiler/CodeGen/Intermediate/Generator.py @@ -0,0 +1,660 @@ +from CodeGen.Intermediate.base_generator import BaseCOOLToCILVisitor +from CodeGen.Intermediate import cil +from Semantic import visitor +from Semantic.scope import * +from Parser import ast + +class COOLToCILVisitor(BaseCOOLToCILVisitor): + + def __init__(self, context): + super(COOLToCILVisitor, self).__init__() + self.context = context + self.program_node = None + + ################################################################################################################## + # VISITOR + ################################################################################################################## + + @visitor.on('node') + def visit(self, node, scope, cil_scope): + pass + + @visitor.when(ast.Program) + def visit(self, node, scope, cil_scope = None): + """ + node.classes -> [ Class ... ] + """ + self.program_node = node + cil_scope = cil.Scope() + + for _class in node.classes: + if _class.name == 'Main': + self.Main_class = True + for f in _class.features: + if f.name == 'main': + self.main_method = True + data = self.register_data(_class.name) + self.types_names[_class.name] = data + cil_scope.create_child() + + self.define_entry_function() + self.predefined_types() + + for _class, child_scope, ch_cil_scope in zip(node.classes, scope.children, cil_scope.children): + self.visit(_class, child_scope, ch_cil_scope) + + self.fill_cil_types(self.context) + + return cil.ProgramNode(self.dottypes, self.dotdata, self.dotcode) + + + @visitor.when(ast.Class) + def visit(self, node, scope, cil_scope): + """ + node.name -> str + node.parent -> Class + node.features -> [ ClassMethod/ClassAttribute ... ] + """ + self.current_type = scope.ctype.defined_types[node.name] + + parent = node.parent if type(node.parent) is str else node.parent.name + cil_type = self.register_type(node.name, parent) + cil_type.attributes = [a for a in self.current_type.get_all_attr()] + + for feature, num in zip(node.features, range(len(node.features))): + child_scope = scope.next_child() + if isinstance(feature, ast.ClassMethod): + self.visit(feature, child_scope, cil_scope.create_child()) + + function_init_attr = self.define_init_attr_function() + self.init_attr_functions[function_init_attr.name] = self.current_type + self.dottypes[-1].methods.append((function_init_attr.name, function_init_attr.name)) + + current = node + current_list = [] + while isinstance(current, ast.Class): + current_list.append(current) + current = current.parent + current_list = current_list[::-1] + + num = 0 + for current in current_list: + indx = self.program_node.classes.index(current) + current_scope = scope.parent.children[indx] + current_scope.child_index = 0 + current_child_scope = cil_scope.parent.children[indx] + + for feature in current.features: + child_scope = current_scope.next_child() + if isinstance(feature, ast.ClassAttribute): + self.current_function = function_init_attr + if feature.init_expr is None: + value = self.define_internal_local() + self.register_instruction(cil.AllocateNode(f'type_{feature.static_type.name}', value)) + else: + value = self.visit(feature.init_expr, child_scope, current_child_scope.create_child()) + self.register_instruction(cil.SetAttribNode('self', num, value)) + self.current_function = None + num += 1 + + self.current_function = function_init_attr + self.register_instruction(cil.ReturnNode('self')) + self.current_function = None + self.current_type = None + + + @visitor.when(ast.ClassMethod) + def visit(self, node, scope,cil_scope): + """ + node.name -> str + node.formal_params -> [ FormalParameter ... ] + node.return_type -> str + node.body -> Expr + """ + function_name = self.to_function_name(node.name, self.current_type.name) + self.dottypes[-1].methods.append((node.name, function_name)) + self.current_function = self.register_function(function_name) + self.current_function.params = [cil.ParamNode('self')] + + for param in node.formal_params: + self.current_function.params.append(cil.ParamNode(param.name)) + cil_scope.define_variable(param.name, param.name, param.static_type) + + value = self.visit(node.body, scope, cil_scope) + + self.register_instruction(cil.ReturnNode(value)) + self.current_function = None + + + @visitor.when(ast.Formal) + def visit(self, node, scope, cil_scope): + """ + node.name -> str + node.param_type -> str + node.init_expr -> Expr/None + """ + vname = self.register_local(VariableInfo(node.name, node.static_type)) + cil_scope.define_variable(node.name, vname, node.static_type) + + if not node.init_expr is None: + value = self.visit(node.init_expr, scope, cil_scope) + self.register_instruction(cil.AssignNode(vname, value)) + + else: + self.register_instruction(cil.AllocateNode(f'type_{node.static_type.name}', vname)) + + + @visitor.when(ast.Object) + def visit(self, node, scope, cil_scope): + """ + node.name -> str + """ + if node.name == 'self': + return node.name + + current_cil_scope = cil_scope + while not current_cil_scope is None: + if not current_cil_scope.local_by_name.get(node.name) is None: + return current_cil_scope.local_by_name[node.name].name + current_cil_scope = current_cil_scope.parent + + current_type = self.current_type + while not current_type is None: + if node.name in list(current_type.attr.keys()): + vname = self.define_internal_local() + self.register_instruction(cil.GetAttribNode(vname, 'self', current_type.get_all_attr().index(node.name))) + return vname + current_type = current_type.parent + + vname = self.register_local(VariableInfo(node.name, node.static_type)) + cil_scope.define_variable(node.name, vname, node.static_type) + return vname + + + @visitor.when(ast.Self) + def visit(self, node, scope, cil_scope): + return 'self' + + + @visitor.when(ast.Integer) + def visit(self, node, scope, cil_scope): + """ + node.content -> int + """ + instance = self.define_internal_local() + self.register_instruction(cil.AllocateNode(f'type_{scope.ctype.INT}', instance, node.content)) + return instance + + + @visitor.when(ast.String) + def visit(self, node, scope, cil_scope): + """ + node.content -> str + """ + data_node = self.register_data(node.content) + + instance = self.define_internal_local() + self.register_instruction(cil.AllocateNode(f'type_{scope.ctype.STRING}', instance, data_node.name)) + return instance + + + @visitor.when(ast.Boolean) + def visit(self, node, scope, cil_scope): + """ + node.content -> bool + """ + false = self.define_internal_local() + self.register_instruction(cil.AllocateNode(f'type_{scope.ctype.BOOL}', false, 0)) + + if node.content: + true = self.define_internal_local() + self.register_instruction(cil.BoolComplementNode(true, false)) + return true + + return false + + + @visitor.when(ast.NewObject) + def visit(self, node, scope, cil_scope): + """ + node.type -> int + """ + instance = self.define_internal_local() + self.register_instruction(cil.AllocateNode(f'type_{node.static_type}', instance)) + self.register_instruction(cil.ArgNode(instance)) + self.register_instruction(cil.StaticCallNode(f'function_initialize_{node.static_type.name}_attributes', instance)) + return instance + + + @visitor.when(ast.IsVoid) + def visit(self, node, scope, cil_scope): + """ + node.expr -> Expr + """ + value = self.visit(node.expr, scope, cil_scope) + + true = self.define_internal_local() + false = self.define_internal_local() + _type1 = self.define_internal_local() + _type2 = self.define_internal_local() + result = self.define_internal_local() + + void = self.register_data(scope.ctype.VOID) + + then_label = cil.LabelNode(self.define_label()) + out_label = cil.LabelNode(self.define_label()) + + self.register_instruction(cil.AllocateNode(f'type_{scope.ctype.BOOL}', false, 0)) + self.register_instruction(cil.BoolComplementNode(true, false)) + + self.register_instruction(cil.TypeOfNode(value, _type1)) + self.register_instruction(cil.LoadNode(_type2, void.name)) + self.register_instruction(cil.BranchEqualNode(_type1, _type2, then_label.name)) + + self.register_instruction(cil.AssignNode(result, false)) + self.register_instruction(cil.GotoNode(out_label.name)) + + self.register_instruction(then_label) + self.register_instruction(cil.AssignNode(result, true)) + self.register_instruction(out_label) + + return result + + + @visitor.when(ast.Assignment) + def visit(self, node, scope, cil_scope): + """ + node.instance -> Object + node.expr -> Expr + """ + value = self.visit(node.expr, scope, cil_scope) + + current_type = self.current_type + while not current_type is None: + if node.instance.name in list(current_type.attr.keys()): + instr = cil.SetAttribNode('self', current_type.get_all_attr().index(node.instance.name), value) + self.register_instruction(instr) + return value + current_type = current_type.parent + + vname = self.visit(node.instance, scope, cil_scope) + self.register_instruction(cil.AssignNode(vname, value)) + return value + + + @visitor.when(ast.Block) + def visit(self, node, scope, cil_scope): + """ + node.expr_list -> [ Expr ... ] + """ + value = self.visit(node.expr_list[0], scope, cil_scope) + for expr in node.expr_list[1:]: + value = self.visit(expr, scope, cil_scope) + return value + + + @visitor.when(ast.DynamicDispatch) + def visit(self, node, scope, cil_scope): + """ + node.instance -> Expr + node.method -> str + node.arguments -> [ Expr ... ] + """ + args = list() + instance = self.visit(node.instance, scope, cil_scope) + dest = self.define_internal_local() + + _type = self.define_internal_local() + self.register_instruction(cil.TypeOfNode(instance, _type)) + + for arg in node.arguments: + args.append(self.visit(arg, scope, cil_scope)) + + labels = list() + for t in list(scope.ctype.defined_types.keys()): + current_type = scope.get_type(t).get_func_context(node.method) + if not current_type is None: + ldata = self.define_internal_local() + label = cil.LabelNode(self.define_label()) + self.register_instruction(cil.LoadNode(ldata, self.types_names[t].name)) + self.register_instruction(cil.BranchEqualNode(_type, ldata, label.name)) + labels.append((label, self.to_function_name(node.method, current_type.name))) + + end_label = cil.LabelNode(self.define_label()) + self.register_instruction(cil.GotoNode(end_label.name)) + + for label, func_name in labels: + self.register_instruction(label) + self.register_instruction(cil.ArgNode(instance)) + for arg in args: + self.register_instruction(cil.ArgNode(arg)) + self.register_instruction(cil.StaticCallNode(func_name, dest)) + self.register_instruction(cil.GotoNode(end_label.name)) + + self.register_instruction(end_label) + return dest + + + @visitor.when(ast.StaticDispatch) + def visit(self, node, scope, cil_scope): + """ + node.instance -> Expr + node.dispatch_type -> str + node.method -> str + node.arguments -> [ Expr ... ] + """ + instance = self.visit(node.instance, scope, cil_scope) + args = list() + dest = self.define_internal_local() + + if node.dispatch_type == scope.ctype.SELF: + _type = self.current_type + else: + _type = scope.get_type(node.dispatch_type) + + for arg in node.arguments: + args.append(self.visit(arg, scope, cil_scope)) + + self.register_instruction(cil.ArgNode(instance)) + + for arg in args: + self.register_instruction(cil.ArgNode(arg)) + + func_name = self.to_function_name(node.method, _type.get_func_context(node.method).name) + self.register_instruction(cil.StaticCallNode(func_name, dest)) + return dest + + + @visitor.when(ast.Let) + def visit(self, node, scope, cil_scope): + """ + node.declarations -> [ Formal ... ] + node.body -> Expr + """ + new_cil_scope = cil_scope.create_child() + child = scope.next_child() + + for declaration in node.declarations: + self.visit(declaration, child, new_cil_scope) + + return self.visit(node.body, child, new_cil_scope) + + + @visitor.when(ast.If) + def visit(self, node, scope, cil_scope): + """ + node.predicate -> Expr + node.then_body -> Expr + node.else_body -> Expr + """ + predicate = self.visit(node.predicate, scope, cil_scope) + + then_label = cil.LabelNode(self.define_label()) + else_label = cil.LabelNode(self.define_label()) + end_label = cil.LabelNode(self.define_label()) + + then_goto = cil.GotoNode(then_label.name) + else_goto = cil.GotoNode(else_label.name) + end_goto = cil.GotoNode(end_label.name) + + self.register_instruction(cil.GotoIfNode(predicate, then_goto.label)) + self.register_instruction(else_goto) + self.register_instruction(then_label) + + vname = self.define_internal_local() + self.register_instruction(cil.AssignNode(vname, self.visit(node.then_body, scope, cil_scope))) + self.register_instruction(end_goto) + + self.register_instruction(else_label) + self.register_instruction(cil.AssignNode(vname, self.visit(node.else_body, scope, cil_scope))) + self.register_instruction(end_label) + return vname + + + @visitor.when(ast.WhileLoop) + def visit(self, node, scope, cil_scope): + """ + node.predicate -> Expr + node.body -> Expr + """ + var_return = self.define_internal_local() + var_void = self.define_internal_local() + + self.register_instruction(cil.AllocateNode(f'type_{scope.ctype.OBJECT}', var_return)) + self.register_instruction(cil.AllocateNode(f'type_{scope.ctype.VOID}', var_void)) + + bucle_label = cil.LabelNode(self.define_label()) + self.register_instruction(bucle_label) + continue_bucle_label = cil.LabelNode(self.define_label()) + end_bucle_label = cil.LabelNode(self.define_label()) + + predicate = self.visit(node.predicate, scope, cil_scope) + self.register_instruction(cil.GotoIfNode(predicate, continue_bucle_label.name)) + self.register_instruction(cil.GotoNode(end_bucle_label.name)) + self.register_instruction(continue_bucle_label) + self.register_instruction(cil.AssignNode(var_return, var_void)) + self.visit(node.body, scope, cil_scope) + + self.register_instruction(cil.GotoNode(bucle_label.name)) + self.register_instruction(end_bucle_label) + return var_return + + + @visitor.when(ast.Case) + def visit(self, node, scope, cil_scope): + """ + node.expr -> Expr + node.actions -> Action + """ + value = self.visit(node.expr, scope, cil_scope) + value_type = self.define_internal_local() + self.register_instruction(cil.TypeOfNode(value, value_type)) + data = self.types_names[scope.ctype.VOID.name].name + void_type = self.define_internal_local() + self.register_instruction(cil.LoadNode(void_type, data)) + + _continue = cil.LabelNode(self.define_label()) + _error = cil.LabelNode(self.define_label()) + self.register_instruction(cil.BranchEqualNode(value_type, void_type, _error.name)) + self.register_instruction(cil.GotoNode(_continue.name)) + self.register_instruction(_error) + error = self.register_data(f'({node.expr.lineno}, {node.expr.linepos}) - RuntimeError: Expression cant\'t be Void type.\\n') + self.register_instruction(cil.RunTimeNode(error.name)) + self.register_instruction(_continue) + + _types = list() + for action in node.actions: + _types.append(scope.get_type(action.action_type)) + + count = self.define_internal_local() + self.register_instruction(cil.AllocateNode(f'type_Int', count, len(_types))) + self.register_instruction(cil.ArgNode(value)) + self.register_instruction(cil.ArgNode(count)) + for _type in _types: + data_node = self.register_data(_type.name) + vdata = self.define_internal_local() + self.register_instruction(cil.LoadNode(vdata, data_node.name)) + self.register_instruction(cil.ArgNode(vdata)) + number = self.define_internal_local() + self.register_instruction(cil.StaticCallNode('get_number_action', number)) + + branchs = list() + for i in range(len(_types)): + opt = self.define_internal_local() + label = cil.LabelNode(self.define_label()) + self.register_instruction(cil.AllocateNode(f'type_Int', opt, i)) + self.register_instruction(cil.BranchEqualNode(number, opt, label.name)) + branchs.append(label) + + end_label = cil.LabelNode(self.define_label()) + data = self.register_data(f'({node.expr.lineno}, {node.expr.linepos}) - RuntimeError: None branch selected\\n') + self.register_instruction(cil.RunTimeNode(data.name)) + vname = self.define_internal_local() + + for i in range(len(_types)): + self.register_instruction(branchs[i]) + new_cil_scope = cil_scope.create_child() + action_type = scope.get_type(node.actions[i].action_type) + id = self.register_local(VariableInfo(node.actions[i].name, action_type)) + new_cil_scope.define_variable(node.actions[i].name, id, action_type) + self.register_instruction(cil.AssignNode(id, value)) + action_value = self.visit(node.actions[i].body, scope.next_child(), new_cil_scope) + self.register_instruction(cil.AssignNode(vname, action_value)) + self.register_instruction(cil.GotoNode(end_label.name)) + + self.register_instruction(end_label) + return vname + + + @visitor.when(ast.IntegerComplement) + def visit(self, node, scope, cil_scope): + """ + node.integer_expr -> Expr + """ + value = self.visit(node.integer_expr, scope, cil_scope) + vname = self.define_internal_local() + self.register_instruction(cil.IntComplementNode(vname, value)) + return vname + + + @visitor.when(ast.BooleanComplement) + def visit(self, node, scope, cil_scope): + """ + node.boolean_expr -> Expr + """ + value = self.visit(node.boolean_expr, scope, cil_scope) + vname = self.define_internal_local() + self.register_instruction(cil.BoolComplementNode(vname, value)) + return vname + + + @visitor.when(ast.Addition) + def visit(self, node, scope, cil_scope): + """ + node.first -> Expr + node.second -> Expr + """ + value1 = self.visit(node.first, scope, cil_scope) + value2 = self.visit(node.second, scope, cil_scope) + vname = self.define_internal_local() + self.register_instruction(cil.PlusNode(vname, value1, value2)) + return vname + + + @visitor.when(ast.Subtraction) + def visit(self, node, scope, cil_scope): + """ + node.first -> Expr + node.second -> Expr + """ + value1 = self.visit(node.first, scope, cil_scope) + value2 = self.visit(node.second, scope, cil_scope) + vname = self.define_internal_local() + self.register_instruction(cil.MinusNode(vname, value1, value2)) + return vname + + @visitor.when(ast.Multiplication) + def visit(self, node, scope, cil_scope): + """ + node.first -> Expr + node.second -> Expr + """ + value1 = self.visit(node.first, scope, cil_scope) + value2 = self.visit(node.second, scope, cil_scope) + vname = self.define_internal_local() + self.register_instruction(cil.StarNode(vname, value1, value2)) + return vname + + + @visitor.when(ast.Division) + def visit(self, node, scope, cil_scope): + """ + node.first -> Expr + node.second -> Expr + """ + value1 = self.visit(node.first, scope, cil_scope) + value2 = self.visit(node.second, scope, cil_scope) + + denominador = self.define_internal_local() + div_by_cero = cil.LabelNode(self.define_label()) + fine = cil.LabelNode(self.define_label()) + self.register_instruction(cil.AllocateNode(f'type_Int', denominador, 0)) + self.register_instruction(cil.BranchEqualNode(value2, denominador, div_by_cero.name)) + self.register_instruction(cil.GotoNode(fine.name)) + self.register_instruction(div_by_cero) + data = self.register_data(f'({node.lineno}, {node.linepos}) - RuntimeError: Division by zero\\n') + self.register_instruction(cil.RunTimeNode(data.name)) + self.register_instruction(fine) + + vname = self.define_internal_local() + self.register_instruction(cil.DivNode(vname, value1, value2)) + return vname + + + @visitor.when(ast.Equal) + def visit(self, node, scope, cil_scope): + """ + node.first -> Expr + node.second -> Expr + """ + first = self.visit(node.first, scope, cil_scope) + second = self.visit(node.second, scope, cil_scope) + + then_label = cil.LabelNode(self.define_label()) + out_label = cil.LabelNode(self.define_label()) + self.register_instruction(cil.BranchEqualNode(first, second, then_label.name)) + + vname = self.define_internal_local() + self.register_instruction(cil.AllocateNode(f'type_{scope.ctype.BOOL}', vname, 0)) + self.register_instruction(cil.GotoNode(out_label.name)) + + self.register_instruction(then_label) + self.register_instruction(cil.AllocateNode(f'type_{scope.ctype.BOOL}', vname, 1)) + self.register_instruction(out_label) + return vname + + + @visitor.when(ast.LessThan) + def visit(self, node, scope, cil_scope): + """ + node.first -> Expr + node.second -> Expr + """ + first = self.visit(node.first, scope, cil_scope) + second = self.visit(node.second, scope, cil_scope) + + then_label = cil.LabelNode(self.define_label()) + out_label = cil.LabelNode(self.define_label()) + self.register_instruction(cil.BranchLTNode(first, second, then_label.name)) + + vname = self.define_internal_local() + self.register_instruction(cil.AllocateNode(f'type_{scope.ctype.BOOL}', vname, 0)) + self.register_instruction(cil.GotoNode(out_label.name)) + + self.register_instruction(then_label) + self.register_instruction(cil.AllocateNode(f'type_{scope.ctype.BOOL}', vname, 1)) + self.register_instruction(out_label) + return vname + + + @visitor.when(ast.LessThanOrEqual) + def visit(self, node, scope, cil_scope): + """ + node.first -> Expr + node.second -> Expr + """ + first = self.visit(node.first, scope, cil_scope) + second = self.visit(node.second, scope, cil_scope) + + then_label = cil.LabelNode(self.define_label()) + out_label = cil.LabelNode(self.define_label()) + self.register_instruction(cil.BranchLENode(first, second, then_label.name)) + + vname = self.define_internal_local() + self.register_instruction(cil.AllocateNode(f'type_{scope.ctype.BOOL}', vname, 0)) + self.register_instruction(cil.GotoNode(out_label.name)) + + self.register_instruction(then_label) + self.register_instruction(cil.AllocateNode(f'type_{scope.ctype.BOOL}', vname, 1)) + self.register_instruction(out_label) + return vname \ No newline at end of file diff --git a/src/Compiler/CodeGen/Intermediate/base_generator.py b/src/Compiler/CodeGen/Intermediate/base_generator.py new file mode 100644 index 000000000..62ab4b3d2 --- /dev/null +++ b/src/Compiler/CodeGen/Intermediate/base_generator.py @@ -0,0 +1,180 @@ +from CodeGen.Intermediate import cil +from Semantic.scope import * + +class BaseCOOLToCILVisitor: + def __init__(self): + self.dottypes = [] + self.dotdata = [] + self.dotcode = [] + self.current_type = None + self.current_method = None + self.current_function = None + self.context = None + self.labels = 0 + self.types_names = dict() + self.init_attr_functions = dict() + self.Main_class = False + self.main_method = False + + @property + def params(self): + return self.current_function.params + + @property + def localvars(self): + return self.current_function.localvars + + @property + def instructions(self): + return self.current_function.instructions + + def register_local(self, vinfo): + vinfo.name = f'local_{self.current_function.name[9:]}_{vinfo.name}_{len(self.localvars)}' + local_node = cil.LocalNode(vinfo.name) + self.localvars.append(local_node) + return vinfo.name + + def define_internal_local(self): + vinfo = VariableInfo('internal', None) + return self.register_local(vinfo) + + def define_label(self): + new_label = f'Label_{self.labels}' + self.labels += 1 + return new_label + + def define_init_attr_function(self): + function_name = f'function_initialize_{self.current_type}_attributes' + function_node = cil.FunctionNode(function_name, [cil.ParamNode('self')], [], []) + self.dotcode.append(function_node) + return function_node + + def register_instruction(self, instruction): + if self.current_function is None: + self.instr_without_context.append(instruction) + return instruction + self.instructions.append(instruction) + return instruction + + def to_function_name(self, method_name, type_name): + return f'function_{method_name}_at_{type_name}' + + def register_function(self, function_name): + function_node = cil.FunctionNode(function_name, [], [], []) + self.dotcode.append(function_node) + return function_node + + def register_type(self, name, parent): + data = self.register_data(name) + self.types_names[name] = data + type_node = cil.TypeNode(data, parent) + self.dottypes.append(type_node) + return type_node + + def register_data(self, value): + vname = f'data_{len(self.dotdata)}' + data_node = cil.DataNode(vname, value) + self.dotdata.append(data_node) + return data_node + + def fill_cil_types(self, context): + for p in [t for t in self.dottypes]: + p_type = context.get_type(p.name.value) + parents = p_type.get_all_parents() + for p_type in parents: + for name in list(p_type.func.keys()): + p.methods.append((name, self.to_function_name(name, p_type.name))) + + + def define_entry_function(self): + self.current_function = self.register_function('main') + instance0 = self.define_internal_local() + instance1 = self.define_internal_local() + result = self.define_internal_local() + ret = self.define_internal_local() + main_method_name = self.to_function_name('main', 'Main') + if self.Main_class: + self.register_instruction(cil.AllocateNode('type_Main', instance0)) + self.register_instruction(cil.ArgNode(instance0)) + self.register_instruction(cil.StaticCallNode('function_initialize_Main_attributes', instance1)) + if self.main_method: + self.register_instruction(cil.ArgNode(instance1)) + self.register_instruction(cil.StaticCallNode(main_method_name, result)) + self.register_instruction(cil.EndProgramNode()) + self.current_function = None + + ################################################################################################################## + # PREDEFINED TYPES + ################################################################################################################## + + def predefined_types(self): + self.register_io_type() + self.register_object_type() + self.register_string_type() + self.register_int_type() + self.register_bool_type() + self.register_void_type() + # ... add more + + #================================================================================================================= + + def register_io_type(self): + self.current_type = self.context.ctype.IO + _type = self.register_type(self.current_type.name, 'Object') + _type.attributes = [v for v in self.current_type.get_all_attr()] + _type.methods = [(f, self.to_function_name(f, 'IO')) for f in self.current_type.get_all_func()] + self.current_function = self.define_init_attr_function() + self.register_instruction(cil.ReturnNode('self')) + self.current_function = None + self.current_type = None + + def register_object_type(self): + self.current_type = self.context.ctype.OBJECT + _type = self.register_type(self.current_type.name, None) + _type.attributes = [v for v in self.current_type.get_all_attr()] + _type.methods = [(f, self.to_function_name(f, 'Object')) for f in self.current_type.get_all_func()] + self.current_function = self.define_init_attr_function() + self.register_instruction(cil.ReturnNode('self')) + self.current_function = None + self.current_type = None + + def register_string_type(self): + self.current_type = self.context.ctype.STRING + _type = self.register_type(self.current_type.name, 'Object') + _type.attributes = [v for v in self.current_type.get_all_attr()] + ["value"] + _type.methods = [(f, self.to_function_name(f, 'String')) for f in self.current_type.get_all_func()] + self.current_function = self.define_init_attr_function() + self.register_instruction(cil.ReturnNode('self')) + self.current_function = None + self.current_type = None + + def register_int_type(self): + self.current_type = self.context.ctype.INT + _type = self.register_type(self.current_type.name, 'Object') + _type.attributes = [v for v in self.current_type.get_all_attr()] + ["value"] + _type.methods = [(f, self.to_function_name(f, 'Int')) for f in self.current_type.get_all_func()] + self.current_function = self.define_init_attr_function() + self.register_instruction(cil.ReturnNode('self')) + self.current_function = None + self.current_type = None + + def register_bool_type(self): + self.current_type = self.context.ctype.BOOL + _type = self.register_type(self.current_type.name, 'Object') + _type.attributes = [v for v in self.current_type.get_all_attr()] + ["value"] + _type.methods = [(f, self.to_function_name(f, 'Bool')) for f in self.current_type.get_all_func()] + self.current_function = self.define_init_attr_function() + self.register_instruction(cil.ReturnNode('self')) + self.current_function = None + self.current_type = None + + def register_void_type(self): + self.current_type = self.context.ctype.VOID + _type = self.register_type(self.current_type.name, 'Object') + _type.attributes = [v for v in self.current_type.get_all_attr()] + _type.methods = [(f, self.to_function_name(f, 'Void')) for f in self.current_type.get_all_func()] + self.current_function = self.define_init_attr_function() + self.register_instruction(cil.ReturnNode('self')) + self.current_function = None + self.current_type = None + \ No newline at end of file diff --git a/src/Compiler/CodeGen/Intermediate/cil.py b/src/Compiler/CodeGen/Intermediate/cil.py new file mode 100644 index 000000000..5f91c2d88 --- /dev/null +++ b/src/Compiler/CodeGen/Intermediate/cil.py @@ -0,0 +1,290 @@ +from Semantic.scope import VariableInfo +import itertools as itt + + +class Node: + pass + +class ProgramNode(Node): + """ + nodo raiz + """ + def __init__(self, dottypes, dotdata, dotcode): + self.dottypes = dottypes + self.dotdata = dotdata + self.dotcode = dotcode + +class TypeNode(Node): + """ + Tipos definidos en el programa cool + """ + def __init__(self, name, parent): + self.name = name + self.parent = parent + self.attributes = [] + self.methods = [] + +class DataNode(Node): + """ + Variables definidas en el programa + """ + def __init__(self, vname, value): + self.name = vname + self.value = value + +class FunctionNode(Node): + """ + Funciones declaradas en el programa + """ + def __init__(self, fname, params, localvars, instructions): + self.name = fname + self.params = params + self.localvars = localvars + self.instructions = instructions + +class ParamNode(Node): + def __init__(self, name): + self.name = name + +class LocalNode(Node): + def __init__(self, name): + self.name = name + +class InstructionNode(Node): + pass + +class AssignNode(InstructionNode): + """ + Asignacion del valor de `source` a la variable `dest` + """ + def __init__(self, dest, source): + self.dest = dest + self.source = source + +class UnaryOperationNode(InstructionNode): + def __init__(self, dest, source): + self.dest = dest + self.source = source + +class IntComplementNode(UnaryOperationNode): + """ + Asignacion del valor de `~ source` a la variable `dest` + """ + pass + +class BoolComplementNode(UnaryOperationNode): + """ + Asignacion del valor de `not source` a la variable `dest` + """ + pass + +class BinaryOperationNode(InstructionNode): + def __init__(self, dest, left, right): + self.dest = dest + self.left = left + self.right = right + +class PlusNode(BinaryOperationNode): + """ + Asignacion del valor de `left + right` a la variable `dest` + """ + pass + +class MinusNode(BinaryOperationNode): + """ + Asignacion del valor de `left - right` a la variable `dest` + """ + pass + +class StarNode(BinaryOperationNode): + """ + Asignacion del valor de `left * right` a la variable `dest` + """ + pass + +class DivNode(BinaryOperationNode): + """ + Asignacion del valor de `left / right` a la variable `dest` + """ + pass + +class GetAttribNode(InstructionNode): + """ + Asignacion del valor del `numb+1`-iesimo atributo de la instancia `_instance` a la variable `dest` + """ + def __init__(self, dest, _instance, numb): + self.dest = dest + self.instance = _instance + self.pos = numb + +class SetAttribNode(InstructionNode): + """ + Asignacion del valor de la variable `source` al `numb+1`-esimo atributo de la instancia `_instance` + """ + def __init__(self, _instance, numb, source): + self.source = source + self.instance = _instance + self.pos = numb + +class AllocateNode(InstructionNode): + """ + Liberar espacio en memoria para crear un objeto de tipo `itype` y almacenar su direccion + en la variable `dest` (si es de tipo Int, Bool o String, se inicializa con el valor `value`) + """ + def __init__(self, itype, dest, value = None): + self.type = itype + self.dest = dest + self.value = value + +class TypeOfNode(InstructionNode): + """ + Obtiene el tipo del objeto `obj` y almacena la direccion del tipo en `dest` + """ + def __init__(self, obj, dest): + self.obj = obj + self.dest = dest + +class LabelNode(InstructionNode): + """ + Crea un label de nombre `name` + """ + def __init__(self, name): + self.name = name + +class GotoNode(InstructionNode): + """ + Salta a la direccion donde se encuentra el label `label.name` + """ + def __init__(self, label): + self.label = label + +class GotoIfNode(InstructionNode): + """ + Si `vname` evalua True, salta a la direccion donde se encuentra el label `goto_label` + """ + def __init__(self, vname, goto_label): + self.vname = vname + self.goto_label = goto_label + +class StaticCallNode(InstructionNode): + """ + Realiza un llamado a la funcion `function` y almacena el valor de retorno en `dest` + """ + def __init__(self, function, dest): + self.function = function + self.dest = dest + +class DynamicCallNode(InstructionNode): + """ + Realiza un llamado a la funcion `function` de la clase `xtype` y almacena el valor de retorno en `dest` + """ + def __init__(self, xtype, function, dest): + self.xtype = xtype + self.function = function + self.dest = dest + +class ArgNode(InstructionNode): + """ + Carga el valor de la variable `name` antes del llamado a una funcion + """ + def __init__(self, name): + self.name = name + +class ReturnNode(InstructionNode): + """ + Retorna el valor de `ret` + """ + def __init__(self, ret = None): + self.ret = ret + +class RunTimeNode(InstructionNode): + """ + Retorna el valor de `ret` + """ + def __init__(self, error): + self.error = error + +class EndProgramNode(InstructionNode): + pass + +class CopyNode(InstructionNode): + """ + Copia el valor de `obj` y lo almacena en la variable `dest` + """ + def __init__(self, dest, obj): + self.dest = dest + self.obj = obj + +class LoadNode(InstructionNode): + """ + Carga la direccion de `msg` en la variable `dest` + """ + def __init__(self, dest, msg): + self.dest = dest + self.msg = msg + +class BranchEqualNode(InstructionNode): + """ + Realiza un salto hacia el label `label` si los valores de las variables `left` y `right` + son iguales + """ + def __init__(self, left, right, label): + self.left = left + self.right = right + self.label = label + +class BranchLTNode(InstructionNode): + """ + Realiza un salto hacia el label `label` si el valor de la variable `left` es menor que + el valor de la variable `right` + """ + def __init__(self, left, right, label): + self.left = left + self.right = right + self.label = label + +class BranchLENode(InstructionNode): + """ + Realiza un salto hacia el label `label` si el valor de la variable `left` es menor o igual que + el valor de la variable `right` + """ + def __init__(self, left, right, label): + self.left = left + self.right = right + self.label = label + +class Scope: + def __init__(self, parent=None): + self.locals = [] + self.parent = parent + self.children = [] + self.local_by_name = dict() + self.index = 0 if parent is None else len(parent) + + def __len__(self): + return len(self.locals) + + def create_child(self): + child = Scope(self) + self.children.append(child) + child.parent = self + return child + + def define_variable(self, name, cil_name, vtype): + info = VariableInfo(cil_name, vtype) + self.locals.append(info) + self.local_by_name[name] = info + return info + + def find_variable(self, vname, index = None): + locals = self.locals if index is None else itt.islice(self.locals, index) + try: + return next(x for x in locals if x.name == vname) + except StopIteration: + return self.parent.find_variable(vname, self.index) if self.parent is None else None + + def is_defined(self, vname): + return self.find_variable(vname) is not None + + def is_local(self, vname): + return any(True for x in self.locals if x.name == vname) \ No newline at end of file diff --git a/src/Compiler/Lexer/Lexer.py b/src/Compiler/Lexer/Lexer.py new file mode 100644 index 000000000..742314ded --- /dev/null +++ b/src/Compiler/Lexer/Lexer.py @@ -0,0 +1,172 @@ +from Lexer.tokens import COOL_Tokens +from Lexer.errors_types import * +import ply.lex as lex +import sys + +class COOL_Lexer: + + def __init__(self): + self.t = COOL_Tokens() + self.tokens = self.t.tokens + self.errors = False + self.states = [('STRING', 'exclusive'), ('COMMENT', 'exclusive')] + self.linelastpos = [-1] + self.lexer = lex.lex(module = self) + + #=============================================================================================================================================== + + # SIMPLE TOKENS + 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_MULTIPLY = r'\*' # * + t_DIVIDE = r'\/' # / + t_PLUS = r'\+' # + + t_MINUS = r'\-' # - + t_INT_COMP = r'~' # ~ + t_LT = r'\<' # < + t_EQ = r'\=' # = + t_LTEQ = r'\<\=' # <= + t_ASSIGN = r'\<\-' # <- + t_ARROW = r'\=\>' # => + + def t_BOOL_TYPE(self, t): + r'(true|false)' + t.value = True if t.value == "true" else False + t.type = "BOOLEAN" + return t + + def t_INT_TYPE(self, t): + r'\d+' + t.value = int(t.value) + t.type = "INTEGER" + return t + + def t_TYPE(self, t): + r'[A-Z][a-zA-Z_0-9]*' + if t.value.lower() in list(self.t.cool_keywords.keys()): + t.value = t.value.lower() + t.type = self.t.cool_keywords[t.value] + return t + t.type = 'TYPE' + return t + + def t_ID(self, t): + r'[a-z][a-zA-Z_0-9]*' + t.type = self.t.cool_keywords.get(t.value.lower(), 'ID') + return t + + t_ignore = ' \t\r\f' + + def t_newline(self, t): + r'\n' + t.lexer.lineno += 1 + self.linelastpos.append(t.lexpos) + + def t_error(self, t): + """ + Error Handling and Reporting Rule. + """ + sys.stdout.write(f'({t.lineno}, {t.lexpos - self.linelastpos[len(self.linelastpos)-1]}) - {LXERR} "{t.value[0]}"\n') + self.errors = True + t.lexer.skip(1) + + #=============================================================================================================================================== + # THE STRING STATE + #----------------------------------------------------------------------------------------------------------------------------------------------- + + def t_begin_STRING(self, t): + r'"' + t.lexer.begin("STRING") + t.lexer.string_backslashed = False + t.lexer.stringbuf = "" + + def t_STRING_newline(self, t): + r'\n' + t.lexer.lineno += 1 + + if not t.lexer.string_backslashed: + sys.stdout.write(f'({t.lineno}, {t.lexpos - self.linelastpos[len(self.linelastpos)-1]}) - {LXUSC}\n') + self.errors = True + t.lexer.begin("INITIAL") + else: + t.lexer.string_backslashed = False + self.linelastpos.append(t.lexpos) + + def t_STRING_end(self, t): + r'"' + if not t.lexer.string_backslashed: + t.lexer.begin("INITIAL") + t.value = t.lexer.stringbuf + t.type = "STRING" + return t + else: + t.lexer.stringbuf += '"' + t.lexer.string_backslashed = False + + def t_STRING_anything(self, t): + r'[^\n\x00]' + if t.lexer.string_backslashed: + if t.value in ['b', 't', 'n', 'f', '\\']: + t.lexer.stringbuf += '\\' + t.lexer.stringbuf += t.value + t.lexer.string_backslashed = False + else: + if t.value != '\\': + t.lexer.stringbuf += t.value + else: + t.lexer.string_backslashed = True + + t_STRING_ignore = '' + + def t_STRING_error(self, t): + sys.stdout.write(f'({t.lineno}, {t.lexpos - self.linelastpos[len(self.linelastpos)-1]}) - {LXSCN}\n') + self.errors = True + t.lexer.skip(1) + + def t_STRING_eof(self, t): + sys.stdout.write(f'({t.lineno}, {t.lexer.lexlen - self.linelastpos[len(self.linelastpos)-1]}) - {LXESC}\n') + self.errors = True + + #=============================================================================================================================================== + # THE COMMENT STATE + #----------------------------------------------------------------------------------------------------------------------------------------------- + + def t_begin_COMMENT(self, t): + r'\(\*' + t.lexer.begin("COMMENT") + t.lexer.comment_count = 1 + + def t_COMMENT_startanother(self, t): + r'\(\*' + t.lexer.comment_count += 1 + + def t_COMMENT_end(self, t): + r'\*\)' + if t.lexer.comment_count == 1: + t.lexer.begin("INITIAL") + else: + t.lexer.comment_count -= 1 + + t_ignore_SINGLE_LINE_COMMENT = r"\-\-[^\n]*" + t_COMMENT_ignore = '' + + def t_COMMENT_newline(self, t): + r'\n' + t.lexer.lineno += 1 + self.linelastpos.append(t.lexpos) + + def t_COMMENT_error(self, t): + t.lexer.skip(1) + + def t_COMMENT_eof(self, t): + sys.stdout.write(f'({t.lineno}, {t.lexer.lexlen - self.linelastpos[len(self.linelastpos)-1]}) - {LXEIC}\n') + self.errors = True + + #=============================================================================================================================================== \ No newline at end of file diff --git a/src/Compiler/Lexer/errors_types.py b/src/Compiler/Lexer/errors_types.py new file mode 100644 index 000000000..8834d04ae --- /dev/null +++ b/src/Compiler/Lexer/errors_types.py @@ -0,0 +1,5 @@ +LXERR = "LexicographicError: ERROR" +LXUSC = "LexicographicError: Unterminated string constant" +LXSCN = "LexicographicError: String contains null character" +LXESC = "LexicographicError: EOF in string constant" +LXEIC = "LexicographicError: EOF in comment" \ No newline at end of file diff --git a/src/Compiler/Lexer/tokens.py b/src/Compiler/Lexer/tokens.py new file mode 100644 index 000000000..fc3f686f2 --- /dev/null +++ b/src/Compiler/Lexer/tokens.py @@ -0,0 +1,49 @@ +class COOL_Tokens: + + def __init__(self): + self.tokens = self.cool_tokens + list(self.cool_keywords.values()) + + @property + def cool_tokens(self): + """ + Collection of COOL Syntax Tokens. + :return: Tuple. + """ + return [ + # 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" + ] + + @property + def cool_keywords(self): + """ + Map of Basic-COOL reserved keywords. + :return: dict. + """ + return { + "case": "CASE", + "class": "CLASS", + "else": "ELSE", + "esac": "ESAC", + "fi": "FI", + "if": "IF", + "in": "IN", + "inherits": "INHERITS", + "isvoid": "ISVOID", + "let": "LET", + "loop": "LOOP", + "new": "NEW", + "of": "OF", + "not": "NOT", + "pool": "POOL", + "then": "THEN", + "while": "WHILE" + } \ No newline at end of file diff --git a/src/Compiler/Parser/Parser.py b/src/Compiler/Parser/Parser.py new file mode 100644 index 000000000..325e2df5f --- /dev/null +++ b/src/Compiler/Parser/Parser.py @@ -0,0 +1,362 @@ +import ply.yacc as yacc +import Parser.ast as AST +from Parser.errors_types import * + +class COOL_Parser: + ''' + CoolParser class. + ''' + def __init__(self, cool_lexer): + self.cool_lexer = cool_lexer + self.tokens = self.cool_lexer.tokens + self.parser = None + self.error_list = [] + self.errors = False + + def run(self, code): + self.parser = yacc.yacc(module = self) + ast = self.parser.parse(input = code, lexer = self.cool_lexer.lexer) + self.errors = self.errors or self.cool_lexer.errors + return ast + + # ################################ 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') + ) + + # ################### START OF FORMAL GRAMMAR RULES DECLARATION #################### + + def p_program(self, parse): + 'program : class_list' + parse[0] = AST.Program(classes=parse[1]) + + def p_class_list(self, parse): + '''class_list : class SEMICOLON class_list + | class SEMICOLON''' + if len(parse) == 4: + parse[0] = [parse[1]] + parse[3] + else: + parse[0] = [parse[1]] + + def p_class(self, parse): + 'class : CLASS TYPE LBRACE features_list_opt RBRACE' + parse[0] = AST.Class(name=parse[2], parent="Object", features=parse[4]) + _l = parse.lineno(2) + _p = parse.lexpos(2) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + def p_class_inherits(self, parse): + 'class : CLASS TYPE INHERITS TYPE LBRACE features_list_opt RBRACE' + parse[0] = AST.Class(name=parse[2], parent=parse[4], features=parse[6]) + _l = parse.lineno(2) + _p = parse.lexpos(2) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + def p_feature_list_opt(self, parse): + '''features_list_opt : features_list + | empty''' + parse[0] = list() if parse.slice[1].type == "empty" else parse[1] + + def p_feature_list(self, parse): + '''features_list : feature SEMICOLON features_list + | empty''' + parse[0] = list() if parse.slice[1].type == "empty" else [parse[1]] + parse[3] + + def p_feature_method(self, parse): + 'feature : ID LPAREN formal_params_list RPAREN COLON TYPE LBRACE expression RBRACE' + parse[0] = AST.ClassMethod(name=parse[1], formal_params=parse[3], return_type=parse[6], body=parse[8]) + _l = parse.lineno(1) + _p = parse.lexpos(1) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + def p_feature_method_no_formals(self, parse): + 'feature : ID LPAREN RPAREN COLON TYPE LBRACE expression RBRACE' + parse[0] = AST.ClassMethod(name=parse[1], formal_params=tuple(), return_type=parse[5], body=parse[7]) + _l = parse.lineno(1) + _p = parse.lexpos(1) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + def p_feature_attr_initialized(self, parse): + 'feature : ID COLON TYPE ASSIGN expression' + parse[0] = AST.ClassAttribute(name=parse[1], attr_type=parse[3], init_expr=parse[5]) + _l = parse.lineno(1) + _p = parse.lexpos(1) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + def p_feature_attr(self, parse): + 'feature : ID COLON TYPE' + parse[0] = AST.ClassAttribute(name=parse[1], attr_type=parse[3], init_expr=None) + _l = parse.lineno(1) + _p = parse.lexpos(1) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + def p_formal_list_many(self, parse): + '''formal_params_list : formal_param COMMA formal_params_list + | formal_param''' + if len(parse) == 4: + parse[0] = [parse[1]] + parse[3] + else: + parse[0] = [parse[1]] + + def p_formal(self, parse): + 'formal_param : ID COLON TYPE' + parse[0] = AST.FormalParameter(name=parse[1], param_type=parse[3]) + _l = parse.lineno(1) + _p = parse.lexpos(1) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + def p_expression_object_identifier(self, parse): + 'expression : ID' + parse[0] = AST.Object(name=parse[1]) + _l = parse.lineno(1) + _p = parse.lexpos(1) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + def p_expression_integer_constant(self, parse): + 'expression : INTEGER' + parse[0] = AST.Integer(content=parse[1]) + _l = parse.lineno(1) + _p = parse.lexpos(1) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + def p_expression_boolean_constant(self, parse): + 'expression : BOOLEAN' + parse[0] = AST.Boolean(content=parse[1]) + _l = parse.lineno(1) + _p = parse.lexpos(1) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + def p_expression_string_constant(self, parse): + 'expression : STRING' + parse[0] = AST.String(content=parse[1]) + _l = parse.lineno(1) + _p = parse.lexpos(1) - self.cool_lexer.linelastpos[_l-1] - len(parse[0].content) - 1 + parse[0].pos(_l, _p) + + def p_expression_block(self, parse): + 'expression : LBRACE block_list RBRACE' + parse[0] = AST.Block(expr_list=parse[2]) + _l = parse.lineno(1) + _p = parse.lexpos(1) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + def p_block_list(self, parse): + '''block_list : expression SEMICOLON block_list + | expression SEMICOLON''' + if len(parse) == 4: + parse[0] = [parse[1]] + parse[3] + else: + parse[0] = [parse[1]] + + def p_expression_assignment(self, parse): + 'expression : ID ASSIGN expression' + parse[0] = AST.Assignment(AST.Object(name=parse[1]), expr=parse[3]) + _l = parse.lineno(2) + _p = parse.lexpos(2) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + # ######################### METHODS DISPATCH ###################################### + + def p_expression_dispatch(self, parse): + 'expression : expression DOT ID LPAREN arguments_list_opt RPAREN' + parse[0] = AST.DynamicDispatch(instance=parse[1], method=parse[3], arguments=parse[5]) + _l = parse.lineno(3) + _p = parse.lexpos(3) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + def p_arguments_list_opt(self, parse): + '''arguments_list_opt : arguments_list + | empty''' + parse[0] = list() if parse.slice[1].type == "empty" else parse[1] + + def p_arguments_list(self, parse): + '''arguments_list : expression COMMA arguments_list + | expression''' + if len(parse) == 4: + parse[0] = [parse[1]] + parse[3] + else: + parse[0] = [parse[1]] + + def p_expression_static_dispatch(self, parse): + 'expression : expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN' + parse[0] = AST.StaticDispatch(instance=parse[1], dispatch_type=parse[3], method=parse[5], arguments=parse[7]) + _l = parse.lineno(5) + _p = parse.lexpos(5) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + def p_expression_self_dispatch(self, parse): + 'expression : ID LPAREN arguments_list_opt RPAREN' + parse[0] = AST.DynamicDispatch(instance=AST.Self(), method=parse[1], arguments=parse[3]) + _l = parse.lineno(1) + _p = parse.lexpos(1) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + # ######################### PARENTHESIZED, MATH & COMPARISONS ##################### + + def p_expression_math_operations(self, parse): + '''expression : expression PLUS expression + | expression MINUS expression + | expression MULTIPLY expression + | expression DIVIDE expression''' + if parse[2] == '+': + parse[0] = AST.Addition(first=parse[1], second=parse[3]) + elif parse[2] == '-': + parse[0] = AST.Subtraction(first=parse[1], second=parse[3]) + elif parse[2] == '*': + parse[0] = AST.Multiplication(first=parse[1], second=parse[3]) + elif parse[2] == '/': + parse[0] = AST.Division(first=parse[1], second=parse[3]) + _l = parse.lineno(2) + _p = parse.lexpos(2) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + def p_expression_math_comparisons(self, parse): + '''expression : expression LT expression + | expression LTEQ expression + | expression EQ expression''' + if parse[2] == '<': + parse[0] = AST.LessThan(first=parse[1], second=parse[3]) + elif parse[2] == '<=': + parse[0] = AST.LessThanOrEqual(first=parse[1], second=parse[3]) + elif parse[2] == '=': + parse[0] = AST.Equal(first=parse[1], second=parse[3]) + _l = parse.lineno(2) + _p = parse.lexpos(2) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + def p_expression_with_parenthesis(self, parse): + 'expression : LPAREN expression RPAREN' + parse[0] = parse[2] + + # ######################### CONTROL FLOW EXPRESSIONS ############################## + + def p_expression_if_conditional(self, parse): + 'expression : IF expression THEN expression ELSE expression FI' + parse[0] = AST.If(predicate=parse[2], then_body=parse[4], else_body=parse[6]) + _l = parse.lineno(1) + _p = parse.lexpos(1) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + def p_expression_while_loop(self, parse): + 'expression : WHILE expression LOOP expression POOL' + parse[0] = AST.WhileLoop(predicate=parse[2], body=parse[4]) + _l = parse.lineno(1) + _p = parse.lexpos(1) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + # ######################### LET EXPRESSIONS ######################################## + + def p_expression_let(self, parse): + 'expression : let_expression' + parse[0] = parse[1] + + def p_expression_let_list(self, parse): + 'let_expression : LET formal_list IN expression' + parse[0] = AST.Let(declarations=parse[2], body=parse[4]) + _l = parse.lineno(1) + _p = parse.lexpos(1) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + def p_formal_list(self, parse): + '''formal_list : formal_list COMMA formal + | formal''' + if len(parse) == 4: + parse[0] = parse[1] + [parse[3]] + else: + parse[0] = [parse[1]] + + def p_formal_let_simpleparam(self, parse): + 'formal : ID COLON TYPE' + parse[0] = AST.Formal(name=parse[1], param_type=parse[3], init_expr=None) + _l = parse.lineno(1) + _p = parse.lexpos(1) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + def p_formal_let_param(self, parse): + 'formal : ID COLON TYPE ASSIGN expression' + parse[0] = AST.Formal(name=parse[1], param_type=parse[3], init_expr=parse[5]) + _l = parse.lineno(1) + _p = parse.lexpos(1) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + # ######################### CASE EXPRESSION ######################################## + + def p_expression_case(self, parse): + 'expression : CASE expression OF actions_list ESAC' + parse[0] = AST.Case(expr=parse[2], actions=parse[4]) + _l = parse.lineno(1) + _p = parse.lexpos(1) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + def p_actions_list(self, parse): + '''actions_list : action actions_list + | action''' + if len(parse) == 3: + parse[0] = [parse[1]] + parse[2] + else: + parse[0] = [parse[1]] + + def p_action_expr(self, parse): + 'action : ID COLON TYPE ARROW expression SEMICOLON' + parse[0] = AST.Action(parse[1], parse[3], parse[5]) + _l = parse.lineno(3) + _p = parse.lexpos(3) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + # ######################### UNARY OPERATIONS ####################################### + + def p_expression_new(self, parse): + 'expression : NEW TYPE' + parse[0] = AST.NewObject(parse[2]) + _l = parse.lineno(2) + _p = parse.lexpos(2) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + def p_expression_isvoid(self, parse): + 'expression : ISVOID expression' + parse[0] = AST.IsVoid(parse[2]) + _l = parse.lineno(1) + _p = parse.lexpos(1) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + def p_expression_integer_complement(self, parse): + 'expression : INT_COMP expression' + parse[0] = AST.IntegerComplement(parse[2]) + _l = parse.lineno(1) + _p = parse.lexpos(1) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + def p_expression_boolean_complement(self, parse): + 'expression : NOT expression' + parse[0] = AST.BooleanComplement(parse[2]) + _l = parse.lineno(1) + _p = parse.lexpos(1) - self.cool_lexer.linelastpos[_l-1] + parse[0].pos(_l, _p) + + # ######################### THE EMPTY PRODUCTION ################################### + + def p_empty(self, parse): + 'empty :' + parse[0] = None + + # ######################### PARSE ERROR HANDLER #################################### + + def p_error(self, parse): + """ + Error rule for Syntax Errors handling and reporting. + """ + if parse is None: + self.error_list.append(f'(0,0) - {PREOF}') + else: + self.error_list.append(f'({parse.lineno}, {parse.lexpos - self.cool_lexer.linelastpos[parse.lineno-1]}) - {PRSTX1} "{parse.value}"') + self.parser.errok() + self.errors = True \ No newline at end of file diff --git a/src/Compiler/Parser/ast.py b/src/Compiler/Parser/ast.py new file mode 100644 index 000000000..82c341e72 --- /dev/null +++ b/src/Compiler/Parser/ast.py @@ -0,0 +1,274 @@ +class AST: + def __init__(self): + self.static_type = None + + def pos(self, lineno, linepos): + self.lineno = lineno + self.linepos = linepos + + @property + def clsname(self): + return str(self.__class__.__name__) + + +# ############################## PROGRAM, TYPE AND OBJECT ############################## + + +class Program(AST): + def __init__(self, classes): + super(Program, self).__init__() + self.classes = classes + + +class Class(AST): + def __init__(self, name, parent, features): + super(Class, self).__init__() + self.name = name + self.parent = parent + self.features = features + + +class ClassFeature(AST): + def __init__(self): + super(ClassFeature, self).__init__() + + +class ClassMethod(ClassFeature): + def __init__(self, name, formal_params, return_type, body): + super(ClassMethod, self).__init__() + self.name = name + self.formal_params = formal_params + self.return_type = return_type + self.body = body + + +class ClassAttribute(ClassFeature): + def __init__(self, name, attr_type, init_expr): + super(ClassAttribute, self).__init__() + self.name = name + self.attr_type = attr_type + self.init_expr = init_expr + + +class FormalParameter(ClassFeature): + def __init__(self, name, param_type): + super(FormalParameter, self).__init__() + self.name = name + self.param_type = param_type + +class Formal(ClassFeature): + def __init__(self, name, param_type, init_expr): + super(Formal, self).__init__() + self.name = name + self.param_type = param_type + self.init_expr = init_expr + + +class Object(AST): + def __init__(self, name): + super(Object, self).__init__() + self.name = name + + +class Self(Object): + def __init__(self): + super(Self, self).__init__("self") + + +# ############################## CONSTANTS ############################## + +class Constant(AST): + def __init__(self): + super(Constant, self).__init__() + +class Integer(Constant): + def __init__(self, content): + super(Integer, self).__init__() + self.content = content + +class String(Constant): + def __init__(self, content): + super(String, self).__init__() + self.content = content + +class Boolean(Constant): + def __init__(self, content): + super(Boolean, self).__init__() + self.content = content + +# ############################## EXPRESSIONS ############################## + + +class Expr(AST): + def __init__(self): + super(Expr, self).__init__() + + +class NewObject(Expr): + def __init__(self, new_type): + super(NewObject, self).__init__() + self.type = new_type + + + +class IsVoid(Expr): + def __init__(self, expr): + super(IsVoid, self).__init__() + self.expr = expr + +class Assignment(Expr): + def __init__(self, instance, expr): + super(Assignment, self).__init__() + self.instance = instance + self.expr = expr + + +class Block(Expr): + def __init__(self, expr_list): + super(Block, self).__init__() + self.expr_list = expr_list + + +class DynamicDispatch(Expr): + def __init__(self, instance, method, arguments): + super(DynamicDispatch, self).__init__() + self.instance = instance + self.method = method + self.arguments = arguments if arguments is not None else list() + + + +class StaticDispatch(Expr): + def __init__(self, instance, dispatch_type, method, arguments): + super(StaticDispatch, self).__init__() + self.instance = instance + self.dispatch_type = dispatch_type + self.method = method + self.arguments = arguments if arguments is not None else list() + + +class Let(Expr): + def __init__(self, declarations, body): + super(Let, self).__init__() + self.declarations = declarations + self.body = body + + +class If(Expr): + def __init__(self, predicate, then_body, else_body): + super(If, self).__init__() + self.predicate = predicate + self.then_body = then_body + self.else_body = else_body + + +class WhileLoop(Expr): + def __init__(self, predicate, body): + super(WhileLoop, self).__init__() + self.predicate = predicate + self.body = body + + +class Case(Expr): + def __init__(self, expr, actions): + super(Case, self).__init__() + self.expr = expr + self.actions = actions + + + +class Action(AST): + def __init__(self, name, action_type, body): + super(Action, self).__init__() + self.name = name + self.action_type = action_type + self.body = body + + + +# ############################## UNARY OPERATIONS ################################## + + +class UnaryOperation(Expr): + def __init__(self): + super(UnaryOperation, self).__init__() + + +class IntegerComplement(UnaryOperation): + def __init__(self, integer_expr): + super(IntegerComplement, self).__init__() + self.symbol = "~" + self.integer_expr = integer_expr + + + +class BooleanComplement(UnaryOperation): + def __init__(self, boolean_expr): + super(BooleanComplement, self).__init__() + self.symbol = "!" + self.boolean_expr = boolean_expr + + + +# ############################## BINARY OPERATIONS ################################## + + +class BinaryOperation(Expr): + def __init__(self): + super(BinaryOperation, self).__init__() + +class Addition(BinaryOperation): + def __init__(self, first, second): + super(Addition, self).__init__() + self.symbol = "+" + self.first = first + self.second = second + + + +class Subtraction(BinaryOperation): + def __init__(self, first, second): + super(Subtraction, self).__init__() + self.symbol = "-" + self.first = first + self.second = second + + +class Multiplication(BinaryOperation): + def __init__(self, first, second): + super(Multiplication, self).__init__() + self.symbol = "*" + self.first = first + self.second = second + + +class Division(BinaryOperation): + def __init__(self, first, second): + super(Division, self).__init__() + self.symbol = "/" + self.first = first + self.second = second + + +class Equal(BinaryOperation): + def __init__(self, first, second): + super(Equal, self).__init__() + self.symbol = "=" + self.first = first + self.second = second + + +class LessThan(BinaryOperation): + def __init__(self, first, second): + super(LessThan, self).__init__() + self.symbol = "<" + self.first = first + self.second = second + + +class LessThanOrEqual(BinaryOperation): + def __init__(self, first, second): + super(LessThanOrEqual, self).__init__() + self.symbol = "<=" + self.first = first + self.second = second \ No newline at end of file diff --git a/src/Compiler/Parser/errors_types.py b/src/Compiler/Parser/errors_types.py new file mode 100644 index 000000000..088843777 --- /dev/null +++ b/src/Compiler/Parser/errors_types.py @@ -0,0 +1,2 @@ +PRSTX1 = "SyntacticError: ERROR at or near" +PREOF = "SyntacticError: ERROR at or near EOF" \ No newline at end of file diff --git a/src/Compiler/Parser/parser.out b/src/Compiler/Parser/parser.out new file mode 100644 index 000000000..b1d78e224 --- /dev/null +++ b/src/Compiler/Parser/parser.out @@ -0,0 +1,3511 @@ +Created by PLY version 3.11 (http://www.dabeaz.com/ply) + +Grammar + +Rule 0 S' -> program +Rule 1 program -> class_list +Rule 2 class_list -> class SEMICOLON class_list +Rule 3 class_list -> class SEMICOLON +Rule 4 class -> CLASS TYPE LBRACE features_list_opt RBRACE +Rule 5 class -> CLASS TYPE INHERITS TYPE LBRACE features_list_opt RBRACE +Rule 6 features_list_opt -> features_list +Rule 7 features_list_opt -> empty +Rule 8 features_list -> feature SEMICOLON features_list +Rule 9 features_list -> empty +Rule 10 feature -> ID LPAREN formal_params_list RPAREN COLON TYPE LBRACE expression RBRACE +Rule 11 feature -> ID LPAREN RPAREN COLON TYPE LBRACE expression RBRACE +Rule 12 feature -> ID COLON TYPE ASSIGN expression +Rule 13 feature -> ID COLON TYPE +Rule 14 formal_params_list -> formal_param COMMA formal_params_list +Rule 15 formal_params_list -> formal_param +Rule 16 formal_param -> ID COLON TYPE +Rule 17 expression -> ID +Rule 18 expression -> INTEGER +Rule 19 expression -> BOOLEAN +Rule 20 expression -> STRING +Rule 21 expression -> LBRACE block_list RBRACE +Rule 22 block_list -> expression SEMICOLON block_list +Rule 23 block_list -> expression SEMICOLON +Rule 24 expression -> ID ASSIGN expression +Rule 25 expression -> expression DOT ID LPAREN arguments_list_opt RPAREN +Rule 26 arguments_list_opt -> arguments_list +Rule 27 arguments_list_opt -> empty +Rule 28 arguments_list -> expression COMMA arguments_list +Rule 29 arguments_list -> expression +Rule 30 expression -> expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN +Rule 31 expression -> ID LPAREN arguments_list_opt RPAREN +Rule 32 expression -> expression PLUS expression +Rule 33 expression -> expression MINUS expression +Rule 34 expression -> expression MULTIPLY expression +Rule 35 expression -> expression DIVIDE expression +Rule 36 expression -> expression LT expression +Rule 37 expression -> expression LTEQ expression +Rule 38 expression -> expression EQ expression +Rule 39 expression -> LPAREN expression RPAREN +Rule 40 expression -> IF expression THEN expression ELSE expression FI +Rule 41 expression -> WHILE expression LOOP expression POOL +Rule 42 expression -> let_expression +Rule 43 let_expression -> LET formal_list IN expression +Rule 44 formal_list -> formal_list COMMA formal +Rule 45 formal_list -> formal +Rule 46 formal -> ID COLON TYPE +Rule 47 formal -> ID COLON TYPE ASSIGN expression +Rule 48 expression -> CASE expression OF actions_list ESAC +Rule 49 actions_list -> action actions_list +Rule 50 actions_list -> action +Rule 51 action -> ID COLON TYPE ARROW expression SEMICOLON +Rule 52 expression -> NEW TYPE +Rule 53 expression -> ISVOID expression +Rule 54 expression -> INT_COMP expression +Rule 55 expression -> NOT expression +Rule 56 empty -> + +Terminals, with rules where they appear + +ARROW : 51 +ASSIGN : 12 24 47 +AT : 30 +BOOLEAN : 19 +CASE : 48 +CLASS : 4 5 +COLON : 10 11 12 13 16 46 47 51 +COMMA : 14 28 44 +DIVIDE : 35 +DOT : 25 30 +ELSE : 40 +EQ : 38 +ESAC : 48 +FI : 40 +ID : 10 11 12 13 16 17 24 25 30 31 46 47 51 +IF : 40 +IN : 43 +INHERITS : 5 +INTEGER : 18 +INT_COMP : 54 +ISVOID : 53 +LBRACE : 4 5 10 11 21 +LET : 43 +LOOP : 41 +LPAREN : 10 11 25 30 31 39 +LT : 36 +LTEQ : 37 +MINUS : 33 +MULTIPLY : 34 +NEW : 52 +NOT : 55 +OF : 48 +PLUS : 32 +POOL : 41 +RBRACE : 4 5 10 11 21 +RPAREN : 10 11 25 30 31 39 +SEMICOLON : 2 3 8 22 23 51 +STRING : 20 +THEN : 40 +TYPE : 4 5 5 10 11 12 13 16 30 46 47 51 52 +WHILE : 41 +error : + +Nonterminals, with rules where they appear + +action : 49 50 +actions_list : 48 49 +arguments_list : 26 28 +arguments_list_opt : 25 30 31 +block_list : 21 22 +class : 2 3 +class_list : 1 2 +empty : 7 9 27 +expression : 10 11 12 22 23 24 25 28 29 30 32 32 33 33 34 34 35 35 36 36 37 37 38 38 39 40 40 40 41 41 43 47 48 51 53 54 55 +feature : 8 +features_list : 6 8 +features_list_opt : 4 5 +formal : 44 45 +formal_list : 43 44 +formal_param : 14 15 +formal_params_list : 10 14 +let_expression : 42 +program : 0 + +Parsing method: LALR + +state 0 + + (0) S' -> . program + (1) program -> . class_list + (2) class_list -> . class SEMICOLON class_list + (3) class_list -> . class SEMICOLON + (4) class -> . CLASS TYPE LBRACE features_list_opt RBRACE + (5) class -> . CLASS TYPE INHERITS TYPE LBRACE features_list_opt RBRACE + + CLASS shift and go to state 4 + + program shift and go to state 1 + class_list shift and go to state 2 + class shift and go to state 3 + +state 1 + + (0) S' -> program . + + + +state 2 + + (1) program -> class_list . + + $end reduce using rule 1 (program -> class_list .) + + +state 3 + + (2) class_list -> class . SEMICOLON class_list + (3) class_list -> class . SEMICOLON + + SEMICOLON shift and go to state 5 + + +state 4 + + (4) class -> CLASS . TYPE LBRACE features_list_opt RBRACE + (5) class -> CLASS . TYPE INHERITS TYPE LBRACE features_list_opt RBRACE + + TYPE shift and go to state 6 + + +state 5 + + (2) class_list -> class SEMICOLON . class_list + (3) class_list -> class SEMICOLON . + (2) class_list -> . class SEMICOLON class_list + (3) class_list -> . class SEMICOLON + (4) class -> . CLASS TYPE LBRACE features_list_opt RBRACE + (5) class -> . CLASS TYPE INHERITS TYPE LBRACE features_list_opt RBRACE + + $end reduce using rule 3 (class_list -> class SEMICOLON .) + CLASS shift and go to state 4 + + class shift and go to state 3 + class_list shift and go to state 7 + +state 6 + + (4) class -> CLASS TYPE . LBRACE features_list_opt RBRACE + (5) class -> CLASS TYPE . INHERITS TYPE LBRACE features_list_opt RBRACE + + LBRACE shift and go to state 8 + INHERITS shift and go to state 9 + + +state 7 + + (2) class_list -> class SEMICOLON class_list . + + $end reduce using rule 2 (class_list -> class SEMICOLON class_list .) + + +state 8 + + (4) class -> CLASS TYPE LBRACE . features_list_opt RBRACE + (6) features_list_opt -> . features_list + (7) features_list_opt -> . empty + (8) features_list -> . feature SEMICOLON features_list + (9) features_list -> . empty + (56) empty -> . + (10) feature -> . ID LPAREN formal_params_list RPAREN COLON TYPE LBRACE expression RBRACE + (11) feature -> . ID LPAREN RPAREN COLON TYPE LBRACE expression RBRACE + (12) feature -> . ID COLON TYPE ASSIGN expression + (13) feature -> . ID COLON TYPE + + RBRACE reduce using rule 56 (empty -> .) + ID shift and go to state 14 + + features_list_opt shift and go to state 10 + features_list shift and go to state 11 + empty shift and go to state 12 + feature shift and go to state 13 + +state 9 + + (5) class -> CLASS TYPE INHERITS . TYPE LBRACE features_list_opt RBRACE + + TYPE shift and go to state 15 + + +state 10 + + (4) class -> CLASS TYPE LBRACE features_list_opt . RBRACE + + RBRACE shift and go to state 16 + + +state 11 + + (6) features_list_opt -> features_list . + + RBRACE reduce using rule 6 (features_list_opt -> features_list .) + + +state 12 + + (7) features_list_opt -> empty . + (9) features_list -> empty . + + ! reduce/reduce conflict for RBRACE resolved using rule 7 (features_list_opt -> empty .) + RBRACE reduce using rule 7 (features_list_opt -> empty .) + + ! RBRACE [ reduce using rule 9 (features_list -> empty .) ] + + +state 13 + + (8) features_list -> feature . SEMICOLON features_list + + SEMICOLON shift and go to state 17 + + +state 14 + + (10) feature -> ID . LPAREN formal_params_list RPAREN COLON TYPE LBRACE expression RBRACE + (11) feature -> ID . LPAREN RPAREN COLON TYPE LBRACE expression RBRACE + (12) feature -> ID . COLON TYPE ASSIGN expression + (13) feature -> ID . COLON TYPE + + LPAREN shift and go to state 18 + COLON shift and go to state 19 + + +state 15 + + (5) class -> CLASS TYPE INHERITS TYPE . LBRACE features_list_opt RBRACE + + LBRACE shift and go to state 20 + + +state 16 + + (4) class -> CLASS TYPE LBRACE features_list_opt RBRACE . + + SEMICOLON reduce using rule 4 (class -> CLASS TYPE LBRACE features_list_opt RBRACE .) + + +state 17 + + (8) features_list -> feature SEMICOLON . features_list + (8) features_list -> . feature SEMICOLON features_list + (9) features_list -> . empty + (10) feature -> . ID LPAREN formal_params_list RPAREN COLON TYPE LBRACE expression RBRACE + (11) feature -> . ID LPAREN RPAREN COLON TYPE LBRACE expression RBRACE + (12) feature -> . ID COLON TYPE ASSIGN expression + (13) feature -> . ID COLON TYPE + (56) empty -> . + + ID shift and go to state 14 + RBRACE reduce using rule 56 (empty -> .) + + feature shift and go to state 13 + features_list shift and go to state 21 + empty shift and go to state 22 + +state 18 + + (10) feature -> ID LPAREN . formal_params_list RPAREN COLON TYPE LBRACE expression RBRACE + (11) feature -> ID LPAREN . RPAREN COLON TYPE LBRACE expression RBRACE + (14) formal_params_list -> . formal_param COMMA formal_params_list + (15) formal_params_list -> . formal_param + (16) formal_param -> . ID COLON TYPE + + RPAREN shift and go to state 25 + ID shift and go to state 23 + + formal_params_list shift and go to state 24 + formal_param shift and go to state 26 + +state 19 + + (12) feature -> ID COLON . TYPE ASSIGN expression + (13) feature -> ID COLON . TYPE + + TYPE shift and go to state 27 + + +state 20 + + (5) class -> CLASS TYPE INHERITS TYPE LBRACE . features_list_opt RBRACE + (6) features_list_opt -> . features_list + (7) features_list_opt -> . empty + (8) features_list -> . feature SEMICOLON features_list + (9) features_list -> . empty + (56) empty -> . + (10) feature -> . ID LPAREN formal_params_list RPAREN COLON TYPE LBRACE expression RBRACE + (11) feature -> . ID LPAREN RPAREN COLON TYPE LBRACE expression RBRACE + (12) feature -> . ID COLON TYPE ASSIGN expression + (13) feature -> . ID COLON TYPE + + RBRACE reduce using rule 56 (empty -> .) + ID shift and go to state 14 + + features_list_opt shift and go to state 28 + features_list shift and go to state 11 + empty shift and go to state 12 + feature shift and go to state 13 + +state 21 + + (8) features_list -> feature SEMICOLON features_list . + + RBRACE reduce using rule 8 (features_list -> feature SEMICOLON features_list .) + + +state 22 + + (9) features_list -> empty . + + RBRACE reduce using rule 9 (features_list -> empty .) + + +state 23 + + (16) formal_param -> ID . COLON TYPE + + COLON shift and go to state 29 + + +state 24 + + (10) feature -> ID LPAREN formal_params_list . RPAREN COLON TYPE LBRACE expression RBRACE + + RPAREN shift and go to state 30 + + +state 25 + + (11) feature -> ID LPAREN RPAREN . COLON TYPE LBRACE expression RBRACE + + COLON shift and go to state 31 + + +state 26 + + (14) formal_params_list -> formal_param . COMMA formal_params_list + (15) formal_params_list -> formal_param . + + COMMA shift and go to state 32 + RPAREN reduce using rule 15 (formal_params_list -> formal_param .) + + +state 27 + + (12) feature -> ID COLON TYPE . ASSIGN expression + (13) feature -> ID COLON TYPE . + + ASSIGN shift and go to state 33 + SEMICOLON reduce using rule 13 (feature -> ID COLON TYPE .) + + +state 28 + + (5) class -> CLASS TYPE INHERITS TYPE LBRACE features_list_opt . RBRACE + + RBRACE shift and go to state 34 + + +state 29 + + (16) formal_param -> ID COLON . TYPE + + TYPE shift and go to state 35 + + +state 30 + + (10) feature -> ID LPAREN formal_params_list RPAREN . COLON TYPE LBRACE expression RBRACE + + COLON shift and go to state 36 + + +state 31 + + (11) feature -> ID LPAREN RPAREN COLON . TYPE LBRACE expression RBRACE + + TYPE shift and go to state 37 + + +state 32 + + (14) formal_params_list -> formal_param COMMA . formal_params_list + (14) formal_params_list -> . formal_param COMMA formal_params_list + (15) formal_params_list -> . formal_param + (16) formal_param -> . ID COLON TYPE + + ID shift and go to state 23 + + formal_param shift and go to state 26 + formal_params_list shift and go to state 38 + +state 33 + + (12) feature -> ID COLON TYPE ASSIGN . expression + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 40 + let_expression shift and go to state 48 + +state 34 + + (5) class -> CLASS TYPE INHERITS TYPE LBRACE features_list_opt RBRACE . + + SEMICOLON reduce using rule 5 (class -> CLASS TYPE INHERITS TYPE LBRACE features_list_opt RBRACE .) + + +state 35 + + (16) formal_param -> ID COLON TYPE . + + COMMA reduce using rule 16 (formal_param -> ID COLON TYPE .) + RPAREN reduce using rule 16 (formal_param -> ID COLON TYPE .) + + +state 36 + + (10) feature -> ID LPAREN formal_params_list RPAREN COLON . TYPE LBRACE expression RBRACE + + TYPE shift and go to state 55 + + +state 37 + + (11) feature -> ID LPAREN RPAREN COLON TYPE . LBRACE expression RBRACE + + LBRACE shift and go to state 56 + + +state 38 + + (14) formal_params_list -> formal_param COMMA formal_params_list . + + RPAREN reduce using rule 14 (formal_params_list -> formal_param COMMA formal_params_list .) + + +state 39 + + (17) expression -> ID . + (24) expression -> ID . ASSIGN expression + (31) expression -> ID . LPAREN arguments_list_opt RPAREN + + DOT reduce using rule 17 (expression -> ID .) + AT reduce using rule 17 (expression -> ID .) + PLUS reduce using rule 17 (expression -> ID .) + MINUS reduce using rule 17 (expression -> ID .) + MULTIPLY reduce using rule 17 (expression -> ID .) + DIVIDE reduce using rule 17 (expression -> ID .) + LT reduce using rule 17 (expression -> ID .) + LTEQ reduce using rule 17 (expression -> ID .) + EQ reduce using rule 17 (expression -> ID .) + SEMICOLON reduce using rule 17 (expression -> ID .) + RPAREN reduce using rule 17 (expression -> ID .) + THEN reduce using rule 17 (expression -> ID .) + LOOP reduce using rule 17 (expression -> ID .) + OF reduce using rule 17 (expression -> ID .) + RBRACE reduce using rule 17 (expression -> ID .) + COMMA reduce using rule 17 (expression -> ID .) + ELSE reduce using rule 17 (expression -> ID .) + POOL reduce using rule 17 (expression -> ID .) + FI reduce using rule 17 (expression -> ID .) + IN reduce using rule 17 (expression -> ID .) + ASSIGN shift and go to state 57 + LPAREN shift and go to state 58 + + +state 40 + + (12) feature -> ID COLON TYPE ASSIGN expression . + (25) expression -> expression . DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> expression . AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (32) expression -> expression . PLUS expression + (33) expression -> expression . MINUS expression + (34) expression -> expression . MULTIPLY expression + (35) expression -> expression . DIVIDE expression + (36) expression -> expression . LT expression + (37) expression -> expression . LTEQ expression + (38) expression -> expression . EQ expression + + SEMICOLON reduce using rule 12 (feature -> ID COLON TYPE ASSIGN expression .) + DOT shift and go to state 59 + AT shift and go to state 60 + PLUS shift and go to state 61 + MINUS shift and go to state 62 + MULTIPLY shift and go to state 63 + DIVIDE shift and go to state 64 + LT shift and go to state 65 + LTEQ shift and go to state 66 + EQ shift and go to state 67 + + +state 41 + + (18) expression -> INTEGER . + + DOT reduce using rule 18 (expression -> INTEGER .) + AT reduce using rule 18 (expression -> INTEGER .) + PLUS reduce using rule 18 (expression -> INTEGER .) + MINUS reduce using rule 18 (expression -> INTEGER .) + MULTIPLY reduce using rule 18 (expression -> INTEGER .) + DIVIDE reduce using rule 18 (expression -> INTEGER .) + LT reduce using rule 18 (expression -> INTEGER .) + LTEQ reduce using rule 18 (expression -> INTEGER .) + EQ reduce using rule 18 (expression -> INTEGER .) + SEMICOLON reduce using rule 18 (expression -> INTEGER .) + RPAREN reduce using rule 18 (expression -> INTEGER .) + THEN reduce using rule 18 (expression -> INTEGER .) + LOOP reduce using rule 18 (expression -> INTEGER .) + OF reduce using rule 18 (expression -> INTEGER .) + RBRACE reduce using rule 18 (expression -> INTEGER .) + COMMA reduce using rule 18 (expression -> INTEGER .) + ELSE reduce using rule 18 (expression -> INTEGER .) + POOL reduce using rule 18 (expression -> INTEGER .) + FI reduce using rule 18 (expression -> INTEGER .) + IN reduce using rule 18 (expression -> INTEGER .) + + +state 42 + + (19) expression -> BOOLEAN . + + DOT reduce using rule 19 (expression -> BOOLEAN .) + AT reduce using rule 19 (expression -> BOOLEAN .) + PLUS reduce using rule 19 (expression -> BOOLEAN .) + MINUS reduce using rule 19 (expression -> BOOLEAN .) + MULTIPLY reduce using rule 19 (expression -> BOOLEAN .) + DIVIDE reduce using rule 19 (expression -> BOOLEAN .) + LT reduce using rule 19 (expression -> BOOLEAN .) + LTEQ reduce using rule 19 (expression -> BOOLEAN .) + EQ reduce using rule 19 (expression -> BOOLEAN .) + SEMICOLON reduce using rule 19 (expression -> BOOLEAN .) + RPAREN reduce using rule 19 (expression -> BOOLEAN .) + THEN reduce using rule 19 (expression -> BOOLEAN .) + LOOP reduce using rule 19 (expression -> BOOLEAN .) + OF reduce using rule 19 (expression -> BOOLEAN .) + RBRACE reduce using rule 19 (expression -> BOOLEAN .) + COMMA reduce using rule 19 (expression -> BOOLEAN .) + ELSE reduce using rule 19 (expression -> BOOLEAN .) + POOL reduce using rule 19 (expression -> BOOLEAN .) + FI reduce using rule 19 (expression -> BOOLEAN .) + IN reduce using rule 19 (expression -> BOOLEAN .) + + +state 43 + + (20) expression -> STRING . + + DOT reduce using rule 20 (expression -> STRING .) + AT reduce using rule 20 (expression -> STRING .) + PLUS reduce using rule 20 (expression -> STRING .) + MINUS reduce using rule 20 (expression -> STRING .) + MULTIPLY reduce using rule 20 (expression -> STRING .) + DIVIDE reduce using rule 20 (expression -> STRING .) + LT reduce using rule 20 (expression -> STRING .) + LTEQ reduce using rule 20 (expression -> STRING .) + EQ reduce using rule 20 (expression -> STRING .) + SEMICOLON reduce using rule 20 (expression -> STRING .) + RPAREN reduce using rule 20 (expression -> STRING .) + THEN reduce using rule 20 (expression -> STRING .) + LOOP reduce using rule 20 (expression -> STRING .) + OF reduce using rule 20 (expression -> STRING .) + RBRACE reduce using rule 20 (expression -> STRING .) + COMMA reduce using rule 20 (expression -> STRING .) + ELSE reduce using rule 20 (expression -> STRING .) + POOL reduce using rule 20 (expression -> STRING .) + FI reduce using rule 20 (expression -> STRING .) + IN reduce using rule 20 (expression -> STRING .) + + +state 44 + + (21) expression -> LBRACE . block_list RBRACE + (22) block_list -> . expression SEMICOLON block_list + (23) block_list -> . expression SEMICOLON + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + block_list shift and go to state 68 + expression shift and go to state 69 + let_expression shift and go to state 48 + +state 45 + + (39) expression -> LPAREN . expression RPAREN + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 70 + let_expression shift and go to state 48 + +state 46 + + (40) expression -> IF . expression THEN expression ELSE expression FI + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 71 + let_expression shift and go to state 48 + +state 47 + + (41) expression -> WHILE . expression LOOP expression POOL + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 72 + let_expression shift and go to state 48 + +state 48 + + (42) expression -> let_expression . + + DOT reduce using rule 42 (expression -> let_expression .) + AT reduce using rule 42 (expression -> let_expression .) + PLUS reduce using rule 42 (expression -> let_expression .) + MINUS reduce using rule 42 (expression -> let_expression .) + MULTIPLY reduce using rule 42 (expression -> let_expression .) + DIVIDE reduce using rule 42 (expression -> let_expression .) + LT reduce using rule 42 (expression -> let_expression .) + LTEQ reduce using rule 42 (expression -> let_expression .) + EQ reduce using rule 42 (expression -> let_expression .) + SEMICOLON reduce using rule 42 (expression -> let_expression .) + RPAREN reduce using rule 42 (expression -> let_expression .) + THEN reduce using rule 42 (expression -> let_expression .) + LOOP reduce using rule 42 (expression -> let_expression .) + OF reduce using rule 42 (expression -> let_expression .) + RBRACE reduce using rule 42 (expression -> let_expression .) + COMMA reduce using rule 42 (expression -> let_expression .) + ELSE reduce using rule 42 (expression -> let_expression .) + POOL reduce using rule 42 (expression -> let_expression .) + FI reduce using rule 42 (expression -> let_expression .) + IN reduce using rule 42 (expression -> let_expression .) + + +state 49 + + (48) expression -> CASE . expression OF actions_list ESAC + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 73 + let_expression shift and go to state 48 + +state 50 + + (52) expression -> NEW . TYPE + + TYPE shift and go to state 74 + + +state 51 + + (53) expression -> ISVOID . expression + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 75 + let_expression shift and go to state 48 + +state 52 + + (54) expression -> INT_COMP . expression + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 76 + let_expression shift and go to state 48 + +state 53 + + (55) expression -> NOT . expression + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 77 + let_expression shift and go to state 48 + +state 54 + + (43) let_expression -> LET . formal_list IN expression + (44) formal_list -> . formal_list COMMA formal + (45) formal_list -> . formal + (46) formal -> . ID COLON TYPE + (47) formal -> . ID COLON TYPE ASSIGN expression + + ID shift and go to state 80 + + formal_list shift and go to state 78 + formal shift and go to state 79 + +state 55 + + (10) feature -> ID LPAREN formal_params_list RPAREN COLON TYPE . LBRACE expression RBRACE + + LBRACE shift and go to state 81 + + +state 56 + + (11) feature -> ID LPAREN RPAREN COLON TYPE LBRACE . expression RBRACE + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 82 + let_expression shift and go to state 48 + +state 57 + + (24) expression -> ID ASSIGN . expression + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 83 + let_expression shift and go to state 48 + +state 58 + + (31) expression -> ID LPAREN . arguments_list_opt RPAREN + (26) arguments_list_opt -> . arguments_list + (27) arguments_list_opt -> . empty + (28) arguments_list -> . expression COMMA arguments_list + (29) arguments_list -> . expression + (56) empty -> . + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + RPAREN reduce using rule 56 (empty -> .) + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + arguments_list_opt shift and go to state 84 + arguments_list shift and go to state 85 + empty shift and go to state 86 + expression shift and go to state 87 + let_expression shift and go to state 48 + +state 59 + + (25) expression -> expression DOT . ID LPAREN arguments_list_opt RPAREN + + ID shift and go to state 88 + + +state 60 + + (30) expression -> expression AT . TYPE DOT ID LPAREN arguments_list_opt RPAREN + + TYPE shift and go to state 89 + + +state 61 + + (32) expression -> expression PLUS . expression + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 90 + let_expression shift and go to state 48 + +state 62 + + (33) expression -> expression MINUS . expression + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 91 + let_expression shift and go to state 48 + +state 63 + + (34) expression -> expression MULTIPLY . expression + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 92 + let_expression shift and go to state 48 + +state 64 + + (35) expression -> expression DIVIDE . expression + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 93 + let_expression shift and go to state 48 + +state 65 + + (36) expression -> expression LT . expression + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 94 + let_expression shift and go to state 48 + +state 66 + + (37) expression -> expression LTEQ . expression + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 95 + let_expression shift and go to state 48 + +state 67 + + (38) expression -> expression EQ . expression + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 96 + let_expression shift and go to state 48 + +state 68 + + (21) expression -> LBRACE block_list . RBRACE + + RBRACE shift and go to state 97 + + +state 69 + + (22) block_list -> expression . SEMICOLON block_list + (23) block_list -> expression . SEMICOLON + (25) expression -> expression . DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> expression . AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (32) expression -> expression . PLUS expression + (33) expression -> expression . MINUS expression + (34) expression -> expression . MULTIPLY expression + (35) expression -> expression . DIVIDE expression + (36) expression -> expression . LT expression + (37) expression -> expression . LTEQ expression + (38) expression -> expression . EQ expression + + SEMICOLON shift and go to state 98 + DOT shift and go to state 59 + AT shift and go to state 60 + PLUS shift and go to state 61 + MINUS shift and go to state 62 + MULTIPLY shift and go to state 63 + DIVIDE shift and go to state 64 + LT shift and go to state 65 + LTEQ shift and go to state 66 + EQ shift and go to state 67 + + +state 70 + + (39) expression -> LPAREN expression . RPAREN + (25) expression -> expression . DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> expression . AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (32) expression -> expression . PLUS expression + (33) expression -> expression . MINUS expression + (34) expression -> expression . MULTIPLY expression + (35) expression -> expression . DIVIDE expression + (36) expression -> expression . LT expression + (37) expression -> expression . LTEQ expression + (38) expression -> expression . EQ expression + + RPAREN shift and go to state 99 + DOT shift and go to state 59 + AT shift and go to state 60 + PLUS shift and go to state 61 + MINUS shift and go to state 62 + MULTIPLY shift and go to state 63 + DIVIDE shift and go to state 64 + LT shift and go to state 65 + LTEQ shift and go to state 66 + EQ shift and go to state 67 + + +state 71 + + (40) expression -> IF expression . THEN expression ELSE expression FI + (25) expression -> expression . DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> expression . AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (32) expression -> expression . PLUS expression + (33) expression -> expression . MINUS expression + (34) expression -> expression . MULTIPLY expression + (35) expression -> expression . DIVIDE expression + (36) expression -> expression . LT expression + (37) expression -> expression . LTEQ expression + (38) expression -> expression . EQ expression + + THEN shift and go to state 100 + DOT shift and go to state 59 + AT shift and go to state 60 + PLUS shift and go to state 61 + MINUS shift and go to state 62 + MULTIPLY shift and go to state 63 + DIVIDE shift and go to state 64 + LT shift and go to state 65 + LTEQ shift and go to state 66 + EQ shift and go to state 67 + + +state 72 + + (41) expression -> WHILE expression . LOOP expression POOL + (25) expression -> expression . DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> expression . AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (32) expression -> expression . PLUS expression + (33) expression -> expression . MINUS expression + (34) expression -> expression . MULTIPLY expression + (35) expression -> expression . DIVIDE expression + (36) expression -> expression . LT expression + (37) expression -> expression . LTEQ expression + (38) expression -> expression . EQ expression + + LOOP shift and go to state 101 + DOT shift and go to state 59 + AT shift and go to state 60 + PLUS shift and go to state 61 + MINUS shift and go to state 62 + MULTIPLY shift and go to state 63 + DIVIDE shift and go to state 64 + LT shift and go to state 65 + LTEQ shift and go to state 66 + EQ shift and go to state 67 + + +state 73 + + (48) expression -> CASE expression . OF actions_list ESAC + (25) expression -> expression . DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> expression . AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (32) expression -> expression . PLUS expression + (33) expression -> expression . MINUS expression + (34) expression -> expression . MULTIPLY expression + (35) expression -> expression . DIVIDE expression + (36) expression -> expression . LT expression + (37) expression -> expression . LTEQ expression + (38) expression -> expression . EQ expression + + OF shift and go to state 102 + DOT shift and go to state 59 + AT shift and go to state 60 + PLUS shift and go to state 61 + MINUS shift and go to state 62 + MULTIPLY shift and go to state 63 + DIVIDE shift and go to state 64 + LT shift and go to state 65 + LTEQ shift and go to state 66 + EQ shift and go to state 67 + + +state 74 + + (52) expression -> NEW TYPE . + + DOT reduce using rule 52 (expression -> NEW TYPE .) + AT reduce using rule 52 (expression -> NEW TYPE .) + PLUS reduce using rule 52 (expression -> NEW TYPE .) + MINUS reduce using rule 52 (expression -> NEW TYPE .) + MULTIPLY reduce using rule 52 (expression -> NEW TYPE .) + DIVIDE reduce using rule 52 (expression -> NEW TYPE .) + LT reduce using rule 52 (expression -> NEW TYPE .) + LTEQ reduce using rule 52 (expression -> NEW TYPE .) + EQ reduce using rule 52 (expression -> NEW TYPE .) + SEMICOLON reduce using rule 52 (expression -> NEW TYPE .) + RPAREN reduce using rule 52 (expression -> NEW TYPE .) + THEN reduce using rule 52 (expression -> NEW TYPE .) + LOOP reduce using rule 52 (expression -> NEW TYPE .) + OF reduce using rule 52 (expression -> NEW TYPE .) + RBRACE reduce using rule 52 (expression -> NEW TYPE .) + COMMA reduce using rule 52 (expression -> NEW TYPE .) + ELSE reduce using rule 52 (expression -> NEW TYPE .) + POOL reduce using rule 52 (expression -> NEW TYPE .) + FI reduce using rule 52 (expression -> NEW TYPE .) + IN reduce using rule 52 (expression -> NEW TYPE .) + + +state 75 + + (53) expression -> ISVOID expression . + (25) expression -> expression . DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> expression . AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (32) expression -> expression . PLUS expression + (33) expression -> expression . MINUS expression + (34) expression -> expression . MULTIPLY expression + (35) expression -> expression . DIVIDE expression + (36) expression -> expression . LT expression + (37) expression -> expression . LTEQ expression + (38) expression -> expression . EQ expression + + PLUS reduce using rule 53 (expression -> ISVOID expression .) + MINUS reduce using rule 53 (expression -> ISVOID expression .) + MULTIPLY reduce using rule 53 (expression -> ISVOID expression .) + DIVIDE reduce using rule 53 (expression -> ISVOID expression .) + LT reduce using rule 53 (expression -> ISVOID expression .) + LTEQ reduce using rule 53 (expression -> ISVOID expression .) + EQ reduce using rule 53 (expression -> ISVOID expression .) + SEMICOLON reduce using rule 53 (expression -> ISVOID expression .) + RPAREN reduce using rule 53 (expression -> ISVOID expression .) + THEN reduce using rule 53 (expression -> ISVOID expression .) + LOOP reduce using rule 53 (expression -> ISVOID expression .) + OF reduce using rule 53 (expression -> ISVOID expression .) + RBRACE reduce using rule 53 (expression -> ISVOID expression .) + COMMA reduce using rule 53 (expression -> ISVOID expression .) + ELSE reduce using rule 53 (expression -> ISVOID expression .) + POOL reduce using rule 53 (expression -> ISVOID expression .) + FI reduce using rule 53 (expression -> ISVOID expression .) + IN reduce using rule 53 (expression -> ISVOID expression .) + DOT shift and go to state 59 + AT shift and go to state 60 + + ! DOT [ reduce using rule 53 (expression -> ISVOID expression .) ] + ! AT [ reduce using rule 53 (expression -> ISVOID expression .) ] + ! PLUS [ shift and go to state 61 ] + ! MINUS [ shift and go to state 62 ] + ! MULTIPLY [ shift and go to state 63 ] + ! DIVIDE [ shift and go to state 64 ] + ! LT [ shift and go to state 65 ] + ! LTEQ [ shift and go to state 66 ] + ! EQ [ shift and go to state 67 ] + + +state 76 + + (54) expression -> INT_COMP expression . + (25) expression -> expression . DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> expression . AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (32) expression -> expression . PLUS expression + (33) expression -> expression . MINUS expression + (34) expression -> expression . MULTIPLY expression + (35) expression -> expression . DIVIDE expression + (36) expression -> expression . LT expression + (37) expression -> expression . LTEQ expression + (38) expression -> expression . EQ expression + + PLUS reduce using rule 54 (expression -> INT_COMP expression .) + MINUS reduce using rule 54 (expression -> INT_COMP expression .) + MULTIPLY reduce using rule 54 (expression -> INT_COMP expression .) + DIVIDE reduce using rule 54 (expression -> INT_COMP expression .) + LT reduce using rule 54 (expression -> INT_COMP expression .) + LTEQ reduce using rule 54 (expression -> INT_COMP expression .) + EQ reduce using rule 54 (expression -> INT_COMP expression .) + SEMICOLON reduce using rule 54 (expression -> INT_COMP expression .) + RPAREN reduce using rule 54 (expression -> INT_COMP expression .) + THEN reduce using rule 54 (expression -> INT_COMP expression .) + LOOP reduce using rule 54 (expression -> INT_COMP expression .) + OF reduce using rule 54 (expression -> INT_COMP expression .) + RBRACE reduce using rule 54 (expression -> INT_COMP expression .) + COMMA reduce using rule 54 (expression -> INT_COMP expression .) + ELSE reduce using rule 54 (expression -> INT_COMP expression .) + POOL reduce using rule 54 (expression -> INT_COMP expression .) + FI reduce using rule 54 (expression -> INT_COMP expression .) + IN reduce using rule 54 (expression -> INT_COMP expression .) + DOT shift and go to state 59 + AT shift and go to state 60 + + ! DOT [ reduce using rule 54 (expression -> INT_COMP expression .) ] + ! AT [ reduce using rule 54 (expression -> INT_COMP expression .) ] + ! PLUS [ shift and go to state 61 ] + ! MINUS [ shift and go to state 62 ] + ! MULTIPLY [ shift and go to state 63 ] + ! DIVIDE [ shift and go to state 64 ] + ! LT [ shift and go to state 65 ] + ! LTEQ [ shift and go to state 66 ] + ! EQ [ shift and go to state 67 ] + + +state 77 + + (55) expression -> NOT expression . + (25) expression -> expression . DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> expression . AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (32) expression -> expression . PLUS expression + (33) expression -> expression . MINUS expression + (34) expression -> expression . MULTIPLY expression + (35) expression -> expression . DIVIDE expression + (36) expression -> expression . LT expression + (37) expression -> expression . LTEQ expression + (38) expression -> expression . EQ expression + + SEMICOLON reduce using rule 55 (expression -> NOT expression .) + RPAREN reduce using rule 55 (expression -> NOT expression .) + THEN reduce using rule 55 (expression -> NOT expression .) + LOOP reduce using rule 55 (expression -> NOT expression .) + OF reduce using rule 55 (expression -> NOT expression .) + RBRACE reduce using rule 55 (expression -> NOT expression .) + COMMA reduce using rule 55 (expression -> NOT expression .) + ELSE reduce using rule 55 (expression -> NOT expression .) + POOL reduce using rule 55 (expression -> NOT expression .) + FI reduce using rule 55 (expression -> NOT expression .) + IN reduce using rule 55 (expression -> NOT expression .) + DOT shift and go to state 59 + AT shift and go to state 60 + PLUS shift and go to state 61 + MINUS shift and go to state 62 + MULTIPLY shift and go to state 63 + DIVIDE shift and go to state 64 + LT shift and go to state 65 + LTEQ shift and go to state 66 + EQ shift and go to state 67 + + ! DOT [ reduce using rule 55 (expression -> NOT expression .) ] + ! AT [ reduce using rule 55 (expression -> NOT expression .) ] + ! PLUS [ reduce using rule 55 (expression -> NOT expression .) ] + ! MINUS [ reduce using rule 55 (expression -> NOT expression .) ] + ! MULTIPLY [ reduce using rule 55 (expression -> NOT expression .) ] + ! DIVIDE [ reduce using rule 55 (expression -> NOT expression .) ] + ! LT [ reduce using rule 55 (expression -> NOT expression .) ] + ! LTEQ [ reduce using rule 55 (expression -> NOT expression .) ] + ! EQ [ reduce using rule 55 (expression -> NOT expression .) ] + + +state 78 + + (43) let_expression -> LET formal_list . IN expression + (44) formal_list -> formal_list . COMMA formal + + IN shift and go to state 103 + COMMA shift and go to state 104 + + +state 79 + + (45) formal_list -> formal . + + IN reduce using rule 45 (formal_list -> formal .) + COMMA reduce using rule 45 (formal_list -> formal .) + + +state 80 + + (46) formal -> ID . COLON TYPE + (47) formal -> ID . COLON TYPE ASSIGN expression + + COLON shift and go to state 105 + + +state 81 + + (10) feature -> ID LPAREN formal_params_list RPAREN COLON TYPE LBRACE . expression RBRACE + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 106 + let_expression shift and go to state 48 + +state 82 + + (11) feature -> ID LPAREN RPAREN COLON TYPE LBRACE expression . RBRACE + (25) expression -> expression . DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> expression . AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (32) expression -> expression . PLUS expression + (33) expression -> expression . MINUS expression + (34) expression -> expression . MULTIPLY expression + (35) expression -> expression . DIVIDE expression + (36) expression -> expression . LT expression + (37) expression -> expression . LTEQ expression + (38) expression -> expression . EQ expression + + RBRACE shift and go to state 107 + DOT shift and go to state 59 + AT shift and go to state 60 + PLUS shift and go to state 61 + MINUS shift and go to state 62 + MULTIPLY shift and go to state 63 + DIVIDE shift and go to state 64 + LT shift and go to state 65 + LTEQ shift and go to state 66 + EQ shift and go to state 67 + + +state 83 + + (24) expression -> ID ASSIGN expression . + (25) expression -> expression . DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> expression . AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (32) expression -> expression . PLUS expression + (33) expression -> expression . MINUS expression + (34) expression -> expression . MULTIPLY expression + (35) expression -> expression . DIVIDE expression + (36) expression -> expression . LT expression + (37) expression -> expression . LTEQ expression + (38) expression -> expression . EQ expression + + SEMICOLON reduce using rule 24 (expression -> ID ASSIGN expression .) + RPAREN reduce using rule 24 (expression -> ID ASSIGN expression .) + THEN reduce using rule 24 (expression -> ID ASSIGN expression .) + LOOP reduce using rule 24 (expression -> ID ASSIGN expression .) + OF reduce using rule 24 (expression -> ID ASSIGN expression .) + RBRACE reduce using rule 24 (expression -> ID ASSIGN expression .) + COMMA reduce using rule 24 (expression -> ID ASSIGN expression .) + ELSE reduce using rule 24 (expression -> ID ASSIGN expression .) + POOL reduce using rule 24 (expression -> ID ASSIGN expression .) + FI reduce using rule 24 (expression -> ID ASSIGN expression .) + IN reduce using rule 24 (expression -> ID ASSIGN expression .) + DOT shift and go to state 59 + AT shift and go to state 60 + PLUS shift and go to state 61 + MINUS shift and go to state 62 + MULTIPLY shift and go to state 63 + DIVIDE shift and go to state 64 + LT shift and go to state 65 + LTEQ shift and go to state 66 + EQ shift and go to state 67 + + ! DOT [ reduce using rule 24 (expression -> ID ASSIGN expression .) ] + ! AT [ reduce using rule 24 (expression -> ID ASSIGN expression .) ] + ! PLUS [ reduce using rule 24 (expression -> ID ASSIGN expression .) ] + ! MINUS [ reduce using rule 24 (expression -> ID ASSIGN expression .) ] + ! MULTIPLY [ reduce using rule 24 (expression -> ID ASSIGN expression .) ] + ! DIVIDE [ reduce using rule 24 (expression -> ID ASSIGN expression .) ] + ! LT [ reduce using rule 24 (expression -> ID ASSIGN expression .) ] + ! LTEQ [ reduce using rule 24 (expression -> ID ASSIGN expression .) ] + ! EQ [ reduce using rule 24 (expression -> ID ASSIGN expression .) ] + + +state 84 + + (31) expression -> ID LPAREN arguments_list_opt . RPAREN + + RPAREN shift and go to state 108 + + +state 85 + + (26) arguments_list_opt -> arguments_list . + + RPAREN reduce using rule 26 (arguments_list_opt -> arguments_list .) + + +state 86 + + (27) arguments_list_opt -> empty . + + RPAREN reduce using rule 27 (arguments_list_opt -> empty .) + + +state 87 + + (28) arguments_list -> expression . COMMA arguments_list + (29) arguments_list -> expression . + (25) expression -> expression . DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> expression . AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (32) expression -> expression . PLUS expression + (33) expression -> expression . MINUS expression + (34) expression -> expression . MULTIPLY expression + (35) expression -> expression . DIVIDE expression + (36) expression -> expression . LT expression + (37) expression -> expression . LTEQ expression + (38) expression -> expression . EQ expression + + COMMA shift and go to state 109 + RPAREN reduce using rule 29 (arguments_list -> expression .) + DOT shift and go to state 59 + AT shift and go to state 60 + PLUS shift and go to state 61 + MINUS shift and go to state 62 + MULTIPLY shift and go to state 63 + DIVIDE shift and go to state 64 + LT shift and go to state 65 + LTEQ shift and go to state 66 + EQ shift and go to state 67 + + +state 88 + + (25) expression -> expression DOT ID . LPAREN arguments_list_opt RPAREN + + LPAREN shift and go to state 110 + + +state 89 + + (30) expression -> expression AT TYPE . DOT ID LPAREN arguments_list_opt RPAREN + + DOT shift and go to state 111 + + +state 90 + + (32) expression -> expression PLUS expression . + (25) expression -> expression . DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> expression . AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (32) expression -> expression . PLUS expression + (33) expression -> expression . MINUS expression + (34) expression -> expression . MULTIPLY expression + (35) expression -> expression . DIVIDE expression + (36) expression -> expression . LT expression + (37) expression -> expression . LTEQ expression + (38) expression -> expression . EQ expression + + PLUS reduce using rule 32 (expression -> expression PLUS expression .) + MINUS reduce using rule 32 (expression -> expression PLUS expression .) + LT reduce using rule 32 (expression -> expression PLUS expression .) + LTEQ reduce using rule 32 (expression -> expression PLUS expression .) + EQ reduce using rule 32 (expression -> expression PLUS expression .) + SEMICOLON reduce using rule 32 (expression -> expression PLUS expression .) + RPAREN reduce using rule 32 (expression -> expression PLUS expression .) + THEN reduce using rule 32 (expression -> expression PLUS expression .) + LOOP reduce using rule 32 (expression -> expression PLUS expression .) + OF reduce using rule 32 (expression -> expression PLUS expression .) + RBRACE reduce using rule 32 (expression -> expression PLUS expression .) + COMMA reduce using rule 32 (expression -> expression PLUS expression .) + ELSE reduce using rule 32 (expression -> expression PLUS expression .) + POOL reduce using rule 32 (expression -> expression PLUS expression .) + FI reduce using rule 32 (expression -> expression PLUS expression .) + IN reduce using rule 32 (expression -> expression PLUS expression .) + DOT shift and go to state 59 + AT shift and go to state 60 + MULTIPLY shift and go to state 63 + DIVIDE shift and go to state 64 + + ! DOT [ reduce using rule 32 (expression -> expression PLUS expression .) ] + ! AT [ reduce using rule 32 (expression -> expression PLUS expression .) ] + ! MULTIPLY [ reduce using rule 32 (expression -> expression PLUS expression .) ] + ! DIVIDE [ reduce using rule 32 (expression -> expression PLUS expression .) ] + ! PLUS [ shift and go to state 61 ] + ! MINUS [ shift and go to state 62 ] + ! LT [ shift and go to state 65 ] + ! LTEQ [ shift and go to state 66 ] + ! EQ [ shift and go to state 67 ] + + +state 91 + + (33) expression -> expression MINUS expression . + (25) expression -> expression . DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> expression . AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (32) expression -> expression . PLUS expression + (33) expression -> expression . MINUS expression + (34) expression -> expression . MULTIPLY expression + (35) expression -> expression . DIVIDE expression + (36) expression -> expression . LT expression + (37) expression -> expression . LTEQ expression + (38) expression -> expression . EQ expression + + PLUS reduce using rule 33 (expression -> expression MINUS expression .) + MINUS reduce using rule 33 (expression -> expression MINUS expression .) + LT reduce using rule 33 (expression -> expression MINUS expression .) + LTEQ reduce using rule 33 (expression -> expression MINUS expression .) + EQ reduce using rule 33 (expression -> expression MINUS expression .) + SEMICOLON reduce using rule 33 (expression -> expression MINUS expression .) + RPAREN reduce using rule 33 (expression -> expression MINUS expression .) + THEN reduce using rule 33 (expression -> expression MINUS expression .) + LOOP reduce using rule 33 (expression -> expression MINUS expression .) + OF reduce using rule 33 (expression -> expression MINUS expression .) + RBRACE reduce using rule 33 (expression -> expression MINUS expression .) + COMMA reduce using rule 33 (expression -> expression MINUS expression .) + ELSE reduce using rule 33 (expression -> expression MINUS expression .) + POOL reduce using rule 33 (expression -> expression MINUS expression .) + FI reduce using rule 33 (expression -> expression MINUS expression .) + IN reduce using rule 33 (expression -> expression MINUS expression .) + DOT shift and go to state 59 + AT shift and go to state 60 + MULTIPLY shift and go to state 63 + DIVIDE shift and go to state 64 + + ! DOT [ reduce using rule 33 (expression -> expression MINUS expression .) ] + ! AT [ reduce using rule 33 (expression -> expression MINUS expression .) ] + ! MULTIPLY [ reduce using rule 33 (expression -> expression MINUS expression .) ] + ! DIVIDE [ reduce using rule 33 (expression -> expression MINUS expression .) ] + ! PLUS [ shift and go to state 61 ] + ! MINUS [ shift and go to state 62 ] + ! LT [ shift and go to state 65 ] + ! LTEQ [ shift and go to state 66 ] + ! EQ [ shift and go to state 67 ] + + +state 92 + + (34) expression -> expression MULTIPLY expression . + (25) expression -> expression . DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> expression . AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (32) expression -> expression . PLUS expression + (33) expression -> expression . MINUS expression + (34) expression -> expression . MULTIPLY expression + (35) expression -> expression . DIVIDE expression + (36) expression -> expression . LT expression + (37) expression -> expression . LTEQ expression + (38) expression -> expression . EQ expression + + PLUS reduce using rule 34 (expression -> expression MULTIPLY expression .) + MINUS reduce using rule 34 (expression -> expression MULTIPLY expression .) + MULTIPLY reduce using rule 34 (expression -> expression MULTIPLY expression .) + DIVIDE reduce using rule 34 (expression -> expression MULTIPLY expression .) + LT reduce using rule 34 (expression -> expression MULTIPLY expression .) + LTEQ reduce using rule 34 (expression -> expression MULTIPLY expression .) + EQ reduce using rule 34 (expression -> expression MULTIPLY expression .) + SEMICOLON reduce using rule 34 (expression -> expression MULTIPLY expression .) + RPAREN reduce using rule 34 (expression -> expression MULTIPLY expression .) + THEN reduce using rule 34 (expression -> expression MULTIPLY expression .) + LOOP reduce using rule 34 (expression -> expression MULTIPLY expression .) + OF reduce using rule 34 (expression -> expression MULTIPLY expression .) + RBRACE reduce using rule 34 (expression -> expression MULTIPLY expression .) + COMMA reduce using rule 34 (expression -> expression MULTIPLY expression .) + ELSE reduce using rule 34 (expression -> expression MULTIPLY expression .) + POOL reduce using rule 34 (expression -> expression MULTIPLY expression .) + FI reduce using rule 34 (expression -> expression MULTIPLY expression .) + IN reduce using rule 34 (expression -> expression MULTIPLY expression .) + DOT shift and go to state 59 + AT shift and go to state 60 + + ! DOT [ reduce using rule 34 (expression -> expression MULTIPLY expression .) ] + ! AT [ reduce using rule 34 (expression -> expression MULTIPLY expression .) ] + ! PLUS [ shift and go to state 61 ] + ! MINUS [ shift and go to state 62 ] + ! MULTIPLY [ shift and go to state 63 ] + ! DIVIDE [ shift and go to state 64 ] + ! LT [ shift and go to state 65 ] + ! LTEQ [ shift and go to state 66 ] + ! EQ [ shift and go to state 67 ] + + +state 93 + + (35) expression -> expression DIVIDE expression . + (25) expression -> expression . DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> expression . AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (32) expression -> expression . PLUS expression + (33) expression -> expression . MINUS expression + (34) expression -> expression . MULTIPLY expression + (35) expression -> expression . DIVIDE expression + (36) expression -> expression . LT expression + (37) expression -> expression . LTEQ expression + (38) expression -> expression . EQ expression + + PLUS reduce using rule 35 (expression -> expression DIVIDE expression .) + MINUS reduce using rule 35 (expression -> expression DIVIDE expression .) + MULTIPLY reduce using rule 35 (expression -> expression DIVIDE expression .) + DIVIDE reduce using rule 35 (expression -> expression DIVIDE expression .) + LT reduce using rule 35 (expression -> expression DIVIDE expression .) + LTEQ reduce using rule 35 (expression -> expression DIVIDE expression .) + EQ reduce using rule 35 (expression -> expression DIVIDE expression .) + SEMICOLON reduce using rule 35 (expression -> expression DIVIDE expression .) + RPAREN reduce using rule 35 (expression -> expression DIVIDE expression .) + THEN reduce using rule 35 (expression -> expression DIVIDE expression .) + LOOP reduce using rule 35 (expression -> expression DIVIDE expression .) + OF reduce using rule 35 (expression -> expression DIVIDE expression .) + RBRACE reduce using rule 35 (expression -> expression DIVIDE expression .) + COMMA reduce using rule 35 (expression -> expression DIVIDE expression .) + ELSE reduce using rule 35 (expression -> expression DIVIDE expression .) + POOL reduce using rule 35 (expression -> expression DIVIDE expression .) + FI reduce using rule 35 (expression -> expression DIVIDE expression .) + IN reduce using rule 35 (expression -> expression DIVIDE expression .) + DOT shift and go to state 59 + AT shift and go to state 60 + + ! DOT [ reduce using rule 35 (expression -> expression DIVIDE expression .) ] + ! AT [ reduce using rule 35 (expression -> expression DIVIDE expression .) ] + ! PLUS [ shift and go to state 61 ] + ! MINUS [ shift and go to state 62 ] + ! MULTIPLY [ shift and go to state 63 ] + ! DIVIDE [ shift and go to state 64 ] + ! LT [ shift and go to state 65 ] + ! LTEQ [ shift and go to state 66 ] + ! EQ [ shift and go to state 67 ] + + +state 94 + + (36) expression -> expression LT expression . + (25) expression -> expression . DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> expression . AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (32) expression -> expression . PLUS expression + (33) expression -> expression . MINUS expression + (34) expression -> expression . MULTIPLY expression + (35) expression -> expression . DIVIDE expression + (36) expression -> expression . LT expression + (37) expression -> expression . LTEQ expression + (38) expression -> expression . EQ expression + + LT reduce using rule 36 (expression -> expression LT expression .) + LTEQ reduce using rule 36 (expression -> expression LT expression .) + EQ reduce using rule 36 (expression -> expression LT expression .) + SEMICOLON reduce using rule 36 (expression -> expression LT expression .) + RPAREN reduce using rule 36 (expression -> expression LT expression .) + THEN reduce using rule 36 (expression -> expression LT expression .) + LOOP reduce using rule 36 (expression -> expression LT expression .) + OF reduce using rule 36 (expression -> expression LT expression .) + RBRACE reduce using rule 36 (expression -> expression LT expression .) + COMMA reduce using rule 36 (expression -> expression LT expression .) + ELSE reduce using rule 36 (expression -> expression LT expression .) + POOL reduce using rule 36 (expression -> expression LT expression .) + FI reduce using rule 36 (expression -> expression LT expression .) + IN reduce using rule 36 (expression -> expression LT expression .) + DOT shift and go to state 59 + AT shift and go to state 60 + PLUS shift and go to state 61 + MINUS shift and go to state 62 + MULTIPLY shift and go to state 63 + DIVIDE shift and go to state 64 + + ! DOT [ reduce using rule 36 (expression -> expression LT expression .) ] + ! AT [ reduce using rule 36 (expression -> expression LT expression .) ] + ! PLUS [ reduce using rule 36 (expression -> expression LT expression .) ] + ! MINUS [ reduce using rule 36 (expression -> expression LT expression .) ] + ! MULTIPLY [ reduce using rule 36 (expression -> expression LT expression .) ] + ! DIVIDE [ reduce using rule 36 (expression -> expression LT expression .) ] + ! LT [ shift and go to state 65 ] + ! LTEQ [ shift and go to state 66 ] + ! EQ [ shift and go to state 67 ] + + +state 95 + + (37) expression -> expression LTEQ expression . + (25) expression -> expression . DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> expression . AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (32) expression -> expression . PLUS expression + (33) expression -> expression . MINUS expression + (34) expression -> expression . MULTIPLY expression + (35) expression -> expression . DIVIDE expression + (36) expression -> expression . LT expression + (37) expression -> expression . LTEQ expression + (38) expression -> expression . EQ expression + + LT reduce using rule 37 (expression -> expression LTEQ expression .) + LTEQ reduce using rule 37 (expression -> expression LTEQ expression .) + EQ reduce using rule 37 (expression -> expression LTEQ expression .) + SEMICOLON reduce using rule 37 (expression -> expression LTEQ expression .) + RPAREN reduce using rule 37 (expression -> expression LTEQ expression .) + THEN reduce using rule 37 (expression -> expression LTEQ expression .) + LOOP reduce using rule 37 (expression -> expression LTEQ expression .) + OF reduce using rule 37 (expression -> expression LTEQ expression .) + RBRACE reduce using rule 37 (expression -> expression LTEQ expression .) + COMMA reduce using rule 37 (expression -> expression LTEQ expression .) + ELSE reduce using rule 37 (expression -> expression LTEQ expression .) + POOL reduce using rule 37 (expression -> expression LTEQ expression .) + FI reduce using rule 37 (expression -> expression LTEQ expression .) + IN reduce using rule 37 (expression -> expression LTEQ expression .) + DOT shift and go to state 59 + AT shift and go to state 60 + PLUS shift and go to state 61 + MINUS shift and go to state 62 + MULTIPLY shift and go to state 63 + DIVIDE shift and go to state 64 + + ! DOT [ reduce using rule 37 (expression -> expression LTEQ expression .) ] + ! AT [ reduce using rule 37 (expression -> expression LTEQ expression .) ] + ! PLUS [ reduce using rule 37 (expression -> expression LTEQ expression .) ] + ! MINUS [ reduce using rule 37 (expression -> expression LTEQ expression .) ] + ! MULTIPLY [ reduce using rule 37 (expression -> expression LTEQ expression .) ] + ! DIVIDE [ reduce using rule 37 (expression -> expression LTEQ expression .) ] + ! LT [ shift and go to state 65 ] + ! LTEQ [ shift and go to state 66 ] + ! EQ [ shift and go to state 67 ] + + +state 96 + + (38) expression -> expression EQ expression . + (25) expression -> expression . DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> expression . AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (32) expression -> expression . PLUS expression + (33) expression -> expression . MINUS expression + (34) expression -> expression . MULTIPLY expression + (35) expression -> expression . DIVIDE expression + (36) expression -> expression . LT expression + (37) expression -> expression . LTEQ expression + (38) expression -> expression . EQ expression + + LT reduce using rule 38 (expression -> expression EQ expression .) + LTEQ reduce using rule 38 (expression -> expression EQ expression .) + EQ reduce using rule 38 (expression -> expression EQ expression .) + SEMICOLON reduce using rule 38 (expression -> expression EQ expression .) + RPAREN reduce using rule 38 (expression -> expression EQ expression .) + THEN reduce using rule 38 (expression -> expression EQ expression .) + LOOP reduce using rule 38 (expression -> expression EQ expression .) + OF reduce using rule 38 (expression -> expression EQ expression .) + RBRACE reduce using rule 38 (expression -> expression EQ expression .) + COMMA reduce using rule 38 (expression -> expression EQ expression .) + ELSE reduce using rule 38 (expression -> expression EQ expression .) + POOL reduce using rule 38 (expression -> expression EQ expression .) + FI reduce using rule 38 (expression -> expression EQ expression .) + IN reduce using rule 38 (expression -> expression EQ expression .) + DOT shift and go to state 59 + AT shift and go to state 60 + PLUS shift and go to state 61 + MINUS shift and go to state 62 + MULTIPLY shift and go to state 63 + DIVIDE shift and go to state 64 + + ! DOT [ reduce using rule 38 (expression -> expression EQ expression .) ] + ! AT [ reduce using rule 38 (expression -> expression EQ expression .) ] + ! PLUS [ reduce using rule 38 (expression -> expression EQ expression .) ] + ! MINUS [ reduce using rule 38 (expression -> expression EQ expression .) ] + ! MULTIPLY [ reduce using rule 38 (expression -> expression EQ expression .) ] + ! DIVIDE [ reduce using rule 38 (expression -> expression EQ expression .) ] + ! LT [ shift and go to state 65 ] + ! LTEQ [ shift and go to state 66 ] + ! EQ [ shift and go to state 67 ] + + +state 97 + + (21) expression -> LBRACE block_list RBRACE . + + DOT reduce using rule 21 (expression -> LBRACE block_list RBRACE .) + AT reduce using rule 21 (expression -> LBRACE block_list RBRACE .) + PLUS reduce using rule 21 (expression -> LBRACE block_list RBRACE .) + MINUS reduce using rule 21 (expression -> LBRACE block_list RBRACE .) + MULTIPLY reduce using rule 21 (expression -> LBRACE block_list RBRACE .) + DIVIDE reduce using rule 21 (expression -> LBRACE block_list RBRACE .) + LT reduce using rule 21 (expression -> LBRACE block_list RBRACE .) + LTEQ reduce using rule 21 (expression -> LBRACE block_list RBRACE .) + EQ reduce using rule 21 (expression -> LBRACE block_list RBRACE .) + SEMICOLON reduce using rule 21 (expression -> LBRACE block_list RBRACE .) + RPAREN reduce using rule 21 (expression -> LBRACE block_list RBRACE .) + THEN reduce using rule 21 (expression -> LBRACE block_list RBRACE .) + LOOP reduce using rule 21 (expression -> LBRACE block_list RBRACE .) + OF reduce using rule 21 (expression -> LBRACE block_list RBRACE .) + RBRACE reduce using rule 21 (expression -> LBRACE block_list RBRACE .) + COMMA reduce using rule 21 (expression -> LBRACE block_list RBRACE .) + ELSE reduce using rule 21 (expression -> LBRACE block_list RBRACE .) + POOL reduce using rule 21 (expression -> LBRACE block_list RBRACE .) + FI reduce using rule 21 (expression -> LBRACE block_list RBRACE .) + IN reduce using rule 21 (expression -> LBRACE block_list RBRACE .) + + +state 98 + + (22) block_list -> expression SEMICOLON . block_list + (23) block_list -> expression SEMICOLON . + (22) block_list -> . expression SEMICOLON block_list + (23) block_list -> . expression SEMICOLON + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + RBRACE reduce using rule 23 (block_list -> expression SEMICOLON .) + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 69 + block_list shift and go to state 112 + let_expression shift and go to state 48 + +state 99 + + (39) expression -> LPAREN expression RPAREN . + + DOT reduce using rule 39 (expression -> LPAREN expression RPAREN .) + AT reduce using rule 39 (expression -> LPAREN expression RPAREN .) + PLUS reduce using rule 39 (expression -> LPAREN expression RPAREN .) + MINUS reduce using rule 39 (expression -> LPAREN expression RPAREN .) + MULTIPLY reduce using rule 39 (expression -> LPAREN expression RPAREN .) + DIVIDE reduce using rule 39 (expression -> LPAREN expression RPAREN .) + LT reduce using rule 39 (expression -> LPAREN expression RPAREN .) + LTEQ reduce using rule 39 (expression -> LPAREN expression RPAREN .) + EQ reduce using rule 39 (expression -> LPAREN expression RPAREN .) + SEMICOLON reduce using rule 39 (expression -> LPAREN expression RPAREN .) + RPAREN reduce using rule 39 (expression -> LPAREN expression RPAREN .) + THEN reduce using rule 39 (expression -> LPAREN expression RPAREN .) + LOOP reduce using rule 39 (expression -> LPAREN expression RPAREN .) + OF reduce using rule 39 (expression -> LPAREN expression RPAREN .) + RBRACE reduce using rule 39 (expression -> LPAREN expression RPAREN .) + COMMA reduce using rule 39 (expression -> LPAREN expression RPAREN .) + ELSE reduce using rule 39 (expression -> LPAREN expression RPAREN .) + POOL reduce using rule 39 (expression -> LPAREN expression RPAREN .) + FI reduce using rule 39 (expression -> LPAREN expression RPAREN .) + IN reduce using rule 39 (expression -> LPAREN expression RPAREN .) + + +state 100 + + (40) expression -> IF expression THEN . expression ELSE expression FI + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 113 + let_expression shift and go to state 48 + +state 101 + + (41) expression -> WHILE expression LOOP . expression POOL + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 114 + let_expression shift and go to state 48 + +state 102 + + (48) expression -> CASE expression OF . actions_list ESAC + (49) actions_list -> . action actions_list + (50) actions_list -> . action + (51) action -> . ID COLON TYPE ARROW expression SEMICOLON + + ID shift and go to state 117 + + actions_list shift and go to state 115 + action shift and go to state 116 + +state 103 + + (43) let_expression -> LET formal_list IN . expression + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 118 + let_expression shift and go to state 48 + +state 104 + + (44) formal_list -> formal_list COMMA . formal + (46) formal -> . ID COLON TYPE + (47) formal -> . ID COLON TYPE ASSIGN expression + + ID shift and go to state 80 + + formal shift and go to state 119 + +state 105 + + (46) formal -> ID COLON . TYPE + (47) formal -> ID COLON . TYPE ASSIGN expression + + TYPE shift and go to state 120 + + +state 106 + + (10) feature -> ID LPAREN formal_params_list RPAREN COLON TYPE LBRACE expression . RBRACE + (25) expression -> expression . DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> expression . AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (32) expression -> expression . PLUS expression + (33) expression -> expression . MINUS expression + (34) expression -> expression . MULTIPLY expression + (35) expression -> expression . DIVIDE expression + (36) expression -> expression . LT expression + (37) expression -> expression . LTEQ expression + (38) expression -> expression . EQ expression + + RBRACE shift and go to state 121 + DOT shift and go to state 59 + AT shift and go to state 60 + PLUS shift and go to state 61 + MINUS shift and go to state 62 + MULTIPLY shift and go to state 63 + DIVIDE shift and go to state 64 + LT shift and go to state 65 + LTEQ shift and go to state 66 + EQ shift and go to state 67 + + +state 107 + + (11) feature -> ID LPAREN RPAREN COLON TYPE LBRACE expression RBRACE . + + SEMICOLON reduce using rule 11 (feature -> ID LPAREN RPAREN COLON TYPE LBRACE expression RBRACE .) + + +state 108 + + (31) expression -> ID LPAREN arguments_list_opt RPAREN . + + DOT reduce using rule 31 (expression -> ID LPAREN arguments_list_opt RPAREN .) + AT reduce using rule 31 (expression -> ID LPAREN arguments_list_opt RPAREN .) + PLUS reduce using rule 31 (expression -> ID LPAREN arguments_list_opt RPAREN .) + MINUS reduce using rule 31 (expression -> ID LPAREN arguments_list_opt RPAREN .) + MULTIPLY reduce using rule 31 (expression -> ID LPAREN arguments_list_opt RPAREN .) + DIVIDE reduce using rule 31 (expression -> ID LPAREN arguments_list_opt RPAREN .) + LT reduce using rule 31 (expression -> ID LPAREN arguments_list_opt RPAREN .) + LTEQ reduce using rule 31 (expression -> ID LPAREN arguments_list_opt RPAREN .) + EQ reduce using rule 31 (expression -> ID LPAREN arguments_list_opt RPAREN .) + SEMICOLON reduce using rule 31 (expression -> ID LPAREN arguments_list_opt RPAREN .) + RPAREN reduce using rule 31 (expression -> ID LPAREN arguments_list_opt RPAREN .) + THEN reduce using rule 31 (expression -> ID LPAREN arguments_list_opt RPAREN .) + LOOP reduce using rule 31 (expression -> ID LPAREN arguments_list_opt RPAREN .) + OF reduce using rule 31 (expression -> ID LPAREN arguments_list_opt RPAREN .) + RBRACE reduce using rule 31 (expression -> ID LPAREN arguments_list_opt RPAREN .) + COMMA reduce using rule 31 (expression -> ID LPAREN arguments_list_opt RPAREN .) + ELSE reduce using rule 31 (expression -> ID LPAREN arguments_list_opt RPAREN .) + POOL reduce using rule 31 (expression -> ID LPAREN arguments_list_opt RPAREN .) + FI reduce using rule 31 (expression -> ID LPAREN arguments_list_opt RPAREN .) + IN reduce using rule 31 (expression -> ID LPAREN arguments_list_opt RPAREN .) + + +state 109 + + (28) arguments_list -> expression COMMA . arguments_list + (28) arguments_list -> . expression COMMA arguments_list + (29) arguments_list -> . expression + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 87 + arguments_list shift and go to state 122 + let_expression shift and go to state 48 + +state 110 + + (25) expression -> expression DOT ID LPAREN . arguments_list_opt RPAREN + (26) arguments_list_opt -> . arguments_list + (27) arguments_list_opt -> . empty + (28) arguments_list -> . expression COMMA arguments_list + (29) arguments_list -> . expression + (56) empty -> . + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + RPAREN reduce using rule 56 (empty -> .) + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 87 + arguments_list_opt shift and go to state 123 + arguments_list shift and go to state 85 + empty shift and go to state 86 + let_expression shift and go to state 48 + +state 111 + + (30) expression -> expression AT TYPE DOT . ID LPAREN arguments_list_opt RPAREN + + ID shift and go to state 124 + + +state 112 + + (22) block_list -> expression SEMICOLON block_list . + + RBRACE reduce using rule 22 (block_list -> expression SEMICOLON block_list .) + + +state 113 + + (40) expression -> IF expression THEN expression . ELSE expression FI + (25) expression -> expression . DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> expression . AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (32) expression -> expression . PLUS expression + (33) expression -> expression . MINUS expression + (34) expression -> expression . MULTIPLY expression + (35) expression -> expression . DIVIDE expression + (36) expression -> expression . LT expression + (37) expression -> expression . LTEQ expression + (38) expression -> expression . EQ expression + + ELSE shift and go to state 125 + DOT shift and go to state 59 + AT shift and go to state 60 + PLUS shift and go to state 61 + MINUS shift and go to state 62 + MULTIPLY shift and go to state 63 + DIVIDE shift and go to state 64 + LT shift and go to state 65 + LTEQ shift and go to state 66 + EQ shift and go to state 67 + + +state 114 + + (41) expression -> WHILE expression LOOP expression . POOL + (25) expression -> expression . DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> expression . AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (32) expression -> expression . PLUS expression + (33) expression -> expression . MINUS expression + (34) expression -> expression . MULTIPLY expression + (35) expression -> expression . DIVIDE expression + (36) expression -> expression . LT expression + (37) expression -> expression . LTEQ expression + (38) expression -> expression . EQ expression + + POOL shift and go to state 126 + DOT shift and go to state 59 + AT shift and go to state 60 + PLUS shift and go to state 61 + MINUS shift and go to state 62 + MULTIPLY shift and go to state 63 + DIVIDE shift and go to state 64 + LT shift and go to state 65 + LTEQ shift and go to state 66 + EQ shift and go to state 67 + + +state 115 + + (48) expression -> CASE expression OF actions_list . ESAC + + ESAC shift and go to state 127 + + +state 116 + + (49) actions_list -> action . actions_list + (50) actions_list -> action . + (49) actions_list -> . action actions_list + (50) actions_list -> . action + (51) action -> . ID COLON TYPE ARROW expression SEMICOLON + + ESAC reduce using rule 50 (actions_list -> action .) + ID shift and go to state 117 + + action shift and go to state 116 + actions_list shift and go to state 128 + +state 117 + + (51) action -> ID . COLON TYPE ARROW expression SEMICOLON + + COLON shift and go to state 129 + + +state 118 + + (43) let_expression -> LET formal_list IN expression . + (25) expression -> expression . DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> expression . AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (32) expression -> expression . PLUS expression + (33) expression -> expression . MINUS expression + (34) expression -> expression . MULTIPLY expression + (35) expression -> expression . DIVIDE expression + (36) expression -> expression . LT expression + (37) expression -> expression . LTEQ expression + (38) expression -> expression . EQ expression + + ! shift/reduce conflict for DOT resolved as shift + ! shift/reduce conflict for AT resolved as shift + ! shift/reduce conflict for PLUS resolved as shift + ! shift/reduce conflict for MINUS resolved as shift + ! shift/reduce conflict for MULTIPLY resolved as shift + ! shift/reduce conflict for DIVIDE resolved as shift + ! shift/reduce conflict for LT resolved as shift + ! shift/reduce conflict for LTEQ resolved as shift + ! shift/reduce conflict for EQ resolved as shift + SEMICOLON reduce using rule 43 (let_expression -> LET formal_list IN expression .) + RPAREN reduce using rule 43 (let_expression -> LET formal_list IN expression .) + THEN reduce using rule 43 (let_expression -> LET formal_list IN expression .) + LOOP reduce using rule 43 (let_expression -> LET formal_list IN expression .) + OF reduce using rule 43 (let_expression -> LET formal_list IN expression .) + RBRACE reduce using rule 43 (let_expression -> LET formal_list IN expression .) + COMMA reduce using rule 43 (let_expression -> LET formal_list IN expression .) + ELSE reduce using rule 43 (let_expression -> LET formal_list IN expression .) + POOL reduce using rule 43 (let_expression -> LET formal_list IN expression .) + FI reduce using rule 43 (let_expression -> LET formal_list IN expression .) + IN reduce using rule 43 (let_expression -> LET formal_list IN expression .) + DOT shift and go to state 59 + AT shift and go to state 60 + PLUS shift and go to state 61 + MINUS shift and go to state 62 + MULTIPLY shift and go to state 63 + DIVIDE shift and go to state 64 + LT shift and go to state 65 + LTEQ shift and go to state 66 + EQ shift and go to state 67 + + ! DOT [ reduce using rule 43 (let_expression -> LET formal_list IN expression .) ] + ! AT [ reduce using rule 43 (let_expression -> LET formal_list IN expression .) ] + ! PLUS [ reduce using rule 43 (let_expression -> LET formal_list IN expression .) ] + ! MINUS [ reduce using rule 43 (let_expression -> LET formal_list IN expression .) ] + ! MULTIPLY [ reduce using rule 43 (let_expression -> LET formal_list IN expression .) ] + ! DIVIDE [ reduce using rule 43 (let_expression -> LET formal_list IN expression .) ] + ! LT [ reduce using rule 43 (let_expression -> LET formal_list IN expression .) ] + ! LTEQ [ reduce using rule 43 (let_expression -> LET formal_list IN expression .) ] + ! EQ [ reduce using rule 43 (let_expression -> LET formal_list IN expression .) ] + + +state 119 + + (44) formal_list -> formal_list COMMA formal . + + IN reduce using rule 44 (formal_list -> formal_list COMMA formal .) + COMMA reduce using rule 44 (formal_list -> formal_list COMMA formal .) + + +state 120 + + (46) formal -> ID COLON TYPE . + (47) formal -> ID COLON TYPE . ASSIGN expression + + IN reduce using rule 46 (formal -> ID COLON TYPE .) + COMMA reduce using rule 46 (formal -> ID COLON TYPE .) + ASSIGN shift and go to state 130 + + +state 121 + + (10) feature -> ID LPAREN formal_params_list RPAREN COLON TYPE LBRACE expression RBRACE . + + SEMICOLON reduce using rule 10 (feature -> ID LPAREN formal_params_list RPAREN COLON TYPE LBRACE expression RBRACE .) + + +state 122 + + (28) arguments_list -> expression COMMA arguments_list . + + RPAREN reduce using rule 28 (arguments_list -> expression COMMA arguments_list .) + + +state 123 + + (25) expression -> expression DOT ID LPAREN arguments_list_opt . RPAREN + + RPAREN shift and go to state 131 + + +state 124 + + (30) expression -> expression AT TYPE DOT ID . LPAREN arguments_list_opt RPAREN + + LPAREN shift and go to state 132 + + +state 125 + + (40) expression -> IF expression THEN expression ELSE . expression FI + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 133 + let_expression shift and go to state 48 + +state 126 + + (41) expression -> WHILE expression LOOP expression POOL . + + DOT reduce using rule 41 (expression -> WHILE expression LOOP expression POOL .) + AT reduce using rule 41 (expression -> WHILE expression LOOP expression POOL .) + PLUS reduce using rule 41 (expression -> WHILE expression LOOP expression POOL .) + MINUS reduce using rule 41 (expression -> WHILE expression LOOP expression POOL .) + MULTIPLY reduce using rule 41 (expression -> WHILE expression LOOP expression POOL .) + DIVIDE reduce using rule 41 (expression -> WHILE expression LOOP expression POOL .) + LT reduce using rule 41 (expression -> WHILE expression LOOP expression POOL .) + LTEQ reduce using rule 41 (expression -> WHILE expression LOOP expression POOL .) + EQ reduce using rule 41 (expression -> WHILE expression LOOP expression POOL .) + SEMICOLON reduce using rule 41 (expression -> WHILE expression LOOP expression POOL .) + RPAREN reduce using rule 41 (expression -> WHILE expression LOOP expression POOL .) + THEN reduce using rule 41 (expression -> WHILE expression LOOP expression POOL .) + LOOP reduce using rule 41 (expression -> WHILE expression LOOP expression POOL .) + OF reduce using rule 41 (expression -> WHILE expression LOOP expression POOL .) + RBRACE reduce using rule 41 (expression -> WHILE expression LOOP expression POOL .) + COMMA reduce using rule 41 (expression -> WHILE expression LOOP expression POOL .) + ELSE reduce using rule 41 (expression -> WHILE expression LOOP expression POOL .) + POOL reduce using rule 41 (expression -> WHILE expression LOOP expression POOL .) + FI reduce using rule 41 (expression -> WHILE expression LOOP expression POOL .) + IN reduce using rule 41 (expression -> WHILE expression LOOP expression POOL .) + + +state 127 + + (48) expression -> CASE expression OF actions_list ESAC . + + DOT reduce using rule 48 (expression -> CASE expression OF actions_list ESAC .) + AT reduce using rule 48 (expression -> CASE expression OF actions_list ESAC .) + PLUS reduce using rule 48 (expression -> CASE expression OF actions_list ESAC .) + MINUS reduce using rule 48 (expression -> CASE expression OF actions_list ESAC .) + MULTIPLY reduce using rule 48 (expression -> CASE expression OF actions_list ESAC .) + DIVIDE reduce using rule 48 (expression -> CASE expression OF actions_list ESAC .) + LT reduce using rule 48 (expression -> CASE expression OF actions_list ESAC .) + LTEQ reduce using rule 48 (expression -> CASE expression OF actions_list ESAC .) + EQ reduce using rule 48 (expression -> CASE expression OF actions_list ESAC .) + SEMICOLON reduce using rule 48 (expression -> CASE expression OF actions_list ESAC .) + RPAREN reduce using rule 48 (expression -> CASE expression OF actions_list ESAC .) + THEN reduce using rule 48 (expression -> CASE expression OF actions_list ESAC .) + LOOP reduce using rule 48 (expression -> CASE expression OF actions_list ESAC .) + OF reduce using rule 48 (expression -> CASE expression OF actions_list ESAC .) + RBRACE reduce using rule 48 (expression -> CASE expression OF actions_list ESAC .) + COMMA reduce using rule 48 (expression -> CASE expression OF actions_list ESAC .) + ELSE reduce using rule 48 (expression -> CASE expression OF actions_list ESAC .) + POOL reduce using rule 48 (expression -> CASE expression OF actions_list ESAC .) + FI reduce using rule 48 (expression -> CASE expression OF actions_list ESAC .) + IN reduce using rule 48 (expression -> CASE expression OF actions_list ESAC .) + + +state 128 + + (49) actions_list -> action actions_list . + + ESAC reduce using rule 49 (actions_list -> action actions_list .) + + +state 129 + + (51) action -> ID COLON . TYPE ARROW expression SEMICOLON + + TYPE shift and go to state 134 + + +state 130 + + (47) formal -> ID COLON TYPE ASSIGN . expression + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 135 + let_expression shift and go to state 48 + +state 131 + + (25) expression -> expression DOT ID LPAREN arguments_list_opt RPAREN . + + DOT reduce using rule 25 (expression -> expression DOT ID LPAREN arguments_list_opt RPAREN .) + AT reduce using rule 25 (expression -> expression DOT ID LPAREN arguments_list_opt RPAREN .) + PLUS reduce using rule 25 (expression -> expression DOT ID LPAREN arguments_list_opt RPAREN .) + MINUS reduce using rule 25 (expression -> expression DOT ID LPAREN arguments_list_opt RPAREN .) + MULTIPLY reduce using rule 25 (expression -> expression DOT ID LPAREN arguments_list_opt RPAREN .) + DIVIDE reduce using rule 25 (expression -> expression DOT ID LPAREN arguments_list_opt RPAREN .) + LT reduce using rule 25 (expression -> expression DOT ID LPAREN arguments_list_opt RPAREN .) + LTEQ reduce using rule 25 (expression -> expression DOT ID LPAREN arguments_list_opt RPAREN .) + EQ reduce using rule 25 (expression -> expression DOT ID LPAREN arguments_list_opt RPAREN .) + SEMICOLON reduce using rule 25 (expression -> expression DOT ID LPAREN arguments_list_opt RPAREN .) + RPAREN reduce using rule 25 (expression -> expression DOT ID LPAREN arguments_list_opt RPAREN .) + THEN reduce using rule 25 (expression -> expression DOT ID LPAREN arguments_list_opt RPAREN .) + LOOP reduce using rule 25 (expression -> expression DOT ID LPAREN arguments_list_opt RPAREN .) + OF reduce using rule 25 (expression -> expression DOT ID LPAREN arguments_list_opt RPAREN .) + RBRACE reduce using rule 25 (expression -> expression DOT ID LPAREN arguments_list_opt RPAREN .) + COMMA reduce using rule 25 (expression -> expression DOT ID LPAREN arguments_list_opt RPAREN .) + ELSE reduce using rule 25 (expression -> expression DOT ID LPAREN arguments_list_opt RPAREN .) + POOL reduce using rule 25 (expression -> expression DOT ID LPAREN arguments_list_opt RPAREN .) + FI reduce using rule 25 (expression -> expression DOT ID LPAREN arguments_list_opt RPAREN .) + IN reduce using rule 25 (expression -> expression DOT ID LPAREN arguments_list_opt RPAREN .) + + +state 132 + + (30) expression -> expression AT TYPE DOT ID LPAREN . arguments_list_opt RPAREN + (26) arguments_list_opt -> . arguments_list + (27) arguments_list_opt -> . empty + (28) arguments_list -> . expression COMMA arguments_list + (29) arguments_list -> . expression + (56) empty -> . + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + RPAREN reduce using rule 56 (empty -> .) + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 87 + arguments_list_opt shift and go to state 136 + arguments_list shift and go to state 85 + empty shift and go to state 86 + let_expression shift and go to state 48 + +state 133 + + (40) expression -> IF expression THEN expression ELSE expression . FI + (25) expression -> expression . DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> expression . AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (32) expression -> expression . PLUS expression + (33) expression -> expression . MINUS expression + (34) expression -> expression . MULTIPLY expression + (35) expression -> expression . DIVIDE expression + (36) expression -> expression . LT expression + (37) expression -> expression . LTEQ expression + (38) expression -> expression . EQ expression + + FI shift and go to state 137 + DOT shift and go to state 59 + AT shift and go to state 60 + PLUS shift and go to state 61 + MINUS shift and go to state 62 + MULTIPLY shift and go to state 63 + DIVIDE shift and go to state 64 + LT shift and go to state 65 + LTEQ shift and go to state 66 + EQ shift and go to state 67 + + +state 134 + + (51) action -> ID COLON TYPE . ARROW expression SEMICOLON + + ARROW shift and go to state 138 + + +state 135 + + (47) formal -> ID COLON TYPE ASSIGN expression . + (25) expression -> expression . DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> expression . AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (32) expression -> expression . PLUS expression + (33) expression -> expression . MINUS expression + (34) expression -> expression . MULTIPLY expression + (35) expression -> expression . DIVIDE expression + (36) expression -> expression . LT expression + (37) expression -> expression . LTEQ expression + (38) expression -> expression . EQ expression + + IN reduce using rule 47 (formal -> ID COLON TYPE ASSIGN expression .) + COMMA reduce using rule 47 (formal -> ID COLON TYPE ASSIGN expression .) + DOT shift and go to state 59 + AT shift and go to state 60 + PLUS shift and go to state 61 + MINUS shift and go to state 62 + MULTIPLY shift and go to state 63 + DIVIDE shift and go to state 64 + LT shift and go to state 65 + LTEQ shift and go to state 66 + EQ shift and go to state 67 + + +state 136 + + (30) expression -> expression AT TYPE DOT ID LPAREN arguments_list_opt . RPAREN + + RPAREN shift and go to state 139 + + +state 137 + + (40) expression -> IF expression THEN expression ELSE expression FI . + + DOT reduce using rule 40 (expression -> IF expression THEN expression ELSE expression FI .) + AT reduce using rule 40 (expression -> IF expression THEN expression ELSE expression FI .) + PLUS reduce using rule 40 (expression -> IF expression THEN expression ELSE expression FI .) + MINUS reduce using rule 40 (expression -> IF expression THEN expression ELSE expression FI .) + MULTIPLY reduce using rule 40 (expression -> IF expression THEN expression ELSE expression FI .) + DIVIDE reduce using rule 40 (expression -> IF expression THEN expression ELSE expression FI .) + LT reduce using rule 40 (expression -> IF expression THEN expression ELSE expression FI .) + LTEQ reduce using rule 40 (expression -> IF expression THEN expression ELSE expression FI .) + EQ reduce using rule 40 (expression -> IF expression THEN expression ELSE expression FI .) + SEMICOLON reduce using rule 40 (expression -> IF expression THEN expression ELSE expression FI .) + RPAREN reduce using rule 40 (expression -> IF expression THEN expression ELSE expression FI .) + THEN reduce using rule 40 (expression -> IF expression THEN expression ELSE expression FI .) + LOOP reduce using rule 40 (expression -> IF expression THEN expression ELSE expression FI .) + OF reduce using rule 40 (expression -> IF expression THEN expression ELSE expression FI .) + RBRACE reduce using rule 40 (expression -> IF expression THEN expression ELSE expression FI .) + COMMA reduce using rule 40 (expression -> IF expression THEN expression ELSE expression FI .) + ELSE reduce using rule 40 (expression -> IF expression THEN expression ELSE expression FI .) + POOL reduce using rule 40 (expression -> IF expression THEN expression ELSE expression FI .) + FI reduce using rule 40 (expression -> IF expression THEN expression ELSE expression FI .) + IN reduce using rule 40 (expression -> IF expression THEN expression ELSE expression FI .) + + +state 138 + + (51) action -> ID COLON TYPE ARROW . expression SEMICOLON + (17) expression -> . ID + (18) expression -> . INTEGER + (19) expression -> . BOOLEAN + (20) expression -> . STRING + (21) expression -> . LBRACE block_list RBRACE + (24) expression -> . ID ASSIGN expression + (25) expression -> . expression DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> . expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (31) expression -> . ID LPAREN arguments_list_opt RPAREN + (32) expression -> . expression PLUS expression + (33) expression -> . expression MINUS expression + (34) expression -> . expression MULTIPLY expression + (35) expression -> . expression DIVIDE expression + (36) expression -> . expression LT expression + (37) expression -> . expression LTEQ expression + (38) expression -> . expression EQ expression + (39) expression -> . LPAREN expression RPAREN + (40) expression -> . IF expression THEN expression ELSE expression FI + (41) expression -> . WHILE expression LOOP expression POOL + (42) expression -> . let_expression + (48) expression -> . CASE expression OF actions_list ESAC + (52) expression -> . NEW TYPE + (53) expression -> . ISVOID expression + (54) expression -> . INT_COMP expression + (55) expression -> . NOT expression + (43) let_expression -> . LET formal_list IN expression + + ID shift and go to state 39 + INTEGER shift and go to state 41 + BOOLEAN shift and go to state 42 + STRING shift and go to state 43 + LBRACE shift and go to state 44 + LPAREN shift and go to state 45 + IF shift and go to state 46 + WHILE shift and go to state 47 + CASE shift and go to state 49 + NEW shift and go to state 50 + ISVOID shift and go to state 51 + INT_COMP shift and go to state 52 + NOT shift and go to state 53 + LET shift and go to state 54 + + expression shift and go to state 140 + let_expression shift and go to state 48 + +state 139 + + (30) expression -> expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN . + + DOT reduce using rule 30 (expression -> expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN .) + AT reduce using rule 30 (expression -> expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN .) + PLUS reduce using rule 30 (expression -> expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN .) + MINUS reduce using rule 30 (expression -> expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN .) + MULTIPLY reduce using rule 30 (expression -> expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN .) + DIVIDE reduce using rule 30 (expression -> expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN .) + LT reduce using rule 30 (expression -> expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN .) + LTEQ reduce using rule 30 (expression -> expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN .) + EQ reduce using rule 30 (expression -> expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN .) + SEMICOLON reduce using rule 30 (expression -> expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN .) + RPAREN reduce using rule 30 (expression -> expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN .) + THEN reduce using rule 30 (expression -> expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN .) + LOOP reduce using rule 30 (expression -> expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN .) + OF reduce using rule 30 (expression -> expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN .) + RBRACE reduce using rule 30 (expression -> expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN .) + COMMA reduce using rule 30 (expression -> expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN .) + ELSE reduce using rule 30 (expression -> expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN .) + POOL reduce using rule 30 (expression -> expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN .) + FI reduce using rule 30 (expression -> expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN .) + IN reduce using rule 30 (expression -> expression AT TYPE DOT ID LPAREN arguments_list_opt RPAREN .) + + +state 140 + + (51) action -> ID COLON TYPE ARROW expression . SEMICOLON + (25) expression -> expression . DOT ID LPAREN arguments_list_opt RPAREN + (30) expression -> expression . AT TYPE DOT ID LPAREN arguments_list_opt RPAREN + (32) expression -> expression . PLUS expression + (33) expression -> expression . MINUS expression + (34) expression -> expression . MULTIPLY expression + (35) expression -> expression . DIVIDE expression + (36) expression -> expression . LT expression + (37) expression -> expression . LTEQ expression + (38) expression -> expression . EQ expression + + SEMICOLON shift and go to state 141 + DOT shift and go to state 59 + AT shift and go to state 60 + PLUS shift and go to state 61 + MINUS shift and go to state 62 + MULTIPLY shift and go to state 63 + DIVIDE shift and go to state 64 + LT shift and go to state 65 + LTEQ shift and go to state 66 + EQ shift and go to state 67 + + +state 141 + + (51) action -> ID COLON TYPE ARROW expression SEMICOLON . + + ID reduce using rule 51 (action -> ID COLON TYPE ARROW expression SEMICOLON .) + ESAC reduce using rule 51 (action -> ID COLON TYPE ARROW expression SEMICOLON .) + +WARNING: +WARNING: Conflicts: +WARNING: +WARNING: shift/reduce conflict for DOT in state 118 resolved as shift +WARNING: shift/reduce conflict for AT in state 118 resolved as shift +WARNING: shift/reduce conflict for PLUS in state 118 resolved as shift +WARNING: shift/reduce conflict for MINUS in state 118 resolved as shift +WARNING: shift/reduce conflict for MULTIPLY in state 118 resolved as shift +WARNING: shift/reduce conflict for DIVIDE in state 118 resolved as shift +WARNING: shift/reduce conflict for LT in state 118 resolved as shift +WARNING: shift/reduce conflict for LTEQ in state 118 resolved as shift +WARNING: shift/reduce conflict for EQ in state 118 resolved as shift +WARNING: reduce/reduce conflict in state 12 resolved using rule (features_list_opt -> empty) +WARNING: rejected rule (features_list -> empty) in state 12 diff --git a/src/Compiler/Semantic/Semantic.py b/src/Compiler/Semantic/Semantic.py new file mode 100644 index 000000000..3a18007ac --- /dev/null +++ b/src/Compiler/Semantic/Semantic.py @@ -0,0 +1,1036 @@ +from Semantic.types import cyclic_inheritance +from Semantic.scope import COOL_Scope +from Semantic.errors_types import * +from Semantic import visitor +from Parser import ast +import sys + +class COOL_Semantic_Checker: + + def __init__(self): + self.errors = False + + @visitor.on('node') + def visit(self, node, scope): + pass + + + @visitor.when(ast.Program) + def visit(self, node : ast.Program, scope_root = None): + """ + node.classes -> [ Class ... ] + """ + scope_root = COOL_Scope(None, None) + + for _class in node.classes: + if not scope_root.set_type(_class.name): + sys.stdout.write(f'({_class.lineno}, {_class.linepos}) - {SEMERROR2 % _class.name}\n') + self.errors = True + return None + COOL_Scope(_class.name, scope_root) + + for (_class, _scope) in zip(node.classes, scope_root.children): + if not _class.parent is None and _scope.get_type(_class.parent) is None: + sys.stdout.write(f'({_class.lineno}, {_class.linepos}) - {TYPERROR14 % (_class.name, _class.parent)}\n') + self.errors = True + return None + elif _class.parent in _scope.ctype.not_inherits_type: + sys.stdout.write(f'({_class.lineno}, {_class.linepos}) - {SEMERROR3 % (_class.name, _class.parent)}\n') + self.errors = True + return None + else: + parent = _scope.ctype.OBJECT if _class.parent is None else _scope.get_type(_class.parent) + _scope.ctype.defined_types[_class.name].parent = parent + if cyclic_inheritance(_scope.get_type(_class.name)): + sys.stdout.write(f'({_class.lineno}, {_class.linepos}) - {SEMERROR6 % (_class.name, _class.name)}\n') + self.errors = True + return None + + for (_class, _scope) in zip(node.classes, scope_root.children): + for _method in _class.features: + if type(_method) is ast.ClassMethod: + if _scope.get_var(_class.name, _method.name) == _scope.ctype.SELF: + sys.stdout.write(f'({_method.lineno}, {_method.linepos}) - {SEMERROR12 % "a method"}\n') + self.errors = True + return None + + return_type = _scope.get_type(_method.return_type) + + if return_type is None: + sys.stdout.write(f'({_method.lineno}, {_method.linepos}) - {TYPERROR11 % _method.return_type}\n') + self.errors = True + return None + + func = {'formal_params':{}, 'return_type': return_type} + for param in _method.formal_params: + func['formal_params'][param.name] = _scope.get_type(param.param_type) + + ret = _scope.get_type(_class.name).add_func(_method.name, func) + if ret is None: + sys.stdout.write(f'({_method.lineno}, {_method.linepos}) - {SEMERROR8 % _method.name}\n') + self.errors = True + return None + + if not ret: + sys.stdout.write(f'({_method.lineno}, {_method.linepos}) - {SEMERROR5 % _method.name}\n') + self.errors = True + return None + + else: + if _scope.get_var(_class.name, _method.name) == _scope.ctype.SELF: + sys.stdout.write(f'({_method.lineno}, {_method.linepos}) - {SEMERROR12 % "an attribute"}\n') + self.errors = True + return None + + attr_type = _scope.get_type(_method.attr_type) + + if attr_type is None: + sys.stdout.write(f'({_method.lineno}, {_method.linepos}) - {TYPERROR11 % _method.attr_type}\n') + self.errors = True + return None + + ret = _scope.get_type(_class.name).add_attr(_method.name, attr_type, _method.init_expr) + if ret is None: + sys.stdout.write(f'({_method.lineno}, {_method.linepos}) - {SEMERROR9 % _method.name}\n') + self.errors = True + return None + + if not ret: + sys.stdout.write(f'({_method.lineno}, {_method.linepos}) - {SEMERROR4 % _method.name}\n') + self.errors = True + return None + + for _class1 in node.classes: + for _class2 in node.classes: + if _class2.name == _class1.parent: + _class1.parent = _class2 + + for (_class, _scope) in zip(node.classes, scope_root.children): + if self.visit(_class, _scope) is None: + return None + + return scope_root + + + @visitor.when(ast.Class) + def visit(self, node, scope): + """ + node.name -> str + node.parent -> Class + node.features -> [ ClassMethod/ClassAttribute ... ] + """ + for meth in node.features: + if self.visit(meth, COOL_Scope(node.name, scope)) is None: + return None + return node + + + @visitor.when(ast.ClassMethod) + def visit(self, node, scope): + """ + node.name -> str + node.formal_params -> [ FormalParameter ... ] + node.return_type -> str + node.body -> Expr + """ + return_type = scope.get_type(node.return_type) + + for param in node.formal_params: + if scope.get_var(scope.classname, param.name) == scope.ctype.SELF: + sys.stdout.write(f'({param.lineno}, {param.linepos}) - {SEMERROR12 % "a formal parameter"}\n') + self.errors = True + return None + if self.visit(param, scope) is None: + return None + + body_type = scope.get_type(self.visit(node.body, scope)) + + if body_type is None: + return None + + if body_type == scope.ctype.SELF or return_type == scope.ctype.SELF: + if body_type != scope.ctype.SELF: + return_type = scope.get_type(scope.classname) + elif return_type != scope.ctype.SELF: + body_type = scope.get_type(scope.classname) + + if not (body_type <= return_type): + sys.stdout.write(f'({node.body.lineno}, {node.body.linepos}) - {TYPERROR13 % (body_type, node.name, return_type)}\n') + self.errors = True + return None + + node.static_type = return_type + return return_type + + + @visitor.when(ast.ClassAttribute) + def visit(self, node, scope): + """ + node.name -> str + node.attr_type -> str + node.init_expr -> Expr + """ + attr_type = scope.get_type(node.attr_type) + + if not node.init_expr is None: + expr_type = scope.get_type(self.visit(node.init_expr, scope)) + + if expr_type is None: + if not self.errors: + sys.stdout.write(f'({node.init_expr.lineno}, {node.init_expr.linepos}) - {NAMERROR1 % node.init_expr.name}\n') + self.errors = True + return None + + if expr_type == scope.ctype.SELF or attr_type == scope.ctype.SELF: + if expr_type != scope.ctype.SELF: + attr_type = scope.get_type(scope.classname) + elif attr_type != scope.ctype.SELF: + expr_type = scope.get_type(scope.classname) + + if expr_type == scope.ctype.VOID: + sys.stdout.write(f'({node.init_expr.lineno}, {node.init_expr.linepos}) - {RNTERROR1}\n') + self.errors = True + return None + + if not (expr_type <= attr_type): + sys.stdout.write(f'({node.init_expr.lineno}, {node.init_expr.linepos}) - {TYPERROR12 % (expr_type, node.name, attr_type)}\n') + self.errors = True + return None + + node.static_type = attr_type + return attr_type + + + @visitor.when(ast.FormalParameter) + def visit(self, node, scope): + """ + node.name -> str + node.param_type -> str + """ + param_type = scope.get_type(node.param_type) + if param_type is None: + sys.stdout.write(f'({node.lineno}, {node.linepos}) - {TYPERROR11 % node.param_type}\n') + self.errors = True + return None + + if not scope.define_new_symbol(node.name, param_type): + sys.stdout.write(f'({node.lineno}, {node.linepos}) - {SEMERROR4 % node.name}\n') + self.errors = True + return None + + node.static_type = param_type + return param_type + + + @visitor.when(ast.Formal) + def visit(self, node, scope): + """ + node.name -> str + node.param_type -> str + node.init_expr -> Expr/None + """ + param_type = scope.get_type(node.param_type) + if param_type is None: + sys.stdout.write(f'({node.lineno}, {node.linepos}) - {TYPERROR11 % node.param_type}\n') + self.errors = True + return None + + if not scope.define_new_symbol(node.name, param_type, True): + sys.stdout.write(f'({node.lineno}, {node.linepos}) - {SEMERROR4 % node.name}\n') + self.errors = True + return None + + if not node.init_expr is None: + expr_type = scope.get_type(self.visit(node.init_expr, scope)) + + if expr_type is None: + if not self.errors: + sys.stdout.write(f'({node.init_expr.lineno}, {node.init_expr.linepos}) - {NAMERROR1 % node.init_expr.name}\n') + self.errors = True + return None + + if expr_type == scope.ctype.VOID: + sys.stdout.write(f'({node.init_expr.lineno}, {node.init_expr.linepos}) - {RNTERROR1}\n') + self.errors = True + return None + + if expr_type == scope.ctype.SELF or param_type == scope.ctype.SELF: + if expr_type != scope.ctype.SELF: + param_type = scope.get_type(scope.classname) + elif param_type != scope.ctype.SELF: + expr_type = scope.get_type(scope.classname) + + if not (expr_type <= param_type): + sys.stdout.write(f'({node.init_expr.lineno}, {node.init_expr.linepos}) - {TYPERROR16 % (expr_type, node.name, param_type)}\n') + self.errors = True + return None + + node.static_type = param_type + return param_type + + + @visitor.when(ast.Object) + def visit(self, node, scope): + """ + node.name -> str + """ + obj_type = scope.get_var(scope.classname, node.name) + + if obj_type is None: + return None + + node.static_type = obj_type + return obj_type + + + @visitor.when(ast.Self) + def visit(self, node, scope): + return_type = scope.ctype.SELF + node.static_type = return_type + return return_type + + + @visitor.when(ast.Integer) + def visit(self, node, scope): + """ + node.content -> int + """ + return_type = scope.ctype.INT + node.static_type = return_type + return return_type + + + @visitor.when(ast.String) + def visit(self, node, scope): + """ + node.content -> str + """ + return_type = scope.ctype.STRING + node.static_type = return_type + return return_type + + + @visitor.when(ast.Boolean) + def visit(self, node, scope): + """ + node.content -> bool + """ + return_type = scope.ctype.BOOL + node.static_type = return_type + return return_type + + + @visitor.when(ast.NewObject) + def visit(self, node, scope): + """ + node.type -> int + """ + new_type = scope.get_type(node.type) + + if new_type is None: + sys.stdout.write(f'({node.lineno}, {node.linepos}) - {TYPERROR10 % node.type}\n') + self.errors = True + return None + + node.static_type = new_type + return new_type + + + @visitor.when(ast.IsVoid) + def visit(self, node, scope): + """ + node.expr -> Expr + """ + if self.visit(node.expr, scope) is None: + if not self.errors: + sys.stdout.write(f'({node.expr.lineno}, {node.expr.linepos}) - {NAMERROR1 % node.expr.name}\n') + self.errors = True + return None + + node.static_type = scope.ctype.BOOL + return node.static_type + + + @visitor.when(ast.Assignment) + def visit(self, node, scope): + """ + node.instance -> Object + node.expr -> Expr + """ + if scope.get_var(scope.classname, node.instance.name) == scope.ctype.SELF: + sys.stdout.write(f'({node.lineno}, {node.linepos}) - {SEMERROR10}\n') + self.errors = True + return None + instance_type = scope.get_type(self.visit(node.instance, scope)) + + expr_type = scope.get_type(self.visit(node.expr, scope)) + if expr_type is None: + if not self.errors: + sys.stdout.write(f'({node.expr.lineno}, {node.expr.linepos}) - {NAMERROR1 % node.expr.name}\n') + self.errors = True + return None + + if expr_type == scope.ctype.SELF or instance_type == scope.ctype.SELF: + if expr_type != scope.ctype.SELF: + instance_type = scope.get_type(scope.classname) + elif instance_type != scope.ctype.SELF: + expr_type = scope.get_type(scope.classname) + + if instance_type is None: + scope.define_new_symbol(node.instance.name, expr_type) + instance_type = expr_type + + if not (expr_type <= instance_type): + sys.stdout.write(f'({node.expr.lineno}, {node.expr.linepos}) - {TYPERROR9 % (expr_type, node.instance.name, instance_type)}\n') + self.errors = True + return None + + node.static_type = expr_type + return expr_type + + + @visitor.when(ast.Block) + def visit(self, node, scope): + """ + node.expr_list -> [ Expr ... ] + """ + return_type = scope.ctype.VOID + + for expr in node.expr_list: + return_type = scope.get_type(self.visit(expr, scope)) + if return_type is None: + if not self.errors: + sys.stdout.write(f'({node.expr.lineno}, {node.expr.linepos}) - {NAMERROR1 % node.expr.name}\n') + self.errors = True + return None + + node.static_type = return_type + return return_type + + + @visitor.when(ast.DynamicDispatch) + def visit(self, node, scope): + """ + node.instance -> Expr + node.method -> str + node.arguments -> [ Expr ... ] + """ + instance_type = scope.get_type(self.visit(node.instance, scope)) + if instance_type is None: + if not self.errors: + sys.stdout.write(f'({node.instance.lineno}, {node.instance.linepos}) - {NAMERROR1 % node.instance.name}\n') + self.errors = True + return None + + if instance_type == scope.ctype.VOID: + sys.stdout.write(f'({node.instance.lineno}, {node.instance.linepos}) - {RNTERROR1}\n') + self.errors = True + return None + + if instance_type == scope.ctype.SELF: + instance_type = scope.get_type(scope.classname) + + node_args = [] + for arg in node.arguments: + _type = scope.get_type(self.visit(arg, scope)) + if _type is None: + if not self.errors: + sys.stdout.write(f'({arg.lineno}, {arg.linepos}) - {NAMERROR1 % arg.name}\n') + self.errors = True + return None + + if _type == scope.ctype.SELF: + _type = scope.get_type(scope.classname) + node_args.append(_type) + + if scope.get_var(scope.classname, node.method) == scope.ctype.SELF: + sys.stdout.write(f'({node.lineno}, {node.linepos}) - {SEMERROR12 % "a dispatch call"}\n') + self.errors = True + return None + + _method = instance_type.get_func(node.method) + if _method is None: + sys.stdout.write(f'({node.lineno}, {node.linepos}) - {ATTRERROR1 % node.method}\n') + self.errors = True + return None + + args_types = list(_method['formal_params'].values()) + args_names = list(_method['formal_params'].keys()) + + if len(args_types) != len(node_args): + sys.stdout.write(f'({node.lineno}, {node.linepos}) - {SEMERROR1 % node.method}\n') + self.errors = True + return None + + for i in range(len(args_types)): + if not (node_args[i] <= args_types[i]): + sys.stdout.write(f'({node.arguments[i].lineno}, {node.arguments[i].linepos}) - {TYPERROR8 % (node.method, node_args[i], args_names[i], args_types[i])}\n') + self.errors = True + return None + + return_type = _method['return_type'] + if return_type == scope.ctype.SELF: + return_type = instance_type + node.static_type = return_type + return return_type + + + @visitor.when(ast.StaticDispatch) + def visit(self, node, scope): + """ + node.instance -> Expr + node.dispatch_type -> str + node.method -> str + node.arguments -> [ Expr ... ] + """ + instance_type = scope.get_type(self.visit(node.instance, scope)) + if instance_type is None: + if not self.errors: + sys.stdout.write(f'({node.instance.lineno}, {node.instance.linepos}) - {NAMERROR1 % node.instance.name}\n') + self.errors = True + return None + + if instance_type == scope.ctype.VOID: + sys.stdout.write(f'({node.instance.lineno}, {node.instance.linepos}) - {RNTERROR1}\n') + self.errors = True + return None + + if instance_type == scope.ctype.SELF: + instance_type = scope.get_type(scope.classname) + + class_type = scope.get_type(node.dispatch_type) + if class_type == scope.ctype.SELF: + class_type = scope.get_type(scope.classname) + + if not (instance_type <= class_type): + sys.stdout.write(f'({node.instance.lineno}, {node.instance.linepos}) - {TYPERROR7 % (instance_type, class_type)}\n') + self.errors = True + return None + + node_args = [] + for arg in node.arguments: + _type = scope.get_type(self.visit(arg, scope)) + if _type is None: + if not self.errors: + sys.stdout.write(f'({arg.lineno}, {arg.linepos}) - {NAMERROR1 % arg.name}\n') + self.errors = True + return None + + if _type == scope.ctype.SELF: + _type = scope.get_type(scope.classname) + node_args.append(_type) + + if scope.get_var(scope.classname, node.method) == scope.ctype.SELF: + sys.stdout.write(f'({node.lineno}, {node.linepos}) - {SEMERROR12 % "a dispatch call"}\n') + self.errors = True + return None + + _method = instance_type.get_func(node.method) + if _method is None: + sys.stdout.write(f'({node.lineno}, {node.linepos}) - {ATTRERROR1 % node.method}\n') + self.errors = True + return None + + args_types = list(_method['formal_params'].values()) + args_names = list(_method['formal_params'].keys()) + + if len(args_types) != len(node.arguments): + sys.stdout.write(f'({node.lineno}, {node.linepos}) - {SEMERROR1 % node.method}\n') + self.errors = True + return None + + for i in range(len(args_types)): + if not (node_args[i] <= args_types[i]): + sys.stdout.write(f'({node.arguments[i].lineno}, {node.arguments[i].linepos}) - {TYPERROR8 % (node.method, node_args[i], args_names[i], args_types[i])}\n') + self.errors = True + return None + + return_type = _method['return_type'] + if return_type == scope.ctype.SELF: + return_type = class_type + node.static_type = return_type + return return_type + + + @visitor.when(ast.Let) + def visit(self, node, scope): + """ + node.declarations -> [ Formal ... ] + node.body -> Expr + """ + new_scope = COOL_Scope(scope.classname, scope) + + for declaration in node.declarations: + if scope.get_var(scope.classname, declaration.name) == scope.ctype.SELF: + sys.stdout.write(f'({declaration.lineno}, {declaration.linepos}) - {SEMERROR11 % "let"}\n') + self.errors = True + return None + + if self.visit(declaration, new_scope) is None: + return None + + body_type = scope.get_type(self.visit(node.body, new_scope)) + + if body_type is None: + if not self.errors: + sys.stdout.write(f'({node.body.lineno}, {node.body.linepos}) - {NAMERROR1 % node.body.name}\n') + self.errors = True + return None + + node.static_type = body_type + return body_type + + + @visitor.when(ast.If) + def visit(self, node, scope): + """ + node.predicate -> Expr + node.then_body -> Expr + node.else_body -> Expr + """ + pred_type = scope.get_type(self.visit(node.predicate, scope)) + + if pred_type is None: + if not self.errors: + sys.stdout.write(f'({node.predicate.lineno}, {node.predicate.linepos}) - {NAMERROR1 % node.predicate.name}\n') + self.errors = True + return None + + if pred_type != scope.ctype.BOOL: + sys.stdout.write(f'({node.predicate.lineno}, {node.predicate.linepos}) - {TYPERROR6}\n') + self.errors = True + return None + + if_type = scope.get_type(self.visit(node.then_body, scope)) + + if if_type is None: + if not self.errors: + sys.stdout.write(f'({node.then_body.lineno}, {node.then_body.linepos}) - {NAMERROR1 % node.then_body.name}\n') + self.errors = True + return None + + else_type = scope.get_type(self.visit(node.else_body, scope)) + + if else_type is None: + if not self.errors: + sys.stdout.write(f'({node.else_body.lineno}, {node.else_body.linepos}) - {NAMERROR1 % node.else_body.name}\n') + self.errors = True + return None + + return_type = if_type + + if if_type != scope.ctype.SELF or else_type != scope.ctype.SELF: + if else_type == scope.ctype.SELF: + return_type = scope.join(return_type, scope.get_type(scope.classname)) + elif if_type == scope.ctype.SELF: + return_type = scope.join(else_type, scope.get_type(scope.classname)) + else: + return_type = scope.join(return_type, else_type) + + node.static_type = return_type + return return_type + + + @visitor.when(ast.WhileLoop) + def visit(self, node, scope): + """ + node.predicate -> Expr + node.body -> Expr + """ + pred_type = scope.get_type(self.visit(node.predicate, scope)) + + if pred_type is None: + if not self.errors: + sys.stdout.write(f'({node.predicate.lineno}, {node.predicate.linepos}) - {NAMERROR1 % node.predicate.name}\n') + self.errors = True + return None + + if pred_type != scope.ctype.BOOL: + sys.stdout.write(f'({node.predicate.lineno}, {node.predicate.linepos}) - {TYPERROR4}\n') + self.errors = True + return None + + body_type = scope.get_type(self.visit(node.body, scope)) + + if body_type is None: + if not self.errors: + sys.stdout.write(f'({node.body.lineno}, {node.body.linepos}) - {NAMERROR1 % node.body.name}\n') + self.errors = True + return None + + node.static_type = scope.ctype.OBJECT + return node.static_type + + + @visitor.when(ast.Case) + def visit(self, node, scope): + """ + node.expr -> Expr + node.actions -> Action + """ + type_expr = scope.get_type(self.visit(node.expr, scope)) + if type_expr is None: + if not self.errors: + sys.stdout.write(f'({node.expr.lineno}, {node.expr.linepos}) - {NAMERROR1 % node.expr.name}\n') + self.errors = True + return None + + if type_expr == scope.ctype.VOID: + sys.stdout.write(f'({node.expr.lineno}, {node.expr.linepos}) - {RNTERROR1}\n') + self.errors = True + return None + + return_type = scope.get_type(self.visit(node.actions[0], scope)) + if return_type is None: + return None + + ids_type = [scope.get_type(node.actions[0].action_type)] + if ids_type[0] is None: + sys.stdout.write(f'({node.action[0].lineno}, {node.action[0].linepos}) - {TYPERROR15 % node.action[0].action_type}\n') + self.errors = True + return None + + for action in node.actions[1:]: + if scope.get_var(scope.classname, action.name) == scope.ctype.SELF: + sys.stdout.write(f'({action.lineno}, {action.linepos}) - {SEMERROR11 % "case"}\n') + self.errors = True + return None + + type_action = scope.get_type(self.visit(action, scope)) + if type_action is None: + return None + + id_type = scope.get_type(action.action_type) + if id_type is None: + sys.stdout.write(f'({action.lineno}, {action.linepos}) - {TYPERROR15 % action.action_type}\n') + self.errors = True + return None + + if id_type in ids_type: + sys.stdout.write(f'({action.lineno}, {action.linepos}) - {SEMERROR7 % id_type}\n') + self.errors = True + return None + + ids_type.append(id_type) + + if return_type != scope.ctype.SELF or type_action != scope.ctype.SELF: + if type_action == scope.ctype.SELF: + return_type = scope.join(return_type, scope.get_type(scope.classname)) + elif return_type == scope.ctype.SELF: + return_type = scope.join(type_action, scope.get_type(scope.classname)) + else: + return_type = scope.join(type_action, return_type) + + if return_type == scope.ctype.VOID: + sys.stdout.write(f'({node.lineno}, {node.linepos}) - {RNTERROR2}\n') + self.errors = True + return None + + node.static_type = return_type + return return_type + + + @visitor.when(ast.Action) + def visit(self, node, scope): + """ + node.name -> str + node.action_type -> str + node.body -> Expr + """ + _type = scope.get_type(node.action_type) + if _type is None: + self.errors = True + + new_scope = COOL_Scope(scope.classname, scope) + if not new_scope.define_new_symbol(node.name, _type): + sys.stdout.write(f'({node.lineno}, {node.linepos}) - {SEMERROR4 % node.name}\n') + self.errors = True + return None + + return_type = scope.get_type(self.visit(node.body, new_scope)) + + if return_type is None: + if not self.errors: + sys.stdout.write(f'({node.body.lineno}, {node.body.linepos}) - {NAMERROR1 % node.body.name}\n') + self.errors = True + return None + + node.static_type = return_type + return return_type + + + @visitor.when(ast.IntegerComplement) + def visit(self, node, scope): + """ + node.integer_expr -> Expr + """ + type_expr = scope.get_type(self.visit(node.integer_expr, scope)) + + if type_expr is None: + if not self.errors: + sys.stdout.write(f'({node.integer_expr.lineno}, {node.integer_expr.linepos}) - {NAMERROR1 % node.integer_expr.name}\n') + self.errors = True + return None + + if type_expr != scope.ctype.INT: + sys.stdout.write(f'({node.lineno}, {node.linepos}) - {TYPERROR3 % (node.symbol, type_expr, scope.ctype.INT)}\n') + self.errors = True + return None + + return_type = scope.ctype.INT + node.static_type = return_type + return return_type + + + @visitor.when(ast.BooleanComplement) + def visit(self, node, scope): + """ + node.boolean_expr -> Expr + """ + type_expr = scope.get_type(self.visit(node.boolean_expr, scope)) + + if type_expr is None: + if not self.errors: + sys.stdout.write(f'({node.boolean_expr.lineno}, {node.boolean_expr.linepos}) - {NAMERROR1 % node.boolean_expr.name}\n') + self.errors = True + return None + + if type_expr != scope.ctype.BOOL: + sys.stdout.write(f'({node.lineno}, {node.linepos}) - {TYPERROR3 % ("not", type_expr, scope.ctype.BOOL)}\n') + self.errors = True + return None + + return_type = scope.ctype.BOOL + node.static_type = return_type + return return_type + + + @visitor.when(ast.Addition) + def visit(self, node, scope): + """ + node.first -> Expr + node.second -> Expr + """ + left_type = scope.get_type(self.visit(node.first, scope)) + + if left_type is None: + if not self.errors: + sys.stdout.write(f'({node.first.lineno}, {node.first.linepos}) - {NAMERROR1 % node.first.name}\n') + self.errors = True + return None + + right_type = scope.get_type(self.visit(node.second, scope)) + + if right_type is None: + if not self.errors: + sys.stdout.write(f'({node.second.lineno}, {node.second.linepos}) - {NAMERROR1 % node.second.name}\n') + self.errors = True + return None + + if left_type != scope.ctype.INT or right_type != scope.ctype.INT: + sys.stdout.write(f'({node.lineno}, {node.linepos}) - {TYPERROR2} {left_type} + {right_type}.\n') + self.errors = True + return None + + return_type = scope.ctype.INT + node.static_type = return_type + return return_type + + + @visitor.when(ast.Subtraction) + def visit(self, node, scope): + """ + node.first -> Expr + node.second -> Expr + """ + left_type = scope.get_type(self.visit(node.first, scope)) + + if left_type is None: + if not self.errors: + sys.stdout.write(f'({node.first.lineno}, {node.first.linepos}) - {NAMERROR1 % node.first.name}\n') + self.errors = True + return None + + right_type = scope.get_type(self.visit(node.second, scope)) + + if right_type is None: + if not self.errors: + sys.stdout.write(f'({node.second.lineno}, {node.second.linepos}) - {NAMERROR1 % node.second.name}\n') + self.errors = True + return None + + if left_type != scope.ctype.INT or right_type != scope.ctype.INT: + sys.stdout.write(f'({node.lineno}, {node.linepos}) - {TYPERROR2} {left_type} - {right_type}.\n') + self.errors = True + return None + + return_type = scope.ctype.INT + node.static_type = return_type + return return_type + + + @visitor.when(ast.Multiplication) + def visit(self, node, scope): + """ + node.first -> Expr + node.second -> Expr + """ + left_type = scope.get_type(self.visit(node.first, scope)) + + if left_type is None: + if not self.errors: + sys.stdout.write(f'({node.first.lineno}, {node.first.linepos}) - {NAMERROR1 % node.first.name}\n') + self.errors = True + return None + + right_type = scope.get_type(self.visit(node.second, scope)) + + if right_type is None: + if not self.errors: + sys.stdout.write(f'({node.second.lineno}, {node.second.linepos}) - {NAMERROR1 % node.second.name}\n') + self.errors = True + return None + + if left_type != scope.ctype.INT or right_type != scope.ctype.INT: + sys.stdout.write(f'({node.lineno}, {node.linepos}) - {TYPERROR2} {left_type} * {right_type}.\n') + self.errors = True + return None + + return_type = scope.ctype.INT + node.static_type = return_type + return return_type + + + @visitor.when(ast.Division) + def visit(self, node, scope): + """ + node.first -> Expr + node.second -> Expr + """ + left_type = scope.get_type(self.visit(node.first, scope)) + + if left_type is None: + if not self.errors: + sys.stdout.write(f'({node.first.lineno}, {node.first.linepos}) - {NAMERROR1 % node.first.name}\n') + self.errors = True + return None + + right_type = scope.get_type(self.visit(node.second, scope)) + + if right_type is None: + if not self.errors: + sys.stdout.write(f'({node.second.lineno}, {node.second.linepos}) - {NAMERROR1 % node.second.name}\n') + self.errors = True + return None + + if left_type != scope.ctype.INT or right_type != scope.ctype.INT: + sys.stdout.write(f'({node.lineno}, {node.linepos}) - {TYPERROR2} {left_type} / {right_type}.\n') + self.errors = True + return None + + return_type = scope.ctype.INT + node.static_type = return_type + return return_type + + + @visitor.when(ast.Equal) + def visit(self, node, scope): + """ + node.first -> Expr + node.second -> Expr + """ + left_type = scope.get_type(self.visit(node.first, scope)) + + if left_type is None: + if not self.errors: + sys.stdout.write(f'({node.first.lineno}, {node.first.linepos}) - {NAMERROR1 % node.first.name}\n') + self.errors = True + return None + + right_type = scope.get_type(self.visit(node.second, scope)) + + if right_type is None: + if not self.errors: + sys.stdout.write(f'({node.second.lineno}, {node.second.linepos}) - {NAMERROR1 % node.second.name}\n') + self.errors = True + return None + + if left_type in scope.ctype.not_inherits_type or right_type in scope.ctype.not_inherits_type: + if left_type == scope.ctype.SELF: + left_type = scope.get_type(scope.classname) + + if right_type == scope.ctype.SELF: + right_type = scope.get_type(scope.classname) + + if left_type != right_type: + sys.stdout.write(f'({node.lineno}, {node.linepos}) - {TYPERROR1}\n') + self.errors = True + return None + + return_type = scope.ctype.BOOL + node.static_type = return_type + return return_type + + + @visitor.when(ast.LessThan) + def visit(self, node, scope): + """ + node.first -> Expr + node.second -> Expr + """ + left_type = scope.get_type(self.visit(node.first, scope)) + + if left_type is None: + if not self.errors: + sys.stdout.write(f'({node.first.lineno}, {node.first.linepos}) - {NAMERROR1 % node.first.name}\n') + self.errors = True + return None + + right_type = scope.get_type(self.visit(node.second, scope)) + + if right_type is None: + if not self.errors: + sys.stdout.write(f'({node.second.lineno}, {node.second.linepos}) - {NAMERROR1 % node.second.name}\n') + self.errors = True + return None + + if left_type != scope.ctype.INT or right_type != scope.ctype.INT: + sys.stdout.write(f'({node.lineno}, {node.linepos}) - {TYPERROR1}\n') + self.errors = True + return None + + return_type = scope.ctype.BOOL + node.static_type = return_type + return return_type + + + @visitor.when(ast.LessThanOrEqual) + def visit(self, node, scope): + """ + node.first -> Expr + node.second -> Expr + """ + left_type = scope.get_type(self.visit(node.first, scope)) + + if left_type is None: + if not self.errors: + sys.stdout.write(f'({node.first.lineno}, {node.first.linepos}) - {NAMERROR1 % node.first.name}\n') + self.errors = True + return None + + right_type = scope.get_type(self.visit(node.second, scope)) + + if right_type is None: + if not self.errors: + sys.stdout.write(f'({node.second.lineno}, {node.second.linepos}) - {NAMERROR1 % node.second.name}\n') + self.errors = True + return None + + if left_type != scope.ctype.INT or right_type != scope.ctype.INT: + sys.stdout.write(f'({node.lineno}, {node.linepos}) - {TYPERROR1}\n') + self.errors = True + return None + + return_type = scope.ctype.BOOL + node.static_type = return_type + return return_type \ No newline at end of file diff --git a/src/Compiler/Semantic/errors_types.py b/src/Compiler/Semantic/errors_types.py new file mode 100644 index 000000000..808fe1385 --- /dev/null +++ b/src/Compiler/Semantic/errors_types.py @@ -0,0 +1,38 @@ +TYPERROR1 = "TypeError: Illegal comparison with a basic type." +TYPERROR2 = "TypeError: non-Int arguments:" +TYPERROR3 = "TypeError: Argument of '%s' has type %s instead of %s." +TYPERROR4 = "TypeError: Loop condition does not have type Bool." +TYPERROR5 = "TypeError: Loop body does not have type Object." +TYPERROR6 = "TypeError: Predicate of 'if' does not have type Bool." +TYPERROR7 = "TypeError: Expression type %s does not conform to declared static dispatch type %s." +TYPERROR8 = "TypeError: In call of method %s, type %s of parameter %s does not conform to declared type %s." +TYPERROR9 = "TypeError: Inferred type %s of assignment expression for variable %s does not conform to declared type %s." +TYPERROR10 = "TypeError: 'new' used with undefined class %s." +TYPERROR11 = "TypeError: Undeclared type %s." +TYPERROR12 = "TypeError: Inferred type %s of initialization of attribute %s does not conform to declared type %s." +TYPERROR13 = "TypeError: Inferred return type %s of method %s does not conform to declared return type %s." +TYPERROR14 = "TypeError: Class %s inherits from an undefined class %s." +TYPERROR15 = "TypeError: Class %s of case branch is undefined." +TYPERROR16 = "TypeError: Inferred type %s of initialization of %s does not conform to identifier's declared type %s." +TYPERROR17 = "TypeError: Undefined return type Integrer in method %s." + +ATTRERROR1 = "AttributeError: Dispatch to undefined method %s." + +SEMERROR1 = "SemanticError: Method %s called with wrong number of arguments." +SEMERROR2 = "SemanticError: Redefinition of basic class %s." +SEMERROR3 = "SemanticError: Class %s cannot inherit class %s." +SEMERROR4 = "SemanticError: Attribute %s is multiply defined in class." +SEMERROR5 = "SemanticError: Method %s is multiply defined." +SEMERROR6 = "SemanticError: Class %s, or an ancestor of %s, is involved in an inheritance cycle." +SEMERROR7 = "SemanticError: Duplicate branch %s in case statement." +SEMERROR8 = "SemanticError: Wrong redefinition of method %s." +SEMERROR9 = "SemanticError: Attribute %s is an attribute of an inherited class." +SEMERROR10 = "SemanticError: Cannot assign to 'self'." +SEMERROR11 = "SemanticError: 'self' cannot be bound in a '%s' expression." +SEMERROR12 = "SemanticError: 'self' cannot be the name of %s." + +RNTERROR1 = "RuntimeError: Expression cant\'t be Void type." +RNTERROR2 = "RuntimeError: None expression selected" + +NAMERROR1 = "NameError: Undeclared identifier %s." + diff --git a/src/Compiler/Semantic/scope.py b/src/Compiler/Semantic/scope.py new file mode 100644 index 000000000..a07bec663 --- /dev/null +++ b/src/Compiler/Semantic/scope.py @@ -0,0 +1,90 @@ +from Semantic.types import * + +class VariableInfo: + def __init__(self, name, vtype): + self.name = name + self.type = vtype + +class COOL_Scope: + + def __init__(self, name, parent): + self.ctype = cool_type() + self.classname = name + self.parent = parent + self.children = list() + self.var = dict() + self.child_index = 0 + + if not parent is None: + self.parent.children.append(self) + self.ctype = parent.ctype + + def next_child(self): + child = self.children[self.child_index] + + self.child_index += 1 + if self.child_index >= len(self.children): + self.child_index = 0 + + return child + + def set_type(self, name): + current_scope = self + while not current_scope is None: + if not current_scope.ctype.defined_types.get(name) is None: + return False + current_scope = current_scope.parent + new_type = COOL_Type(name) + self.ctype.defined_types[name] = new_type + return True + + + def get_type(self, _type): + if type(_type) is str: + try: + return self.get_type(self.ctype.defined_types[_type]) + except: + return None + elif type(_type) is COOL_Type: + return _type + else: + return None + + def define_new_symbol(self, name, _type, override = False): + current_scope = self + while not current_scope.classname is None: + if not current_scope.var.get(name) is None: + if not override: + return False + current_scope.var[name] = _type + return True + current_scope = current_scope.parent + self.var[name] = _type + return True + + def get_symbol_type(self, name): + current_scope = self + while not current_scope.classname is None: + if not current_scope.var.get(name) is None: + return current_scope.var[name] + current_scope = current_scope.parent + return None + + def get_var(self, _class, name): + if name == 'self': + return self.ctype.SELF + symbol = self.get_symbol_type(name) + attr = self.get_type(_class).get_attr_type(name) + if not symbol is None: + return symbol + if not attr is None: + return attr + return None + + + def join(self, type1, type2): + if type1 <= type2: + return type2 + if type2 <= type1: + return type1 + return self.join(type1.parent, type2.parent) \ No newline at end of file diff --git a/src/Compiler/Semantic/types.py b/src/Compiler/Semantic/types.py new file mode 100644 index 000000000..1741c9622 --- /dev/null +++ b/src/Compiler/Semantic/types.py @@ -0,0 +1,165 @@ +class COOL_Type: + + def __init__(self, name, parent = None): + self.name = name + self.parent = parent + self.attr = dict() + self.func = dict() + + def add_func(self, name, func): + if not self.func.get(name) is None: + return False + current = self.parent + while not current is None: + if not current.func.get(name) is None: + _function = current.func[name] + if list(_function['formal_params'].values()) != list(func['formal_params'].values()): + return None + if _function['return_type'] != func['return_type']: + return None + self.func[name] = func + return True + current = current.parent + self.func[name] = func + return True + + def add_funcs(self, funcs): + result = True + for (name, func) in funcs: + result &= self.add_func(name, func) + return result + + def add_attr(self, name, _type, expr = None): + if not self.attr.get(name) is None: + return False + current = self.parent + while not current is None: + if not current.attr.get(name) is None: + return None + current = current.parent + self.attr[name] = {'expresion': expr, 'type': _type} + return True + + def get_func(self, name): + current = self + while not current is None: + if not current.func.get(name) is None: + return current.func[name] + current = current.parent + return None + + def get_func_context(self, name): + current = self + while not current is None: + if not current.func.get(name) is None: + return current + current = current.parent + return None + + def get_all_parents(self): + parents = list() + current = self.parent + while not current is None: + parents.append(current) + current = current.parent + return parents + + def get_attr_type(self, name): + current = self + while not current is None: + if not current.attr.get(name) is None: + return current.attr[name]['type'] + current = current.parent + return None + + def get_all_attr(self): + attr = list() + current = self + while not current is None: + attr += list(current.attr.keys())[::-1] + current = current.parent + return attr[::-1] + + def get_all_func(self): + return list(self.func.keys()) + + def __str__(self): + return self.name + + def __eq__(type1, type2): + return str(type1) == str(type2) + + def __lt__(type1, type2): + if type1.parent is None: + return False + if type1.parent == type2: + return True + return type1.parent < type2 + + def __le__(type1, type2): + if type1 == type2 or type1 < type2: + return True + return False + + def __gt__(type1, type2): + if type2.parent is None: + return False + if type2.parent == type1: + return True + return type1 > type2.parent + + def __ge__(type1, type2): + if type1 == type2 or type1 < type2: + return True + return False + + +class cool_type: + + def __init__(self): + + self.OBJECT = COOL_Type("Object") + self.SELF = COOL_Type("SELF_TYPE") + self.VOID = COOL_Type("Void", self.OBJECT) + self.INT = COOL_Type("Int", self.OBJECT) + self.BOOL = COOL_Type("Bool", self.OBJECT) + self.STRING = COOL_Type("String", self.OBJECT) + self.IO = COOL_Type("IO", self.OBJECT) + self.IO.add_funcs([ + ('out_string', {'formal_params': {'x_1': self.STRING}, 'return_type': self.SELF}), + ('out_int', {'formal_params': {'x_1': self.INT}, 'return_type': self.SELF}), + ('in_string', {'formal_params': {}, 'return_type': self.STRING}), + ('in_int', {'formal_params': {}, 'return_type': self.INT}) + ]) + self.OBJECT.add_funcs([ + ('type_name', {'formal_params': {}, 'return_type': self.STRING}), + ('copy', {'formal_params': {}, 'return_type': self.SELF}), + ('abort', {'formal_params': {}, 'return_type': self.OBJECT}) + ]) + self.STRING.add_funcs([ + ('length', {'formal_params': {}, 'return_type': self.INT}), + ('concat', {'formal_params': {'x_1': self.STRING}, 'return_type': self.STRING}), + ('substr', {'formal_params': {'x_1': self.INT, 'x_2': self.INT}, 'return_type': self.STRING}) + ]) + + self.not_inherits_type = [self.INT, self.BOOL, self.STRING] + + self.defined_types = { + "Object": self.OBJECT, + "SELF_TYPE": self.SELF, + "Void": self.VOID, + "Int": self.INT, + "Bool": self.BOOL, + "String": self.STRING, + "IO": self.IO + } + + self.basic_types = self.defined_types.copy() + +def cyclic_inheritance(_type): + current = _type + while not current is None: + current = current.parent + if current == _type: + return True + return False \ No newline at end of file diff --git a/src/Compiler/Semantic/visitor.py b/src/Compiler/Semantic/visitor.py new file mode 100644 index 000000000..82cce83b5 --- /dev/null +++ b/src/Compiler/Semantic/visitor.py @@ -0,0 +1,54 @@ +import inspect + +def on(param_name): + def f(fn): + dispatcher = Dispatcher(param_name, fn) + return dispatcher + return f + +def when(param_type): + def f(fn): + frame = inspect.currentframe().f_back + func_name = fn.func_name if 'func_name' in dir(fn) else fn.__name__ + dispatcher = frame.f_locals[func_name] + + if not isinstance(dispatcher, Dispatcher): + dispatcher = dispatcher.dispatcher + dispatcher.add_target(param_type, fn) + + def ff(*args, **kw): + return dispatcher(*args, **kw) + ff.dispatcher = dispatcher + return ff + return f + + +class Dispatcher(object): + def __init__(self, param_name, fn): + self.param_index = self.__argspec(fn).args.index(param_name) + self.param_name = param_name + self.targets = {} + + def __call__(self, *args, **kw): + typ = args[self.param_index].__class__ + d = self.targets.get(typ) + if d is not None: + return d(*args, **kw) + else: + issub = issubclass + t = self.targets + ks = t.keys() + ans = [t[k](*args, **kw) for k in ks if issub(typ, k)] + if len(ans) == 1: + return ans.pop() + return ans + + def add_target(self, typ, target): + self.targets[typ] = target + + @staticmethod + def __argspec(fn): + if hasattr(inspect, 'getfullargspec'): + return inspect.getfullargspec(fn) + else: + return inspect.getargspec(fn) \ No newline at end of file diff --git a/src/Compiler/compiler.py b/src/Compiler/compiler.py new file mode 100644 index 000000000..f81ca2477 --- /dev/null +++ b/src/Compiler/compiler.py @@ -0,0 +1,72 @@ +from CodeGen.Intermediate.Generator import COOLToCILVisitor +from CodeGen.Intermediate.cil import Scope +from CodeGen.Assembler.Generator import CILToSPIMVisitor +from Semantic.Semantic import COOL_Semantic_Checker +from Parser.Parser import COOL_Parser +from Lexer.Lexer import COOL_Lexer +import sys + +class COOL_Compiler: + + def __init__(self): + self.cool_lexer = COOL_Lexer() + self.cool_parser = COOL_Parser(self.cool_lexer) + + def run(self, code): + # Lexic & Sintactic Analizer + ast = self.cool_parser.run(code) + + if self.cool_lexer.errors: + exit(1) + + if self.cool_parser.errors: + for error in self.cool_parser.error_list: + sys.stdout.write(f'{error}\n') + exit(1) + + # Semantic Analyzer + cool_checker = COOL_Semantic_Checker() + scope = cool_checker.visit(ast) + + if cool_checker.errors: + exit(1) + + # Intermediate Code Gen + cool_intermediate_code = COOLToCILVisitor(scope) + cil_code = cool_intermediate_code.visit(ast, scope) + + # MIPS Code Gen + cil_smips_code = CILToSPIMVisitor() + (data, text) = cil_smips_code.visit(cil_code) + + mips_data = ".data" + for d in data: + mips_data += str(d) + mips_text = "\n\n.text\n.globl main" + for t in text: + mips_text += str(t) + + return mips_data + mips_text + + +def main(file): + with open(file, "r") as fd: + data = fd.read() + data = data.replace('\t', " ") + + _cmp = COOL_Compiler() + mips_instr = _cmp.run(data) + + with open('code.mips', "r") as fd: + mips_instr += fd.read() + + output_file = file.split('.') + output_file[-1] = 'mips' + mips_exec = ".".join(output_file) + + with open(mips_exec, "w") as fd: + fd.write(mips_instr) + + +if __name__ == '__main__': + main(sys.argv[1]) \ No newline at end of file diff --git a/src/code.mips b/src/code.mips new file mode 100644 index 000000000..f062185b9 --- /dev/null +++ b/src/code.mips @@ -0,0 +1,524 @@ + +################ OBJECT ################ + +function_copy_at_Object: + addi $sp, $sp, -4 + sw $ra, 0($sp) + lw $a0, 4($sp) + lw $a0, 0($a0) + jal create_instance + lw $a2, 0($v0) + lw $a2, 0($a2) + move $a1, $v0 + lw $a0, 4($sp) + jal copy + move $v0, $a1 + lw $ra, 0($sp) + addi $sp, $sp, 4 + jr $ra + +function_abort_at_Object: + lw $t0, 0($sp) + lw $t0, 0($t0) + lw $s0, 8($t0) + la $a0, abort_message + li $v0, 4 + syscall + move $a0, $s0 + li $v0, 4 + syscall + la $a0, eol + li $v0, 4 + syscall + li $v0, 10 + syscall + +function_type_name_at_Object: + addi $sp, $sp, -4 + sw $ra, 0($sp) + lw $a0, 4($sp) + lw $a0, 0($a0) + lw $a0, 8($a0) + jal str_assigment_from_str + lw $ra, 0($sp) + addi $sp, $sp, 4 + jr $ra + +################ IO ################ + +function_out_string_at_IO: + addi $sp, $sp, -4 + sw $ra, 0($sp) + lw $a0, 8($sp) + lw $a0, 4($a0) + li $v0, 4 + syscall + lw $v0, 4($sp) + lw $ra, 0($sp) + addi $sp, $sp, 4 + jr $ra + +function_out_int_at_IO: + addi $sp, $sp, -4 + sw $ra, 0($sp) + lw $a0, 8($sp) + lw $a0, 4($a0) + li $v0, 1 + syscall + lw $v0, 4($sp) + lw $ra, 0($sp) + addi $sp, $sp, 4 + jr $ra + +function_in_string_at_IO: + addi $sp, $sp, -4 + sw $ra, 0($sp) + li $v0, 9 + li $a0, 4 + syscall + move $a0, $v0 + + move $s0, $sp + _loop: + li $v0, 8 + li $a1, 2 + syscall + lb $t0, 0($a0) + beq $t0, 0xA, _end + beq $t0, 0x0, _end + sb $t0, -1($sp) + addi $sp, $sp, -1 + j _loop + _end: + + sub $a0, $s0, $sp + move $s1, $a0 + addi $a0, $a0, 1 + move $sp, $s0 + li $v0, 9 + syscall + move $a0, $v0 + _copy: + beq $s1, $zero, _end_copy + lb $t1, -1($s0) + sb $t1, 0($v0) + addi $s0, $s0, -1 + addi $s1, $s1, -1 + addi $v0, $v0, 1 + j _copy + _end_copy: + + jal str_assigment_from_str + lw $ra, 0($sp) + addi $sp, $sp, 4 + jr $ra + +function_in_int_at_IO: + addi $sp, $sp, -4 + sw $ra, 0($sp) + la $a0, type_Int + jal create_instance + move $s0, $v0 + li $v0, 5 + syscall + sw $v0, 4($s0) + move $v0, $s0 + lw $ra, 0($sp) + addi $sp, $sp, 4 + jr $ra + +################ STRING ################ + +function_length_at_String: + addi $sp, $sp, -4 + sw $ra, 0($sp) + lw $a0, 4($sp) # cargar variabke de tipo string + lw $a0, 4($a0) # cargar direccion del string + jal str_length + move $s0, $v0 + la $a0, type_Int + jal create_instance + sw $s0, 4($v0) + lw $ra, 0($sp) + addi $sp, $sp, 4 + jr $ra + +function_concat_at_String: + addi $sp, $sp, -4 + sw $ra, 0($sp) + lw $a0, 4($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal function_length_at_String + lw $s1, 4($v0) + addi $sp, $sp, 4 + lw $a0, 8($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal function_length_at_String + lw $s2, 4($v0) + addi $sp, $sp, 4 + add $a0, $s1, $s2 + addi $a0, $a0, 1 + li $v0, 9 + syscall + move $s3, $v0 + lw $a0, 4($sp) # cargar la primera variabke de tipo string + lw $a0, 4($a0) # cargar direccion del string + move $a1, $v0 + move $a2, $s1 + jal copy + lw $a0, 8($sp) # cargar la segunda variabke de tipo string + lw $a0, 4($a0) # cargar direccion del string + add $a1, $a1, $s1 + move $a2, $s2 + jal copy + move $a0, $s3 + jal str_assigment_from_str + lw $ra, 0($sp) + addi $sp, $sp 4 + jr $ra + +function_substr_at_String: + addi $sp, $sp, -8 + sw $ra, 0($sp) + la $a0, type_String + jal create_instance + sw $v0, 4($sp) + lw $a0, 16($sp) + lw $a0, 4($a0) + addi $a0, $a0, 1 + li $v0, 9 + syscall + lw $a0, 8($sp) + lw $a0, 4($a0) + lw $t0, 12($sp) + lw $t0, 4($t0) + add $a0, $a0, $t0 + move $a1, $v0 + lw $a2, 16($sp) + lw $a2, 4($a2) + jal copy + lw $v0, 4($sp) + sw $a1, 4($v0) + lw $ra, 0($sp) + addi $sp, $sp, 8 + jr $ra + +################ UTILS ################ + +# Arg: +# $a0 Direccion del tipo a partir del cual se quiere crear una instancia +# Return: +# $v0 Direccion del espacio en memoria de la nueva instancia + +create_instance: + addi $sp, $sp, -8 + sw $ra, 0($sp) + sw $a0, 4($sp) + + li $v0, 9 + lw $a0, 0($a0) + syscall + + lw $t0, 4($sp) + sw $t0, 0($v0) + + la $t1, type_String + bne $t1, $t0, not_str + la $t0, empty_string + sw $t0, 4($v0) + not_str: + + lw $a0, 4($sp) + lw $ra, 0($sp) + addi $sp, $sp, 8 + + jr $ra + + +# Arg: +# $a0 Origen de la copia +# $a1 Destino de la copia +# $a2 Tamaño de la copia + +copy: + addi $sp, $sp, -12 + sw $a0, 0($sp) + sw $a1, 4($sp) + sw $a2, 8($sp) + +loop_copy: + beq $a2, $zero, end_loop_copy + lb $t0, 0($a0) + sb $t0, 0($a1) + addi $a0, $a0, 1 + addi $a1, $a1, 1 + addi $a2, $a2, -1 + j loop_copy + +end_loop_copy: + lw $a0, 0($sp) + lw $a1, 4($sp) + lw $a2, 8($sp) + addi $sp, $sp, 12 + jr $ra + + +# Arg: +# $a0 Direccion de la instancia a asignar +# Return: +# $v0 Direccion a la nueva instancia + +val_assigment: + addi $sp, $sp, -8 + sw $ra, 0($sp) + sw $a0, 4($sp) + + lw $a0, 0($a0) + jal create_instance + + lw $a0, 4($sp) + move $a1, $v0 + lw $a2, 0($a0) + lw $a2, 0($a2) + + jal copy + + move $v0, $a1 + lw $ra, 0($sp) + addi $sp, $sp, 8 + jr $ra + +# Desde una instancia +str_assigment: + addi $sp, $sp, -4 + sw $ra, 0($sp) + lw $a0, 4($a0) + jal str_assigment_from_str + lw $ra, 0($sp) + addi $sp, $sp, 4 + jr $ra + +# Desde un string +str_assigment_from_str: + addi $sp, $sp, -20 + sw $ra, 0($sp) + sw $s0, 4($sp) + sw $a0, 8($sp) + + sw $a0, 12($sp) + la $a0, type_String + jal create_instance + sw $v0, 16($sp) + lw $a0, 12($sp) + jal str_length + addi $s0, $v0, 1 + move $a0, $s0 + li $v0, 9 + syscall + lw $a0, 12($sp) + move $a1, $v0 + move $a2, $s0 + jal copy + lw $v0, 16($sp) + sw $a1, 4($v0) + + lw $a0, 8($sp) + lw $s0, 4($sp) + lw $ra, 0($sp) + addi $sp, $sp, 20 + jr $ra + +ref_assigment: + move $v0, $a0 + jr $ra + + +# Arg: +# $a0 Direccion de la primera instancia +# $a1 Direccion de la segunda instancia +# Return: +# $v0 Booleano que indica si ambas instancias son iguales segun +# el criterio de comparacion definido en sus tipos + +val_equal: + addi $sp, $sp, -4 + sw $ra, 0($sp) + lw $t0, 0($a0) + lw $t0, 0($t0) + + addi $s0, $zero, 1 + + loop_val_equal: + beq $t0, $zero, are_val_equal + lw $t1, 0($a0) + lw $t2, 0($a1) + bne $t1, $t2, not_val_equal + addi $a0, $a0, 4 + addi $a1, $a1, 4 + addi $t0, $t0, -4 + j loop_val_equal + not_val_equal: + move $s0, $zero + are_val_equal: + + la $a0, type_Bool + jal create_instance + sw $s0, 4($v0) + + lw $ra, 0($sp) + addi $sp, $sp, 4 + jr $ra + +str_equal: + addi $sp, $sp, -24 + sw $ra, 0($sp) + sw $s6, 4($sp) + sw $s0, 8($sp) + sw $s1, 12($sp) + sw $a0, 16($sp) + sw $s2, 20($sp) + + addi $s6, $zero, 1 + lw $t0, 0($a0) + lw $t1, 0($a1) + bne $t0, $t1, not_str_equal + move $s0, $a0 + move $s1, $a1 + lw $a0, 4($a0) + jal str_length + move $s2, $v0 + lw $a0, 4($s1) + jal str_length + bne $s2, $v0, not_str_equal + lw $a0, 4($s0) + lw $a1, 4($s1) + loop_str_equal: + lb $t0, 0($a0) + lb $t1, 0($a1) + beq $t0, $zero, first_equal_zero + beq $t1, $zero, second_equal_zero + bne $t0, $t1, not_str_equal + addi $a0, $a0, 1 + addi $a1, $a1, 1 + j loop_str_equal + first_equal_zero: + beq $t1, $zero, are_str_equal + j not_str_equal + second_equal_zero: + beq $t0, $zero, are_str_equal + j not_str_equal + not_str_equal: + move $s6, $zero + are_str_equal: + + la $a0, type_Bool + jal create_instance + sw $s6, 4($v0) + + lw $s2, 20($sp) + lw $a0, 16($sp) + lw $s1, 12($sp) + lw $s0, 8($sp) + lw $s6, 4($sp) + lw $ra, 0($sp) + addi $sp, $sp, 24 + jr $ra + +ref_equal: + addi $sp, $sp, -12 + sw $ra, 0($sp) + sw $s0, 4($sp) + sw $a0, 8($sp) + addi $s0, $zero, 1 + bne $a0, $a1, not_ref_equal + j are_ref_equal + not_ref_equal: + move $s0, $zero + are_ref_equal: + + la $a0, type_Bool + jal create_instance + sw $s0, 4($v0) + + lw $a0, 8($sp) + lw $s0, 4($sp) + lw $ra, 0($sp) + addi $sp, $sp, 12 + jr $ra + +# Arg: +# $a0 Direccion del string +# Return: +# $v0 Longitud del string + +str_length: + addi $sp, $sp, -4 + sw $a0, 0($sp) + move $v0, $zero + loop_length: + lb $t0, 0($a0) + beq $t0, $zero, end_loop_length + addi $v0, $v0, 1 + addi $a0, $a0, 1 + j loop_length + end_loop_length: + lw $a0, 0($sp) + addi $sp, $sp, 4 + jr $ra + +runtime_error: + li $v0, 4 + syscall + li $v0, 10 + syscall + +get_number_action: + addi $sp, $sp, -4 + sw $ra, 0($sp) + + lw $s0, 4($sp) # Carga en $s0 + lw $s0, 0($s0) # Carga el tipo de en $s0 + _loop_1: + beq $s0, $zero, _end_loop_1 + lw $a0, 8($s0) # Carga el nombre del tipo de en $a0 + jal str_assigment_from_str + move $a0, $v0 # Mueve la instancia de str del nombre del tipo de a $a0 + lw $s2, 8($sp) # Carga la instancia de int del numero de actions en $s2 + lw $s2, 4($s2) # Carga el numero de actions en $s2 + move $s3, $sp # Guarda el estado actual de $sp en $s3 + _loop_2: + beq $s2, $zero, _end_loop_2 + lw $a1, 12($sp) # Carga el tipo del action (instancia str) + move $s4, $sp + move $sp, $s3 + jal str_equal + move $sp, $s4 + lw $t1, 4($v0) + li $t2, 1 + beq $t1, $t2, get_number + addi $s2, $s2, -1 + addi $sp, $sp, 4 + j _loop_2 + _end_loop_2: + lw $s0, 20($s0) + move $sp, $s3 + j _loop_1 + _end_loop_1: + move $sp, $s3 + li $s0, -1 + j fin + get_number: + move $sp, $s3 + lw $t0, 8($sp) + lw $t0, 4($t0) + sub $s0, $t0, $s2 + fin: + la $a0, type_Int + jal create_instance + sw $s0, 4($v0) + + lw $ra, 0($sp) + addi $sp, $sp, 4 + jr $ra \ No newline at end of file diff --git a/src/coolc.sh b/src/coolc.sh index 3088de4f9..88b5f9e7f 100755 --- a/src/coolc.sh +++ b/src/coolc.sh @@ -4,8 +4,11 @@ INPUT_FILE=$1 OUTPUT_FILE=${INPUT_FILE:0: -2}mips # 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 "Cool Compiler 2021 v1.0" # TODO: Recuerde cambiar estas +echo "Copyright (c) 2019: Miguel Asin, Gabriel Martin" # TODO: líneas a los valores correctos # Llamar al compilador -echo "Compiling $INPUT_FILE into $OUTPUT_FILE" +#"Compiling $INPUT_FILE into $OUTPUT_FILE" + +python3 Compiler/compiler.py $INPUT_FILE +# spim -file $OUTPUT_FILE