From a2285e2885b845769744aa1fd92536f70482d980 Mon Sep 17 00:00:00 2001 From: Ale Date: Mon, 13 Dec 2021 18:14:40 -0800 Subject: [PATCH 01/83] cmp files --- src/cmp/__init__.py | 0 src/cmp/ast.py | 62 +++ src/cmp/automata.py | 207 +++++++ src/cmp/cil.py | 231 ++++++++ src/cmp/evaluation.py | 33 ++ src/cmp/languages.py | 228 ++++++++ src/cmp/nbpackage.py | 87 +++ src/cmp/pycompiler.py | 512 ++++++++++++++++++ src/cmp/semantic.py | 264 +++++++++ .../.ipynb_checkpoints/__init__-checkpoint.py | 0 .../.ipynb_checkpoints/automata-checkpoint.py | 3 + .../evaluation-checkpoint.py | 3 + .../.ipynb_checkpoints/parsing-checkpoint.py | 10 + src/cmp/tools/__init__.py | 0 src/cmp/tools/automata.py | 3 + src/cmp/tools/evaluation.py | 3 + src/cmp/tools/parsing.py | 16 + src/cmp/tools/regex.py | 3 + src/cmp/utils.py | 219 ++++++++ src/cmp/visitor.py | 80 +++ 20 files changed, 1964 insertions(+) create mode 100644 src/cmp/__init__.py create mode 100644 src/cmp/ast.py create mode 100644 src/cmp/automata.py create mode 100644 src/cmp/cil.py create mode 100644 src/cmp/evaluation.py create mode 100644 src/cmp/languages.py create mode 100644 src/cmp/nbpackage.py create mode 100644 src/cmp/pycompiler.py create mode 100644 src/cmp/semantic.py create mode 100644 src/cmp/tools/.ipynb_checkpoints/__init__-checkpoint.py create mode 100644 src/cmp/tools/.ipynb_checkpoints/automata-checkpoint.py create mode 100644 src/cmp/tools/.ipynb_checkpoints/evaluation-checkpoint.py create mode 100644 src/cmp/tools/.ipynb_checkpoints/parsing-checkpoint.py create mode 100644 src/cmp/tools/__init__.py create mode 100644 src/cmp/tools/automata.py create mode 100644 src/cmp/tools/evaluation.py create mode 100644 src/cmp/tools/parsing.py create mode 100644 src/cmp/tools/regex.py create mode 100644 src/cmp/utils.py create mode 100644 src/cmp/visitor.py diff --git a/src/cmp/__init__.py b/src/cmp/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/cmp/ast.py b/src/cmp/ast.py new file mode 100644 index 000000000..ec162b83b --- /dev/null +++ b/src/cmp/ast.py @@ -0,0 +1,62 @@ +import cmp.visitor as visitor + +class Node: + def evaluate(self): + raise NotImplementedError() + +class AtomicNode(Node): + def __init__(self, lex): + self.lex = lex + +class UnaryNode(Node): + def __init__(self, node): + self.node = node + + def evaluate(self): + value = self.node.evaluate() + return self.operate(value) + + @staticmethod + def operate(value): + raise NotImplementedError() + +class BinaryNode(Node): + def __init__(self, left, right): + self.left = left + self.right = right + + def evaluate(self): + lvalue = self.left.evaluate() + rvalue = self.right.evaluate() + return self.operate(lvalue, rvalue) + + @staticmethod + def operate(lvalue, rvalue): + raise NotImplementedError() + +def get_printer(AtomicNode=AtomicNode, UnaryNode=UnaryNode, BinaryNode=BinaryNode, ): + + class PrintVisitor(object): + @visitor.on('node') + def visit(self, node, tabs): + pass + + @visitor.when(UnaryNode) + def visit(self, node, tabs=0): + ans = '\t' * tabs + f'\\__ {node.__class__.__name__}' + child = self.visit(node.node, tabs + 1) + return f'{ans}\n{child}' + + @visitor.when(BinaryNode) + def visit(self, node, tabs=0): + ans = '\t' * tabs + f'\\__ {node.__class__.__name__} ' + left = self.visit(node.left, tabs + 1) + right = self.visit(node.right, tabs + 1) + return f'{ans}\n{left}\n{right}' + + @visitor.when(AtomicNode) + def visit(self, node, tabs=0): + return '\t' * tabs + f'\\__ {node.__class__.__name__}: {node.lex}' + + printer = PrintVisitor() + return (lambda ast: printer.visit(ast)) \ No newline at end of file diff --git a/src/cmp/automata.py b/src/cmp/automata.py new file mode 100644 index 000000000..f42b6f00c --- /dev/null +++ b/src/cmp/automata.py @@ -0,0 +1,207 @@ +try: + import pydot +except: + pass + +class State: + def __init__(self, state, final=False, formatter=lambda x: str(x), shape='circle'): + self.state = state + self.final = final + self.transitions = {} + self.epsilon_transitions = set() + self.tag = None + self.formatter = formatter + self.shape = shape + + # The method name is set this way from compatibility issues. + def set_formatter(self, value, attr='formatter', visited=None): + if visited is None: + visited = set() + elif self in visited: + return + + visited.add(self) + self.__setattr__(attr, value) + for destinations in self.transitions.values(): + for node in destinations: + node.set_formatter(value, attr, visited) + for node in self.epsilon_transitions: + node.set_formatter(value, attr, visited) + return self + + def has_transition(self, symbol): + return symbol in self.transitions + + def add_transition(self, symbol, state): + try: + self.transitions[symbol].append(state) + except: + self.transitions[symbol] = [state] + return self + + def add_epsilon_transition(self, state): + self.epsilon_transitions.add(state) + return self + + def recognize(self, string): + states = self.epsilon_closure + for symbol in string: + states = self.move_by_state(symbol, *states) + states = self.epsilon_closure_by_state(*states) + return any(s.final for s in states) + + def to_deterministic(self, formatter=lambda x: str(x)): + closure = self.epsilon_closure + start = State(tuple(closure), any(s.final for s in closure), formatter) + + closures = [ closure ] + states = [ start ] + pending = [ start ] + + while pending: + state = pending.pop() + symbols = { symbol for s in state.state for symbol in s.transitions } + + for symbol in symbols: + move = self.move_by_state(symbol, *state.state) + closure = self.epsilon_closure_by_state(*move) + + if closure not in closures: + new_state = State(tuple(closure), any(s.final for s in closure), formatter) + closures.append(closure) + states.append(new_state) + pending.append(new_state) + else: + index = closures.index(closure) + new_state = states[index] + + state.add_transition(symbol, new_state) + + return start + + @staticmethod + def from_nfa(nfa, get_states=False): + states = [] + for n in range(nfa.states): + state = State(n, n in nfa.finals) + states.append(state) + + for (origin, symbol), destinations in nfa.map.items(): + origin = states[origin] + origin[symbol] = [ states[d] for d in destinations ] + + if get_states: + return states[nfa.start], states + return states[nfa.start] + + @staticmethod + def move_by_state(symbol, *states): + return { s for state in states if state.has_transition(symbol) for s in state[symbol]} + + @staticmethod + def epsilon_closure_by_state(*states): + closure = { state for state in states } + + l = 0 + while l != len(closure): + l = len(closure) + tmp = [s for s in closure] + for s in tmp: + for epsilon_state in s.epsilon_transitions: + closure.add(epsilon_state) + return closure + + @property + def epsilon_closure(self): + return self.epsilon_closure_by_state(self) + + @property + def name(self): + return self.formatter(self.state) + + def get(self, symbol): + target = self.transitions[symbol] + assert len(target) == 1 + return target[0] + + def __getitem__(self, symbol): + if symbol == '': + return self.epsilon_transitions + try: + return self.transitions[symbol] + except KeyError: + return None + + def __setitem__(self, symbol, value): + if symbol == '': + self.epsilon_transitions = value + else: + self.transitions[symbol] = value + + def __repr__(self): + return str(self) + + def __str__(self): + return str(self.state) + + def __hash__(self): + return hash(self.state) + + def __iter__(self): + yield from self._visit() + + def _visit(self, visited=None): + if visited is None: + visited = set() + elif self in visited: + return + + visited.add(self) + yield self + + for destinations in self.transitions.values(): + for node in destinations: + yield from node._visit(visited) + for node in self.epsilon_transitions: + yield from node._visit(visited) + + def graph(self): + G = pydot.Dot(rankdir='LR', margin=0.1) + G.add_node(pydot.Node('start', shape='plaintext', label='', width=0, height=0)) + + visited = set() + def visit(start): + ids = id(start) + if ids not in visited: + visited.add(ids) + G.add_node(pydot.Node(ids, label=start.name, shape=self.shape, style='bold' if start.final else '')) + for tran, destinations in start.transitions.items(): + for end in destinations: + visit(end) + G.add_edge(pydot.Edge(ids, id(end), label=tran, labeldistance=2)) + for end in start.epsilon_transitions: + visit(end) + G.add_edge(pydot.Edge(ids, id(end), label='ε', labeldistance=2)) + + visit(self) + G.add_edge(pydot.Edge('start', id(self), label='', style='dashed')) + + return G + + def _repr_svg_(self): + try: + return self.graph().create_svg().decode('utf8') + except: + pass + + def write_to(self, fname): + return self.graph().write_svg(fname) + +def multiline_formatter(state): + return '\n'.join(str(item) for item in state) + +def lr0_formatter(state): + try: + return '\n'.join(str(item)[:-4] for item in state) + except TypeError: + return str(state)[:-4] \ No newline at end of file diff --git a/src/cmp/cil.py b/src/cmp/cil.py new file mode 100644 index 000000000..de6782c16 --- /dev/null +++ b/src/cmp/cil.py @@ -0,0 +1,231 @@ +import cmp.visitor as visitor + + +class Node: + pass + +class ProgramNode(Node): + def __init__(self, dottypes, dotdata, dotcode): + self.dottypes = dottypes + self.dotdata = dotdata + self.dotcode = dotcode + +class TypeNode(Node): + def __init__(self, name): + self.name = name + self.attributes = [] + self.methods = [] + +class DataNode(Node): + def __init__(self, vname, value): + self.name = vname + self.value = value + +class FunctionNode(Node): + 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): + def __init__(self, dest, source): + self.dest = dest + self.source = source + +class ArithmeticNode(InstructionNode): + def __init__(self, dest, left, right): + self.dest = dest + self.left = left + self.right = right + +class PlusNode(ArithmeticNode): + pass + +class MinusNode(ArithmeticNode): + pass + +class StarNode(ArithmeticNode): + pass + +class DivNode(ArithmeticNode): + pass + +class GetAttribNode(InstructionNode): + pass + +class SetAttribNode(InstructionNode): + pass + +class GetIndexNode(InstructionNode): + pass + +class SetIndexNode(InstructionNode): + pass + +class AllocateNode(InstructionNode): + def __init__(self, itype, dest): + self.type = itype + self.dest = dest + +class ArrayNode(InstructionNode): + pass + +class TypeOfNode(InstructionNode): + def __init__(self, obj, dest): + self.obj = obj + self.dest = dest + +class LabelNode(InstructionNode): + pass + +class GotoNode(InstructionNode): + pass + +class GotoIfNode(InstructionNode): + pass + +class StaticCallNode(InstructionNode): + def __init__(self, function, dest): + self.function = function + self.dest = dest + +class DynamicCallNode(InstructionNode): + def __init__(self, xtype, method, dest): + self.type = xtype + self.method = method + self.dest = dest + +class ArgNode(InstructionNode): + def __init__(self, name): + self.name = name + +class ReturnNode(InstructionNode): + def __init__(self, value=None): + self.value = value + +class LoadNode(InstructionNode): + def __init__(self, dest, msg): + self.dest = dest + self.msg = msg + +class LengthNode(InstructionNode): + pass + +class ConcatNode(InstructionNode): + pass + +class PrefixNode(InstructionNode): + pass + +class SubstringNode(InstructionNode): + pass + +class ToStrNode(InstructionNode): + def __init__(self, dest, ivalue): + self.dest = dest + self.ivalue = ivalue + +class ReadNode(InstructionNode): + def __init__(self, dest): + self.dest = dest + +class PrintNode(InstructionNode): + def __init__(self, str_addr): + self.str_addr = str_addr + +def get_formatter(): + + class PrintVisitor(object): + @visitor.on('node') + def visit(self, node): + pass + + @visitor.when(ProgramNode) + def visit(self, node): + dottypes = '\n'.join(self.visit(t) for t in node.dottypes) + dotdata = '\n'.join(self.visit(t) for t in node.dotdata) + dotcode = '\n'.join(self.visit(t) for t in node.dotcode) + + return f'.TYPES\n{dottypes}\n\n.DATA\n{dotdata}\n\n.CODE\n{dotcode}' + + @visitor.when(TypeNode) + def visit(self, node): + attributes = '\n\t'.join(f'attribute {x}' for x in node.attributes) + methods = '\n\t'.join(f'method {x}: {y}' for x,y in node.methods) + + return f'type {node.name} {{\n\t{attributes}\n\n\t{methods}\n}}' + + @visitor.when(FunctionNode) + def visit(self, node): + params = '\n\t'.join(self.visit(x) for x in node.params) + localvars = '\n\t'.join(self.visit(x) for x in node.localvars) + instructions = '\n\t'.join(self.visit(x) for x in node.instructions) + + return f'function {node.name} {{\n\t{params}\n\n\t{localvars}\n\n\t{instructions}\n}}' + + @visitor.when(ParamNode) + def visit(self, node): + return f'PARAM {node.name}' + + @visitor.when(LocalNode) + def visit(self, node): + return f'LOCAL {node.name}' + + @visitor.when(AssignNode) + def visit(self, node): + return f'{node.dest} = {node.source}' + + @visitor.when(PlusNode) + def visit(self, node): + return f'{node.dest} = {node.left} + {node.right}' + + @visitor.when(MinusNode) + def visit(self, node): + return f'{node.dest} = {node.left} - {node.right}' + + @visitor.when(StarNode) + def visit(self, node): + return f'{node.dest} = {node.left} * {node.right}' + + @visitor.when(DivNode) + def visit(self, node): + return f'{node.dest} = {node.left} / {node.right}' + + @visitor.when(AllocateNode) + def visit(self, node): + return f'{node.dest} = ALLOCATE {node.type}' + + @visitor.when(TypeOfNode) + def visit(self, node): + return f'{node.dest} = TYPEOF {node.type}' + + @visitor.when(StaticCallNode) + def visit(self, node): + return f'{node.dest} = CALL {node.function}' + + @visitor.when(DynamicCallNode) + def visit(self, node): + return f'{node.dest} = VCALL {node.type} {node.method}' + + @visitor.when(ArgNode) + def visit(self, node): + return f'ARG {node.name}' + + @visitor.when(ReturnNode) + def visit(self, node): + return f'RETURN {node.value if node.value is not None else ""}' + + printer = PrintVisitor() + return (lambda ast: printer.visit(ast)) \ No newline at end of file diff --git a/src/cmp/evaluation.py b/src/cmp/evaluation.py new file mode 100644 index 000000000..90bdbf935 --- /dev/null +++ b/src/cmp/evaluation.py @@ -0,0 +1,33 @@ +from cmp.pycompiler import EOF +from cmp.tools.parsing import ShiftReduceParser + +def evaluate_reverse_parse(G, right_parse, operations, tokens): + if not right_parse or not operations or not tokens: + return + + right_parse = iter(right_parse) + tokens = iter(tokens) + stack = [] + for operation in operations: + if operation == ShiftReduceParser.SHIFT: + token = next(tokens) + stack.append(token.lex) + elif operation == ShiftReduceParser.REDUCE: + production = next(right_parse) + head, body = production + attributes = production.attributes + assert all(rule is None for rule in attributes[1:]), 'There must be only synteticed attributes.' + rule = attributes[0] + + if len(body): + synteticed = [None] + stack[-len(body):] + value = rule(None, synteticed) + stack[-len(body):] = [value] + else: + stack.append(rule(None, None)) + else: + raise Exception('Invalid action!!!') + + assert len(stack) == 1 + assert isinstance(G[next(tokens).token_type], EOF) + return stack[0] \ No newline at end of file diff --git a/src/cmp/languages.py b/src/cmp/languages.py new file mode 100644 index 000000000..e2c0c33da --- /dev/null +++ b/src/cmp/languages.py @@ -0,0 +1,228 @@ +from cmp.pycompiler import Sentence, Production +from cmp.utils import ContainerSet, Token, UnknownToken +from cmp.tools.parsing import build_parsing_table, metodo_predictivo_no_recursivo + +class BasicXCool: + def __init__(self, G): + self.G = G + self.fixed_tokens = { lex: Token(lex, G[lex]) for lex in '+ - * / ( )'.split() } + + @property + def firsts(self): + G = self.G + return { + G['+']: ContainerSet(G['+'] , contains_epsilon=False), + G['-']: ContainerSet(G['-'] , contains_epsilon=False), + G['*']: ContainerSet(G['*'] , contains_epsilon=False), + G['/']: ContainerSet(G['/'] , contains_epsilon=False), + G['(']: ContainerSet(G['('] , contains_epsilon=False), + G[')']: ContainerSet(G[')'] , contains_epsilon=False), + G['num']: ContainerSet(G['num'] , contains_epsilon=False), + G['E']: ContainerSet(G['num'], G['('] , contains_epsilon=False), + G['T']: ContainerSet(G['num'], G['('] , contains_epsilon=False), + G['F']: ContainerSet(G['num'], G['('] , contains_epsilon=False), + G['X']: ContainerSet(G['-'], G['+'] , contains_epsilon=True), + G['Y']: ContainerSet(G['/'], G['*'] , contains_epsilon=True), + Sentence(G['T'], G['X']): ContainerSet(G['num'], G['('] , contains_epsilon=False), + Sentence(G['+'], G['T'], G['X']): ContainerSet(G['+'] , contains_epsilon=False), + Sentence(G['-'], G['T'], G['X']): ContainerSet(G['-'] , contains_epsilon=False), + G.Epsilon: ContainerSet( contains_epsilon=True), + Sentence(G['F'], G['Y']): ContainerSet(G['num'], G['('] , contains_epsilon=False), + Sentence(G['*'], G['F'], G['Y']): ContainerSet(G['*'] , contains_epsilon=False), + Sentence(G['/'], G['F'], G['Y']): ContainerSet(G['/'] , contains_epsilon=False), + Sentence(G['num']): ContainerSet(G['num'] , contains_epsilon=False), + Sentence(G['('], G['E'], G[')']): ContainerSet(G['('] , contains_epsilon=False) + } + + @property + def follows(self): + G = self.G + return { + G['E']: ContainerSet(G[')'], G.EOF , contains_epsilon=False), + G['T']: ContainerSet(G[')'], G['-'], G.EOF, G['+'] , contains_epsilon=False), + G['F']: ContainerSet(G['-'], G.EOF, G['*'], G['/'], G[')'], G['+'] , contains_epsilon=False), + G['X']: ContainerSet(G[')'], G.EOF , contains_epsilon=False), + G['Y']: ContainerSet(G[')'], G['-'], G.EOF, G['+'] , contains_epsilon=False) + } + + @property + def table(self): + G = self.G + return { + ( G['E'], G['num'], ): [ Production(G['E'], Sentence(G['T'], G['X'])), ], + ( G['E'], G['('], ): [ Production(G['E'], Sentence(G['T'], G['X'])), ], + ( G['X'], G['+'], ): [ Production(G['X'], Sentence(G['+'], G['T'], G['X'])), ], + ( G['X'], G['-'], ): [ Production(G['X'], Sentence(G['-'], G['T'], G['X'])), ], + ( G['X'], G[')'], ): [ Production(G['X'], G.Epsilon), ], + ( G['X'], G.EOF, ): [ Production(G['X'], G.Epsilon), ], + ( G['T'], G['num'], ): [ Production(G['T'], Sentence(G['F'], G['Y'])), ], + ( G['T'], G['('], ): [ Production(G['T'], Sentence(G['F'], G['Y'])), ], + ( G['Y'], G['*'], ): [ Production(G['Y'], Sentence(G['*'], G['F'], G['Y'])), ], + ( G['Y'], G['/'], ): [ Production(G['Y'], Sentence(G['/'], G['F'], G['Y'])), ], + ( G['Y'], G[')'], ): [ Production(G['Y'], G.Epsilon), ], + ( G['Y'], G['-'], ): [ Production(G['Y'], G.Epsilon), ], + ( G['Y'], G.EOF, ): [ Production(G['Y'], G.Epsilon), ], + ( G['Y'], G['+'], ): [ Production(G['Y'], G.Epsilon), ], + ( G['F'], G['num'], ): [ Production(G['F'], Sentence(G['num'])), ], + ( G['F'], G['('], ): [ Production(G['F'], Sentence(G['('], G['E'], G[')'])), ] + } + + @property + def tokenizer(self): + G = self.G + fixed_tokens = self.fixed_tokens + + def tokenize_text(text): + tokens = [] + for item in text.split(): + try: + float(item) + token = Token(item, G['num']) + except ValueError: + try: + token = fixed_tokens[item] + except: + token = UnknownToken(item) + tokens.append(token) + eof = Token('$', G.EOF) + tokens.append(eof) + return tokens + + return tokenize_text + +class PowXCool: + def __init__(self, G): + self.G = G + + @property + def firsts(self): + G = self.G + return { + G['+']: ContainerSet(G['+'] , contains_epsilon=False), + G['-']: ContainerSet(G['-'] , contains_epsilon=False), + G['*']: ContainerSet(G['*'] , contains_epsilon=False), + G['/']: ContainerSet(G['/'] , contains_epsilon=False), + G['^']: ContainerSet(G['^'] , contains_epsilon=False), + G['(']: ContainerSet(G['('] , contains_epsilon=False), + G[')']: ContainerSet(G[')'] , contains_epsilon=False), + G['num']: ContainerSet(G['num'] , contains_epsilon=False), + G['E']: ContainerSet(G['num'], G['('] , contains_epsilon=False), + G['T']: ContainerSet(G['num'], G['('] , contains_epsilon=False), + G['F']: ContainerSet(G['num'], G['('] , contains_epsilon=False), + G['A']: ContainerSet(G['num'], G['('] , contains_epsilon=False), + G['X']: ContainerSet(G['-'], G['+'] , contains_epsilon=True), + G['Y']: ContainerSet(G['/'], G['*'] , contains_epsilon=True), + G['Z']: ContainerSet(G['^'] , contains_epsilon=True), + Sentence(G['T'], G['X']): ContainerSet(G['num'], G['('] , contains_epsilon=False), + Sentence(G['+'], G['T'], G['X']): ContainerSet(G['+'] , contains_epsilon=False), + Sentence(G['-'], G['T'], G['X']): ContainerSet(G['-'] , contains_epsilon=False), + G.Epsilon: ContainerSet( contains_epsilon=True), + Sentence(G['F'], G['Y']): ContainerSet(G['num'], G['('] , contains_epsilon=False), + Sentence(G['*'], G['F'], G['Y']): ContainerSet(G['*'] , contains_epsilon=False), + Sentence(G['/'], G['F'], G['Y']): ContainerSet(G['/'] , contains_epsilon=False), + Sentence(G['A'], G['Z']): ContainerSet(G['num'], G['('] , contains_epsilon=False), + Sentence(G['^'], G['F']): ContainerSet(G['^'] , contains_epsilon=False), + Sentence(G['num']): ContainerSet(G['num'] , contains_epsilon=False), + Sentence(G['('], G['E'], G[')']): ContainerSet(G['('] , contains_epsilon=False) + } + + @property + def follows(self): + G = self.G + return { + G['E']: ContainerSet(G[')'], G.EOF , contains_epsilon=False), + G['T']: ContainerSet(G['-'], G[')'], G.EOF, G['+'] , contains_epsilon=False), + G['F']: ContainerSet(G['-'], G['*'], G['/'], G[')'], G.EOF, G['+'] , contains_epsilon=False), + G['A']: ContainerSet(G['-'], G['*'], G['/'], G['^'], G[')'], G.EOF, G['+'] , contains_epsilon=False), + G['X']: ContainerSet(G[')'], G.EOF , contains_epsilon=False), + G['Y']: ContainerSet(G['-'], G[')'], G.EOF, G['+'] , contains_epsilon=False), + G['Z']: ContainerSet(G['-'], G['*'], G['/'], G[')'], G.EOF, G['+'] , contains_epsilon=False) + } + +class Regex: + def __init__(self, G): + self.G = G + + @property + def firsts(self): + G = self.G + return { + G['|']: ContainerSet(G['|'] , contains_epsilon=False), + G['*']: ContainerSet(G['*'] , contains_epsilon=False), + G['(']: ContainerSet(G['('] , contains_epsilon=False), + G[')']: ContainerSet(G[')'] , contains_epsilon=False), + G['symbol']: ContainerSet(G['symbol'] , contains_epsilon=False), + G['ε']: ContainerSet(G['ε'] , contains_epsilon=False), + G['E']: ContainerSet(G['symbol'], G['ε'], G['('] , contains_epsilon=False), + G['T']: ContainerSet(G['symbol'], G['ε'], G['('] , contains_epsilon=False), + G['F']: ContainerSet(G['symbol'], G['ε'], G['('] , contains_epsilon=False), + G['A']: ContainerSet(G['ε'], G['symbol'], G['('] , contains_epsilon=False), + G['X']: ContainerSet(G['|'] , contains_epsilon=True), + G['Y']: ContainerSet(G['symbol'], G['ε'], G['('] , contains_epsilon=True), + G['Z']: ContainerSet(G['*'] , contains_epsilon=True), + Sentence(G['T'], G['X']): ContainerSet(G['symbol'], G['ε'], G['('] , contains_epsilon=False), + Sentence(G['|'], G['E']): ContainerSet(G['|'] , contains_epsilon=False), + G.Epsilon: ContainerSet( contains_epsilon=True), + Sentence(G['F'], G['Y']): ContainerSet(G['symbol'], G['ε'], G['('] , contains_epsilon=False), + Sentence(G['T']): ContainerSet(G['symbol'], G['ε'], G['('] , contains_epsilon=False), + Sentence(G['A'], G['Z']): ContainerSet(G['symbol'], G['ε'], G['('] , contains_epsilon=False), + Sentence(G['*']): ContainerSet(G['*'] , contains_epsilon=False), + Sentence(G['symbol']): ContainerSet(G['symbol'] , contains_epsilon=False), + Sentence(G['ε']): ContainerSet(G['ε'] , contains_epsilon=False), + Sentence(G['('], G['E'], G[')']): ContainerSet(G['('] , contains_epsilon=False) + } + + @property + def follows(self): + G = self.G + return { + G['E']: ContainerSet(G[')'], G.EOF , contains_epsilon=False), + G['T']: ContainerSet(G[')'], G.EOF, G['|'] , contains_epsilon=False), + G['F']: ContainerSet(G[')'], G.EOF, G['symbol'], G['|'], G['ε'], G['('] , contains_epsilon=False), + G['A']: ContainerSet(G.EOF, G['|'], G['*'], G['('], G[')'], G['symbol'], G['ε'] , contains_epsilon=False), + G['X']: ContainerSet(G[')'], G.EOF , contains_epsilon=False), + G['Y']: ContainerSet(G[')'], G.EOF, G['|'] , contains_epsilon=False), + G['Z']: ContainerSet(G.EOF, G['|'], G['('], G[')'], G['symbol'], G['ε'] , contains_epsilon=False) + } + + @property + def table(self): + G = self.G + return { + ( G['E'], G['symbol'], ): [ Production(G['E'], Sentence(G['T'], G['X'])), ], + ( G['E'], G['ε'], ): [ Production(G['E'], Sentence(G['T'], G['X'])), ], + ( G['E'], G['('], ): [ Production(G['E'], Sentence(G['T'], G['X'])), ], + ( G['X'], G['|'], ): [ Production(G['X'], Sentence(G['|'], G['E'])), ], + ( G['X'], G[')'], ): [ Production(G['X'], G.Epsilon), ], + ( G['X'], G.EOF, ): [ Production(G['X'], G.Epsilon), ], + ( G['T'], G['symbol'], ): [ Production(G['T'], Sentence(G['F'], G['Y'])), ], + ( G['T'], G['ε'], ): [ Production(G['T'], Sentence(G['F'], G['Y'])), ], + ( G['T'], G['('], ): [ Production(G['T'], Sentence(G['F'], G['Y'])), ], + ( G['Y'], G['symbol'], ): [ Production(G['Y'], Sentence(G['T'])), ], + ( G['Y'], G['ε'], ): [ Production(G['Y'], Sentence(G['T'])), ], + ( G['Y'], G['('], ): [ Production(G['Y'], Sentence(G['T'])), ], + ( G['Y'], G[')'], ): [ Production(G['Y'], G.Epsilon), ], + ( G['Y'], G.EOF, ): [ Production(G['Y'], G.Epsilon), ], + ( G['Y'], G['|'], ): [ Production(G['Y'], G.Epsilon), ], + ( G['F'], G['symbol'], ): [ Production(G['F'], Sentence(G['A'], G['Z'])), ], + ( G['F'], G['ε'], ): [ Production(G['F'], Sentence(G['A'], G['Z'])), ], + ( G['F'], G['('], ): [ Production(G['F'], Sentence(G['A'], G['Z'])), ], + ( G['Z'], G['*'], ): [ Production(G['Z'], Sentence(G['*'])), ], + ( G['Z'], G.EOF, ): [ Production(G['Z'], G.Epsilon), ], + ( G['Z'], G['|'], ): [ Production(G['Z'], G.Epsilon), ], + ( G['Z'], G['('], ): [ Production(G['Z'], G.Epsilon), ], + ( G['Z'], G[')'], ): [ Production(G['Z'], G.Epsilon), ], + ( G['Z'], G['symbol'], ): [ Production(G['Z'], G.Epsilon), ], + ( G['Z'], G['ε'], ): [ Production(G['Z'], G.Epsilon), ], + ( G['A'], G['symbol'], ): [ Production(G['A'], Sentence(G['symbol'])), ], + ( G['A'], G['ε'], ): [ Production(G['A'], Sentence(G['ε'])), ], + ( G['A'], G['('], ): [ Production(G['A'], Sentence(G['('], G['E'], G[')'])), ] + } + + @property + def parser(self): + firsts = self.firsts + follows = self.follows + M = build_parsing_table(self.G, firsts, follows) + parser = metodo_predictivo_no_recursivo(self.G, M) + return parser \ No newline at end of file diff --git a/src/cmp/nbpackage.py b/src/cmp/nbpackage.py new file mode 100644 index 000000000..e89c62ad3 --- /dev/null +++ b/src/cmp/nbpackage.py @@ -0,0 +1,87 @@ +import io, os, sys, types + +from IPython import get_ipython +from nbformat import read +from IPython.core.interactiveshell import InteractiveShell + +def find_notebook(fullname, path=None): + """find a notebook, given its fully qualified name and an optional path + + This turns "foo.bar" into "foo/bar.ipynb" + and tries turning "Foo_Bar" into "Foo Bar" if Foo_Bar + does not exist. + """ + name = fullname.rsplit('.', 1)[-1] + if not path: + path = [''] + for d in path: + nb_path = os.path.join(d, name + ".ipynb") + if os.path.isfile(nb_path): + return nb_path + # let import Notebook_Name find "Notebook Name.ipynb" + nb_path = nb_path.replace("_", " ") + if os.path.isfile(nb_path): + return nb_path + +class NotebookLoader(object): + """Module Loader for Jupyter Notebooks""" + def __init__(self, path=None): + self.shell = InteractiveShell.instance() + self.path = path + + def load_module(self, fullname): + """import a notebook as a module""" + path = find_notebook(fullname, self.path) + + print ("importing Jupyter notebook from %s" % path) + + # load the notebook object + with io.open(path, 'r', encoding='utf-8') as f: + nb = read(f, 4) + + + # create the module and add it to sys.modules + # if name in sys.modules: + # return sys.modules[name] + mod = types.ModuleType(fullname) + mod.__file__ = path + mod.__loader__ = self + mod.__dict__['get_ipython'] = get_ipython + sys.modules[fullname] = mod + + # extra work to ensure that magics that would affect the user_ns + # actually affect the notebook module's ns + save_user_ns = self.shell.user_ns + self.shell.user_ns = mod.__dict__ + + try: + for cell in nb.cells: + if cell.cell_type == 'code': + # transform the input to executable Python + code = self.shell.input_transformer_manager.transform_cell(cell.source) + # run the code in themodule + exec(code, mod.__dict__) + finally: + self.shell.user_ns = save_user_ns + return mod + +class NotebookFinder(object): + """Module finder that locates Jupyter Notebooks""" + def __init__(self): + self.loaders = {} + + def find_module(self, fullname, path=None): + nb_path = find_notebook(fullname, path) + if not nb_path: + return + + key = path + if path: + # lists aren't hashable + key = os.path.sep.join(path) + + if key not in self.loaders: + self.loaders[key] = NotebookLoader(path) + return self.loaders[key] + +sys.meta_path.append(NotebookFinder()) \ No newline at end of file diff --git a/src/cmp/pycompiler.py b/src/cmp/pycompiler.py new file mode 100644 index 000000000..2815e9ea3 --- /dev/null +++ b/src/cmp/pycompiler.py @@ -0,0 +1,512 @@ +import json + +class Symbol(object): + + def __init__(self, name, grammar): + self.Name = name + self.Grammar = grammar + + def __str__(self): + return self.Name + + def __repr__(self): + return repr(self.Name) + + def __add__(self, other): + if isinstance(other, Symbol): + return Sentence(self, other) + + raise TypeError(other) + + def __or__(self, other): + + if isinstance(other, (Sentence)): + return SentenceList(Sentence(self), other) + + raise TypeError(other) + + @property + def IsEpsilon(self): + return False + + def __len__(self): + return 1 + +class NonTerminal(Symbol): + + + def __init__(self, name, grammar): + super().__init__(name, grammar) + self.productions = [] + + + def __imod__(self, other): + + if isinstance(other, (Sentence)): + p = Production(self, other) + self.Grammar.Add_Production(p) + return self + + if isinstance(other, tuple): + assert len(other) > 1 + + if len(other) == 2: + other += (None,) * len(other[0]) + + assert len(other) == len(other[0]) + 2, "Debe definirse una, y solo una, regla por cada símbolo de la producción" + # assert len(other) == 2, "Tiene que ser una Tupla de 2 elementos (sentence, attribute)" + + if isinstance(other[0], Symbol) or isinstance(other[0], Sentence): + p = AttributeProduction(self, other[0], other[1:]) + else: + raise Exception("") + + self.Grammar.Add_Production(p) + return self + + if isinstance(other, Symbol): + p = Production(self, Sentence(other)) + self.Grammar.Add_Production(p) + return self + + if isinstance(other, SentenceList): + + for s in other: + p = Production(self, s) + self.Grammar.Add_Production(p) + + return self + + raise TypeError(other) + + @property + def IsTerminal(self): + return False + + @property + def IsNonTerminal(self): + return True + + @property + def IsEpsilon(self): + return False + +class Terminal(Symbol): + + def __init__(self, name, grammar): + super().__init__(name, grammar) + + @property + def IsTerminal(self): + return True + + @property + def IsNonTerminal(self): + return False + + @property + def IsEpsilon(self): + return False + +class EOF(Terminal): + + def __init__(self, Grammar): + super().__init__('$', Grammar) + +class Sentence(object): + + def __init__(self, *args): + self._symbols = tuple(x for x in args if not x.IsEpsilon) + self.hash = hash(self._symbols) + + def __len__(self): + return len(self._symbols) + + def __add__(self, other): + if isinstance(other, Symbol): + return Sentence(*(self._symbols + (other,))) + + if isinstance(other, Sentence): + return Sentence(*(self._symbols + other._symbols)) + + raise TypeError(other) + + def __or__(self, other): + if isinstance(other, Sentence): + return SentenceList(self, other) + + if isinstance(other, Symbol): + return SentenceList(self, Sentence(other)) + + raise TypeError(other) + + def __repr__(self): + return str(self) + + def __str__(self): + return ("%s " * len(self._symbols) % tuple(self._symbols)).strip() + + def __iter__(self): + return iter(self._symbols) + + def __getitem__(self, index): + return self._symbols[index] + + def __eq__(self, other): + return self._symbols == other._symbols + + def __hash__(self): + return self.hash + + @property + def IsEpsilon(self): + return False + +class SentenceList(object): + + def __init__(self, *args): + self._sentences = list(args) + + def Add(self, symbol): + if not symbol and (symbol is None or not symbol.IsEpsilon): + raise ValueError(symbol) + + self._sentences.append(symbol) + + def __iter__(self): + return iter(self._sentences) + + def __or__(self, other): + if isinstance(other, Sentence): + self.Add(other) + return self + + if isinstance(other, Symbol): + return self | Sentence(other) + + +class Epsilon(Terminal, Sentence): + + def __init__(self, grammar): + super().__init__('epsilon', grammar) + + + def __str__(self): + return "e" + + def __repr__(self): + return 'epsilon' + + def __iter__(self): + yield from () + + def __len__(self): + return 0 + + def __add__(self, other): + return other + + def __eq__(self, other): + return isinstance(other, (Epsilon,)) + + def __hash__(self): + return hash("") + + @property + def IsEpsilon(self): + return True + +class Production(object): + + def __init__(self, nonTerminal, sentence): + + self.Left = nonTerminal + self.Right = sentence + + def __str__(self): + + return '%s := %s' % (self.Left, self.Right) + + def __repr__(self): + return '%s -> %s' % (self.Left, self.Right) + + def __iter__(self): + yield self.Left + yield self.Right + + def __eq__(self, other): + return isinstance(other, Production) and self.Left == other.Left and self.Right == other.Right + + def __hash__(self): + return hash((self.Left, self.Right)) + + @property + def IsEpsilon(self): + return self.Right.IsEpsilon + +class AttributeProduction(Production): + + def __init__(self, nonTerminal, sentence, attributes): + if not isinstance(sentence, Sentence) and isinstance(sentence, Symbol): + sentence = Sentence(sentence) + super(AttributeProduction, self).__init__(nonTerminal, sentence) + + self.attributes = attributes + + def __str__(self): + return '%s := %s' % (self.Left, self.Right) + + def __repr__(self): + return '%s -> %s' % (self.Left, self.Right) + + def __iter__(self): + yield self.Left + yield self.Right + + + @property + def IsEpsilon(self): + return self.Right.IsEpsilon + + # sintetizar en ingles??????, pending aggrement + def syntetice(self): + pass + +class Grammar(): + + def __init__(self): + + self.Productions = [] + self.nonTerminals = [] + self.terminals = [] + self.startSymbol = None + # production type + self.pType = None + self.Epsilon = Epsilon(self) + self.EOF = EOF(self) + + self.symbDict = { 'eof': self.EOF } + + def NonTerminal(self, name, startSymbol = False): + + name = name.strip() + if not name: + raise Exception("Empty name") + + term = NonTerminal(name,self) + + if startSymbol: + + if self.startSymbol is None: + self.startSymbol = term + else: + raise Exception("Cannot define more than one start symbol.") + + self.nonTerminals.append(term) + self.symbDict[name] = term + return term + + def NonTerminals(self, names): + + ans = tuple((self.NonTerminal(x) for x in names.strip().split())) + + return ans + + + def Add_Production(self, production): + + if len(self.Productions) == 0: + self.pType = type(production) + + assert type(production) == self.pType, "The Productions most be of only 1 type." + + production.Left.productions.append(production) + self.Productions.append(production) + + + def Terminal(self, name): + + name = name.strip() + if not name: + raise Exception("Empty name") + + term = Terminal(name, self) + self.terminals.append(term) + self.symbDict[name] = term + return term + + def Terminals(self, names): + + ans = tuple((self.Terminal(x) for x in names.strip().split())) + + return ans + + + def __str__(self): + + mul = '%s, ' + + ans = 'Non-Terminals:\n\t' + + nonterminals = mul * (len(self.nonTerminals)-1) + '%s\n' + + ans += nonterminals % tuple(self.nonTerminals) + + ans += 'Terminals:\n\t' + + terminals = mul * (len(self.terminals)-1) + '%s\n' + + ans += terminals % tuple(self.terminals) + + ans += 'Productions:\n\t' + + ans += str(self.Productions) + + return ans + + def __getitem__(self, name): + try: + return self.symbDict[name] + except KeyError: + return None + + @property + def to_json(self): + + productions = [] + + for p in self.Productions: + head = p.Left.Name + + body = [] + + for s in p.Right: + body.append(s.Name) + + productions.append({'Head':head, 'Body':body}) + + d={'NonTerminals':[symb.Name for symb in self.nonTerminals], 'Terminals': [symb.Name for symb in self.terminals],\ + 'Productions':productions} + + # [{'Head':p.Left.Name, "Body": [s.Name for s in p.Right]} for p in self.Productions] + return json.dumps(d) + + @staticmethod + def from_json(data): + data = json.loads(data) + + G = Grammar() + dic = {'epsilon':G.Epsilon} + + for term in data['Terminals']: + dic[term] = G.Terminal(term) + + for noTerm in data['NonTerminals']: + dic[noTerm] = G.NonTerminal(noTerm) + + for p in data['Productions']: + head = p['Head'] + dic[head] %= Sentence(*[dic[term] for term in p['Body']]) + + return G + + def copy(self): + G = Grammar() + G.Productions = self.Productions.copy() + G.nonTerminals = self.nonTerminals.copy() + G.terminals = self.terminals.copy() + G.pType = self.pType + G.startSymbol = self.startSymbol + G.Epsilon = self.Epsilon + G.EOF = self.EOF + G.symbDict = self.symbDict.copy() + + return G + + @property + def IsAugmentedGrammar(self): + augmented = 0 + for left, right in self.Productions: + if self.startSymbol == left: + augmented += 1 + if augmented <= 1: + return True + else: + return False + + def AugmentedGrammar(self, force=False): + if not self.IsAugmentedGrammar or force: + + G = self.copy() + # S, self.startSymbol, SS = self.startSymbol, None, self.NonTerminal('S\'', True) + S = G.startSymbol + G.startSymbol = None + SS = G.NonTerminal('S\'', True) + if G.pType is AttributeProduction: + SS %= S + G.Epsilon, lambda x : x + else: + SS %= S + G.Epsilon + + return G + else: + return self.copy() + #endchange + +class Item: + + def __init__(self, production, pos, lookaheads=[]): + self.production = production + self.pos = pos + self.lookaheads = frozenset(look for look in lookaheads) + + def __str__(self): + s = str(self.production.Left) + " -> " + if len(self.production.Right) > 0: + for i,c in enumerate(self.production.Right): + if i == self.pos: + s += "." + s += str(self.production.Right[i]) + if self.pos == len(self.production.Right): + s += "." + else: + s += "." + s += ", " + str(self.lookaheads)[10:-1] + return s + + def __repr__(self): + return str(self) + + + def __eq__(self, other): + return ( + (self.pos == other.pos) and + (self.production == other.production) and + (set(self.lookaheads) == set(other.lookaheads)) + ) + + def __hash__(self): + return hash((self.production,self.pos,self.lookaheads)) + + @property + def IsReduceItem(self): + return len(self.production.Right) == self.pos + + @property + def NextSymbol(self): + if self.pos < len(self.production.Right): + return self.production.Right[self.pos] + else: + return None + + def NextItem(self): + if self.pos < len(self.production.Right): + return Item(self.production,self.pos+1,self.lookaheads) + else: + return None + + def Preview(self, skip=1): + unseen = self.production.Right[self.pos+skip:] + return [ unseen + (lookahead,) for lookahead in self.lookaheads ] + + def Center(self): + return Item(self.production, self.pos) \ No newline at end of file diff --git a/src/cmp/semantic.py b/src/cmp/semantic.py new file mode 100644 index 000000000..c463fbe25 --- /dev/null +++ b/src/cmp/semantic.py @@ -0,0 +1,264 @@ +import itertools as itt +from collections import OrderedDict + + +class SemanticError(Exception): + @property + def text(self): + return self.args[0] + +class Attribute: + def __init__(self, name, typex): + self.name = name + self.type = typex + + def __str__(self): + return f'[attrib] {self.name} : {self.type.name};' + + def __repr__(self): + return str(self) + +class Method: + def __init__(self, name, param_names, params_types, return_type): + self.name = name + self.param_names = param_names + self.param_types = params_types + self.return_type = return_type + self.expected_param_types = dict() + self.expected_return_type = None + + def __str__(self): + params = ', '.join(f'{n}:{t.name}' for n,t in zip(self.param_names, self.param_types)) + return f'[method] {self.name}({params}): {self.return_type.name};' + + def __eq__(self, other): + return other.name == self.name and \ + other.return_type == self.return_type and \ + other.param_types == self.param_types + +class Type: + def __init__(self, name:str): + self.name = name + self.attributes = [] + self.methods = [] + self.parent = None + + def set_parent(self, parent): + if self.parent is not None: + raise SemanticError(f'Parent type is already set for {self.name}.') + self.parent = parent + + def get_attribute(self, name:str): + try: + return next(attr for attr in self.attributes if attr.name == name) + except StopIteration: + if self.parent is None: + raise SemanticError(f'Attribute "{name}" is not defined in {self.name}.') + try: + return self.parent.get_attribute(name) + except SemanticError: + raise SemanticError(f'Attribute "{name}" is not defined in {self.name}.') + + def define_attribute(self, name:str, typex): + try: + self.get_attribute(name) + except SemanticError: + attribute = Attribute(name, typex) + self.attributes.append(attribute) + return attribute + else: + raise SemanticError(f'Attribute "{name}" is already defined in {self.name}.') + + def get_method(self, name:str): + try: + return next(method for method in self.methods if method.name == name) + except StopIteration: + if self.parent is None: + raise SemanticError(f'Method "{name}" is not defined in {self.name}.') + try: + return self.parent.get_method(name) + except SemanticError: + raise SemanticError(f'Method "{name}" is not defined in {self.name}.') + + def define_method(self, name:str, param_names:list, param_types:list, return_type): + if name in (method.name for method in self.methods): + raise SemanticError(f'Method "{name}" already defined in {self.name}') + + method = Method(name, param_names, param_types, return_type) + self.methods.append(method) + return method + + def all_attributes(self, clean=True): + plain = OrderedDict() if self.parent is None else self.parent.all_attributes(False) + for attr in self.attributes: + plain[attr.name] = (attr, self) + return plain.values() if clean else plain + + def all_methods(self, clean=True): + plain = OrderedDict() if self.parent is None else self.parent.all_methods(False) + for method in self.methods: + plain[method.name] = (method, self) + return plain.values() if clean else plain + + def conforms_to(self, other): + return other.bypass() or self == other or self.parent is not None and self.parent.conforms_to(other) + + def bypass(self): + return False + + def __str__(self): + output = f'type {self.name}' + parent = '' if self.parent is None else f' : {self.parent.name}' + output += parent + output += ' {' + output += '\n\t' if self.attributes or self.methods else '' + output += '\n\t'.join(str(x) for x in self.attributes) + output += '\n\t' if self.attributes else '' + output += '\n\t'.join(str(x) for x in self.methods) + output += '\n' if self.methods else '' + output += '}\n' + return output + + def __repr__(self): + return str(self) + + def join(self, other): + if self is ErrorType(): return ErrorType() + if self.name == 'AUTO_TYPE' or other.name == 'AUTO_TYPE': + return self if self.name != 'AUTO_TYPE' else other + + current_parent = other + while not self.conforms_to(current_parent): + current_parent = current_parent.parent + + return current_parent + +class AutoType(Type): + def __init__(self): + Type.__init__(self, 'AUTO_TYPE') + + def conforms_to(self, other): + return True + + def bypass(self): + return True + + def get_method(self, name:str): + raise SemanticError(None) + + def __eq__(self, other): + return isinstance(other, Type) + +class ErrorType(Type): + def __init__(self): + Type.__init__(self, '') + + def conforms_to(self, other): + return True + + def bypass(self): + return True + + def get_method(self, name:str): + raise SemanticError(None) + + def __eq__(self, other): + return isinstance(other, Type) + +class VoidType(Type): + def __init__(self): + Type.__init__(self, '') + + def conforms_to(self, other): + raise Exception('Invalid type: void type.') + + def bypass(self): + return True + + def __eq__(self, other): + return isinstance(other, VoidType) + +class IntType(Type): + def __init__(self): + Type.__init__(self, 'int') + + def __eq__(self, other): + return other.name == self.name or isinstance(other, IntType) + +class Context: + def __init__(self): + self.types = {} + + def create_type(self, name:str): + if name in self.types: + raise SemanticError(f'Type with the same name ({name}) already in context.') + typex = self.types[name] = Type(name) + return typex + + def get_type(self, name:str): + if name == '': + return ErrorType() + + try: + return self.types[name] + except KeyError: + raise SemanticError(f'Type "{name}" is not defined.') + + def __str__(self): + return '{\n\t' + '\n\t'.join(y for x in self.types.values() for y in str(x).split('\n')) + '\n}' + + def __repr__(self): + return str(self) + +class VariableInfo: + def __init__(self, name, vtype): + self.name = name + self.type = vtype + self.expected_types = [] + + def update_type(self): + infered_type = self.expected_types[0] if self.expected_types else None + + for typex in self.expected_types[1:]: + infered_type = infered_type.join(typex) + + self.type = infered_type + + if not self.type: + self.type = AutoType() + + self.expected_types = [] + + +class Scope: + def __init__(self, parent=None): + self.locals = [] + self.parent = parent + self.children = [] + 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) + return child + + def define_variable(self, vname, vtype): + info = VariableInfo(vname, vtype) + self.locals.append(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 not 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) diff --git a/src/cmp/tools/.ipynb_checkpoints/__init__-checkpoint.py b/src/cmp/tools/.ipynb_checkpoints/__init__-checkpoint.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/cmp/tools/.ipynb_checkpoints/automata-checkpoint.py b/src/cmp/tools/.ipynb_checkpoints/automata-checkpoint.py new file mode 100644 index 000000000..59643cc5b --- /dev/null +++ b/src/cmp/tools/.ipynb_checkpoints/automata-checkpoint.py @@ -0,0 +1,3 @@ +import zlib, base64 +exec(zlib.decompress(base64.b64decode('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'))) +# Created by pyminifier (https://github.com/liftoff/pyminifier) diff --git a/src/cmp/tools/.ipynb_checkpoints/evaluation-checkpoint.py b/src/cmp/tools/.ipynb_checkpoints/evaluation-checkpoint.py new file mode 100644 index 000000000..d49df0ce5 --- /dev/null +++ b/src/cmp/tools/.ipynb_checkpoints/evaluation-checkpoint.py @@ -0,0 +1,3 @@ +import zlib, base64 +exec(zlib.decompress(base64.b64decode('eJxdUMFuwjAMvecrfGy3qoLrJN86YGViCO2GECrF1SLSpErcqf37OUWwsZPtZ/v5+TXetVC3Xd6NtWs7bciDbjvnGV4/FmqJmsmrE1oaWFnUQdvAla1JFbhxltQaDVm1QLJ9S75iUmdqgL4r00tx7CofKGmyMn1RoBuwjqEB56ekFAw8ce+tggaXSZMqKCWWEge8kSQnaWSRQ0EVAok2K1iZ5uwuZI88dpSJWmlfyWB4EJF03p37mrWzkSXT9ou8/HU+xgHCImrbZAZ/5xSMf6q8Yvb61DMFBYz74vCUrBOTPs/l5OV/vZ8d8N8J+U5e1tkOtIVFYrJ5PBn92OVv4ZN8q21lInR78LLXBx2giBBLjtO/hgYByASaZld4miy7b+0QV/k7NRyxLY6yGDO5swVhi54X0+bEj9vkknF6P3H3azXZFEekGWlmh7u1150HxkmQSP0BhJm25Q=='))) +# Created by pyminifier (https://github.com/liftoff/pyminifier) diff --git a/src/cmp/tools/.ipynb_checkpoints/parsing-checkpoint.py b/src/cmp/tools/.ipynb_checkpoints/parsing-checkpoint.py new file mode 100644 index 000000000..02d672f4b --- /dev/null +++ b/src/cmp/tools/.ipynb_checkpoints/parsing-checkpoint.py @@ -0,0 +1,10 @@ +import zlib, base64 +exec(zlib.decompress(base64.b64decode('eJytVVtr2zAUfvevEH2yqWfa14AeypKGlXlNL5SCMUZO5FTMlhRZbpZu++87ujiOm3QwGJRU56pzvu8cuVKiQUxTpYWoW8QaKZRGrK3ZkgaVMS4bmXSaDcbPgmvCOFUPVAcrWqGlaGSnaVGLJamLiqlWh/a3jUktX0g0CVCFnSZAEltlgKb4MFMYBUirHbiiBZbJl3YmW1YLHiD6Y0mldoZrUrc0QKxCC6OYJi3VBXWeJgMFszFUQqE5YhxJI6EUV9k8N6dp0skV0TRMIyNCIi40SpOlK6Xtk9kwVCpKvsOpT3t8oaK6UxxNR0C4VsO5a/zn7wDN8KPqoHBTV2nqmieAecM49GPrzcp8DEcZOW/tvLngj+MAnR/ht31hNUUzY5/1UNkkty7JQolVt9RMcJsDPePb5CuttDlLON+z9YsVrgCvZ4uXpwQ6B5W0qoGPXntUCEI3+ORUxNJaZ7/wNHkhalV4Nm569dWR2iNcjREWdS22AHHssB6P2GaEObXSX7DcnMJyk82TVhOlH3ZNKep3DvNkdnv9PxG/xxuPuIlmcbszCSjvGqoMEjJygMPAtjvYjm9DD86A7iBDu8udsKcN8pWYZjJm3nLI3oHxA7rcQxCCx/llDHfSKHKRQNVdv0pV6ZVQXFV+sErjkPuB2I0ltuxYvSokUS3j60KTsqZ7cmPP9pjkCo5OH8B+9xSTk7g/Y9LDvoBjj7oJoCagyhb5ZDTuafYc0zwhUlK+Ckn0fvCdHWfEwGr6hgynOx8uMTvlogd6Tt0z5ujwJg9ZaiFrqBYrUUhFVwxafRUFF4Wiyw4wfBWAXooNYx5Ef3aIWcHCyQY8xYAnNJTCRwAZt4lvkB0qTODRa+cdxdhR4FNLa5xT/BHrUCc42CbDrZ38J5zZnYvHWwmWpsEX8O8NZ0ZyC2kW396+xk+JFNK9SQRvs6bJ/bu/hi0ar5BRYkwm+2EGyV7aT3D/OUAHXwRkKjjHl8E7rVSM6/BsppRQCboq4csJPSZJcuaXxXNpgApGocNwLHCarWOSZxd+ee3bYGZJEb6mYU15uHDTHH26jO1f1Ff11A+V98hY7m9+21tOjNs/1u2lt/1sNsEfuhaMXQ=='))) +# Created by pyminifier (https://github.com/liftoff/pyminifier) + +deprecated_metodo_predictivo_no_recursivo = metodo_predictivo_no_recursivo +def metodo_predictivo_no_recursivo(G, M=None, firsts=None, follows=None): + parser = deprecated_metodo_predictivo_no_recursivo(G, M, firsts, follows) + def updated(tokens): + return parser([t.token_type for t in tokens]) + return updated \ No newline at end of file diff --git a/src/cmp/tools/__init__.py b/src/cmp/tools/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/cmp/tools/automata.py b/src/cmp/tools/automata.py new file mode 100644 index 000000000..59643cc5b --- /dev/null +++ b/src/cmp/tools/automata.py @@ -0,0 +1,3 @@ +import zlib, base64 +exec(zlib.decompress(base64.b64decode('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'))) +# Created by pyminifier (https://github.com/liftoff/pyminifier) diff --git a/src/cmp/tools/evaluation.py b/src/cmp/tools/evaluation.py new file mode 100644 index 000000000..d49df0ce5 --- /dev/null +++ b/src/cmp/tools/evaluation.py @@ -0,0 +1,3 @@ +import zlib, base64 +exec(zlib.decompress(base64.b64decode('eJxdUMFuwjAMvecrfGy3qoLrJN86YGViCO2GECrF1SLSpErcqf37OUWwsZPtZ/v5+TXetVC3Xd6NtWs7bciDbjvnGV4/FmqJmsmrE1oaWFnUQdvAla1JFbhxltQaDVm1QLJ9S75iUmdqgL4r00tx7CofKGmyMn1RoBuwjqEB56ekFAw8ce+tggaXSZMqKCWWEge8kSQnaWSRQ0EVAok2K1iZ5uwuZI88dpSJWmlfyWB4EJF03p37mrWzkSXT9ou8/HU+xgHCImrbZAZ/5xSMf6q8Yvb61DMFBYz74vCUrBOTPs/l5OV/vZ8d8N8J+U5e1tkOtIVFYrJ5PBn92OVv4ZN8q21lInR78LLXBx2giBBLjtO/hgYByASaZld4miy7b+0QV/k7NRyxLY6yGDO5swVhi54X0+bEj9vkknF6P3H3azXZFEekGWlmh7u1150HxkmQSP0BhJm25Q=='))) +# Created by pyminifier (https://github.com/liftoff/pyminifier) diff --git a/src/cmp/tools/parsing.py b/src/cmp/tools/parsing.py new file mode 100644 index 000000000..d0275cbcb --- /dev/null +++ b/src/cmp/tools/parsing.py @@ -0,0 +1,16 @@ +import zlib, base64 +exec(zlib.decompress(base64.b64decode('eJytVVtr2zAUfvevEH2yqWfa14AeypKGlXlNL5SCMUZO5FTMlhRZbpZu++87ujiOm3QwGJRU56pzvu8cuVKiQUxTpYWoW8QaKZRGrK3ZkgaVMS4bmXSaDcbPgmvCOFUPVAcrWqGlaGSnaVGLJamLiqlWh/a3jUktX0g0CVCFnSZAEltlgKb4MFMYBUirHbiiBZbJl3YmW1YLHiD6Y0mldoZrUrc0QKxCC6OYJi3VBXWeJgMFszFUQqE5YhxJI6EUV9k8N6dp0skV0TRMIyNCIi40SpOlK6Xtk9kwVCpKvsOpT3t8oaK6UxxNR0C4VsO5a/zn7wDN8KPqoHBTV2nqmieAecM49GPrzcp8DEcZOW/tvLngj+MAnR/ht31hNUUzY5/1UNkkty7JQolVt9RMcJsDPePb5CuttDlLON+z9YsVrgCvZ4uXpwQ6B5W0qoGPXntUCEI3+ORUxNJaZ7/wNHkhalV4Nm569dWR2iNcjREWdS22AHHssB6P2GaEObXSX7DcnMJyk82TVhOlH3ZNKep3DvNkdnv9PxG/xxuPuIlmcbszCSjvGqoMEjJygMPAtjvYjm9DD86A7iBDu8udsKcN8pWYZjJm3nLI3oHxA7rcQxCCx/llDHfSKHKRQNVdv0pV6ZVQXFV+sErjkPuB2I0ltuxYvSokUS3j60KTsqZ7cmPP9pjkCo5OH8B+9xSTk7g/Y9LDvoBjj7oJoCagyhb5ZDTuafYc0zwhUlK+Ckn0fvCdHWfEwGr6hgynOx8uMTvlogd6Tt0z5ujwJg9ZaiFrqBYrUUhFVwxafRUFF4Wiyw4wfBWAXooNYx5Ef3aIWcHCyQY8xYAnNJTCRwAZt4lvkB0qTODRa+cdxdhR4FNLa5xT/BHrUCc42CbDrZ38J5zZnYvHWwmWpsEX8O8NZ0ZyC2kW396+xk+JFNK9SQRvs6bJ/bu/hi0ar5BRYkwm+2EGyV7aT3D/OUAHXwRkKjjHl8E7rVSM6/BsppRQCboq4csJPSZJcuaXxXNpgApGocNwLHCarWOSZxd+ee3bYGZJEb6mYU15uHDTHH26jO1f1Ff11A+V98hY7m9+21tOjNs/1u2lt/1sNsEfuhaMXQ=='))) +# Created by pyminifier (https://github.com/liftoff/pyminifier) + +deprecated_metodo_predictivo_no_recursivo = metodo_predictivo_no_recursivo +def metodo_predictivo_no_recursivo(G, M=None, firsts=None, follows=None): + parser = deprecated_metodo_predictivo_no_recursivo(G, M, firsts, follows) + def updated(tokens): + return parser([t.token_type for t in tokens]) + return updated + +exec(zlib.decompress(base64.b64decode('eJx9U8GO2jAQvfMVZi9JtCFarqiuVLUsRUilWranCEUmGcBaY0e2s3TV7b/X9iQhpaiXxJ4Zv3nzZqYUzBiyOfK9fYKqKeE70wb0bEQ2X5ePzzQKv2hEnuZffnye0wj/zrBe0Wi9cocK9qQouOS2KGIDYp8u0lfQO2WAPjJhIHFoxDuyBV10xy6i/XdmVlquJP31uzMclFWDa7FruKiK2rHk8lBYthMQJy2JWz7/KhDQjBsg35RdnmoBJ5AWqrnWSvfPi5IJ0dVwTg9gC+OFKXRQZliMZeULzR+27lw22ihNH9xRNbZuLM29WdWgma/F4P185ALIs27AA3gECzTg5JOpDyBCqRd2BFbRc46gwcz3fwk2qzWXNg4v0+jDZDJ5f3efj1HavZptE3wXhyRpj5tIZQmXQ6EDF4KQ/4QnA+ddkCojn3ZKW6dulmV36NdgGy2dsNI3kSBuatmBDvLkV9hdZW27MTSMGjK6qJexugZZxZcITBsEuKd5D+lTBti2I/d06m8grtPgBP83D4ZgImxq53ZJ0BxS7lT1Rp0pWPZKE/N22inhRdbgGmagin1MgtmQdFarOkYQ4pYPtB3aHcmA0RV5PSUkLES/Gq2wvaa9LoGfj9jeVmG9mo1uUbrJKOxu5mzabi7s2lABEsfRRU6HI4HK+Tb7wbteJ8fJQIwx6aUPCdI1uCbt1s5/llB7dxwt5SsTvGqLGY/HUTL6AyImjec='))) +# Created by pyminifier (https://github.com/liftoff/pyminifier) + +exec(zlib.decompress(base64.b64decode('eJyFVltP4zoQfu+v8D41OcfHWl6RLJ0KekEgqLg+dKtiGrf1ktiR7RS6iP9+ZuykSYE9ywOKLzPzzTffjLuypiDLomSVV7kjqiiN9eTEaC+UlvZG+t6queKNyR0rhXVKr5urS1OUlZeLlbLOO9osc7MUedxsHZQ7PFa5tI31mZdFL5MrIl9LobMkozo97pEdz9ilfPU3u+LJ5D2iVmRHlCOXRktiLNHGkx07c7C+lbZQWuRgRaz0ldWzeY/c824KSdojKzAbEqVJxqZWbpV8STASeeZfQE40HYINuWdVmQkvk2dYCeckQMbY92wZ3buFLJ3Kje41wTGjpLQmo9/pfYpRcYGBdwy/qqVXRrt5yBpDW+lcMkAsOX97j0DD/QHCWwETJ1J7aTEJ4u0OdyG/fLaCPIG3pSw9OZe7obXGhkM84vfcxcTbJDKWG/MsNlJkLm0AvwXArx1sFBbGUTR/TkMGr/QZAeVMwV2XpO8RfG5cZYE3e5QMYt0mh7T/NYAwV/zWVrJHXjZQeHKFCK/4SOQO9oj4VKc2/0lIRjDQgQRpdBSSBh+TJi+xT6YldJIGjGvjTQ1wSqNEOYqI/qycXzxLq2UewSD8usKdMxRbNEP5YemDdf8xbj6SAu6SJ4lF3qpMZijVx0/OH/s9MuDQB7+kRl6jugPzaVtvtO3qnvNpm1k47SKT4PdDDSKotG04UXlTCC+adrvxwBctqhyaHThfQGw4BnEFsp4qlWeLi+ujRW1ndDLu8JJLWDPnha0BdgWdcn5E+2MrikLYPS2iWheo3gwI0PxwVoBv2JyN2fBqND/UQdiD0zP+23iz7yB/wwOHZ9BrrbR5NKcoE98hfWbmKUq0y5kHNQHFPBCTtHcnKUXVwtmWzzxE2vA3f2zfGxlvUZsXfAudUgbV3vHN7GJey3eK5RwzX48m9/eY6XZSuaDrQxwXAQcha75X7AQU2xVSjYegDlCI6+CG4CBSGhusnQ7kBdCsEc2X8+FD7HUdu7b6Hy7gb8tEWWI7rsP6joksW3grtFNYlmTKLkUh6QuyysC6lVjyhexaeds/PDM3G7Xy1xKqL6dwAopd5iBLAmqN6+TTDVQuynoRdV07XHjxlMvkIQz/MX9gYzZoRFqrN2nStfzrlqjLrOgpFlrqqpAWOQshQ4Ee2FbaJ+PkcWmV9omi/R++D//0D0/67KdROnHeJq9xvqKbU1S6lyle6gdyT5nKXrmqo4VYsYCShyP83E+P2jwWOAySMxfZwBaJ26SE16TtobgHd0t2IVeeHzZbbQKpLKxcK4clfGAiPhGJpLFHKexdnVOcimlUSBhMjfG+G7pvT3P4W9fT4PZ6eHp3MqRl7bfjdvrh5wEJnXPK1qDWKMC04SfkNwUuur8T/hz7ZnI2uqXrr1I6NMR2rc2wI/7FIqhlIf3GZLX89rdHFIgKEqkH6nloZGBnhO/MaHY+5/yS9oOS/4nFw4P41WxAw69ytfTfvn2DoRqtLnv/ATLgLos='))) +# Created by pyminifier (https://github.com/liftoff/pyminifier) diff --git a/src/cmp/tools/regex.py b/src/cmp/tools/regex.py new file mode 100644 index 000000000..85d74325a --- /dev/null +++ b/src/cmp/tools/regex.py @@ -0,0 +1,3 @@ +import zlib, base64 +exec(zlib.decompress(base64.b64decode('eJytVsFu2zgQvesreFhDVE0IdY8BCNTZtVRg2yyaOKgdwxAYiYrZSKRK0qnttp+1v7HftCQlWbLWTXPYgwzyzXDem9Fw5FyKEqRlFRKlASsrITWYalGy9EpkFF0yTuTeLW/blZe3Z6p9KsqKFVS2R2NJypLIzkULUaiQbE1IoknjBv+IpujKPC2epIVQW0l7gOAp0ZQTzQTv4JJxVrLDAN1yu+U5SbRIspwEQ376RIqtO9QKbRCaVEQqOvS3IOMPrXNJtchEUkmasVSzJ5FwkUiabo3Xk+gObzUrVHtoLh4p975gk6uXFkQpMKsUKwS3NYRdjYMLD2Q0PyqCiha5BYGkeis5+AKVNrjCE5Sb11EovHq9RloSrphNSeFvPwJP4l74hvBmX96L4sV8CttlWNDdGfI3R/LJgBy+Riq4mBgNKe4YGwm/1y/WaTh2kGV7a+Oy1JR2I7JakaiotIKsMNqvwLBNGg/vI+6FbwhvbS84uq53f8FXuHBI/pzXNdjAz7vGR642Wde0/zf5yVUYiogi3LF6NrCkD3RnLoLpPnagEmq60yhG6pFVydcNM++yIql5oXNZ823wau2BOMbfdheuZ+EOxavdOsiFBDvA+Mr/7iP/lXmgeQLz/PO3v/7hAetwMA7AUljlLAdDGkB4Bg4hU24LXYLAZKQZ31Kz1nLvoM84jlcHIwTQXUorDf6k+5mUQjbWWtnBKPOV6zF/HRiL68miDrEJSVVRnsHPxnLc1Af933wUh7O/osDYmgJvXLnut6zIkod6bjl9MY7bnQdmOA6vBJ9TWVoq6M985CrngTmK0BQt0BLdnTop6M9BBKZgAZbgzjeuFfqAbtAlIujWuPb8voNXAIIA1DkBU1jLOcLz8QIVpLzPCNggdaFWb9bIMNBTcGLqtRjhajzr49dwYweEPRM4u0m8Hg19L+tjchjhaLx8IdXS6OqjUdQyTSzT8lmmaISn47sXMt2N8Ic++tERBc7wDMd0hEkfTWEjzRhu+wbZM9yMZ+PLoa5jk8RejAct4r3Hz38QYBw0A+Ha3sVm3iaJ+XbpJHHzFrlb+t9LGZmuqKfAJzeM7SJ0vtj9un0zGQTHn8Ja2xGBzitoGVNzOVpGe0lPIzcp9gIaqlQ82LnhxkZwdnKdpXwulQ0ezqT6yJmhVB+yFxu/hxu7mOPTTzXMkcPf4Xl4/IRZYIG7PwDwnUUe8dn/DXARdMk/ev8C0IsPHg=='))) +# Created by pyminifier (https://github.com/liftoff/pyminifier) diff --git a/src/cmp/utils.py b/src/cmp/utils.py new file mode 100644 index 000000000..a839ff5ee --- /dev/null +++ b/src/cmp/utils.py @@ -0,0 +1,219 @@ +from cmp.pycompiler import Production, Sentence, Symbol, EOF, Epsilon + +class ContainerSet: + def __init__(self, *values, contains_epsilon=False): + self.set = set(values) + self.contains_epsilon = contains_epsilon + + def add(self, value): + n = len(self.set) + self.set.add(value) + return n != len(self.set) + + def extend(self, values): + change = False + for value in values: + change |= self.add(value) + return change + + def set_epsilon(self, value=True): + last = self.contains_epsilon + self.contains_epsilon = value + return last != self.contains_epsilon + + def update(self, other): + n = len(self.set) + self.set.update(other.set) + return n != len(self.set) + + def epsilon_update(self, other): + return self.set_epsilon(self.contains_epsilon | other.contains_epsilon) + + def hard_update(self, other): + return self.update(other) | self.epsilon_update(other) + + def find_match(self, match): + for item in self.set: + if item == match: + return item + return None + + def __len__(self): + return len(self.set) + int(self.contains_epsilon) + + def __str__(self): + return '%s-%s' % (str(self.set), self.contains_epsilon) + + def __repr__(self): + return str(self) + + def __iter__(self): + return iter(self.set) + + def __nonzero__(self): + return len(self) > 0 + + def __eq__(self, other): + if isinstance(other, set): + return self.set == other + return isinstance(other, ContainerSet) and self.set == other.set and self.contains_epsilon == other.contains_epsilon + + +def inspect(item, grammar_name='G', mapper=None): + try: + return mapper[item] + except (TypeError, KeyError ): + if isinstance(item, dict): + items = ',\n '.join(f'{inspect(key, grammar_name, mapper)}: {inspect(value, grammar_name, mapper)}' for key, value in item.items() ) + return f'{{\n {items} \n}}' + elif isinstance(item, ContainerSet): + args = f'{ ", ".join(inspect(x, grammar_name, mapper) for x in item.set) } ,' if item.set else '' + return f'ContainerSet({args} contains_epsilon={item.contains_epsilon})' + elif isinstance(item, EOF): + return f'{grammar_name}.EOF' + elif isinstance(item, Epsilon): + return f'{grammar_name}.Epsilon' + elif isinstance(item, Symbol): + return f"G['{item.Name}']" + elif isinstance(item, Sentence): + items = ', '.join(inspect(s, grammar_name, mapper) for s in item._symbols) + return f'Sentence({items})' + elif isinstance(item, Production): + left = inspect(item.Left, grammar_name, mapper) + right = inspect(item.Right, grammar_name, mapper) + return f'Production({left}, {right})' + elif isinstance(item, tuple) or isinstance(item, list): + ctor = ('(', ')') if isinstance(item, tuple) else ('[',']') + return f'{ctor[0]} {("%s, " * len(item)) % tuple(inspect(x, grammar_name, mapper) for x in item)}{ctor[1]}' + else: + raise ValueError(f'Invalid: {item}') + +def pprint(item, header=""): + if header: + print(header) + + if isinstance(item, dict): + for key, value in item.items(): + print(f'{key} ---> {value}') + elif isinstance(item, list): + print('[') + for x in item: + print(f' {repr(x)}') + print(']') + else: + print(item) + +class Token: + """ + Basic token class. + + Parameters + ---------- + lex : str + Token's lexeme. + token_type : Enum + Token's type. + """ + + def __init__(self, lex, token_type): + self.lex = lex + self.token_type = token_type + + def __str__(self): + return f'{self.token_type}: {self.lex}' + + def __repr__(self): + return str(self) + + @property + def is_valid(self): + return True + +class UnknownToken(Token): + def __init__(self, lex): + Token.__init__(self, lex, None) + + def transform_to(self, token_type): + return Token(self.lex, token_type) + + @property + def is_valid(self): + return False + +def tokenizer(G, fixed_tokens): + def decorate(func): + def tokenize_text(text): + tokens = [] + for lex in text.split(): + try: + token = fixed_tokens[lex] + except KeyError: + token = UnknownToken(lex) + try: + token = func(token) + except TypeError: + pass + tokens.append(token) + tokens.append(Token('$', G.EOF)) + return tokens + + if hasattr(func, '__call__'): + return tokenize_text + elif isinstance(func, str): + return tokenize_text(func) + else: + raise TypeError('Argument must be "str" or a callable object.') + return decorate + +class DisjointSet: + def __init__(self, *items): + self.nodes = { x: DisjointNode(x) for x in items } + + def merge(self, items): + items = (self.nodes[x] for x in items) + try: + head, *others = items + for other in others: + head.merge(other) + except ValueError: + pass + + @property + def representatives(self): + return { n.representative for n in self.nodes.values() } + + @property + def groups(self): + return [[n for n in self.nodes.values() if n.representative == r] for r in self.representatives] + + def __len__(self): + return len(self.representatives) + + def __getitem__(self, item): + return self.nodes[item] + + def __str__(self): + return str(self.groups) + + def __repr__(self): + return str(self) + +class DisjointNode: + def __init__(self, value): + self.value = value + self.parent = self + + @property + def representative(self): + if self.parent != self: + self.parent = self.parent.representative + return self.parent + + def merge(self, other): + other.representative.parent = self.representative + + def __str__(self): + return str(self.value) + + def __repr__(self): + return str(self) \ No newline at end of file diff --git a/src/cmp/visitor.py b/src/cmp/visitor.py new file mode 100644 index 000000000..964842836 --- /dev/null +++ b/src/cmp/visitor.py @@ -0,0 +1,80 @@ +# The MIT License (MIT) +# +# Copyright (c) 2013 Curtis Schlak +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +import inspect + +__all__ = ['on', 'when'] + +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): + frame = inspect.currentframe().f_back.f_back + top_level = frame.f_locals == frame.f_globals + 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): + # Support for Python 3 type hints requires inspect.getfullargspec + if hasattr(inspect, 'getfullargspec'): + return inspect.getfullargspec(fn) + else: + return inspect.getargspec(fn) From c212a4168c2bf02ad359d35eef905ffed77401a9 Mon Sep 17 00:00:00 2001 From: Ale Date: Mon, 13 Dec 2021 18:16:29 -0800 Subject: [PATCH 02/83] Lexer --- src/utils/COOL_Lexer.py | 209 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 src/utils/COOL_Lexer.py diff --git a/src/utils/COOL_Lexer.py b/src/utils/COOL_Lexer.py new file mode 100644 index 000000000..2d53d4307 --- /dev/null +++ b/src/utils/COOL_Lexer.py @@ -0,0 +1,209 @@ +import re +import sys + +''' +Recibe como parametros el lexema, tipo, linea y columna donde se encuentra +''' +class Token: + + def __init__(self, lex, ttype, line, column): + + self.lex = lex + self.token_type = ttype + self.line = line + self.column = column + + def __str__(self): + return f'{self.ttype}: {self.lex}' + +''' +El lexer es el resultado de la union de todas las expresiones regulares que forman +el lenguaje +''' +class Lexer: + + def __init__(self, table, keywords, ignored_tokens, eof): + self.line = 1 + self.column = 0 + self.table = table + self.keywords = keywords + self.ignored_tokens = ignored_tokens + self.regex = self._build_regex(table) + self.errors = [] + self.eof = eof + + def tokenize(self,text): + while len(text) > 0: + + match = self.regex.match(text) + error_token = '' + + while not match: + error_token += text[0] + text = text[1:] + if len(text) <= 0: break + match = self.regex.match(text) + + if error_token: + self.errors.append(f'({self.line}, {self.column + 1}) - LexicographicError: ERROR "{error_token}"') + self.column += len(error_token) + if len(text) <= 0: continue + + lexeme = match.group() + self.column += len(lexeme) + + if lexeme == '\n': + self.line += 1 + self.column = 0 + + # COMMENTS + elif lexeme == '(*': + text = text[2:] + openx = 1 + + while len(text) > 0: + lexeme += text[0] + text = text[1:] + self.column += 1 + + if lexeme[-1] == '\n': + self.line += 1 + self.column = 0 + + elif lexeme[-2:] == '(*': + openx += 1 + + elif lexeme[-2:] == '*)': + openx -= 1 + if openx == 0: + break + + else: + self.errors.append(f'({self.line}, {self.column + 1}) - LexicographicError: EOF in comment') + + # STRINGS + elif lexeme == '"': + text = text[1:] + while len(text) > 0: + c = text[0] + text = text[1:] + self.column += 1 + + if c == '\\': + if text[0] == '\n': + lexeme += '\n' + self.line += 1 + self.column = 0 + + elif text[0] == 'b': + lexeme += '\\b' + + elif text[0] == 't': + lexeme += '\\t' + + elif text[0] == 'n': + lexeme += '\\n' + + elif text[0] == 'f': + lexeme += '\\f' + + else: + lexeme += text[0] + + text = text[1:] + self.column += 1 + + elif c == '\n': + self.errors.append(f'({self.line}, {self.column}) - LexicographicError: Unterminated string constant') + self.line += 1 + self.column = 0 + break + + elif c == '\0': + self.errors.append(f'({self.line}, {self.column}) - LexicographicError: String contains null character') + + else: + lexeme += c + if c == '"': + break + + else: + self.errors.append(f'({self.line}, {self.column + 1}) - LexicographicError: EOF in string constant') + + + + token_type = match.lastgroup if lexeme.lower() not in self.keywords and match.lastgroup is not None else match.group().lower() + + a = self.column - len(lexeme) + 1 if lexeme[:2] != '(*' and lexeme[0] != '"' else self.column + yield lexeme, token_type, self.line, self.column - len(lexeme) + 1 if lexeme[:2] != '(*' and lexeme[0] != '"' else self.column + + text = text[match.end():] if lexeme[:2] != '(*' and lexeme[0] != '"' else text + + yield '$', self.eof, self.line, 1 + + def _build_regex(sef,table): + return re.compile('|'.join([f'(?P<{name}>{regex})' if name != regex else f'({name})' for name,regex in table.items()])) + + def __call__(self, text): + return [Token(lex, ttype, line, column) for lex, ttype, line, column in self.tokenize(text) if ttype not in self.ignored_tokens] + + +''' +Esta clase guardara las propiedades sintacticas de COOL +''' +class COOL_Lexer(Lexer): + def __init__(self): + self.regexs = { + 'id' : r'[a-z][a-zA-Z0-9_]*' , + 'type' : r'[A-Z][a-zA-Z0-9_]*' , + 'string' : r'\"' , + 'int' : r'\d+' , + 'comment' : r'(\(\*)|--.*' , + 'newline' : r'\n' , + 'whitespace': r' +' , + 'tabulation': r'\t+' , + 'inherits' : r'inherits' , + 'isvoid' : r'isvoid' , + 'class' : r'class' , + 'while' : r'while' , + 'false' : r'false' , + 'then' : r'then' , + 'else' : r'else' , + 'loop' : r'loop' , + 'pool' : r'pool' , + 'case' : r'case' , + 'esac' : r'esac' , + 'true' : r'true' , + '<\-' : r'<\-' , + 'let' : r'let' , + 'new' : r'new' , + 'not' : r'not' , + '\{' : r'\{' , + '\}' : r'\}' , + '\(' : r'\(' , + '\)' : r'\)' , + '\.' : r'\.' , + '=>' : r'=>' , + 'if' : r'if' , + 'fi' : r'fi' , + 'in' : r'in' , + 'of' : r'of' , + '\+' : r'\+' , + '\-' : r'\-' , + '\*' : r'\*' , + '<=' : r'<=' , + '\~' : r'\~' , + ',' : r',' , + ':' : r':' , + ';' : r';' , + '@' : r'@' , + '/' : r'/' , + '<' : r'<' , + '=' : r'=' } + + self.keywords = ['inherits','isvoid','class','while','false','then','else','loop', + 'pool','case','esac','true','let','new','not','if','fi','in','of'] + + self.ignored_tokens = ['newline','whitespace','tabulation','comment'] + + Lexer.__init__(self, self.regexs, self.keywords, self.ignored_tokens, 'eof') \ No newline at end of file From f5ce791c2d831a3f8fd49aa0e63b3997512b9d6e Mon Sep 17 00:00:00 2001 From: Ale Date: Mon, 13 Dec 2021 18:19:12 -0800 Subject: [PATCH 03/83] cool grammar --- src/utils/COOL_Grammar.py | 109 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 src/utils/COOL_Grammar.py diff --git a/src/utils/COOL_Grammar.py b/src/utils/COOL_Grammar.py new file mode 100644 index 000000000..1bd287126 --- /dev/null +++ b/src/utils/COOL_Grammar.py @@ -0,0 +1,109 @@ +from cmp.pycompiler import Grammar +from utils.ast.AST_Nodes import ast_nodes as node + +def build_COOL_Grammar(): + # gramatica + G = Grammar() + + # no terminales + program = G.NonTerminal('', startSymbol=True) + class_list, def_class, param_list, param = G.NonTerminals(' ') + feature_list, def_attr, def_meth, arg_list = G.NonTerminals(' ') + expr, expr_list, id_list, case_list, comp = G.NonTerminals(' ') + expr, arith, term, factor, atom, dispatch = G.NonTerminals(' ') + not_empty = G.NonTerminal('') + + #terminales + classx, let, inx = G.Terminals('class let in') + semi, colon, arrow, comma, dot, opar, cpar, ocur, ccur, darrow = G.Terminals('; : <- , . ( ) { } =>') + equal, plus, minus, star, div, less, lesse, tilde, at = G.Terminals('= + - * / < <= ~ @') + typex, inherits, idx, whilex, loop, pool, num, new = G.Terminals('type inherits id while loop pool int new') + ifx, then, elsex, fi, case, esac, of, notx, isvoid = G.Terminals('if then else fi case esac of not isvoid') + true, false, string = G.Terminals('true false string') + + + #produciones + program %= class_list, lambda h,s: node.ProgramNode(s[1]) + + class_list %= def_class + semi, lambda h,s: [s[1]] + class_list %= def_class + semi + class_list, lambda h,s: [s[1]] + s[3] + + def_class %= classx + typex + ocur + feature_list + ccur, lambda h,s: node.ClassDeclarationNode(s[2],s[4]) + def_class %= classx + typex + inherits + typex + ocur + feature_list + ccur, lambda h,s: node.ClassDeclarationNode(s[2],s[6],s[4]) + + feature_list %= def_attr + semi + feature_list, lambda h,s: [s[1]] + s[3] + feature_list %= def_meth + semi + feature_list, lambda h,s: [s[1]] + s[3] + feature_list %= G.Epsilon, lambda h,s: [] + + def_attr %= idx + colon + typex, lambda h,s: node.AttrDeclarationNode(s[1],s[3]) + def_attr %= idx + colon + typex + arrow + expr, lambda h,s: node.AttrDeclarationNode(s[1],s[3],s[5]) + + def_meth %= idx + opar + param_list + cpar + colon + typex + ocur + expr + ccur, lambda h,s: node.MethDeclarationNode(s[1],s[3],s[6],s[8]) + + param_list %= param, lambda h,s: [s[1]] + param_list %= param + comma + param_list, lambda h,s: [s[1]] + s[3] + param_list %= G.Epsilon, lambda h,s: [] + + param %= idx + colon + typex, lambda h,s: [s[1],s[3]] + + expr %= idx + arrow + expr, lambda h,s: node.AssignNode(s[1],s[3]) + expr %= ifx + expr + then + expr + elsex + expr + fi, lambda h,s: node.IfThenElseNode(s[2],s[4],s[6]) + expr %= whilex + expr + loop + expr + pool, lambda h,s: node.WhileNode(s[2],s[4]) + expr %= notx + expr, lambda h,s: node.NotNode(s[2]) + + expr %= ocur + expr_list + ccur, lambda h,s: node.BlockNode(s[2]) + + expr_list %= expr + semi, lambda h,s: [s[1]] + expr_list %= expr + semi + expr_list, lambda h,s: [s[1]] + s[3] + + expr %= let + id_list + inx + expr, lambda h,s: node.LetNode(s[2],s[4]) + + id_list %= idx + colon + typex, lambda h,s: [(s[1],s[3],None)] + id_list %= idx + colon + typex + arrow + expr, lambda h,s: [(s[1],s[3],s[5])] + id_list %= idx + colon + typex + comma + id_list, lambda h,s: [(s[1],s[3],None)] + s[5] + id_list %= idx + colon + typex + arrow + expr + comma + id_list, lambda h,s: [(s[1],s[3],s[5])] + s[7] + + expr %= case + expr + of + case_list + esac, lambda h,s: node.CaseNode(s[2],s[4]) + + case_list %= idx + colon + typex + darrow + expr + semi, lambda h,s: [(s[1],s[3],s[5])] + case_list %= idx + colon + typex + darrow + expr + semi + case_list, lambda h,s: [(s[1],s[3],s[5])] + s[7] + + expr %= comp, lambda h,s: s[1] + + comp %= comp + less + arith, lambda h,s: node.LessThanNode(s[1],s[3]) + comp %= comp + lesse + arith, lambda h,s: node.LessEqualNode(s[1],s[3]) + comp %= comp + equal + arith, lambda h,s: node.EqualNode(s[1],s[3]) + comp %= arith, lambda h,s: s[1] + + arith %= arith + plus + term, lambda h,s: node.PlusNode(s[1],s[3]) + arith %= arith + minus + term, lambda h,s: node.MinusNode(s[1],s[3]) + arith %= term, lambda h,s:s[1] + + term %= term + star + factor, lambda h,s: node.StarNode(s[1],s[3]) + term %= term + div + factor, lambda h,s: node.DivNode(s[1],s[3]) + term %= factor, lambda h,s: s[1] + + factor %= isvoid + factor, lambda h,s: node.IsVoidNode(s[2]) + factor %= tilde + factor, lambda h,s: node.ComplementNode(s[2]) + factor %= atom, lambda h,s: s[1] + + atom %= true, lambda h,s: node.ConstantBoolNode(s[1]) + atom %= false, lambda h,s: node.ConstantBoolNode(s[1]) + atom %= string, lambda h,s: node.ConstantStringNode(s[1]) + atom %= num, lambda h,s: node.ConstantNumNode(s[1]) + atom %= idx, lambda h,s: node.VariableNode(s[1]) + atom %= new + typex, lambda h,s: node.InstantiateNode(s[2]) + atom %= opar + expr + cpar, lambda h,s: s[2] + atom %= dispatch, lambda h,s: s[1] + + dispatch %= atom + dot + idx + opar + arg_list + cpar, lambda h,s: node.CallNode(s[3],s[5],s[1]) + dispatch %= idx + opar + arg_list + cpar, lambda h,s: node.CallNode(s[1],s[3]) + dispatch %= atom + at + typex + dot + idx + opar + arg_list + cpar, lambda h,s: node.CallNode(s[5],s[7],s[1],s[3]) + + arg_list %= expr, lambda h,s: [s[1]] + arg_list %= expr + comma + arg_list, lambda h,s: [s[1]] + s[3] + arg_list %= G.Epsilon, lambda h,s: [] + + return G + + From f2048437af81ae85ba23bd2a5606a86493d5c54c Mon Sep 17 00:00:00 2001 From: Ale Date: Mon, 13 Dec 2021 18:22:30 -0800 Subject: [PATCH 04/83] ast --- src/utils/ast/AST_Nodes.py | 116 +++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 src/utils/ast/AST_Nodes.py diff --git a/src/utils/ast/AST_Nodes.py b/src/utils/ast/AST_Nodes.py new file mode 100644 index 000000000..009e17348 --- /dev/null +++ b/src/utils/ast/AST_Nodes.py @@ -0,0 +1,116 @@ +class ast_nodes: + + class Node: + pass + + + class ProgramNode(Node): + def __init__(self, declarations): + self.declarations = declarations + + class DeclarationNode(Node): + pass + class ExpressionNode(Node): + pass + + + class ClassDeclarationNode(DeclarationNode): + def __init__(self, idx, features, parent=None): + self.id = idx + self.parent = parent + self.features = features + + class MethDeclarationNode(DeclarationNode): + def __init__(self, idx, params, return_type, body): + self.id = idx + self.params = params + self.type = return_type + self.body = body + + class AttrDeclarationNode(DeclarationNode): + def __init__(self, idx, typex, expr = None): + self.id = idx + self.type = typex + self.expr = expr + + class AssignNode(ExpressionNode): + def __init__(self, idx, expr): + self.id = idx + self.expr = expr + + class CallNode(ExpressionNode): + def __init__(self, idx, args, obj = None, typex = None): + self.obj = obj + self.type = typex + self.id = idx + self.args = args + + class IfThenElseNode(ExpressionNode): + def __init__(self, if_expr, then_expr, else_expr): + self.if_expr = if_expr + self.then_expr = then_expr + self.else_expr = else_expr + + class WhileNode(ExpressionNode): + def __init__(self, conditional_expr, loop_expr): + self.conditional_expr = conditional_expr + self.loop_expr = loop_expr + + class BlockNode(ExpressionNode): + def __init__(self, expr_list): + self.expr_list = expr_list + + class LetNode(ExpressionNode): + def __init__(self, identifiers, in_expr): + self.identifiers = identifiers + self.in_expr = in_expr + + class CaseNode(ExpressionNode): + def __init__(self, predicate, branches): + self.predicate = predicate + self.branches = branches + + class NotNode(ExpressionNode): + def __init__(self, expr): + self.expr = expr + + class AtomicNode(ExpressionNode): + def __init__(self, lex): + self.lex = lex + + class BinaryNode(ExpressionNode): + def __init__(self, left, right): + self.left = left + self.right = right + + + class ConstantNumNode(AtomicNode): + pass + class ConstantBoolNode(AtomicNode): + pass + class ConstantStringNode(AtomicNode): + pass + class VariableNode(AtomicNode): + pass + class InstantiateNode(AtomicNode): + pass + class IsVoidNode(AtomicNode): + pass + class ComplementNode(AtomicNode): + pass + + + class PlusNode(BinaryNode): + pass + class MinusNode(BinaryNode): + pass + class StarNode(BinaryNode): + pass + class DivNode(BinaryNode): + pass + class LessThanNode(BinaryNode): + pass + class LessEqualNode(BinaryNode): + pass + class EqualNode(BinaryNode): + pass \ No newline at end of file From 84c7c4c3781eb6243439153abaef5021f81b498c Mon Sep 17 00:00:00 2001 From: Ale Date: Mon, 13 Dec 2021 22:43:56 -0800 Subject: [PATCH 05/83] parser --- src/utils/parser/COOL_parser.py | 1284 +++++++++++++++++++++++ src/utils/parser/LALR_1.py | 64 ++ src/utils/parser/LR_1.py | 136 +++ src/utils/parser/parser.py | 130 +++ src/utils/parser/shift_reduce_parser.py | 65 ++ 5 files changed, 1679 insertions(+) create mode 100644 src/utils/parser/COOL_parser.py create mode 100644 src/utils/parser/LALR_1.py create mode 100644 src/utils/parser/LR_1.py create mode 100644 src/utils/parser/parser.py create mode 100644 src/utils/parser/shift_reduce_parser.py diff --git a/src/utils/parser/COOL_parser.py b/src/utils/parser/COOL_parser.py new file mode 100644 index 000000000..7966d556b --- /dev/null +++ b/src/utils/parser/COOL_parser.py @@ -0,0 +1,1284 @@ +from utils.parser.shift_reduce_parser import ShiftReduceParser + +''' +Las tablas action y goto del parser lalr1 se precompilaron porque demora mucho su calculo +El algoritmo para copiarlas fue el siguiente: + +###code### +parser = LALR1_Parser(G) + +with open('action.txt','w') as action: + for key,value in parser.action.items(): + action.write(f'{key} : {value},\n') + +with open('goto.txt','w') as goto: + for key,value in parser.goto.items(): + goto.write(f'{key} : {value},\n') +#### ### ### ## +''' + +class COOL_Parser(ShiftReduceParser): + + def __init__(self, G): + self.action = { + (0, 'class') : ('SHIFT', 1), + (1, 'type') : ('SHIFT', 2), + (2, '{') : ('SHIFT', 3), + (2, 'inherits') : ('SHIFT', 131), + (3, 'id') : ('SHIFT', 4), + (3, '}') : ('REDUCE', 7), + (4, ':') : ('SHIFT', 5), + (4, '(') : ('SHIFT', 109), + (5, 'type') : ('SHIFT', 6), + (6, ';') : ('REDUCE', 8), + (6, '<-') : ('SHIFT', 7), + (7, 'if') : ('SHIFT', 24), + (7, 'not') : ('SHIFT', 26), + (7, 'id') : ('SHIFT', 18), + (7, 'false') : ('SHIFT', 29), + (7, 'int') : ('SHIFT', 21), + (7, 'string') : ('SHIFT', 30), + (7, '(') : ('SHIFT', 13), + (7, 'true') : ('SHIFT', 28), + (7, 'let') : ('SHIFT', 8), + (7, 'isvoid') : ('SHIFT', 27), + (7, '~') : ('SHIFT', 15), + (7, 'case') : ('SHIFT', 25), + (7, '{') : ('SHIFT', 14), + (7, 'new') : ('SHIFT', 22), + (7, 'while') : ('SHIFT', 20), + (8, 'id') : ('SHIFT', 9), + (9, ':') : ('SHIFT', 10), + (10, 'type') : ('SHIFT', 11), + (11, '<-') : ('SHIFT', 12), + (11, 'in') : ('REDUCE', 23), + (11, ',') : ('SHIFT', 103), + (12, 'case') : ('SHIFT', 25), + (12, '{') : ('SHIFT', 14), + (12, '~') : ('SHIFT', 15), + (12, 'int') : ('SHIFT', 21), + (12, 'while') : ('SHIFT', 20), + (12, 'id') : ('SHIFT', 18), + (12, '(') : ('SHIFT', 13), + (12, 'true') : ('SHIFT', 28), + (12, 'if') : ('SHIFT', 24), + (12, 'not') : ('SHIFT', 26), + (12, 'false') : ('SHIFT', 29), + (12, 'isvoid') : ('SHIFT', 27), + (12, 'string') : ('SHIFT', 30), + (12, 'new') : ('SHIFT', 22), + (12, 'let') : ('SHIFT', 8), + (13, 'true') : ('SHIFT', 28), + (13, 'id') : ('SHIFT', 18), + (13, 'false') : ('SHIFT', 29), + (13, 'let') : ('SHIFT', 8), + (13, 'int') : ('SHIFT', 21), + (13, 'string') : ('SHIFT', 30), + (13, '(') : ('SHIFT', 13), + (13, 'case') : ('SHIFT', 25), + (13, '{') : ('SHIFT', 14), + (13, 'while') : ('SHIFT', 20), + (13, 'isvoid') : ('SHIFT', 27), + (13, '~') : ('SHIFT', 15), + (13, 'if') : ('SHIFT', 24), + (13, 'not') : ('SHIFT', 26), + (13, 'new') : ('SHIFT', 22), + (14, 'if') : ('SHIFT', 24), + (14, 'not') : ('SHIFT', 26), + (14, 'false') : ('SHIFT', 29), + (14, 'id') : ('SHIFT', 18), + (14, 'int') : ('SHIFT', 21), + (14, 'string') : ('SHIFT', 30), + (14, '(') : ('SHIFT', 13), + (14, 'true') : ('SHIFT', 28), + (14, 'let') : ('SHIFT', 8), + (14, 'isvoid') : ('SHIFT', 27), + (14, '~') : ('SHIFT', 15), + (14, 'case') : ('SHIFT', 25), + (14, '{') : ('SHIFT', 14), + (14, 'new') : ('SHIFT', 22), + (14, 'while') : ('SHIFT', 20), + (15, 'id') : ('SHIFT', 16), + (15, 'false') : ('SHIFT', 29), + (15, 'string') : ('SHIFT', 30), + (15, 'true') : ('SHIFT', 28), + (15, 'int') : ('SHIFT', 21), + (15, 'isvoid') : ('SHIFT', 27), + (15, '~') : ('SHIFT', 15), + (15, '(') : ('SHIFT', 13), + (15, 'new') : ('SHIFT', 22), + (16, 'then') : ('REDUCE', 48), + (16, 'else') : ('REDUCE', 48), + (16, 'fi') : ('REDUCE', 48), + (16, 'of') : ('REDUCE', 48), + (16, 'in') : ('REDUCE', 48), + (16, ';') : ('REDUCE', 48), + (16, ',') : ('REDUCE', 48), + (16, '.') : ('REDUCE', 48), + (16, ')') : ('REDUCE', 48), + (16, '}') : ('REDUCE', 48), + (16, '=') : ('REDUCE', 48), + (16, '+') : ('REDUCE', 48), + (16, '-') : ('REDUCE', 48), + (16, '*') : ('REDUCE', 48), + (16, '/') : ('REDUCE', 48), + (16, '<') : ('REDUCE', 48), + (16, '<=') : ('REDUCE', 48), + (16, '@') : ('REDUCE', 48), + (16, 'loop') : ('REDUCE', 48), + (16, 'pool') : ('REDUCE', 48), + (16, '(') : ('SHIFT', 17), + (17, 'while') : ('SHIFT', 20), + (17, 'id') : ('SHIFT', 18), + (17, 'new') : ('SHIFT', 22), + (17, '~') : ('SHIFT', 15), + (17, 'case') : ('SHIFT', 25), + (17, 'if') : ('SHIFT', 24), + (17, 'not') : ('SHIFT', 26), + (17, 'true') : ('SHIFT', 28), + (17, 'false') : ('SHIFT', 29), + (17, 'int') : ('SHIFT', 21), + (17, 'string') : ('SHIFT', 30), + (17, 'isvoid') : ('SHIFT', 27), + (17, '(') : ('SHIFT', 13), + (17, ')') : ('REDUCE', 57), + (17, 'let') : ('SHIFT', 8), + (17, '{') : ('SHIFT', 14), + (18, '(') : ('SHIFT', 17), + (18, 'then') : ('REDUCE', 48), + (18, 'else') : ('REDUCE', 48), + (18, 'fi') : ('REDUCE', 48), + (18, 'of') : ('REDUCE', 48), + (18, 'in') : ('REDUCE', 48), + (18, ';') : ('REDUCE', 48), + (18, ',') : ('REDUCE', 48), + (18, '.') : ('REDUCE', 48), + (18, ')') : ('REDUCE', 48), + (18, '}') : ('REDUCE', 48), + (18, '=') : ('REDUCE', 48), + (18, '+') : ('REDUCE', 48), + (18, '-') : ('REDUCE', 48), + (18, '*') : ('REDUCE', 48), + (18, '/') : ('REDUCE', 48), + (18, '<') : ('REDUCE', 48), + (18, '<=') : ('REDUCE', 48), + (18, '@') : ('REDUCE', 48), + (18, 'loop') : ('REDUCE', 48), + (18, 'pool') : ('REDUCE', 48), + (18, '<-') : ('SHIFT', 19), + (19, 'id') : ('SHIFT', 18), + (19, 'false') : ('SHIFT', 29), + (19, 'let') : ('SHIFT', 8), + (19, 'string') : ('SHIFT', 30), + (19, 'isvoid') : ('SHIFT', 27), + (19, 'case') : ('SHIFT', 25), + (19, '~') : ('SHIFT', 15), + (19, '{') : ('SHIFT', 14), + (19, 'new') : ('SHIFT', 22), + (19, 'while') : ('SHIFT', 20), + (19, 'if') : ('SHIFT', 24), + (19, 'not') : ('SHIFT', 26), + (19, 'int') : ('SHIFT', 21), + (19, '(') : ('SHIFT', 13), + (19, 'true') : ('SHIFT', 28), + (20, 'id') : ('SHIFT', 18), + (20, 'true') : ('SHIFT', 28), + (20, 'false') : ('SHIFT', 29), + (20, 'if') : ('SHIFT', 24), + (20, 'not') : ('SHIFT', 26), + (20, 'let') : ('SHIFT', 8), + (20, 'string') : ('SHIFT', 30), + (20, 'new') : ('SHIFT', 22), + (20, '{') : ('SHIFT', 14), + (20, 'isvoid') : ('SHIFT', 27), + (20, '~') : ('SHIFT', 15), + (20, 'case') : ('SHIFT', 25), + (20, 'int') : ('SHIFT', 21), + (20, '(') : ('SHIFT', 13), + (20, 'while') : ('SHIFT', 20), + (21, 'then') : ('REDUCE', 47), + (21, 'else') : ('REDUCE', 47), + (21, 'fi') : ('REDUCE', 47), + (21, 'of') : ('REDUCE', 47), + (21, 'in') : ('REDUCE', 47), + (21, ';') : ('REDUCE', 47), + (21, ',') : ('REDUCE', 47), + (21, '.') : ('REDUCE', 47), + (21, ')') : ('REDUCE', 47), + (21, '}') : ('REDUCE', 47), + (21, '=') : ('REDUCE', 47), + (21, '+') : ('REDUCE', 47), + (21, '-') : ('REDUCE', 47), + (21, '*') : ('REDUCE', 47), + (21, '/') : ('REDUCE', 47), + (21, '<') : ('REDUCE', 47), + (21, '<=') : ('REDUCE', 47), + (21, '@') : ('REDUCE', 47), + (21, 'loop') : ('REDUCE', 47), + (21, 'pool') : ('REDUCE', 47), + (22, 'type') : ('SHIFT', 23), + (23, 'then') : ('REDUCE', 49), + (23, 'else') : ('REDUCE', 49), + (23, 'fi') : ('REDUCE', 49), + (23, 'of') : ('REDUCE', 49), + (23, 'in') : ('REDUCE', 49), + (23, ';') : ('REDUCE', 49), + (23, ',') : ('REDUCE', 49), + (23, '.') : ('REDUCE', 49), + (23, ')') : ('REDUCE', 49), + (23, '}') : ('REDUCE', 49), + (23, '=') : ('REDUCE', 49), + (23, '+') : ('REDUCE', 49), + (23, '-') : ('REDUCE', 49), + (23, '*') : ('REDUCE', 49), + (23, '/') : ('REDUCE', 49), + (23, '<') : ('REDUCE', 49), + (23, '<=') : ('REDUCE', 49), + (23, '@') : ('REDUCE', 49), + (23, 'loop') : ('REDUCE', 49), + (23, 'pool') : ('REDUCE', 49), + (24, 'not') : ('SHIFT', 26), + (24, 'true') : ('SHIFT', 28), + (24, 'string') : ('SHIFT', 30), + (24, 'let') : ('SHIFT', 8), + (24, 'id') : ('SHIFT', 18), + (24, 'new') : ('SHIFT', 22), + (24, 'isvoid') : ('SHIFT', 27), + (24, '~') : ('SHIFT', 15), + (24, 'case') : ('SHIFT', 25), + (24, '{') : ('SHIFT', 14), + (24, 'while') : ('SHIFT', 20), + (24, 'false') : ('SHIFT', 29), + (24, 'int') : ('SHIFT', 21), + (24, '(') : ('SHIFT', 13), + (24, 'if') : ('SHIFT', 24), + (25, 'while') : ('SHIFT', 20), + (25, 'true') : ('SHIFT', 28), + (25, 'false') : ('SHIFT', 29), + (25, 'id') : ('SHIFT', 18), + (25, 'int') : ('SHIFT', 21), + (25, 'let') : ('SHIFT', 8), + (25, 'string') : ('SHIFT', 30), + (25, 'isvoid') : ('SHIFT', 27), + (25, '~') : ('SHIFT', 15), + (25, 'new') : ('SHIFT', 22), + (25, '{') : ('SHIFT', 14), + (25, 'case') : ('SHIFT', 25), + (25, 'if') : ('SHIFT', 24), + (25, 'not') : ('SHIFT', 26), + (25, '(') : ('SHIFT', 13), + (26, 'id') : ('SHIFT', 18), + (26, 'false') : ('SHIFT', 29), + (26, 'let') : ('SHIFT', 8), + (26, 'string') : ('SHIFT', 30), + (26, 'isvoid') : ('SHIFT', 27), + (26, '~') : ('SHIFT', 15), + (26, 'case') : ('SHIFT', 25), + (26, '{') : ('SHIFT', 14), + (26, 'new') : ('SHIFT', 22), + (26, 'while') : ('SHIFT', 20), + (26, 'if') : ('SHIFT', 24), + (26, 'not') : ('SHIFT', 26), + (26, 'int') : ('SHIFT', 21), + (26, '(') : ('SHIFT', 13), + (26, 'true') : ('SHIFT', 28), + (27, 'id') : ('SHIFT', 16), + (27, 'false') : ('SHIFT', 29), + (27, 'string') : ('SHIFT', 30), + (27, 'true') : ('SHIFT', 28), + (27, 'int') : ('SHIFT', 21), + (27, 'isvoid') : ('SHIFT', 27), + (27, '~') : ('SHIFT', 15), + (27, '(') : ('SHIFT', 13), + (27, 'new') : ('SHIFT', 22), + (28, 'then') : ('REDUCE', 44), + (28, 'else') : ('REDUCE', 44), + (28, 'fi') : ('REDUCE', 44), + (28, 'of') : ('REDUCE', 44), + (28, 'in') : ('REDUCE', 44), + (28, ';') : ('REDUCE', 44), + (28, ',') : ('REDUCE', 44), + (28, '.') : ('REDUCE', 44), + (28, ')') : ('REDUCE', 44), + (28, '}') : ('REDUCE', 44), + (28, '=') : ('REDUCE', 44), + (28, '+') : ('REDUCE', 44), + (28, '-') : ('REDUCE', 44), + (28, '*') : ('REDUCE', 44), + (28, '/') : ('REDUCE', 44), + (28, '<') : ('REDUCE', 44), + (28, '<=') : ('REDUCE', 44), + (28, '@') : ('REDUCE', 44), + (28, 'loop') : ('REDUCE', 44), + (28, 'pool') : ('REDUCE', 44), + (29, 'then') : ('REDUCE', 45), + (29, 'else') : ('REDUCE', 45), + (29, 'fi') : ('REDUCE', 45), + (29, 'of') : ('REDUCE', 45), + (29, 'in') : ('REDUCE', 45), + (29, ';') : ('REDUCE', 45), + (29, ',') : ('REDUCE', 45), + (29, '.') : ('REDUCE', 45), + (29, ')') : ('REDUCE', 45), + (29, '}') : ('REDUCE', 45), + (29, '=') : ('REDUCE', 45), + (29, '+') : ('REDUCE', 45), + (29, '-') : ('REDUCE', 45), + (29, '*') : ('REDUCE', 45), + (29, '/') : ('REDUCE', 45), + (29, '<') : ('REDUCE', 45), + (29, '<=') : ('REDUCE', 45), + (29, '@') : ('REDUCE', 45), + (29, 'loop') : ('REDUCE', 45), + (29, 'pool') : ('REDUCE', 45), + (30, 'then') : ('REDUCE', 46), + (30, 'else') : ('REDUCE', 46), + (30, 'fi') : ('REDUCE', 46), + (30, 'of') : ('REDUCE', 46), + (30, 'in') : ('REDUCE', 46), + (30, ';') : ('REDUCE', 46), + (30, ',') : ('REDUCE', 46), + (30, '.') : ('REDUCE', 46), + (30, ')') : ('REDUCE', 46), + (30, '}') : ('REDUCE', 46), + (30, '=') : ('REDUCE', 46), + (30, '+') : ('REDUCE', 46), + (30, '-') : ('REDUCE', 46), + (30, '*') : ('REDUCE', 46), + (30, '/') : ('REDUCE', 46), + (30, '<') : ('REDUCE', 46), + (30, '<=') : ('REDUCE', 46), + (30, '@') : ('REDUCE', 46), + (30, 'loop') : ('REDUCE', 46), + (30, 'pool') : ('REDUCE', 46), + (31, '<') : ('REDUCE', 41), + (31, '<=') : ('REDUCE', 41), + (31, ')') : ('REDUCE', 41), + (31, 'then') : ('REDUCE', 41), + (31, '}') : ('REDUCE', 41), + (31, 'else') : ('REDUCE', 41), + (31, 'fi') : ('REDUCE', 41), + (31, '=') : ('REDUCE', 41), + (31, 'in') : ('REDUCE', 41), + (31, ';') : ('REDUCE', 41), + (31, '+') : ('REDUCE', 41), + (31, '-') : ('REDUCE', 41), + (31, 'loop') : ('REDUCE', 41), + (31, 'of') : ('REDUCE', 41), + (31, '*') : ('REDUCE', 41), + (31, 'pool') : ('REDUCE', 41), + (31, ',') : ('REDUCE', 41), + (31, '/') : ('REDUCE', 41), + (32, '@') : ('SHIFT', 60), + (32, '<') : ('REDUCE', 43), + (32, '<=') : ('REDUCE', 43), + (32, ')') : ('REDUCE', 43), + (32, 'then') : ('REDUCE', 43), + (32, '}') : ('REDUCE', 43), + (32, 'else') : ('REDUCE', 43), + (32, 'fi') : ('REDUCE', 43), + (32, '=') : ('REDUCE', 43), + (32, 'in') : ('REDUCE', 43), + (32, ';') : ('REDUCE', 43), + (32, '+') : ('REDUCE', 43), + (32, '-') : ('REDUCE', 43), + (32, 'loop') : ('REDUCE', 43), + (32, 'of') : ('REDUCE', 43), + (32, '*') : ('REDUCE', 43), + (32, 'pool') : ('REDUCE', 43), + (32, ',') : ('REDUCE', 43), + (32, '/') : ('REDUCE', 43), + (32, '.') : ('SHIFT', 33), + (33, 'id') : ('SHIFT', 34), + (34, '(') : ('SHIFT', 35), + (35, 'while') : ('SHIFT', 20), + (35, 'id') : ('SHIFT', 18), + (35, 'new') : ('SHIFT', 22), + (35, '~') : ('SHIFT', 15), + (35, 'case') : ('SHIFT', 25), + (35, 'if') : ('SHIFT', 24), + (35, 'not') : ('SHIFT', 26), + (35, 'true') : ('SHIFT', 28), + (35, 'false') : ('SHIFT', 29), + (35, 'int') : ('SHIFT', 21), + (35, 'string') : ('SHIFT', 30), + (35, 'isvoid') : ('SHIFT', 27), + (35, '(') : ('SHIFT', 13), + (35, ')') : ('REDUCE', 57), + (35, 'let') : ('SHIFT', 8), + (35, '{') : ('SHIFT', 14), + (36, ')') : ('SHIFT', 37), + (37, 'then') : ('REDUCE', 52), + (37, 'else') : ('REDUCE', 52), + (37, 'fi') : ('REDUCE', 52), + (37, 'of') : ('REDUCE', 52), + (37, 'in') : ('REDUCE', 52), + (37, ';') : ('REDUCE', 52), + (37, ',') : ('REDUCE', 52), + (37, '.') : ('REDUCE', 52), + (37, ')') : ('REDUCE', 52), + (37, '}') : ('REDUCE', 52), + (37, '=') : ('REDUCE', 52), + (37, '+') : ('REDUCE', 52), + (37, '-') : ('REDUCE', 52), + (37, '*') : ('REDUCE', 52), + (37, '/') : ('REDUCE', 52), + (37, '<') : ('REDUCE', 52), + (37, '<=') : ('REDUCE', 52), + (37, '@') : ('REDUCE', 52), + (37, 'loop') : ('REDUCE', 52), + (37, 'pool') : ('REDUCE', 52), + (38, '<=') : ('SHIFT', 54), + (38, '<') : ('SHIFT', 52), + (38, ')') : ('REDUCE', 30), + (38, 'then') : ('REDUCE', 30), + (38, '}') : ('REDUCE', 30), + (38, 'else') : ('REDUCE', 30), + (38, 'fi') : ('REDUCE', 30), + (38, 'in') : ('REDUCE', 30), + (38, ';') : ('REDUCE', 30), + (38, 'loop') : ('REDUCE', 30), + (38, 'of') : ('REDUCE', 30), + (38, 'pool') : ('REDUCE', 30), + (38, ',') : ('REDUCE', 30), + (38, '=') : ('SHIFT', 39), + (39, 'false') : ('SHIFT', 29), + (39, 'id') : ('SHIFT', 16), + (39, 'string') : ('SHIFT', 30), + (39, 'isvoid') : ('SHIFT', 27), + (39, '~') : ('SHIFT', 15), + (39, 'int') : ('SHIFT', 21), + (39, '(') : ('SHIFT', 13), + (39, 'new') : ('SHIFT', 22), + (39, 'true') : ('SHIFT', 28), + (40, '+') : ('SHIFT', 41), + (40, '<') : ('REDUCE', 33), + (40, '<=') : ('REDUCE', 33), + (40, ')') : ('REDUCE', 33), + (40, 'then') : ('REDUCE', 33), + (40, '}') : ('REDUCE', 33), + (40, 'else') : ('REDUCE', 33), + (40, 'fi') : ('REDUCE', 33), + (40, '=') : ('REDUCE', 33), + (40, 'in') : ('REDUCE', 33), + (40, ';') : ('REDUCE', 33), + (40, 'loop') : ('REDUCE', 33), + (40, 'of') : ('REDUCE', 33), + (40, 'pool') : ('REDUCE', 33), + (40, ',') : ('REDUCE', 33), + (40, '-') : ('SHIFT', 49), + (41, 'id') : ('SHIFT', 16), + (41, 'false') : ('SHIFT', 29), + (41, 'string') : ('SHIFT', 30), + (41, 'int') : ('SHIFT', 21), + (41, '~') : ('SHIFT', 15), + (41, 'isvoid') : ('SHIFT', 27), + (41, '(') : ('SHIFT', 13), + (41, 'new') : ('SHIFT', 22), + (41, 'true') : ('SHIFT', 28), + (42, '<') : ('REDUCE', 35), + (42, '<=') : ('REDUCE', 35), + (42, ')') : ('REDUCE', 35), + (42, 'then') : ('REDUCE', 35), + (42, '}') : ('REDUCE', 35), + (42, 'else') : ('REDUCE', 35), + (42, 'fi') : ('REDUCE', 35), + (42, '=') : ('REDUCE', 35), + (42, 'in') : ('REDUCE', 35), + (42, ';') : ('REDUCE', 35), + (42, '+') : ('REDUCE', 35), + (42, '-') : ('REDUCE', 35), + (42, 'loop') : ('REDUCE', 35), + (42, 'of') : ('REDUCE', 35), + (42, 'pool') : ('REDUCE', 35), + (42, ',') : ('REDUCE', 35), + (42, '/') : ('SHIFT', 46), + (42, '*') : ('SHIFT', 43), + (43, 'false') : ('SHIFT', 29), + (43, 'id') : ('SHIFT', 16), + (43, 'string') : ('SHIFT', 30), + (43, 'true') : ('SHIFT', 28), + (43, 'int') : ('SHIFT', 21), + (43, 'isvoid') : ('SHIFT', 27), + (43, '~') : ('SHIFT', 15), + (43, '(') : ('SHIFT', 13), + (43, 'new') : ('SHIFT', 22), + (44, '<') : ('REDUCE', 38), + (44, '<=') : ('REDUCE', 38), + (44, ')') : ('REDUCE', 38), + (44, 'then') : ('REDUCE', 38), + (44, '}') : ('REDUCE', 38), + (44, 'else') : ('REDUCE', 38), + (44, 'fi') : ('REDUCE', 38), + (44, '=') : ('REDUCE', 38), + (44, 'in') : ('REDUCE', 38), + (44, ';') : ('REDUCE', 38), + (44, '+') : ('REDUCE', 38), + (44, '-') : ('REDUCE', 38), + (44, 'loop') : ('REDUCE', 38), + (44, 'of') : ('REDUCE', 38), + (44, '*') : ('REDUCE', 38), + (44, 'pool') : ('REDUCE', 38), + (44, ',') : ('REDUCE', 38), + (44, '/') : ('REDUCE', 38), + (45, 'then') : ('REDUCE', 51), + (45, 'else') : ('REDUCE', 51), + (45, 'fi') : ('REDUCE', 51), + (45, 'of') : ('REDUCE', 51), + (45, 'in') : ('REDUCE', 51), + (45, ';') : ('REDUCE', 51), + (45, ',') : ('REDUCE', 51), + (45, '.') : ('REDUCE', 51), + (45, ')') : ('REDUCE', 51), + (45, '}') : ('REDUCE', 51), + (45, '=') : ('REDUCE', 51), + (45, '+') : ('REDUCE', 51), + (45, '-') : ('REDUCE', 51), + (45, '*') : ('REDUCE', 51), + (45, '/') : ('REDUCE', 51), + (45, '<') : ('REDUCE', 51), + (45, '<=') : ('REDUCE', 51), + (45, '@') : ('REDUCE', 51), + (45, 'loop') : ('REDUCE', 51), + (45, 'pool') : ('REDUCE', 51), + (46, 'false') : ('SHIFT', 29), + (46, 'id') : ('SHIFT', 16), + (46, 'string') : ('SHIFT', 30), + (46, 'true') : ('SHIFT', 28), + (46, 'int') : ('SHIFT', 21), + (46, 'isvoid') : ('SHIFT', 27), + (46, '~') : ('SHIFT', 15), + (46, '(') : ('SHIFT', 13), + (46, 'new') : ('SHIFT', 22), + (47, '<') : ('REDUCE', 39), + (47, '<=') : ('REDUCE', 39), + (47, ')') : ('REDUCE', 39), + (47, 'then') : ('REDUCE', 39), + (47, '}') : ('REDUCE', 39), + (47, 'else') : ('REDUCE', 39), + (47, 'fi') : ('REDUCE', 39), + (47, '=') : ('REDUCE', 39), + (47, 'in') : ('REDUCE', 39), + (47, ';') : ('REDUCE', 39), + (47, '+') : ('REDUCE', 39), + (47, '-') : ('REDUCE', 39), + (47, 'loop') : ('REDUCE', 39), + (47, 'of') : ('REDUCE', 39), + (47, '*') : ('REDUCE', 39), + (47, 'pool') : ('REDUCE', 39), + (47, ',') : ('REDUCE', 39), + (47, '/') : ('REDUCE', 39), + (48, '<') : ('REDUCE', 40), + (48, '<=') : ('REDUCE', 40), + (48, ')') : ('REDUCE', 40), + (48, 'then') : ('REDUCE', 40), + (48, '}') : ('REDUCE', 40), + (48, 'else') : ('REDUCE', 40), + (48, 'fi') : ('REDUCE', 40), + (48, '=') : ('REDUCE', 40), + (48, 'in') : ('REDUCE', 40), + (48, ';') : ('REDUCE', 40), + (48, '+') : ('REDUCE', 40), + (48, '-') : ('REDUCE', 40), + (48, 'loop') : ('REDUCE', 40), + (48, 'of') : ('REDUCE', 40), + (48, '*') : ('REDUCE', 40), + (48, 'pool') : ('REDUCE', 40), + (48, ',') : ('REDUCE', 40), + (48, '/') : ('REDUCE', 40), + (49, 'id') : ('SHIFT', 16), + (49, 'false') : ('SHIFT', 29), + (49, 'string') : ('SHIFT', 30), + (49, 'int') : ('SHIFT', 21), + (49, '~') : ('SHIFT', 15), + (49, 'isvoid') : ('SHIFT', 27), + (49, '(') : ('SHIFT', 13), + (49, 'new') : ('SHIFT', 22), + (49, 'true') : ('SHIFT', 28), + (50, '/') : ('SHIFT', 46), + (50, '<') : ('REDUCE', 36), + (50, '<=') : ('REDUCE', 36), + (50, ')') : ('REDUCE', 36), + (50, 'then') : ('REDUCE', 36), + (50, '}') : ('REDUCE', 36), + (50, 'else') : ('REDUCE', 36), + (50, 'fi') : ('REDUCE', 36), + (50, '=') : ('REDUCE', 36), + (50, 'in') : ('REDUCE', 36), + (50, ';') : ('REDUCE', 36), + (50, '+') : ('REDUCE', 36), + (50, '-') : ('REDUCE', 36), + (50, 'loop') : ('REDUCE', 36), + (50, 'of') : ('REDUCE', 36), + (50, 'pool') : ('REDUCE', 36), + (50, ',') : ('REDUCE', 36), + (50, '*') : ('SHIFT', 43), + (51, '<') : ('REDUCE', 37), + (51, '<=') : ('REDUCE', 37), + (51, ')') : ('REDUCE', 37), + (51, 'then') : ('REDUCE', 37), + (51, '}') : ('REDUCE', 37), + (51, 'else') : ('REDUCE', 37), + (51, 'fi') : ('REDUCE', 37), + (51, '=') : ('REDUCE', 37), + (51, 'in') : ('REDUCE', 37), + (51, ';') : ('REDUCE', 37), + (51, '+') : ('REDUCE', 37), + (51, '-') : ('REDUCE', 37), + (51, 'loop') : ('REDUCE', 37), + (51, 'of') : ('REDUCE', 37), + (51, 'pool') : ('REDUCE', 37), + (51, ',') : ('REDUCE', 37), + (51, '/') : ('SHIFT', 46), + (51, '*') : ('SHIFT', 43), + (52, 'false') : ('SHIFT', 29), + (52, 'id') : ('SHIFT', 16), + (52, 'string') : ('SHIFT', 30), + (52, 'isvoid') : ('SHIFT', 27), + (52, '~') : ('SHIFT', 15), + (52, 'int') : ('SHIFT', 21), + (52, '(') : ('SHIFT', 13), + (52, 'new') : ('SHIFT', 22), + (52, 'true') : ('SHIFT', 28), + (53, '<') : ('REDUCE', 31), + (53, '<=') : ('REDUCE', 31), + (53, ')') : ('REDUCE', 31), + (53, 'then') : ('REDUCE', 31), + (53, '}') : ('REDUCE', 31), + (53, 'else') : ('REDUCE', 31), + (53, 'fi') : ('REDUCE', 31), + (53, '=') : ('REDUCE', 31), + (53, 'in') : ('REDUCE', 31), + (53, ';') : ('REDUCE', 31), + (53, 'loop') : ('REDUCE', 31), + (53, 'of') : ('REDUCE', 31), + (53, 'pool') : ('REDUCE', 31), + (53, ',') : ('REDUCE', 31), + (53, '+') : ('SHIFT', 41), + (53, '-') : ('SHIFT', 49), + (54, 'false') : ('SHIFT', 29), + (54, 'id') : ('SHIFT', 16), + (54, 'string') : ('SHIFT', 30), + (54, 'isvoid') : ('SHIFT', 27), + (54, '~') : ('SHIFT', 15), + (54, 'int') : ('SHIFT', 21), + (54, '(') : ('SHIFT', 13), + (54, 'new') : ('SHIFT', 22), + (54, 'true') : ('SHIFT', 28), + (55, '-') : ('SHIFT', 49), + (55, '+') : ('SHIFT', 41), + (55, '<') : ('REDUCE', 32), + (55, '<=') : ('REDUCE', 32), + (55, ')') : ('REDUCE', 32), + (55, 'then') : ('REDUCE', 32), + (55, '}') : ('REDUCE', 32), + (55, 'else') : ('REDUCE', 32), + (55, 'fi') : ('REDUCE', 32), + (55, '=') : ('REDUCE', 32), + (55, 'in') : ('REDUCE', 32), + (55, ';') : ('REDUCE', 32), + (55, 'loop') : ('REDUCE', 32), + (55, 'of') : ('REDUCE', 32), + (55, 'pool') : ('REDUCE', 32), + (55, ',') : ('REDUCE', 32), + (56, ',') : ('SHIFT', 57), + (56, ')') : ('REDUCE', 55), + (57, 'while') : ('SHIFT', 20), + (57, 'id') : ('SHIFT', 18), + (57, 'new') : ('SHIFT', 22), + (57, '~') : ('SHIFT', 15), + (57, 'case') : ('SHIFT', 25), + (57, 'if') : ('SHIFT', 24), + (57, 'not') : ('SHIFT', 26), + (57, 'true') : ('SHIFT', 28), + (57, 'false') : ('SHIFT', 29), + (57, 'int') : ('SHIFT', 21), + (57, 'string') : ('SHIFT', 30), + (57, 'isvoid') : ('SHIFT', 27), + (57, '(') : ('SHIFT', 13), + (57, ')') : ('REDUCE', 57), + (57, 'let') : ('SHIFT', 8), + (57, '{') : ('SHIFT', 14), + (58, ')') : ('REDUCE', 56), + (59, '<') : ('REDUCE', 34), + (59, '<=') : ('REDUCE', 34), + (59, ')') : ('REDUCE', 34), + (59, 'then') : ('REDUCE', 34), + (59, '}') : ('REDUCE', 34), + (59, 'else') : ('REDUCE', 34), + (59, 'fi') : ('REDUCE', 34), + (59, '=') : ('REDUCE', 34), + (59, 'in') : ('REDUCE', 34), + (59, ';') : ('REDUCE', 34), + (59, 'loop') : ('REDUCE', 34), + (59, 'of') : ('REDUCE', 34), + (59, 'pool') : ('REDUCE', 34), + (59, ',') : ('REDUCE', 34), + (59, '+') : ('SHIFT', 41), + (59, '-') : ('SHIFT', 49), + (60, 'type') : ('SHIFT', 61), + (61, '.') : ('SHIFT', 62), + (62, 'id') : ('SHIFT', 63), + (63, '(') : ('SHIFT', 64), + (64, 'while') : ('SHIFT', 20), + (64, 'id') : ('SHIFT', 18), + (64, 'new') : ('SHIFT', 22), + (64, '~') : ('SHIFT', 15), + (64, 'case') : ('SHIFT', 25), + (64, 'if') : ('SHIFT', 24), + (64, 'not') : ('SHIFT', 26), + (64, 'true') : ('SHIFT', 28), + (64, 'false') : ('SHIFT', 29), + (64, 'int') : ('SHIFT', 21), + (64, 'string') : ('SHIFT', 30), + (64, 'isvoid') : ('SHIFT', 27), + (64, '(') : ('SHIFT', 13), + (64, ')') : ('REDUCE', 57), + (64, 'let') : ('SHIFT', 8), + (64, '{') : ('SHIFT', 14), + (65, ')') : ('SHIFT', 66), + (66, 'then') : ('REDUCE', 54), + (66, 'else') : ('REDUCE', 54), + (66, 'fi') : ('REDUCE', 54), + (66, 'of') : ('REDUCE', 54), + (66, 'in') : ('REDUCE', 54), + (66, ';') : ('REDUCE', 54), + (66, ',') : ('REDUCE', 54), + (66, '.') : ('REDUCE', 54), + (66, ')') : ('REDUCE', 54), + (66, '}') : ('REDUCE', 54), + (66, '=') : ('REDUCE', 54), + (66, '+') : ('REDUCE', 54), + (66, '-') : ('REDUCE', 54), + (66, '*') : ('REDUCE', 54), + (66, '/') : ('REDUCE', 54), + (66, '<') : ('REDUCE', 54), + (66, '<=') : ('REDUCE', 54), + (66, '@') : ('REDUCE', 54), + (66, 'loop') : ('REDUCE', 54), + (66, 'pool') : ('REDUCE', 54), + (67, ')') : ('REDUCE', 18), + (67, 'then') : ('REDUCE', 18), + (67, '}') : ('REDUCE', 18), + (67, 'else') : ('REDUCE', 18), + (67, 'fi') : ('REDUCE', 18), + (67, 'in') : ('REDUCE', 18), + (67, ';') : ('REDUCE', 18), + (67, 'loop') : ('REDUCE', 18), + (67, 'of') : ('REDUCE', 18), + (67, 'pool') : ('REDUCE', 18), + (67, ',') : ('REDUCE', 18), + (68, 'of') : ('SHIFT', 69), + (69, 'id') : ('SHIFT', 70), + (70, ':') : ('SHIFT', 71), + (71, 'type') : ('SHIFT', 72), + (72, '=>') : ('SHIFT', 73), + (73, 'if') : ('SHIFT', 24), + (73, 'not') : ('SHIFT', 26), + (73, 'id') : ('SHIFT', 18), + (73, 'false') : ('SHIFT', 29), + (73, 'int') : ('SHIFT', 21), + (73, 'string') : ('SHIFT', 30), + (73, '(') : ('SHIFT', 13), + (73, 'true') : ('SHIFT', 28), + (73, 'let') : ('SHIFT', 8), + (73, 'isvoid') : ('SHIFT', 27), + (73, '~') : ('SHIFT', 15), + (73, 'case') : ('SHIFT', 25), + (73, '{') : ('SHIFT', 14), + (73, 'new') : ('SHIFT', 22), + (73, 'while') : ('SHIFT', 20), + (74, ';') : ('SHIFT', 75), + (75, 'id') : ('SHIFT', 70), + (75, 'esac') : ('REDUCE', 28), + (76, 'esac') : ('REDUCE', 29), + (77, 'esac') : ('SHIFT', 78), + (78, ')') : ('REDUCE', 27), + (78, 'then') : ('REDUCE', 27), + (78, '}') : ('REDUCE', 27), + (78, 'else') : ('REDUCE', 27), + (78, 'fi') : ('REDUCE', 27), + (78, 'in') : ('REDUCE', 27), + (78, ';') : ('REDUCE', 27), + (78, 'loop') : ('REDUCE', 27), + (78, 'of') : ('REDUCE', 27), + (78, 'pool') : ('REDUCE', 27), + (78, ',') : ('REDUCE', 27), + (79, 'then') : ('SHIFT', 80), + (80, 'id') : ('SHIFT', 18), + (80, 'let') : ('SHIFT', 8), + (80, 'false') : ('SHIFT', 29), + (80, 'int') : ('SHIFT', 21), + (80, 'isvoid') : ('SHIFT', 27), + (80, '~') : ('SHIFT', 15), + (80, 'string') : ('SHIFT', 30), + (80, '(') : ('SHIFT', 13), + (80, 'case') : ('SHIFT', 25), + (80, 'new') : ('SHIFT', 22), + (80, 'while') : ('SHIFT', 20), + (80, 'if') : ('SHIFT', 24), + (80, 'not') : ('SHIFT', 26), + (80, '{') : ('SHIFT', 14), + (80, 'true') : ('SHIFT', 28), + (81, 'else') : ('SHIFT', 82), + (82, 'case') : ('SHIFT', 25), + (82, 'not') : ('SHIFT', 26), + (82, 'int') : ('SHIFT', 21), + (82, '(') : ('SHIFT', 13), + (82, 'while') : ('SHIFT', 20), + (82, 'id') : ('SHIFT', 18), + (82, 'true') : ('SHIFT', 28), + (82, 'if') : ('SHIFT', 24), + (82, 'false') : ('SHIFT', 29), + (82, 'let') : ('SHIFT', 8), + (82, 'string') : ('SHIFT', 30), + (82, 'isvoid') : ('SHIFT', 27), + (82, '~') : ('SHIFT', 15), + (82, 'new') : ('SHIFT', 22), + (82, '{') : ('SHIFT', 14), + (83, 'fi') : ('SHIFT', 84), + (84, ')') : ('REDUCE', 16), + (84, 'then') : ('REDUCE', 16), + (84, '}') : ('REDUCE', 16), + (84, 'else') : ('REDUCE', 16), + (84, 'fi') : ('REDUCE', 16), + (84, 'in') : ('REDUCE', 16), + (84, ';') : ('REDUCE', 16), + (84, 'loop') : ('REDUCE', 16), + (84, 'of') : ('REDUCE', 16), + (84, 'pool') : ('REDUCE', 16), + (84, ',') : ('REDUCE', 16), + (85, 'loop') : ('SHIFT', 86), + (86, 'let') : ('SHIFT', 8), + (86, 'new') : ('SHIFT', 22), + (86, 'id') : ('SHIFT', 18), + (86, 'isvoid') : ('SHIFT', 27), + (86, '~') : ('SHIFT', 15), + (86, 'case') : ('SHIFT', 25), + (86, '{') : ('SHIFT', 14), + (86, 'true') : ('SHIFT', 28), + (86, 'while') : ('SHIFT', 20), + (86, 'false') : ('SHIFT', 29), + (86, 'int') : ('SHIFT', 21), + (86, 'string') : ('SHIFT', 30), + (86, '(') : ('SHIFT', 13), + (86, 'if') : ('SHIFT', 24), + (86, 'not') : ('SHIFT', 26), + (87, 'pool') : ('SHIFT', 88), + (88, ')') : ('REDUCE', 17), + (88, 'then') : ('REDUCE', 17), + (88, '}') : ('REDUCE', 17), + (88, 'else') : ('REDUCE', 17), + (88, 'fi') : ('REDUCE', 17), + (88, 'in') : ('REDUCE', 17), + (88, ';') : ('REDUCE', 17), + (88, 'loop') : ('REDUCE', 17), + (88, 'of') : ('REDUCE', 17), + (88, 'pool') : ('REDUCE', 17), + (88, ',') : ('REDUCE', 17), + (89, ')') : ('REDUCE', 15), + (89, 'then') : ('REDUCE', 15), + (89, '}') : ('REDUCE', 15), + (89, 'else') : ('REDUCE', 15), + (89, 'fi') : ('REDUCE', 15), + (89, 'in') : ('REDUCE', 15), + (89, ';') : ('REDUCE', 15), + (89, 'loop') : ('REDUCE', 15), + (89, 'of') : ('REDUCE', 15), + (89, 'pool') : ('REDUCE', 15), + (89, ',') : ('REDUCE', 15), + (90, ')') : ('SHIFT', 91), + (91, 'then') : ('REDUCE', 53), + (91, 'else') : ('REDUCE', 53), + (91, 'fi') : ('REDUCE', 53), + (91, 'of') : ('REDUCE', 53), + (91, 'in') : ('REDUCE', 53), + (91, ';') : ('REDUCE', 53), + (91, ',') : ('REDUCE', 53), + (91, '.') : ('REDUCE', 53), + (91, ')') : ('REDUCE', 53), + (91, '}') : ('REDUCE', 53), + (91, '=') : ('REDUCE', 53), + (91, '+') : ('REDUCE', 53), + (91, '-') : ('REDUCE', 53), + (91, '*') : ('REDUCE', 53), + (91, '/') : ('REDUCE', 53), + (91, '<') : ('REDUCE', 53), + (91, '<=') : ('REDUCE', 53), + (91, '@') : ('REDUCE', 53), + (91, 'loop') : ('REDUCE', 53), + (91, 'pool') : ('REDUCE', 53), + (92, '<') : ('REDUCE', 42), + (92, '<=') : ('REDUCE', 42), + (92, ')') : ('REDUCE', 42), + (92, 'then') : ('REDUCE', 42), + (92, '}') : ('REDUCE', 42), + (92, 'else') : ('REDUCE', 42), + (92, 'fi') : ('REDUCE', 42), + (92, '=') : ('REDUCE', 42), + (92, 'in') : ('REDUCE', 42), + (92, ';') : ('REDUCE', 42), + (92, '+') : ('REDUCE', 42), + (92, '-') : ('REDUCE', 42), + (92, 'loop') : ('REDUCE', 42), + (92, 'of') : ('REDUCE', 42), + (92, '*') : ('REDUCE', 42), + (92, 'pool') : ('REDUCE', 42), + (92, ',') : ('REDUCE', 42), + (92, '/') : ('REDUCE', 42), + (93, '}') : ('SHIFT', 94), + (94, ')') : ('REDUCE', 19), + (94, 'then') : ('REDUCE', 19), + (94, '}') : ('REDUCE', 19), + (94, 'else') : ('REDUCE', 19), + (94, 'fi') : ('REDUCE', 19), + (94, 'in') : ('REDUCE', 19), + (94, ';') : ('REDUCE', 19), + (94, 'loop') : ('REDUCE', 19), + (94, 'of') : ('REDUCE', 19), + (94, 'pool') : ('REDUCE', 19), + (94, ',') : ('REDUCE', 19), + (95, ';') : ('SHIFT', 96), + (96, 'if') : ('SHIFT', 24), + (96, 'not') : ('SHIFT', 26), + (96, 'id') : ('SHIFT', 18), + (96, 'false') : ('SHIFT', 29), + (96, 'int') : ('SHIFT', 21), + (96, 'string') : ('SHIFT', 30), + (96, '(') : ('SHIFT', 13), + (96, '}') : ('REDUCE', 20), + (96, 'true') : ('SHIFT', 28), + (96, 'let') : ('SHIFT', 8), + (96, 'isvoid') : ('SHIFT', 27), + (96, '~') : ('SHIFT', 15), + (96, 'case') : ('SHIFT', 25), + (96, '{') : ('SHIFT', 14), + (96, 'new') : ('SHIFT', 22), + (96, 'while') : ('SHIFT', 20), + (97, '}') : ('REDUCE', 21), + (98, ')') : ('SHIFT', 99), + (99, 'then') : ('REDUCE', 50), + (99, 'else') : ('REDUCE', 50), + (99, 'fi') : ('REDUCE', 50), + (99, 'of') : ('REDUCE', 50), + (99, 'in') : ('REDUCE', 50), + (99, ';') : ('REDUCE', 50), + (99, ',') : ('REDUCE', 50), + (99, '.') : ('REDUCE', 50), + (99, ')') : ('REDUCE', 50), + (99, '}') : ('REDUCE', 50), + (99, '=') : ('REDUCE', 50), + (99, '+') : ('REDUCE', 50), + (99, '-') : ('REDUCE', 50), + (99, '*') : ('REDUCE', 50), + (99, '/') : ('REDUCE', 50), + (99, '<') : ('REDUCE', 50), + (99, '<=') : ('REDUCE', 50), + (99, '@') : ('REDUCE', 50), + (99, 'loop') : ('REDUCE', 50), + (99, 'pool') : ('REDUCE', 50), + (100, 'in') : ('REDUCE', 24), + (100, ',') : ('SHIFT', 101), + (101, 'id') : ('SHIFT', 9), + (102, 'in') : ('REDUCE', 26), + (103, 'id') : ('SHIFT', 9), + (104, 'in') : ('REDUCE', 25), + (105, 'in') : ('SHIFT', 106), + (106, 'id') : ('SHIFT', 18), + (106, 'false') : ('SHIFT', 29), + (106, 'let') : ('SHIFT', 8), + (106, 'string') : ('SHIFT', 30), + (106, 'isvoid') : ('SHIFT', 27), + (106, 'case') : ('SHIFT', 25), + (106, '~') : ('SHIFT', 15), + (106, '{') : ('SHIFT', 14), + (106, 'new') : ('SHIFT', 22), + (106, 'while') : ('SHIFT', 20), + (106, 'if') : ('SHIFT', 24), + (106, 'not') : ('SHIFT', 26), + (106, 'int') : ('SHIFT', 21), + (106, '(') : ('SHIFT', 13), + (106, 'true') : ('SHIFT', 28), + (107, ')') : ('REDUCE', 22), + (107, 'then') : ('REDUCE', 22), + (107, '}') : ('REDUCE', 22), + (107, 'else') : ('REDUCE', 22), + (107, 'fi') : ('REDUCE', 22), + (107, 'in') : ('REDUCE', 22), + (107, ';') : ('REDUCE', 22), + (107, 'loop') : ('REDUCE', 22), + (107, 'of') : ('REDUCE', 22), + (107, 'pool') : ('REDUCE', 22), + (107, ',') : ('REDUCE', 22), + (108, ';') : ('REDUCE', 9), + (109, ')') : ('REDUCE', 13), + (109, 'id') : ('SHIFT', 110), + (110, ':') : ('SHIFT', 111), + (111, 'type') : ('SHIFT', 112), + (112, ',') : ('REDUCE', 14), + (112, ')') : ('REDUCE', 14), + (113, ')') : ('SHIFT', 114), + (114, ':') : ('SHIFT', 115), + (115, 'type') : ('SHIFT', 116), + (116, '{') : ('SHIFT', 117), + (117, 'string') : ('SHIFT', 30), + (117, '(') : ('SHIFT', 13), + (117, 'isvoid') : ('SHIFT', 27), + (117, '~') : ('SHIFT', 15), + (117, 'let') : ('SHIFT', 8), + (117, 'true') : ('SHIFT', 28), + (117, 'case') : ('SHIFT', 25), + (117, '{') : ('SHIFT', 14), + (117, 'while') : ('SHIFT', 20), + (117, 'id') : ('SHIFT', 18), + (117, 'new') : ('SHIFT', 22), + (117, 'if') : ('SHIFT', 24), + (117, 'not') : ('SHIFT', 26), + (117, 'false') : ('SHIFT', 29), + (117, 'int') : ('SHIFT', 21), + (118, '}') : ('SHIFT', 119), + (119, ';') : ('REDUCE', 10), + (120, ',') : ('SHIFT', 121), + (120, ')') : ('REDUCE', 11), + (121, ')') : ('REDUCE', 13), + (121, 'id') : ('SHIFT', 110), + (122, ')') : ('REDUCE', 12), + (123, '}') : ('SHIFT', 124), + (124, ';') : ('REDUCE', 3), + (125, ';') : ('SHIFT', 126), + (126, 'id') : ('SHIFT', 4), + (126, '}') : ('REDUCE', 7), + (127, '}') : ('REDUCE', 5), + (128, ';') : ('SHIFT', 129), + (129, 'id') : ('SHIFT', 4), + (129, '}') : ('REDUCE', 7), + (130, '}') : ('REDUCE', 6), + (131, 'type') : ('SHIFT', 132), + (132, '{') : ('SHIFT', 133), + (133, 'id') : ('SHIFT', 4), + (133, '}') : ('REDUCE', 7), + (134, '}') : ('SHIFT', 135), + (135, ';') : ('REDUCE', 4), + (136, '$') : ('REDUCE', 0), + (137, ';') : ('SHIFT', 138), + (138, 'class') : ('SHIFT', 1), + (138, '$') : ('REDUCE', 1), + (139, '$') : ('REDUCE', 2), + (140, '$') : ('OK', None) + } + + + + + self.goto = { + (0, '') : 137, + (0, ''): 140, + (0, '') : 136, + (3, '') : 123, + (3, '') : 125, + (3, '') : 128, + (7, '') : 59, + (7, '') : 38, + (7, '') : 48, + (7, '') : 51, + (7, '') : 32, + (7, '') : 45, + (7, '') : 108, + (8, '') : 105, + (12, '') : 51, + (12, '') : 48, + (12, '') : 38, + (12, '') : 100, + (12, '') : 32, + (12, '') : 45, + (12, '') : 59, + (13, '') : 51, + (13, '') : 38, + (13, '') : 59, + (13, '') : 32, + (13, '') : 45, + (13, '') : 98, + (13, '') : 48, + (14, '') : 95, + (14, '') : 32, + (14, '') : 59, + (14, '') : 38, + (14, '') : 48, + (14, '') : 51, + (14, '') : 45, + (14, '') : 93, + (15, '') : 45, + (15, '') : 92, + (15, '') : 32, + (17, '') : 38, + (17, '') : 48, + (17, '') : 51, + (17, '') : 59, + (17, '') : 32, + (17, '') : 90, + (17, '') : 45, + (17, '') : 56, + (19, '') : 38, + (19, '') : 51, + (19, '') : 32, + (19, '') : 59, + (19, '') : 48, + (19, '') : 89, + (19, '') : 45, + (20, '') : 59, + (20, '') : 38, + (20, '') : 32, + (20, '') : 51, + (20, '') : 48, + (20, '') : 85, + (20, '') : 45, + (24, '') : 38, + (24, '') : 32, + (24, '') : 51, + (24, '') : 59, + (24, '') : 48, + (24, '') : 79, + (24, '') : 45, + (25, '') : 59, + (25, '') : 51, + (25, '') : 38, + (25, '') : 32, + (25, '') : 48, + (25, '') : 45, + (25, '') : 68, + (26, '') : 38, + (26, '') : 51, + (26, '') : 32, + (26, '') : 67, + (26, '') : 59, + (26, '') : 48, + (26, '') : 45, + (27, '') : 31, + (27, '') : 45, + (27, '') : 32, + (35, '') : 38, + (35, '') : 36, + (35, '') : 48, + (35, '') : 51, + (35, '') : 59, + (35, '') : 32, + (35, '') : 45, + (35, '') : 56, + (39, '') : 40, + (39, '') : 51, + (39, '') : 32, + (39, '') : 48, + (39, '') : 45, + (41, '') : 42, + (41, '') : 32, + (41, '') : 48, + (41, '') : 45, + (43, '') : 45, + (43, '') : 32, + (43, '') : 44, + (46, '') : 45, + (46, '') : 32, + (46, '') : 47, + (49, '') : 50, + (49, '') : 32, + (49, '') : 48, + (49, '') : 45, + (52, '') : 53, + (52, '') : 51, + (52, '') : 32, + (52, '') : 48, + (52, '') : 45, + (54, '') : 55, + (54, '') : 51, + (54, '') : 32, + (54, '') : 48, + (54, '') : 45, + (57, '') : 38, + (57, '') : 48, + (57, '') : 51, + (57, '') : 59, + (57, '') : 32, + (57, '') : 58, + (57, '') : 45, + (57, '') : 56, + (64, '') : 38, + (64, '') : 48, + (64, '') : 51, + (64, '') : 59, + (64, '') : 32, + (64, '') : 45, + (64, '') : 56, + (64, '') : 65, + (69, '') : 77, + (73, '') : 59, + (73, '') : 38, + (73, '') : 48, + (73, '') : 51, + (73, '') : 32, + (73, '') : 74, + (73, '') : 45, + (75, '') : 76, + (80, '') : 48, + (80, '') : 51, + (80, '') : 59, + (80, '') : 32, + (80, '') : 38, + (80, '') : 45, + (80, '') : 81, + (82, '') : 32, + (82, '') : 38, + (82, '') : 59, + (82, '') : 51, + (82, '') : 45, + (82, '') : 48, + (82, '') : 83, + (86, '') : 59, + (86, '') : 48, + (86, '') : 51, + (86, '') : 38, + (86, '') : 32, + (86, '') : 45, + (86, '') : 87, + (96, '') : 95, + (96, '') : 59, + (96, '') : 38, + (96, '') : 48, + (96, '') : 51, + (96, '') : 32, + (96, '') : 45, + (96, '') : 97, + (101, '') : 102, + (103, '') : 104, + (106, '') : 38, + (106, '') : 51, + (106, '') : 32, + (106, '') : 59, + (106, '') : 48, + (106, '') : 45, + (106, '') : 107, + (109, '') : 113, + (109, '') : 120, + (117, '') : 51, + (117, '') : 59, + (117, '') : 45, + (117, '') : 32, + (117, '') : 118, + (117, '') : 38, + (117, '') : 48, + (121, '') : 120, + (121, '') : 122, + (126, '') : 127, + (126, '') : 125, + (126, '') : 128, + (129, '') : 130, + (129, '') : 125, + (129, '') : 128, + (133, '') : 134, + (133, '') : 125, + (133, '') : 128, + (138, '') : 137, + (138, '') : 139 + } + + + ShiftReduceParser.__init__(self,G) \ No newline at end of file diff --git a/src/utils/parser/LALR_1.py b/src/utils/parser/LALR_1.py new file mode 100644 index 000000000..e9dfb1374 --- /dev/null +++ b/src/utils/parser/LALR_1.py @@ -0,0 +1,64 @@ +from utils.parser.LR_1 import LR1_Parser +from cmp.automata import State, multiline_formatter +from cmp.utils import ContainerSet +from cmp.pycompiler import Item + +class LALR1_Parser(LR1_Parser): + + def build_automaton(self,G): + assert len(G.startSymbol.productions) == 1, 'Grammar must be augmented' + + firsts = self.firsts + firsts[G.EOF] = ContainerSet(G.EOF) + + start_production = G.startSymbol.productions[0] + start_item = Item(start_production, 0, lookaheads=ContainerSet(G.EOF)) + start = frozenset([start_item.Center()]) + + closure = self.closure_lr1([start_item], firsts) + automaton = State(frozenset(closure), True) + + pending = [start] + visited = {start: automaton} + + while pending: + current = pending.pop() + current_state = visited[current] + + for symbol in G.terminals + G.nonTerminals: + a = self.goto_lr1(current_state.state, symbol, just_kernel=True) + closure = self.closure_lr1(a, firsts) + center = frozenset(item.Center() for item in a) + + if not a: + continue + + try: + next_state = visited[center] + centers = {item.Center(): item for item in next_state.state} + centers = {item.Center(): (centers[item.Center()], item) for item in closure} + + updated_items = set() + for c, (itemA, itemB) in centers.items(): + item = Item(c.production, c.pos, itemA.lookaheads | itemB.lookaheads) + updated_items.add(item) + + updated_items = frozenset(updated_items) + if next_state.state != updated_items: + pending.append(center) + next_state.state = updated_items + + except KeyError: + visited[center] = next_state = State(frozenset(closure), True) + pending.append(center) + + if current_state[symbol.Name] is None: + current_state.add_transition(symbol.Name, next_state) + else: + assert current_state.get(symbol.Name) is next_state, 'Error!!!' + + automaton.set_formatter(multiline_formatter) + return automaton + + def __str__(self): + return 'LALR(1)' \ No newline at end of file diff --git a/src/utils/parser/LR_1.py b/src/utils/parser/LR_1.py new file mode 100644 index 000000000..5125d2d33 --- /dev/null +++ b/src/utils/parser/LR_1.py @@ -0,0 +1,136 @@ +from utils.parser.shift_reduce_parser import ShiftReduceParser +from cmp.automata import State, multiline_formatter +from cmp.utils import ContainerSet +from cmp.pycompiler import Item + +class LR1_Parser(ShiftReduceParser): + + def _build_parsing_table(self): + + automaton = self.build_automaton(self.G) + self.automaton = automaton + + for i, node in enumerate(automaton): + node.idx = i + + for node in automaton: + idx = node.idx + for item in node.state: + + # - Fill `self.Action` and `self.Goto` according to `item`) + # - Feel free to use `self._register(...)`) + p = item.production + if item.IsReduceItem: + if p.Left == self.G.startSymbol: + self._register(self.action,(idx,self.G.EOF.Name),(ShiftReduceParser.OK,None)) + else: + for c in item.lookaheads: + self._register(self.action,(idx,c.Name),(ShiftReduceParser.REDUCE,self.G.Productions.index(p))) + else: + + if item.NextSymbol.IsTerminal: + self._register(self.action,(idx,item.NextSymbol.Name),(ShiftReduceParser.SHIFT, node[item.NextSymbol.Name][0].idx)) + else: + self._register(self.goto,(idx,item.NextSymbol.Name),(node[item.NextSymbol.Name][0].idx)) + + + def build_automaton(self,G): + assert len(G.startSymbol.productions) == 1, 'Grammar must be augmented' + + firsts = self.firsts + firsts[G.EOF] = ContainerSet(G.EOF) + + start_production = G.startSymbol.productions[0] + start_item = Item(start_production, 0, lookaheads=(G.EOF,)) + start = frozenset([start_item]) + + closure = self.closure_lr1(start, firsts) + automaton = State(frozenset(closure), True) + + pending = [ start ] + visited = { start: automaton } + + while pending: + current = pending.pop() + current_state = visited[current] + + for symbol in G.terminals + G.nonTerminals: + # (Get/Build `next_state`) + a = self.goto_lr1(current_state.state,symbol,firsts,True) + + if not a: + continue + + try: + next_state = visited[a] + except: + next_state = State(frozenset(self.goto_lr1(current_state.state,symbol,firsts)),True) + visited[a] = next_state + pending.append(a) + + current_state.add_transition(symbol.Name, next_state) + + automaton.set_formatter(multiline_formatter) + return automaton + + + def goto_lr1(self,items, symbol, firsts=None, just_kernel=False): + assert just_kernel or firsts is not None, '`firsts` must be provided if `just_kernel=False`' + items = frozenset(item.NextItem() for item in items if item.NextSymbol == symbol) + return items if just_kernel else self.closure_lr1(items, firsts) + + + def closure_lr1(self,items, firsts): + closure = ContainerSet(*items) + + changed = True + while changed: + changed = False + + new_items = ContainerSet() + + #por cada item hacer expand y añadirlo a new_items + for item in closure: + e = self.expand(item,firsts) + new_items.extend(e) + + changed = closure.update(new_items) + + return self.compress(closure) + + + def compress(self,items): + centers = {} + + for item in items: + center = item.Center() + try: + lookaheads = centers[center] + except KeyError: + centers[center] = lookaheads = set() + lookaheads.update(item.lookaheads) + + return { Item(x.production, x.pos, set(lookahead)) for x, lookahead in centers.items() } + + + def expand(self,item, firsts): + next_symbol = item.NextSymbol + if next_symbol is None or not next_symbol.IsNonTerminal: + return [] + + lookaheads = ContainerSet() + # (Compute lookahead for child items) + #calcular el first a todos los preview posibles + for p in item.Preview(): + for first in self.compute_local_first(firsts,p): + lookaheads.add(first) + + assert not lookaheads.contains_epsilon + # (Build and return child items) + _list = [] + for production in next_symbol.productions: + _list.append(Item(production,0,lookaheads)) + return _list + + def __str__(self): + return 'LR(1)' \ No newline at end of file diff --git a/src/utils/parser/parser.py b/src/utils/parser/parser.py new file mode 100644 index 000000000..c94fbc8cc --- /dev/null +++ b/src/utils/parser/parser.py @@ -0,0 +1,130 @@ +from cmp.utils import ContainerSet +from cmp.pycompiler import Sentence +from itertools import islice +from collections import deque + +class Parser: + def __init__(self,G): + self.G = G + if not self.action: + self.firsts = self.compute_firsts() + self.follows = self.compute_follows() + self._build_parsing_table() + + def _build_parsing_table(self): + raise NotImplementedError() + + def _find_conflict(self): + raise NotImplementedError() + + # Computes First(Vt) U First(Vn) U First(alpha) + # P: X -> alpha + def compute_firsts(self): + firsts = {} + change = True + + # init First(Vt) + for terminal in self.G.terminals: + firsts[terminal] = ContainerSet(terminal) + + # init First(Vn) + for nonterminal in self.G.nonTerminals: + firsts[nonterminal] = ContainerSet() + + while change: + change = False + + # P: X -> alpha + for production in self.G.Productions: + X = production.Left + alpha = production.Right + + # get current First(X) + first_X = firsts[X] + + # init First(alpha) + try: + first_alpha = firsts[alpha] + except: + first_alpha = firsts[alpha] = ContainerSet() + + # CurrentFirst(alpha)??? + local_first = self.compute_local_first(firsts, alpha) + + # update First(X) and First(alpha) from CurrentFirst(alpha) + change |= first_alpha.hard_update(local_first) + change |= first_X.hard_update(local_first) + + # First(Vt) + First(Vt) + First(RightSides) + return firsts + + # Computes First(alpha), given First(Vt) and First(Vn) + # alpha in (Vt U Vn)* + def compute_local_first(self,firsts, alpha): + first_alpha = ContainerSet() + + try: + alpha_is_epsilon = alpha.IsEpsilon + except: + alpha_is_epsilon = False + + # alpha == epsilon ? First(alpha) = { epsilon } + if alpha_is_epsilon: + first_alpha.set_epsilon() + + # alpha = X1 ... XN + # First(Xi) subconjunto First(alpha) + # epsilon pertenece a First(X1)...First(Xi) ? First(Xi+1) subconjunto de First(X) y First(alpha) + # epsilon pertenece a First(X1)...First(XN) ? epsilon pertence a First(X) y al First(alpha) + else: + for item in alpha: + first_symbol = firsts[item] + first_alpha.update(first_symbol) + if not first_symbol.contains_epsilon: + break + else: + first_alpha.set_epsilon() + + # First(alpha) + return first_alpha + + + def compute_follows(self): + follows = { } + change = True + + local_firsts = {} + + # init Follow(Vn) + for nonterminal in self.G.nonTerminals: + follows[nonterminal] = ContainerSet() + follows[self.G.startSymbol] = ContainerSet(self.G.EOF) + + while change: + change = False + + # P: X -> alpha + for production in self.G.Productions: + X = production.Left + alpha = production.Right + + follow_X = follows[X] + + # X -> zeta Y beta + # First(beta) - { epsilon } subset of Follow(Y) + # beta ->* epsilon or X -> zeta Y ? Follow(X) subset of Follow(Y) + for i,symbol in enumerate(alpha): + if symbol.IsNonTerminal: + follow_Y = follows[symbol] + try: + firts_beta = local_firsts[alpha,i] + except KeyError: + firts_beta = local_firsts[alpha,i] = self.compute_local_first(self.firsts,islice(alpha,i+1,None)) + + change |= follow_Y.update(firts_beta) + + if firts_beta.contains_epsilon: + change |= follow_Y.update(follow_X) + + # Follow(Vn) + return follows \ No newline at end of file diff --git a/src/utils/parser/shift_reduce_parser.py b/src/utils/parser/shift_reduce_parser.py new file mode 100644 index 000000000..bed02cf7b --- /dev/null +++ b/src/utils/parser/shift_reduce_parser.py @@ -0,0 +1,65 @@ +from utils.parser.parser import Parser + +class ShiftReduceParser(Parser): + SHIFT = 'SHIFT' + REDUCE = 'REDUCE' + OK = 'OK' + + def __init__(self, G): + try: + self.action + except AttributeError: + self.action = {} + self.goto = {} + self.automaton = None + + self.error = '' + Parser.__init__(self, G) + + def __call__(self, w): + stack = [ 0 ] + cursor = 0 + output = [] + operations = [] + + while True: + state = stack[-1] + lookahead = w[cursor] + + # (Detect error) + + try: + action, tag = self.action[state, self.G[lookahead.token_type].Name] + + # (Shift case) + if action == self.SHIFT: + stack.append(tag) + cursor += 1 + + # (Reduce case) + elif action == self.REDUCE: + tag = self.G.Productions[tag] + output.append(tag) + for _ in tag.Right: stack.pop() + a = self.goto[stack[-1], tag.Left.Name] + stack.append(a) + + + # (OK case) + elif action == self.OK: + return output, operations + + # (Invalid case) + else: + raise Exception ['Error...'] + + operations.append(action) + + except: + self.error = f'({lookahead.line}, {lookahead.column}) - SyntacticError: ERROR at or near "{lookahead.lex}"' + return None, None + + @staticmethod + def _register(table, key, value): + assert key not in table or table[key] == value, 'Shift-Reduce or Reduce-Reduce conflict!!!' + table[key] = value \ No newline at end of file From 59abcc7633d473dd20a71f30be7f8f5c32deb9af Mon Sep 17 00:00:00 2001 From: Ale Date: Tue, 14 Dec 2021 00:28:24 -0800 Subject: [PATCH 06/83] type_collector-type_builder --- src/cmp/evaluation.py | 2 +- src/cmp/semantic.py | 26 ++----- src/utils/semantic_check/type_builder.py | 89 ++++++++++++++++++++++ src/utils/semantic_check/type_collector.py | 56 ++++++++++++++ 4 files changed, 152 insertions(+), 21 deletions(-) create mode 100644 src/utils/semantic_check/type_builder.py create mode 100644 src/utils/semantic_check/type_collector.py diff --git a/src/cmp/evaluation.py b/src/cmp/evaluation.py index 90bdbf935..37390cfdc 100644 --- a/src/cmp/evaluation.py +++ b/src/cmp/evaluation.py @@ -11,7 +11,7 @@ def evaluate_reverse_parse(G, right_parse, operations, tokens): for operation in operations: if operation == ShiftReduceParser.SHIFT: token = next(tokens) - stack.append(token.lex) + stack.append(token) elif operation == ShiftReduceParser.REDUCE: production = next(right_parse) head, body = production diff --git a/src/cmp/semantic.py b/src/cmp/semantic.py index c463fbe25..8cf53c8a2 100644 --- a/src/cmp/semantic.py +++ b/src/cmp/semantic.py @@ -1,6 +1,8 @@ import itertools as itt from collections import OrderedDict +from utils.COOL_Lexer import Token + class SemanticError(Exception): @property @@ -124,8 +126,6 @@ def __repr__(self): def join(self, other): if self is ErrorType(): return ErrorType() - if self.name == 'AUTO_TYPE' or other.name == 'AUTO_TYPE': - return self if self.name != 'AUTO_TYPE' else other current_parent = other while not self.conforms_to(current_parent): @@ -133,22 +133,6 @@ def join(self, other): return current_parent -class AutoType(Type): - def __init__(self): - Type.__init__(self, 'AUTO_TYPE') - - def conforms_to(self, other): - return True - - def bypass(self): - return True - - def get_method(self, name:str): - raise SemanticError(None) - - def __eq__(self, other): - return isinstance(other, Type) - class ErrorType(Type): def __init__(self): Type.__init__(self, '') @@ -189,13 +173,15 @@ class Context: def __init__(self): self.types = {} - def create_type(self, name:str): + def create_type(self, token): + name = token.lex if isinstance(token, Token) else token if name in self.types: raise SemanticError(f'Type with the same name ({name}) already in context.') typex = self.types[name] = Type(name) return typex - def get_type(self, name:str): + def get_type(self, token): + name = token.lex if isinstance(token, Token) else token if name == '': return ErrorType() diff --git a/src/utils/semantic_check/type_builder.py b/src/utils/semantic_check/type_builder.py new file mode 100644 index 000000000..de0ba4add --- /dev/null +++ b/src/utils/semantic_check/type_builder.py @@ -0,0 +1,89 @@ +import cmp.visitor as visitor +from utils.ast.AST_Nodes import ast_nodes as nodes +from cmp.semantic import SemanticError, ErrorType + +class TypeBuilder: + def __init__(self, context, errors): + self.context = context + self.current_type = None + self.errors = errors + + @visitor.on('node') + def visit(self, node): + pass + + @visitor.when(nodes.ProgramNode) + def visit(self,node): + for dec in node.declarations: + self.visit(dec) + return + + + @visitor.when(nodes.ClassDeclarationNode) + def visit(self,node): + self.current_type = self.context.get_type(node.id) + + if node.parent is not None: + + if node.parent.lex in ['Int', 'String', 'SELF_TYPE', 'Bool']: + self.errors.append(f'Cannot inherit from {node.parent}') + + else: + try: + parent_type = self.context.get_type(node.parent) + except SemanticError as se: + parent_type = ErrorType() + self.errors.append(se.text) + + try: + self.current_type.set_parent(parent_type) + except SemanticError as se: + self.errors.append(se.text) + + elif not self.current_type.parent: + self.current_type.set_parent(self.context.get_type('Object')) + + for feat in node.features: + self.visit(feat) + + return + + + @visitor.when(nodes.AttrDeclarationNode) + def visit(self,node): + try: + attrType = self.context.get_type(node.type) + self.current_type.define_attribute(node.id, attrType) + except SemanticError as se: + self.errors.append(se.text) + self.current_type.define_attribute(node.id, ErrorType()) + + return + + + @visitor.when(nodes.MethDeclarationNode) + def visit(self,node): + param_names = [] + param_types = [] + + for name, typex in node.params: + param_names.append(name) + + try: + param_types.append(self.context.get_type(typex)) + except SemanticError as se: + self.errors.append(se.text) + param_types.append(ErrorType()) + + try: + returnType = self.context.get_type(node.type) + except SemanticError as se: + self.errors.append(se.text) + returnType = ErrorType() + + try: + self.current_type.define_method(node.id, param_names, param_types, returnType) + except SemanticError as se: + self.errors.append(se.text) + + return \ No newline at end of file diff --git a/src/utils/semantic_check/type_collector.py b/src/utils/semantic_check/type_collector.py new file mode 100644 index 000000000..1a5b4f828 --- /dev/null +++ b/src/utils/semantic_check/type_collector.py @@ -0,0 +1,56 @@ +import cmp.visitor as visitor +from utils.ast.AST_Nodes import ast_nodes as nodes +from cmp.semantic import SemanticError + +class TypeCollector(object): + def __init__(self, context, errors): + self.context = context + self.errors = errors + + @visitor.on('node') + def visit(self, node): + pass + + @visitor.when(nodes.ProgramNode) + def visit(self, node): + + # añadimos algunos tipos predeterminados + object_type = self.context.create_type('Object') + self_type = self.context.create_type('SELF_TYPE') + int_type = self.context.create_type('Int') + string_type = self.context.create_type('String') + bool_type = self.context.create_type('Bool') + io_type = self.context.create_type('IO') + + # todos heredan de Object + int_type.set_parent(object_type) + string_type.set_parent(object_type) + bool_type.set_parent(object_type) + io_type.set_parent(object_type) + + # agregar los metodos a los tipos basicos + object_type.define_method('abort', [], [], object_type) + object_type.define_method('type_name', [], [], string_type) + object_type.define_method('copy', [], [], self_type) + + io_type.define_method('out_string', ['x'], [string_type], self_type) + io_type.define_method('out_int', ['x'], [int_type], self_type) + io_type.define_method('in_string', [], [], string_type) + io_type.define_method('in_int', [], [], int_type) + + string_type.define_method('length', [], [], int_type) + string_type.define_method('concat', ['s'], [string_type], string_type) + string_type.define_method('substr', ['i', 'l'], [int_type, int_type], string_type) + + for dec in node.declarations: + self.visit(dec) + return + + + @visitor.when(nodes.ClassDeclarationNode) + def visit(self,node): + try: + self.context.create_type(node.id) + except SemanticError as se: + self.errors.append(se.text) + return \ No newline at end of file From 06712f449213f3f12d5ded1850c11a0b7e490cc6 Mon Sep 17 00:00:00 2001 From: Ale Date: Tue, 14 Dec 2021 16:11:51 -0800 Subject: [PATCH 07/83] fixing some issues for type_check --- src/cmp/evaluation.py | 1 + src/cmp/semantic.py | 44 ++++++++++-------------- src/utils/COOL_Grammar.py | 18 +++++----- src/utils/COOL_Lexer.py | 5 ++- src/utils/ast/AST_Nodes.py | 3 +- src/utils/semantic_check/type_builder.py | 5 ++- 6 files changed, 36 insertions(+), 40 deletions(-) diff --git a/src/cmp/evaluation.py b/src/cmp/evaluation.py index 37390cfdc..aa6e8f665 100644 --- a/src/cmp/evaluation.py +++ b/src/cmp/evaluation.py @@ -12,6 +12,7 @@ def evaluate_reverse_parse(G, right_parse, operations, tokens): if operation == ShiftReduceParser.SHIFT: token = next(tokens) stack.append(token) + elif operation == ShiftReduceParser.REDUCE: production = next(right_parse) head, body = production diff --git a/src/cmp/semantic.py b/src/cmp/semantic.py index 8cf53c8a2..1555fabf2 100644 --- a/src/cmp/semantic.py +++ b/src/cmp/semantic.py @@ -50,7 +50,8 @@ def set_parent(self, parent): raise SemanticError(f'Parent type is already set for {self.name}.') self.parent = parent - def get_attribute(self, name:str): + def get_attribute(self, token): + name = token if isinstance(token, str) else token.lex try: return next(attr for attr in self.attributes if attr.name == name) except StopIteration: @@ -61,7 +62,8 @@ def get_attribute(self, name:str): except SemanticError: raise SemanticError(f'Attribute "{name}" is not defined in {self.name}.') - def define_attribute(self, name:str, typex): + def define_attribute(self, token, typex): + name = token if isinstance(token, str) else token.lex try: self.get_attribute(name) except SemanticError: @@ -71,7 +73,8 @@ def define_attribute(self, name:str, typex): else: raise SemanticError(f'Attribute "{name}" is already defined in {self.name}.') - def get_method(self, name:str): + def get_method(self, token): + name = token if isinstance(token, str) else token.lex try: return next(method for method in self.methods if method.name == name) except StopIteration: @@ -82,7 +85,8 @@ def get_method(self, name:str): except SemanticError: raise SemanticError(f'Method "{name}" is not defined in {self.name}.') - def define_method(self, name:str, param_names:list, param_types:list, return_type): + def define_method(self, token, param_names:list, param_types:list, return_type): + name = token if isinstance(token, str) else token.lex if name in (method.name for method in self.methods): raise SemanticError(f'Method "{name}" already defined in {self.name}') @@ -143,7 +147,7 @@ def conforms_to(self, other): def bypass(self): return True - def get_method(self, name:str): + def get_method(self, token): raise SemanticError(None) def __eq__(self, other): @@ -174,14 +178,14 @@ def __init__(self): self.types = {} def create_type(self, token): - name = token.lex if isinstance(token, Token) else token + name = token if isinstance(token, str) else token.lex if name in self.types: raise SemanticError(f'Type with the same name ({name}) already in context.') typex = self.types[name] = Type(name) return typex def get_type(self, token): - name = token.lex if isinstance(token, Token) else token + name = token if isinstance(token, str) else token.lex if name == '': return ErrorType() @@ -200,20 +204,6 @@ class VariableInfo: def __init__(self, name, vtype): self.name = name self.type = vtype - self.expected_types = [] - - def update_type(self): - infered_type = self.expected_types[0] if self.expected_types else None - - for typex in self.expected_types[1:]: - infered_type = infered_type.join(typex) - - self.type = infered_type - - if not self.type: - self.type = AutoType() - - self.expected_types = [] class Scope: @@ -231,20 +221,24 @@ def create_child(self): self.children.append(child) return child - def define_variable(self, vname, vtype): + def define_variable(self, token, vtype): + vname = token if isinstance(token, str) else token.lex info = VariableInfo(vname, vtype) self.locals.append(info) return info - def find_variable(self, vname, index=None): + def find_variable(self, token, index=None): + vname = token if isinstance(token, str) else token.lex 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 not None else None - def is_defined(self, vname): + def is_defined(self, token): + vname = token if isinstance(token, str) else token.lex return self.find_variable(vname) is not None - def is_local(self, vname): + def is_local(self, token): + vname = token if isinstance(token, str) else token.lex return any(True for x in self.locals if x.name == vname) diff --git a/src/utils/COOL_Grammar.py b/src/utils/COOL_Grammar.py index 1bd287126..9cd165f25 100644 --- a/src/utils/COOL_Grammar.py +++ b/src/utils/COOL_Grammar.py @@ -70,17 +70,17 @@ def build_COOL_Grammar(): expr %= comp, lambda h,s: s[1] - comp %= comp + less + arith, lambda h,s: node.LessThanNode(s[1],s[3]) - comp %= comp + lesse + arith, lambda h,s: node.LessEqualNode(s[1],s[3]) - comp %= comp + equal + arith, lambda h,s: node.EqualNode(s[1],s[3]) + comp %= comp + less + arith, lambda h,s: node.LessThanNode(s[1],s[3],s[2]) + comp %= comp + lesse + arith, lambda h,s: node.LessEqualNode(s[1],s[3],s[2]) + comp %= comp + equal + arith, lambda h,s: node.EqualNode(s[1],s[3],s[2]) comp %= arith, lambda h,s: s[1] - arith %= arith + plus + term, lambda h,s: node.PlusNode(s[1],s[3]) - arith %= arith + minus + term, lambda h,s: node.MinusNode(s[1],s[3]) + arith %= arith + plus + term, lambda h,s: node.PlusNode(s[1],s[3],s[2]) + arith %= arith + minus + term, lambda h,s: node.MinusNode(s[1],s[3],s[2]) arith %= term, lambda h,s:s[1] - term %= term + star + factor, lambda h,s: node.StarNode(s[1],s[3]) - term %= term + div + factor, lambda h,s: node.DivNode(s[1],s[3]) + term %= term + star + factor, lambda h,s: node.StarNode(s[1],s[3],s[2]) + term %= term + div + factor, lambda h,s: node.DivNode(s[1],s[3],s[2]) term %= factor, lambda h,s: s[1] factor %= isvoid + factor, lambda h,s: node.IsVoidNode(s[2]) @@ -104,6 +104,4 @@ def build_COOL_Grammar(): arg_list %= expr + comma + arg_list, lambda h,s: [s[1]] + s[3] arg_list %= G.Epsilon, lambda h,s: [] - return G - - + return G \ No newline at end of file diff --git a/src/utils/COOL_Lexer.py b/src/utils/COOL_Lexer.py index 2d53d4307..9b684991f 100644 --- a/src/utils/COOL_Lexer.py +++ b/src/utils/COOL_Lexer.py @@ -14,7 +14,7 @@ def __init__(self, lex, ttype, line, column): self.column = column def __str__(self): - return f'{self.ttype}: {self.lex}' + return f'{self.token_type}: {self.lex}' ''' El lexer es el resultado de la union de todas las expresiones regulares que forman @@ -50,7 +50,7 @@ def tokenize(self,text): if len(text) <= 0: continue lexeme = match.group() - self.column += len(lexeme) + self.column += len(lexeme) if lexeme != '\t' else 4 if lexeme == '\n': self.line += 1 @@ -134,7 +134,6 @@ def tokenize(self,text): token_type = match.lastgroup if lexeme.lower() not in self.keywords and match.lastgroup is not None else match.group().lower() - a = self.column - len(lexeme) + 1 if lexeme[:2] != '(*' and lexeme[0] != '"' else self.column yield lexeme, token_type, self.line, self.column - len(lexeme) + 1 if lexeme[:2] != '(*' and lexeme[0] != '"' else self.column text = text[match.end():] if lexeme[:2] != '(*' and lexeme[0] != '"' else text diff --git a/src/utils/ast/AST_Nodes.py b/src/utils/ast/AST_Nodes.py index 009e17348..0f45c1f1d 100644 --- a/src/utils/ast/AST_Nodes.py +++ b/src/utils/ast/AST_Nodes.py @@ -79,9 +79,10 @@ def __init__(self, lex): self.lex = lex class BinaryNode(ExpressionNode): - def __init__(self, left, right): + def __init__(self, left, right, symbol): self.left = left self.right = right + self.symbol = symbol class ConstantNumNode(AtomicNode): diff --git a/src/utils/semantic_check/type_builder.py b/src/utils/semantic_check/type_builder.py index de0ba4add..cec2f0ab8 100644 --- a/src/utils/semantic_check/type_builder.py +++ b/src/utils/semantic_check/type_builder.py @@ -2,6 +2,9 @@ from utils.ast.AST_Nodes import ast_nodes as nodes from cmp.semantic import SemanticError, ErrorType +NOT_INHERIT_FROM_BASICS_TYPES = '(%s, %s) - TypeError: Type %s cannot inherit from basic type %s' + + class TypeBuilder: def __init__(self, context, errors): self.context = context @@ -26,7 +29,7 @@ def visit(self,node): if node.parent is not None: if node.parent.lex in ['Int', 'String', 'SELF_TYPE', 'Bool']: - self.errors.append(f'Cannot inherit from {node.parent}') + self.errors.append(NOT_INHERIT_FROM_BASICS_TYPES % (node.id.line, node.id.column, node.id.lex, node.parent.lex)) else: try: From c9f53ac3ca6f62e6e6bdfda378e6a5531a8eda39 Mon Sep 17 00:00:00 2001 From: Ale Date: Tue, 14 Dec 2021 23:08:51 -0800 Subject: [PATCH 08/83] ast with tokens files-columns --- src/utils/ast/AST_Nodes.py | 77 ++++++++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 24 deletions(-) diff --git a/src/utils/ast/AST_Nodes.py b/src/utils/ast/AST_Nodes.py index 0f45c1f1d..afb715ae8 100644 --- a/src/utils/ast/AST_Nodes.py +++ b/src/utils/ast/AST_Nodes.py @@ -1,7 +1,11 @@ +from utils.COOL_Lexer import Token + + class ast_nodes: class Node: - pass + line = 0 + column = 0 class ProgramNode(Node): @@ -15,74 +19,99 @@ class ExpressionNode(Node): class ClassDeclarationNode(DeclarationNode): - def __init__(self, idx, features, parent=None): - self.id = idx + def __init__(self, token, features, parent=None): + self.id = token.lex + self.line = token.line + self.column = token.column self.parent = parent self.features = features class MethDeclarationNode(DeclarationNode): - def __init__(self, idx, params, return_type, body): - self.id = idx + def __init__(self, token, params, return_type, body): + self.id = token.lex + self.line = token.line + self.column = token.column self.params = params self.type = return_type self.body = body class AttrDeclarationNode(DeclarationNode): - def __init__(self, idx, typex, expr = None): - self.id = idx + def __init__(self, token, typex, expr = None): + self.id = token.lex + self.line = token.line + self.column = token.column self.type = typex self.expr = expr class AssignNode(ExpressionNode): - def __init__(self, idx, expr): - self.id = idx + def __init__(self, token, expr, token_pos): + self.id = token.lex + self.line = token_pos.line + self.column = token_pos.column self.expr = expr class CallNode(ExpressionNode): - def __init__(self, idx, args, obj = None, typex = None): - self.obj = obj + def __init__(self, token, args, obj = None, typex = None): + self.obj = obj.lex self.type = typex - self.id = idx + self.id = token.lex + self.line = token.line + self.column = token.column self.args = args class IfThenElseNode(ExpressionNode): - def __init__(self, if_expr, then_expr, else_expr): + def __init__(self, if_expr, then_expr, else_expr,token): self.if_expr = if_expr self.then_expr = then_expr self.else_expr = else_expr + self.line = token.line + self.column = token.column class WhileNode(ExpressionNode): - def __init__(self, conditional_expr, loop_expr): + def __init__(self, conditional_expr, loop_expr, token): self.conditional_expr = conditional_expr self.loop_expr = loop_expr + self.line = token.line + self.column = token.column class BlockNode(ExpressionNode): - def __init__(self, expr_list): + def __init__(self, expr_list, token): self.expr_list = expr_list + self.line = token.line + self.column = token.column class LetNode(ExpressionNode): - def __init__(self, identifiers, in_expr): - self.identifiers = identifiers + def __init__(self, identifiers, in_expr, token): + self.identifiers = [tuple([item.lex if isinstance(item, Token) else item for item in _list]) for _list in identifiers] self.in_expr = in_expr + self.line = token.line + self.column = token.column class CaseNode(ExpressionNode): - def __init__(self, predicate, branches): + def __init__(self, predicate, branches, token): self.predicate = predicate - self.branches = branches + self.branches = [tuple([item.lex if isinstance(item, Token) else item for item in _list]) for _list in branches] + self.line = token.line + self.column = token.column class NotNode(ExpressionNode): - def __init__(self, expr): + def __init__(self, expr, token): self.expr = expr + self.line = token.line + self.column = token.column class AtomicNode(ExpressionNode): - def __init__(self, lex): - self.lex = lex + def __init__(self, token): + self.lex = token.lex + self.line = token.line + self.column = token.column class BinaryNode(ExpressionNode): - def __init__(self, left, right, symbol): + def __init__(self, left, right, token): self.left = left self.right = right - self.symbol = symbol + self.line = token.line + self.column = token.column class ConstantNumNode(AtomicNode): From 08ec1767c76047ec680cf7f9f998d6db6843bca2 Mon Sep 17 00:00:00 2001 From: Ale Date: Tue, 14 Dec 2021 23:10:22 -0800 Subject: [PATCH 09/83] cool grammar lines-columns --- src/utils/COOL_Grammar.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/utils/COOL_Grammar.py b/src/utils/COOL_Grammar.py index 9cd165f25..ed1760b15 100644 --- a/src/utils/COOL_Grammar.py +++ b/src/utils/COOL_Grammar.py @@ -46,24 +46,24 @@ def build_COOL_Grammar(): param %= idx + colon + typex, lambda h,s: [s[1],s[3]] - expr %= idx + arrow + expr, lambda h,s: node.AssignNode(s[1],s[3]) - expr %= ifx + expr + then + expr + elsex + expr + fi, lambda h,s: node.IfThenElseNode(s[2],s[4],s[6]) - expr %= whilex + expr + loop + expr + pool, lambda h,s: node.WhileNode(s[2],s[4]) - expr %= notx + expr, lambda h,s: node.NotNode(s[2]) + expr %= idx + arrow + expr, lambda h,s: node.AssignNode(s[1],s[3],s[2]) + expr %= ifx + expr + then + expr + elsex + expr + fi, lambda h,s: node.IfThenElseNode(s[2],s[4],s[6],s[1]) + expr %= whilex + expr + loop + expr + pool, lambda h,s: node.WhileNode(s[2],s[4],s[1]) + expr %= notx + expr, lambda h,s: node.NotNode(s[2],s[1]) - expr %= ocur + expr_list + ccur, lambda h,s: node.BlockNode(s[2]) + expr %= ocur + expr_list + ccur, lambda h,s: node.BlockNode(s[2],s[1]) expr_list %= expr + semi, lambda h,s: [s[1]] expr_list %= expr + semi + expr_list, lambda h,s: [s[1]] + s[3] - expr %= let + id_list + inx + expr, lambda h,s: node.LetNode(s[2],s[4]) + expr %= let + id_list + inx + expr, lambda h,s: node.LetNode(s[2],s[4],s[1]) id_list %= idx + colon + typex, lambda h,s: [(s[1],s[3],None)] id_list %= idx + colon + typex + arrow + expr, lambda h,s: [(s[1],s[3],s[5])] id_list %= idx + colon + typex + comma + id_list, lambda h,s: [(s[1],s[3],None)] + s[5] id_list %= idx + colon + typex + arrow + expr + comma + id_list, lambda h,s: [(s[1],s[3],s[5])] + s[7] - expr %= case + expr + of + case_list + esac, lambda h,s: node.CaseNode(s[2],s[4]) + expr %= case + expr + of + case_list + esac, lambda h,s: node.CaseNode(s[2],s[4],s[1]) case_list %= idx + colon + typex + darrow + expr + semi, lambda h,s: [(s[1],s[3],s[5])] case_list %= idx + colon + typex + darrow + expr + semi + case_list, lambda h,s: [(s[1],s[3],s[5])] + s[7] From 74b84d17aeafc63f566cf58b65d05cdab70f6352 Mon Sep 17 00:00:00 2001 From: Ale Date: Tue, 14 Dec 2021 23:28:32 -0800 Subject: [PATCH 10/83] type checker --- src/utils/semantic_check/type_checker.py | 452 +++++++++++++++++++++++ 1 file changed, 452 insertions(+) create mode 100644 src/utils/semantic_check/type_checker.py diff --git a/src/utils/semantic_check/type_checker.py b/src/utils/semantic_check/type_checker.py new file mode 100644 index 000000000..b21d62088 --- /dev/null +++ b/src/utils/semantic_check/type_checker.py @@ -0,0 +1,452 @@ +import cmp.visitor as visitor +from utils.ast.AST_Nodes import ast_nodes as nodes +from cmp.semantic import SemanticError, ErrorType, Scope + +MAIN_DONT_EXISTS = '(0, 0) - TypeError: COOL program must have a class Main' +MAIN_METHOD_DONT_EXISTS = '(%s, %s) - TypeError: Main class must have a method main()' +MAIN_METHOD_DONT_HAVE_PARAMS = '(%s, %s) - TypeError: main method must not have params' + +INVALID_OPERATION = '(%s, %s) - TypeError: non-Int arguments: %s %s %s' + +INCOMPATIBLE_TYPES = '(%s, %s) - TypeError: Cannot convert %s into %s.' +WRONG_SIGNATURE = '(%s, %s) - TypeError: Method "%s" already defined in "%s" with a different signature.' +SELF_IS_READONLY = '(%s, %s) - TypeError: Variable "self" is read-only.' +LOCAL_ALREADY_DEFINED = '(%s, %s) - TypeError: Variable "%s" is already defined in method "%s".' + +VARIABLE_NOT_DEFINED = '(%s, %s) - TypeError: Variable "%s" is not defined in "%s".' + + + +class TypeChecker: + def __init__(self, context, errors): + self.context = context + self.current_type = None + self.current_method = None + self.errors = errors + + @visitor.on('node') + def visit(self, node, scope): + pass + + + @visitor.when(nodes.ProgramNode) + def visit(self, node, scope=None): + # verificando que el programa tenga una clase Main + try: + self.context.get_type('Main') + + except SemanticError: + self.errors.append(MAIN_DONT_EXISTS) + + + scope = Scope() if scope == None else scope + + for dec in node.declarations: + self.visit(dec, scope.create_child()) + + return scope + + + @visitor.when(nodes.ClassDeclarationNode) + def visit(self, node, scope): + self.current_type = self.context.get_type(node.id) + + # verificando la existencia del metodo main + if self.current_type.name == 'Main': + try: + self.current_type.get_method('main') + + except SemanticError: + self.errors.append(MAIN_METHOD_DONT_EXISTS % (node.id.line, node.id.column)) + + + # verficando herencia circular en los ancestros de current_type (deben llegar a object sin pasar por el nuevamente) + current_parent = self.current_type.parent + + while current_parent != self.context.get_type('Object') and current_parent != None: + if current_parent == self.current_type: + self.errors.append(f'Class {self.current_type.name} cannot inherit from class {self.current_type.parent.name}') + self.current_type.parent = ErrorType() + break + current_parent = current_parent.parent + + attrs = [feat for feat in node.features if isinstance(feat, nodes.AttrDeclarationNode)] + for attr in attrs: + self.visit(attr, scope) + + meths = [feat for feat in node.features if isinstance(feat, nodes.MethDeclarationNode)] + for meth in meths: + self.visit(meth, scope.create_child()) + + return + + @visitor.when(nodes.AttrDeclarationNode) + def visit(self, node, scope): + attr_type = self.context.get_type(node.type) if node.type.lex != 'SELF_TYPE' else self.current_type + + if node.expr: + type_expr = self.visit(node.expr, scope.create_child()) + + if not type_expr.conforms_to(attr_type): + self.errors.append(INCOMPATIBLE_TYPES % (node.type.line, node.type.column, type_expr.name, attr_type.name)) + + if node.id.lex == 'self': + self.errors.append('self cannot be used as an attribute name') + + scope.define_variable(node.id, attr_type) + + return + + + @visitor.when(nodes.MethDeclarationNode) + def visit(self, node, scope): + self.current_method = self.current_type.get_method(node.id) + + # verificando que el metodo main no tenga parametros + if self.current_method.name == 'main' and self.current_method.param_names: + self.errors.append(MAIN_METHOD_DONT_HAVE_PARAMS % (node.id.line, node.id.column)) + + # verificabdo redefinicion de metodos + current_parent = self.current_type.parent + + while current_parent != self.context.get_type('Object') and current_parent != None: + try: + parent_method = current_parent.get_method(node.id) + if parent_method != self.current_method: + self.error.append(WRONG_SIGNATURE % (self.current_method.name, current_parent.name)) + break + except: + pass + current_parent = current_parent.parent + + + scope.define_variable('self', self.current_type) + + for name, typex in zip(self.current_method.param_names, self.current_method.param_types): + if scope.is_local(name): + self.errors.append(LOCAL_ALREADY_DEFINED % (name,self.current_method.name)) + + elif typex == 'SELF_TYPE': + self.errors.append('SELF_TYPE cannot be used as a parameter type') + scope.define_variable(name, ErrorType()) + + else: + scope.define_variable(name, self.context.get_type(typex.name)) + + body_type = self.visit(node.body, scope) + try: + returnType = self.context.get_type(node.type) if node.type != 'SELF_TYPE' else self.current_type + except SemanticError as se: + self.errors.append(se.text) + returnType = ErrorType() + + if not body_type.conforms_to(returnType): + self.errors.append(INCOMPATIBLE_TYPES % (body_type.name, returnType.name)) + + return + + + @visitor.when(nodes.AssignNode) + def visit(self, node, scope): + var = scope.find_variable(node.id) + + type_expr = self.visit(node.expr, scope.create_child()) + + if var is None: + self.errors.append(VARIABLE_NOT_DEFINED % (node.id, self.current_method.name)) + + elif var.name == 'self': + self.errors.append(SELF_IS_READONLY) + + elif not type_expr.conforms_to(var.type): + self.errors.append(INCOMPATIBLE_TYPES % (type_expr.name, var.type.name)) + + return type_expr + + + @visitor.when(nodes.CallNode) + def visit(self, node, scope): + if node.obj is None: + obj_type = self.current_type + else: + obj_type = self.visit(node.obj, scope) + + if node.type is not None: + if node.type == 'SELF_TYPE': + self.errors.append('SELF_TYPE cannot be used as a type of a dispatch') + typex = ErrorType() + + else: + try: + typex = self.context.get_type(node.type) + except SemanticError as se: + self.errors.append(se.text) + typex = ErrorType() + + if not obj_type.conforms_to(typex): + self.errors.append(INCOMPATIBLE_TYPES % (obj_type.name, typex.name)) + + obj_type = typex + + try: + meth = obj_type.get_method(node.id) + except SemanticError as se: + if se.text: self.errors.append(se.text) + for arg in node.args: + self.visit(arg, scope) + return ErrorType() + + if len(node.args) != len(meth.param_names): + self.errors.append(f'Method {meth.name} defined in {obj_type.name} receive {len(meth.param_names)} parameters') + + for i,arg in enumerate(node.args): + type_arg = self.visit(arg, scope) + if i< len(meth.param_types) and not type_arg.conforms_to(meth.param_types[i]): + self.errors.append(INCOMPATIBLE_TYPES % (type_arg.name, meth.param_types[i].name)) + + return meth.return_type if meth.return_type.name != 'SELF_TYPE' else obj_type + + + @visitor.when(nodes.IfThenElseNode) + def visit(self, node, scope): + if_type = self.visit(node.if_expr, scope.create_child()) + + if not if_type.conforms_to(self.context.get_type('Bool')): + self.errors.append(INCOMPATIBLE_TYPES % (if_type.name, 'Bool')) + + then_type = self.visit(node.then_expr, scope.create_child()) + else_type = self.visit(node.else_expr, scope.create_child()) + + return then_type.join(else_type) + + + @visitor.when(nodes.WhileNode) + def visit(self, node, scope): + type_conditional = self.visit(node.conditional_expr, scope) + + if not type_conditional.conforms_to(self.context.get_type('Bool')): + self.errors.append(INCOMPATIBLE_TYPES % (type_conditional.name, 'Bool')) + + self.visit(node.loop_expr, scope.create_child()) + + return self.context.get_type('Object') + + + @visitor.when(nodes.BlockNode) + def visit(self, node, scope): + type_expr = ErrorType() + + for expr in node.expr_list: + type_expr = self.visit(expr, scope.create_child()) + + return type_expr + + + @visitor.when(nodes.LetNode) + def visit(self, node, scope): + for idx, typex, id_expr in node.identifiers: + try: + id_type = self.context.get_type(typex) if typex != 'SELF_TYPE' else self.current_type + except SemanticError as se: + id_type = ErrorType() + self.errors.append(se.text) + + if scope.is_local(idx): + self.errors.append(LOCAL_ALREADY_DEFINED % (idx, self.current_method.name)) + else: + scope.define_variable(idx, id_type) + + if id_expr is not None: + id_expr_type = self.visit(id_expr, scope.create_child()) + if not id_expr_type.conforms_to(id_type): + self.errors.append(INCOMPATIBLE_TYPES % (id_expr_type.name, id_type.name)) + + body_type = self.visit(node.in_expr, scope.create_child()) + + return body_type + + + @visitor.when(nodes.CaseNode) + def visit(self, node, scope): + self.visit(node.predicate, scope) + case_type = None + + for idx, typex, expr in node.branches: + if typex == 'SELF_TYPE': + self.errors.append('SELF_TYPE cannot be used as a type of a case branch') + id_type = ErrorType() + + else: + try: + id_type = self.context.get_type(typex) + except SemanticError as se: + id_type = ErrorType() + self.errors.append(se.text) + + inner_scope = scope.create_child() + inner_scope.define_variable(idx, id_type) + + type_expr = self.visit(expr, inner_scope) + case_type = case_type.join(type_expr) if case_type is not None else type_expr + + return case_type + + + @visitor.when(nodes.NotNode) + def visit(self, node, scope): + typex = self.visit(node.expr, scope) + + if not typex.conforms_to(self.context.get_type('Bool')): + self.errors.append(INCOMPATIBLE_TYPES % (typex.name, 'Bool')) + return ErrorType() + + return typex + + + @visitor.when(nodes.ConstantNumNode) + def visit(self, node, scope): + return self.context.get_type('Int') + + + @visitor.when(nodes.ConstantBoolNode) + def visit(self, node, scope): + return self.context.get_type('Bool') + + + @visitor.when(nodes.ConstantStringNode) + def visit(self, node, scope): + return self.context.get_type('String') + + + @visitor.when(nodes.VariableNode) + def visit(self, node, scope): + var = scope.find_variable(node.lex) + + if var is None: + self.errors.append(VARIABLE_NOT_DEFINED % (node.lex, self.current_method.name)) + return ErrorType() + + return var.type + + + @visitor.when(nodes.InstantiateNode) + def visit(self, node, scope): + if node.lex == 'SELF_TYPE': + return self.current_type + + try: + return self.context.get_type(node.lex) + except SemanticError as se: + self.errors.append(se.text) + return ErrorType() + + + @visitor.when(nodes.IsVoidNode) + def visit(self, node, scope): + self.visit(node.lex, scope) + return self.context.get_type('Bool') + + + @visitor.when(nodes.ComplementNode) + def visit(self, node, scope): + typex = self.visit(node.lex, scope) + + if not typex.conforms_to(self.context.get_type('Int')): + self.errors.append(INCOMPATIBLE_TYPES % (typex.name, 'Int')) + return ErrorType() + + return typex + + + @visitor.when(nodes.PlusNode) + def visit(self, node, scope): + type_left = self.visit(node.left, scope) + type_right = self.visit(node.right, scope) + + if not type_left.conforms_to(self.context.get_type('Int')) or not type_right.conforms_to(self.context.get_type('Int')): + self.errors.append(INVALID_OPERATION % (node.symbol.line, node.symbol.column, type_left.name, '+', type_right.name)) + return ErrorType() + + else: + return self.context.get_type('Int') + + + @visitor.when(nodes.MinusNode) + def visit(self, node, scope): + type_left = self.visit(node.left, scope) + type_right = self.visit(node.right, scope) + + if not type_left.conforms_to(self.context.get_type('Int')) or not type_right.conforms_to(self.context.get_type('Int')): + self.errors.append(INVALID_OPERATION % (node.symbol.line, node.symbol.column, type_left.name, '-', type_right.name)) + return ErrorType() + + else: + return self.context.get_type('Int') + + + @visitor.when(nodes.StarNode) + def visit(self, node, scope): + type_left = self.visit(node.left, scope) + type_right = self.visit(node.right, scope) + + if not type_left.conforms_to(self.context.get_type('Int')) or not type_right.conforms_to(self.context.get_type('Int')): + self.errors.append(INVALID_OPERATION % (node.symbol.line, node.symbol.column, type_left.name, '*', type_right.name)) + return ErrorType() + + else: + return self.context.get_type('Int') + + + @visitor.when(nodes.DivNode) + def visit(self, node, scope): + type_left = self.visit(node.left, scope) + type_right = self.visit(node.right, scope) + + if not type_left.conforms_to(self.context.get_type('Int')) or not type_right.conforms_to(self.context.get_type('Int')): + self.errors.append(INVALID_OPERATION % (node.symbol.line, node.symbol.column, type_left.name, '/', type_right.name)) + return ErrorType() + + else: + return self.context.get_type('Int') + + + @visitor.when(nodes.LessThanNode) + def visit(self, node, scope): + type_left = self.visit(node.left, scope) + type_right = self.visit(node.right, scope) + + if not type_left.conforms_to(self.context.get_type('Int')) or not type_right.conforms_to(self.context.get_type('Int')): + self.errors.append(INVALID_OPERATION % (node.symbol.line, node.symbol.column, type_left.name, '<', type_right.name)) + return ErrorType() + + else: + return self.context.get_type('Bool') + + + @visitor.when(nodes.LessEqualNode) + def visit(self, node, scope): + type_left = self.visit(node.left, scope) + type_right = self.visit(node.right, scope) + + if not type_left.conforms_to(self.context.get_type('Int')) or not type_right.conforms_to(self.context.get_type('Int')): + self.errors.append(INVALID_OPERATION % (node.symbol.line, node.symbol.column, type_left.name, '<=', type_right.name)) + return ErrorType() + + else: + return self.context.get_type('Bool') + + + @visitor.when(nodes.EqualNode) + def visit(self, node, scope): + type_left = self.visit(node.left, scope) + type_right = self.visit(node.right, scope) + + int_type = self.context.get_type('Int') + bool_type = self.context.get_type('Bool') + string_type = self.context.get_type('String') + + if (type_left == int_type and not type_right.conforms_to(int_type)) or (type_right == int_type and not type_left.conforms_to(int_type)) or (type_left == bool_type and not type_right.conforms_to(bool_type)) or (type_right == bool_type and not type_left.conforms_to(bool_type)) or (type_left == string_type and not type_right.conforms_to(string_type)) or (type_right == string_type and not type_left.conforms_to(string_type)): + self.errors.append(INVALID_OPERATION % (node.symbol.line, node.symbol.column, type_left.name, '=', type_right.name)) + return ErrorType() + + return bool_type \ No newline at end of file From 80b120bfb208d73f476b8648485df353f09cfcaf Mon Sep 17 00:00:00 2001 From: Ale Date: Tue, 14 Dec 2021 23:52:54 -0800 Subject: [PATCH 11/83] semantic fixed --- src/cmp/semantic.py | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/src/cmp/semantic.py b/src/cmp/semantic.py index 1555fabf2..3cf8c49a6 100644 --- a/src/cmp/semantic.py +++ b/src/cmp/semantic.py @@ -1,8 +1,6 @@ import itertools as itt from collections import OrderedDict -from utils.COOL_Lexer import Token - class SemanticError(Exception): @property @@ -50,8 +48,7 @@ def set_parent(self, parent): raise SemanticError(f'Parent type is already set for {self.name}.') self.parent = parent - def get_attribute(self, token): - name = token if isinstance(token, str) else token.lex + def get_attribute(self, name:str): try: return next(attr for attr in self.attributes if attr.name == name) except StopIteration: @@ -62,8 +59,7 @@ def get_attribute(self, token): except SemanticError: raise SemanticError(f'Attribute "{name}" is not defined in {self.name}.') - def define_attribute(self, token, typex): - name = token if isinstance(token, str) else token.lex + def define_attribute(self, name:str, typex): try: self.get_attribute(name) except SemanticError: @@ -73,8 +69,7 @@ def define_attribute(self, token, typex): else: raise SemanticError(f'Attribute "{name}" is already defined in {self.name}.') - def get_method(self, token): - name = token if isinstance(token, str) else token.lex + def get_method(self, name:str): try: return next(method for method in self.methods if method.name == name) except StopIteration: @@ -85,8 +80,7 @@ def get_method(self, token): except SemanticError: raise SemanticError(f'Method "{name}" is not defined in {self.name}.') - def define_method(self, token, param_names:list, param_types:list, return_type): - name = token if isinstance(token, str) else token.lex + def define_method(self, name:str, param_names:list, param_types:list, return_type): if name in (method.name for method in self.methods): raise SemanticError(f'Method "{name}" already defined in {self.name}') @@ -147,7 +141,7 @@ def conforms_to(self, other): def bypass(self): return True - def get_method(self, token): + def get_method(self, name:str): raise SemanticError(None) def __eq__(self, other): @@ -177,15 +171,13 @@ class Context: def __init__(self): self.types = {} - def create_type(self, token): - name = token if isinstance(token, str) else token.lex + def create_type(self, name:str): if name in self.types: raise SemanticError(f'Type with the same name ({name}) already in context.') typex = self.types[name] = Type(name) return typex - def get_type(self, token): - name = token if isinstance(token, str) else token.lex + def get_type(self, name:str): if name == '': return ErrorType() @@ -221,24 +213,20 @@ def create_child(self): self.children.append(child) return child - def define_variable(self, token, vtype): - vname = token if isinstance(token, str) else token.lex + def define_variable(self, vname, vtype): info = VariableInfo(vname, vtype) self.locals.append(info) return info - def find_variable(self, token, index=None): - vname = token if isinstance(token, str) else token.lex + 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 not None else None - def is_defined(self, token): - vname = token if isinstance(token, str) else token.lex + def is_defined(self, vname): return self.find_variable(vname) is not None - def is_local(self, token): - vname = token if isinstance(token, str) else token.lex + def is_local(self, vname): return any(True for x in self.locals if x.name == vname) From 0ae8c6dc6fb67252797d07e40093bc990e49541c Mon Sep 17 00:00:00 2001 From: Ale Date: Tue, 14 Dec 2021 23:54:25 -0800 Subject: [PATCH 12/83] type builder fixed --- src/utils/semantic_check/type_builder.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/semantic_check/type_builder.py b/src/utils/semantic_check/type_builder.py index cec2f0ab8..f6af1804e 100644 --- a/src/utils/semantic_check/type_builder.py +++ b/src/utils/semantic_check/type_builder.py @@ -28,8 +28,8 @@ def visit(self,node): if node.parent is not None: - if node.parent.lex in ['Int', 'String', 'SELF_TYPE', 'Bool']: - self.errors.append(NOT_INHERIT_FROM_BASICS_TYPES % (node.id.line, node.id.column, node.id.lex, node.parent.lex)) + if node.parent in ['Int', 'String', 'SELF_TYPE', 'Bool']: + self.errors.append(NOT_INHERIT_FROM_BASICS_TYPES % (node.line, node.column, node.id, node.parent)) else: try: From f6607a7e8599a75e3680e4f56ec79ff79850a68b Mon Sep 17 00:00:00 2001 From: Ale Date: Wed, 15 Dec 2021 01:06:08 -0800 Subject: [PATCH 13/83] fixing tokens in ast --- src/utils/ast/AST_Nodes.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/utils/ast/AST_Nodes.py b/src/utils/ast/AST_Nodes.py index afb715ae8..f05451370 100644 --- a/src/utils/ast/AST_Nodes.py +++ b/src/utils/ast/AST_Nodes.py @@ -23,7 +23,7 @@ def __init__(self, token, features, parent=None): self.id = token.lex self.line = token.line self.column = token.column - self.parent = parent + self.parent = parent.lex if parent else parent self.features = features class MethDeclarationNode(DeclarationNode): @@ -31,8 +31,8 @@ def __init__(self, token, params, return_type, body): self.id = token.lex self.line = token.line self.column = token.column - self.params = params - self.type = return_type + self.params = [[item.lex if isinstance(item, Token) else item for item in _list] for _list in params] + self.type = return_type.lex self.body = body class AttrDeclarationNode(DeclarationNode): @@ -52,7 +52,7 @@ def __init__(self, token, expr, token_pos): class CallNode(ExpressionNode): def __init__(self, token, args, obj = None, typex = None): - self.obj = obj.lex + self.obj = obj self.type = typex self.id = token.lex self.line = token.line From cb800e71615ba34a5b0e91473fadfd80fe624356 Mon Sep 17 00:00:00 2001 From: Ale Date: Wed, 15 Dec 2021 01:08:02 -0800 Subject: [PATCH 14/83] working on type errors --- src/utils/semantic_check/type_checker.py | 92 +++++++++++++----------- 1 file changed, 50 insertions(+), 42 deletions(-) diff --git a/src/utils/semantic_check/type_checker.py b/src/utils/semantic_check/type_checker.py index b21d62088..de37e1e1d 100644 --- a/src/utils/semantic_check/type_checker.py +++ b/src/utils/semantic_check/type_checker.py @@ -6,14 +6,19 @@ MAIN_METHOD_DONT_EXISTS = '(%s, %s) - TypeError: Main class must have a method main()' MAIN_METHOD_DONT_HAVE_PARAMS = '(%s, %s) - TypeError: main method must not have params' -INVALID_OPERATION = '(%s, %s) - TypeError: non-Int arguments: %s %s %s' - -INCOMPATIBLE_TYPES = '(%s, %s) - TypeError: Cannot convert %s into %s.' -WRONG_SIGNATURE = '(%s, %s) - TypeError: Method "%s" already defined in "%s" with a different signature.' +SELF_ERROR = '(%s, %s) - TypeError: self cannot be used as an attribute name' SELF_IS_READONLY = '(%s, %s) - TypeError: Variable "self" is read-only.' -LOCAL_ALREADY_DEFINED = '(%s, %s) - TypeError: Variable "%s" is already defined in method "%s".' +SELF_TYPE_ERROR = '(%s, %s) - TypeError: SELF_TYPE cannot be used as a parameter type in method %s' +SELF_TYPE_IN_DISPATCH = '(%s, %s) - TypeError: SELF_TYPE cannot be used as a type of a dispatch' +SELF_TYPE_IN_CASE_BRANCH = '(%s, %s) - TypeError: SELF_TYPE cannot be used as a type of a case branch' -VARIABLE_NOT_DEFINED = '(%s, %s) - TypeError: Variable "%s" is not defined in "%s".' +INCOMPATIBLE_TYPES = '(%s, %s) - TypeError: Cannot convert %s into %s.' +WRONG_SIGNATURE = '(%s, %s) - TypeError: Method %s already defined in %s with a different signature.' +LOCAL_ALREADY_DEFINED = '(%s, %s) - TypeError: Variable %s is already defined in method %s.' +INVALID_OPERATION = '(%s, %s) - TypeError: Operation "%s" is not defined between %s and %s.' +VARIABLE_NOT_DEFINED = '(%s, %s) - TypeError: Variable %s is not defined in %s.' +INHERIT_ERROR = '(%s, %s) - TypeError: Class %s cannot inherit from class %s because they form a cycle.' +METHOD_PARAMETERS = '(%s, %s) - TypeError: Method %s defined in %s receive %d parameters' @@ -34,9 +39,9 @@ def visit(self, node, scope=None): # verificando que el programa tenga una clase Main try: self.context.get_type('Main') - + except SemanticError: - self.errors.append(MAIN_DONT_EXISTS) + self.errors.append(MAIN_DONT_EXISTS) scope = Scope() if scope == None else scope @@ -57,7 +62,8 @@ def visit(self, node, scope): self.current_type.get_method('main') except SemanticError: - self.errors.append(MAIN_METHOD_DONT_EXISTS % (node.id.line, node.id.column)) + self.errors.append(MAIN_METHOD_DONT_EXISTS % (node.line, node.column)) + # verficando herencia circular en los ancestros de current_type (deben llegar a object sin pasar por el nuevamente) @@ -65,7 +71,7 @@ def visit(self, node, scope): while current_parent != self.context.get_type('Object') and current_parent != None: if current_parent == self.current_type: - self.errors.append(f'Class {self.current_type.name} cannot inherit from class {self.current_type.parent.name}') + self.errors.append(INHERIT_ERROR % (node.line, node.column, self.current_type.name, self.current_type.parent.name)) self.current_type.parent = ErrorType() break current_parent = current_parent.parent @@ -82,16 +88,16 @@ def visit(self, node, scope): @visitor.when(nodes.AttrDeclarationNode) def visit(self, node, scope): - attr_type = self.context.get_type(node.type) if node.type.lex != 'SELF_TYPE' else self.current_type + attr_type = self.context.get_type(node.type) if node.type != 'SELF_TYPE' else self.current_type if node.expr: type_expr = self.visit(node.expr, scope.create_child()) if not type_expr.conforms_to(attr_type): - self.errors.append(INCOMPATIBLE_TYPES % (node.type.line, node.type.column, type_expr.name, attr_type.name)) + self.errors.append(INCOMPATIBLE_TYPES % (node.line, node.column, type_expr.name, attr_type.name)) - if node.id.lex == 'self': - self.errors.append('self cannot be used as an attribute name') + if node.id == 'self': + self.errors.append(SELF_ERROR % (node.line, node.column)) scope.define_variable(node.id, attr_type) @@ -104,7 +110,7 @@ def visit(self, node, scope): # verificando que el metodo main no tenga parametros if self.current_method.name == 'main' and self.current_method.param_names: - self.errors.append(MAIN_METHOD_DONT_HAVE_PARAMS % (node.id.line, node.id.column)) + self.errors.append(MAIN_METHOD_DONT_HAVE_PARAMS % (node.line, node.column)) # verificabdo redefinicion de metodos current_parent = self.current_type.parent @@ -113,7 +119,7 @@ def visit(self, node, scope): try: parent_method = current_parent.get_method(node.id) if parent_method != self.current_method: - self.error.append(WRONG_SIGNATURE % (self.current_method.name, current_parent.name)) + self.errors.append(WRONG_SIGNATURE % (node.line, node.column, self.current_method.name, self.current_type.name)) break except: pass @@ -124,10 +130,10 @@ def visit(self, node, scope): for name, typex in zip(self.current_method.param_names, self.current_method.param_types): if scope.is_local(name): - self.errors.append(LOCAL_ALREADY_DEFINED % (name,self.current_method.name)) + self.errors.append(LOCAL_ALREADY_DEFINED % (node.line, node.column, name,self.current_method.name)) elif typex == 'SELF_TYPE': - self.errors.append('SELF_TYPE cannot be used as a parameter type') + self.errors.append(SELF_TYPE_ERROR % (node.line, node.column, self.current_method.name)) scope.define_variable(name, ErrorType()) else: @@ -141,7 +147,7 @@ def visit(self, node, scope): returnType = ErrorType() if not body_type.conforms_to(returnType): - self.errors.append(INCOMPATIBLE_TYPES % (body_type.name, returnType.name)) + self.errors.append(INCOMPATIBLE_TYPES % (node.line, node.column, body_type.name, returnType.name)) return @@ -153,13 +159,13 @@ def visit(self, node, scope): type_expr = self.visit(node.expr, scope.create_child()) if var is None: - self.errors.append(VARIABLE_NOT_DEFINED % (node.id, self.current_method.name)) + self.errors.append(VARIABLE_NOT_DEFINED % (node.line, node.column, node.id, self.current_method.name)) elif var.name == 'self': - self.errors.append(SELF_IS_READONLY) + self.errors.append(SELF_IS_READONLY % (node.line, node.column)) elif not type_expr.conforms_to(var.type): - self.errors.append(INCOMPATIBLE_TYPES % (type_expr.name, var.type.name)) + self.errors.append(INCOMPATIBLE_TYPES % (node.line, node.column, type_expr.name, var.type.name)) return type_expr @@ -173,7 +179,7 @@ def visit(self, node, scope): if node.type is not None: if node.type == 'SELF_TYPE': - self.errors.append('SELF_TYPE cannot be used as a type of a dispatch') + self.errors.append(SELF_TYPE_IN_DISPATCH % (node.line, node.column)) typex = ErrorType() else: @@ -184,7 +190,7 @@ def visit(self, node, scope): typex = ErrorType() if not obj_type.conforms_to(typex): - self.errors.append(INCOMPATIBLE_TYPES % (obj_type.name, typex.name)) + self.errors.append(INCOMPATIBLE_TYPES % (node.line, node.column, obj_type.name, typex.name)) obj_type = typex @@ -197,12 +203,12 @@ def visit(self, node, scope): return ErrorType() if len(node.args) != len(meth.param_names): - self.errors.append(f'Method {meth.name} defined in {obj_type.name} receive {len(meth.param_names)} parameters') + self.errors.append(METHOD_PARAMETERS % (node.line, node.column, meth.name, obj_type.name, len(meth.param_names))) for i,arg in enumerate(node.args): type_arg = self.visit(arg, scope) if i< len(meth.param_types) and not type_arg.conforms_to(meth.param_types[i]): - self.errors.append(INCOMPATIBLE_TYPES % (type_arg.name, meth.param_types[i].name)) + self.errors.append(INCOMPATIBLE_TYPES % (node.line, node.column, type_arg.name, meth.param_types[i].name)) return meth.return_type if meth.return_type.name != 'SELF_TYPE' else obj_type @@ -212,7 +218,7 @@ def visit(self, node, scope): if_type = self.visit(node.if_expr, scope.create_child()) if not if_type.conforms_to(self.context.get_type('Bool')): - self.errors.append(INCOMPATIBLE_TYPES % (if_type.name, 'Bool')) + self.errors.append(INCOMPATIBLE_TYPES % (node.line, node.column, if_type.name, 'Bool')) then_type = self.visit(node.then_expr, scope.create_child()) else_type = self.visit(node.else_expr, scope.create_child()) @@ -225,7 +231,7 @@ def visit(self, node, scope): type_conditional = self.visit(node.conditional_expr, scope) if not type_conditional.conforms_to(self.context.get_type('Bool')): - self.errors.append(INCOMPATIBLE_TYPES % (type_conditional.name, 'Bool')) + self.errors.append(INCOMPATIBLE_TYPES % (node.line, node.column, type_conditional.name, 'Bool')) self.visit(node.loop_expr, scope.create_child()) @@ -252,14 +258,14 @@ def visit(self, node, scope): self.errors.append(se.text) if scope.is_local(idx): - self.errors.append(LOCAL_ALREADY_DEFINED % (idx, self.current_method.name)) + self.errors.append(LOCAL_ALREADY_DEFINED % (node.line, node.column, idx, self.current_method.name)) else: scope.define_variable(idx, id_type) if id_expr is not None: id_expr_type = self.visit(id_expr, scope.create_child()) if not id_expr_type.conforms_to(id_type): - self.errors.append(INCOMPATIBLE_TYPES % (id_expr_type.name, id_type.name)) + self.errors.append(INCOMPATIBLE_TYPES % (node.line, node.column, id_expr_type.name, id_type.name)) body_type = self.visit(node.in_expr, scope.create_child()) @@ -273,7 +279,7 @@ def visit(self, node, scope): for idx, typex, expr in node.branches: if typex == 'SELF_TYPE': - self.errors.append('SELF_TYPE cannot be used as a type of a case branch') + self.errors.append(SELF_TYPE_IN_CASE_BRANCH % (node.line, node.column)) id_type = ErrorType() else: @@ -297,7 +303,7 @@ def visit(self, node, scope): typex = self.visit(node.expr, scope) if not typex.conforms_to(self.context.get_type('Bool')): - self.errors.append(INCOMPATIBLE_TYPES % (typex.name, 'Bool')) + self.errors.append(INCOMPATIBLE_TYPES % (node.line, node.column, typex.name, 'Bool')) return ErrorType() return typex @@ -323,7 +329,7 @@ def visit(self, node, scope): var = scope.find_variable(node.lex) if var is None: - self.errors.append(VARIABLE_NOT_DEFINED % (node.lex, self.current_method.name)) + self.errors.append(VARIABLE_NOT_DEFINED % (node.line, node.column, node.lex, self.current_method.name)) return ErrorType() return var.type @@ -352,7 +358,7 @@ def visit(self, node, scope): typex = self.visit(node.lex, scope) if not typex.conforms_to(self.context.get_type('Int')): - self.errors.append(INCOMPATIBLE_TYPES % (typex.name, 'Int')) + self.errors.append(INCOMPATIBLE_TYPES % (node.line, node.column, typex.name, 'Int')) return ErrorType() return typex @@ -364,7 +370,7 @@ def visit(self, node, scope): type_right = self.visit(node.right, scope) if not type_left.conforms_to(self.context.get_type('Int')) or not type_right.conforms_to(self.context.get_type('Int')): - self.errors.append(INVALID_OPERATION % (node.symbol.line, node.symbol.column, type_left.name, '+', type_right.name)) + self.errors.append(INVALID_OPERATION % (node.line, node.column, '+', type_left.name, type_right.name)) return ErrorType() else: @@ -377,7 +383,7 @@ def visit(self, node, scope): type_right = self.visit(node.right, scope) if not type_left.conforms_to(self.context.get_type('Int')) or not type_right.conforms_to(self.context.get_type('Int')): - self.errors.append(INVALID_OPERATION % (node.symbol.line, node.symbol.column, type_left.name, '-', type_right.name)) + self.errors.append(INVALID_OPERATION % (node.line, node.column, '-', type_left.name, type_right.name)) return ErrorType() else: @@ -390,7 +396,7 @@ def visit(self, node, scope): type_right = self.visit(node.right, scope) if not type_left.conforms_to(self.context.get_type('Int')) or not type_right.conforms_to(self.context.get_type('Int')): - self.errors.append(INVALID_OPERATION % (node.symbol.line, node.symbol.column, type_left.name, '*', type_right.name)) + self.errors.append(INVALID_OPERATION % (node.line, node.column, '*', type_left.name, type_right.name)) return ErrorType() else: @@ -403,7 +409,7 @@ def visit(self, node, scope): type_right = self.visit(node.right, scope) if not type_left.conforms_to(self.context.get_type('Int')) or not type_right.conforms_to(self.context.get_type('Int')): - self.errors.append(INVALID_OPERATION % (node.symbol.line, node.symbol.column, type_left.name, '/', type_right.name)) + self.errors.append(INVALID_OPERATION % (node.line, node.column, '/', type_left.name, type_right.name)) return ErrorType() else: @@ -416,7 +422,7 @@ def visit(self, node, scope): type_right = self.visit(node.right, scope) if not type_left.conforms_to(self.context.get_type('Int')) or not type_right.conforms_to(self.context.get_type('Int')): - self.errors.append(INVALID_OPERATION % (node.symbol.line, node.symbol.column, type_left.name, '<', type_right.name)) + self.errors.append(INVALID_OPERATION % (node.line, node.column, '<', type_left.name, type_right.name)) return ErrorType() else: @@ -429,7 +435,7 @@ def visit(self, node, scope): type_right = self.visit(node.right, scope) if not type_left.conforms_to(self.context.get_type('Int')) or not type_right.conforms_to(self.context.get_type('Int')): - self.errors.append(INVALID_OPERATION % (node.symbol.line, node.symbol.column, type_left.name, '<=', type_right.name)) + self.errors.append(INVALID_OPERATION % (node.line, node.column, '<=', type_left.name, type_right.name)) return ErrorType() else: @@ -445,8 +451,10 @@ def visit(self, node, scope): bool_type = self.context.get_type('Bool') string_type = self.context.get_type('String') - if (type_left == int_type and not type_right.conforms_to(int_type)) or (type_right == int_type and not type_left.conforms_to(int_type)) or (type_left == bool_type and not type_right.conforms_to(bool_type)) or (type_right == bool_type and not type_left.conforms_to(bool_type)) or (type_left == string_type and not type_right.conforms_to(string_type)) or (type_right == string_type and not type_left.conforms_to(string_type)): - self.errors.append(INVALID_OPERATION % (node.symbol.line, node.symbol.column, type_left.name, '=', type_right.name)) + if type_left.name == 'AUTO_TYPE' or type_right.name == 'AUTO_TYPE': + pass + elif (type_left == int_type and not type_right.conforms_to(int_type)) or (type_right == int_type and not type_left.conforms_to(int_type)) or (type_left == bool_type and not type_right.conforms_to(bool_type)) or (type_right == bool_type and not type_left.conforms_to(bool_type)) or (type_left == string_type and not type_right.conforms_to(string_type)) or (type_right == string_type and not type_left.conforms_to(string_type)): + self.errors.append(INVALID_OPERATION % (node.line, node.column, '=', type_left.name, type_right.name)) return ErrorType() return bool_type \ No newline at end of file From d2f0420c6e87f6a8de5ae92e3fa90600895e5ac6 Mon Sep 17 00:00:00 2001 From: Ale Date: Thu, 16 Dec 2021 14:34:40 -0800 Subject: [PATCH 15/83] main --- src/main.py | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 src/main.py diff --git a/src/main.py b/src/main.py new file mode 100644 index 000000000..f90e0cd20 --- /dev/null +++ b/src/main.py @@ -0,0 +1,67 @@ +import argparse +from utils.COOL_Grammar import build_COOL_Grammar +from utils.COOL_Lexer import COOL_Lexer +from utils.parser.COOL_parser import COOL_Parser +from cmp.evaluation import evaluate_reverse_parse +from cmp.semantic import Context +from utils.semantic_check.type_collector import TypeCollector +from utils.semantic_check.type_builder import TypeBuilder +from utils.semantic_check.type_checker import TypeChecker +from utils.semantic_check.type_inference import TypeInference +from utils.print_code import PrintCode + +def main(args): + + try: + with open(args.file, 'r') as file: + code = file.read() + except: + print(f"(0,0) - CompilerError: file {args.file} not found") + exit(1) + + G = build_COOL_Grammar() + + # lexer + lexer = COOL_Lexer() + tokens = lexer(code) + + if lexer.errors: + for error in lexer.errors: + print(error) + exit(1) + + # parser + parser = COOL_Parser(G) + derivation, operations = parser(tokens) + + if parser.error: + print(parser.error) + exit(1) + + # ast + ast = evaluate_reverse_parse(G, derivation, operations, tokens) + + context = Context() + semantic_errors = [] + + collector = TypeCollector(context, semantic_errors) + collector.visit(ast) + + builder = TypeBuilder(context, semantic_errors) + builder.visit(ast) + + checker = TypeChecker(context, semantic_errors) + scope = checker.visit(ast) + + if semantic_errors: + for error in semantic_errors: + print(error) + exit(1) + +if __name__ == "__main__": + + parser = argparse.ArgumentParser(description='description') + parser.add_argument('-f', '--file', type=str, default='', help='file to read') + + args = parser.parse_args() + main(args) \ No newline at end of file From 9373a10034da22960815e8eea437954aaca54c1b Mon Sep 17 00:00:00 2001 From: Ale Date: Thu, 16 Dec 2021 14:38:31 -0800 Subject: [PATCH 16/83] changing lin-col in some tokens like tests --- src/utils/COOL_Grammar.py | 4 ++-- src/utils/COOL_Lexer.py | 4 ++-- src/utils/ast/AST_Nodes.py | 23 +++++++++++++---------- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/utils/COOL_Grammar.py b/src/utils/COOL_Grammar.py index ed1760b15..914f9f0cf 100644 --- a/src/utils/COOL_Grammar.py +++ b/src/utils/COOL_Grammar.py @@ -49,7 +49,7 @@ def build_COOL_Grammar(): expr %= idx + arrow + expr, lambda h,s: node.AssignNode(s[1],s[3],s[2]) expr %= ifx + expr + then + expr + elsex + expr + fi, lambda h,s: node.IfThenElseNode(s[2],s[4],s[6],s[1]) expr %= whilex + expr + loop + expr + pool, lambda h,s: node.WhileNode(s[2],s[4],s[1]) - expr %= notx + expr, lambda h,s: node.NotNode(s[2],s[1]) + expr %= notx + expr, lambda h,s: node.NotNode(s[2]) expr %= ocur + expr_list + ccur, lambda h,s: node.BlockNode(s[2],s[1]) @@ -92,7 +92,7 @@ def build_COOL_Grammar(): atom %= string, lambda h,s: node.ConstantStringNode(s[1]) atom %= num, lambda h,s: node.ConstantNumNode(s[1]) atom %= idx, lambda h,s: node.VariableNode(s[1]) - atom %= new + typex, lambda h,s: node.InstantiateNode(s[2]) + atom %= new + typex, lambda h,s: node.InstantiateNode(s[2],s[1]) atom %= opar + expr + cpar, lambda h,s: s[2] atom %= dispatch, lambda h,s: s[1] diff --git a/src/utils/COOL_Lexer.py b/src/utils/COOL_Lexer.py index 9b684991f..3fd1bc052 100644 --- a/src/utils/COOL_Lexer.py +++ b/src/utils/COOL_Lexer.py @@ -156,11 +156,11 @@ def __init__(self): 'id' : r'[a-z][a-zA-Z0-9_]*' , 'type' : r'[A-Z][a-zA-Z0-9_]*' , 'string' : r'\"' , - 'int' : r'\d+' , + 'int' : r'\d' , 'comment' : r'(\(\*)|--.*' , 'newline' : r'\n' , 'whitespace': r' +' , - 'tabulation': r'\t+' , + 'tabulation': r'\t' , 'inherits' : r'inherits' , 'isvoid' : r'isvoid' , 'class' : r'class' , diff --git a/src/utils/ast/AST_Nodes.py b/src/utils/ast/AST_Nodes.py index f05451370..899be306f 100644 --- a/src/utils/ast/AST_Nodes.py +++ b/src/utils/ast/AST_Nodes.py @@ -38,9 +38,9 @@ def __init__(self, token, params, return_type, body): class AttrDeclarationNode(DeclarationNode): def __init__(self, token, typex, expr = None): self.id = token.lex - self.line = token.line - self.column = token.column - self.type = typex + self.line = expr.line if expr else token.line + self.column = expr.column if expr else token.column + self.type = typex.lex self.expr = expr class AssignNode(ExpressionNode): @@ -52,11 +52,11 @@ def __init__(self, token, expr, token_pos): class CallNode(ExpressionNode): def __init__(self, token, args, obj = None, typex = None): - self.obj = obj + self.obj = obj.lex if isinstance(obj, Token) else obj self.type = typex self.id = token.lex - self.line = token.line - self.column = token.column + self.line = obj.line if obj else token.line + self.column = obj.column if obj else token.column self.args = args class IfThenElseNode(ExpressionNode): @@ -97,12 +97,12 @@ def __init__(self, predicate, branches, token): class NotNode(ExpressionNode): def __init__(self, expr, token): self.expr = expr - self.line = token.line - self.column = token.column + self.line = token.line + 4 + self.column = token.column + 4 class AtomicNode(ExpressionNode): def __init__(self, token): - self.lex = token.lex + self.lex = token.lex if isinstance(token, Token) else token self.line = token.line self.column = token.column @@ -123,7 +123,10 @@ class ConstantStringNode(AtomicNode): class VariableNode(AtomicNode): pass class InstantiateNode(AtomicNode): - pass + def __init__(self, typex, token): + self.lex = typex.lex + self.line = token.line + self.column = token.column class IsVoidNode(AtomicNode): pass class ComplementNode(AtomicNode): From f04e9152295606b66629592cba7f065d4383160c Mon Sep 17 00:00:00 2001 From: Ale Date: Thu, 16 Dec 2021 14:43:12 -0800 Subject: [PATCH 17/83] execute project --- src/coolc.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/coolc.sh b/src/coolc.sh index 3088de4f9..5d3764e5f 100755 --- a/src/coolc.sh +++ b/src/coolc.sh @@ -1,4 +1,4 @@ -# Incluya aquí las instrucciones necesarias para ejecutar su compilador +# Incluya aquí las instrucciones necesarias para ejecutar su compilador INPUT_FILE=$1 OUTPUT_FILE=${INPUT_FILE:0: -2}mips @@ -9,3 +9,4 @@ echo "Copyright (c) 2019: Nombre1, Nombre2, Nombre3" # TODO: líneas a los va # Llamar al compilador echo "Compiling $INPUT_FILE into $OUTPUT_FILE" +python main.py -f $INPUT_FILE \ No newline at end of file From 5fa3965ddba24cb72671903d206f750c165502fd Mon Sep 17 00:00:00 2001 From: Ale Date: Thu, 16 Dec 2021 14:50:08 -0800 Subject: [PATCH 18/83] changing some semantic errors like tests --- src/utils/semantic_check/type_checker.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/utils/semantic_check/type_checker.py b/src/utils/semantic_check/type_checker.py index de37e1e1d..89a4b74c4 100644 --- a/src/utils/semantic_check/type_checker.py +++ b/src/utils/semantic_check/type_checker.py @@ -12,10 +12,12 @@ SELF_TYPE_IN_DISPATCH = '(%s, %s) - TypeError: SELF_TYPE cannot be used as a type of a dispatch' SELF_TYPE_IN_CASE_BRANCH = '(%s, %s) - TypeError: SELF_TYPE cannot be used as a type of a case branch' +INCOMPATIBLE_TYPES_ATTR = '(%s, %s) - TypeError: Inferred type %s of initialization of attribute %s does not conform to declared type %s.' +INCOMPATIBLE_TYPES_COMPLEMENT = '(%s, %s) - TypeError: Argument of %s has type %s instead of %s.' INCOMPATIBLE_TYPES = '(%s, %s) - TypeError: Cannot convert %s into %s.' WRONG_SIGNATURE = '(%s, %s) - TypeError: Method %s already defined in %s with a different signature.' LOCAL_ALREADY_DEFINED = '(%s, %s) - TypeError: Variable %s is already defined in method %s.' -INVALID_OPERATION = '(%s, %s) - TypeError: Operation "%s" is not defined between %s and %s.' +INVALID_OPERATION = '(%s, %s) - TypeError: non-Int arguments: %s %s %s' VARIABLE_NOT_DEFINED = '(%s, %s) - TypeError: Variable %s is not defined in %s.' INHERIT_ERROR = '(%s, %s) - TypeError: Class %s cannot inherit from class %s because they form a cycle.' METHOD_PARAMETERS = '(%s, %s) - TypeError: Method %s defined in %s receive %d parameters' @@ -94,7 +96,7 @@ def visit(self, node, scope): type_expr = self.visit(node.expr, scope.create_child()) if not type_expr.conforms_to(attr_type): - self.errors.append(INCOMPATIBLE_TYPES % (node.line, node.column, type_expr.name, attr_type.name)) + self.errors.append(INCOMPATIBLE_TYPES_ATTR % (node.line, node.column, type_expr.name, node.id, attr_type.name)) if node.id == 'self': self.errors.append(SELF_ERROR % (node.line, node.column)) @@ -358,7 +360,7 @@ def visit(self, node, scope): typex = self.visit(node.lex, scope) if not typex.conforms_to(self.context.get_type('Int')): - self.errors.append(INCOMPATIBLE_TYPES % (node.line, node.column, typex.name, 'Int')) + self.errors.append(INCOMPATIBLE_TYPES_COMPLEMENT % (node.line, node.column, '~' ,typex.name, 'Int')) return ErrorType() return typex @@ -370,7 +372,7 @@ def visit(self, node, scope): type_right = self.visit(node.right, scope) if not type_left.conforms_to(self.context.get_type('Int')) or not type_right.conforms_to(self.context.get_type('Int')): - self.errors.append(INVALID_OPERATION % (node.line, node.column, '+', type_left.name, type_right.name)) + self.errors.append(INVALID_OPERATION % (node.line, node.column, type_left.name, '+', type_right.name)) return ErrorType() else: @@ -383,7 +385,7 @@ def visit(self, node, scope): type_right = self.visit(node.right, scope) if not type_left.conforms_to(self.context.get_type('Int')) or not type_right.conforms_to(self.context.get_type('Int')): - self.errors.append(INVALID_OPERATION % (node.line, node.column, '-', type_left.name, type_right.name)) + self.errors.append(INVALID_OPERATION % (node.line, node.column, type_left.name, '-', type_right.name)) return ErrorType() else: @@ -396,7 +398,7 @@ def visit(self, node, scope): type_right = self.visit(node.right, scope) if not type_left.conforms_to(self.context.get_type('Int')) or not type_right.conforms_to(self.context.get_type('Int')): - self.errors.append(INVALID_OPERATION % (node.line, node.column, '*', type_left.name, type_right.name)) + self.errors.append(INVALID_OPERATION % (node.line, node.column, type_left.name, '*', type_right.name)) return ErrorType() else: @@ -409,7 +411,7 @@ def visit(self, node, scope): type_right = self.visit(node.right, scope) if not type_left.conforms_to(self.context.get_type('Int')) or not type_right.conforms_to(self.context.get_type('Int')): - self.errors.append(INVALID_OPERATION % (node.line, node.column, '/', type_left.name, type_right.name)) + self.errors.append(INVALID_OPERATION % (node.line, node.column, type_left.name, '/', type_right.name)) return ErrorType() else: @@ -422,7 +424,7 @@ def visit(self, node, scope): type_right = self.visit(node.right, scope) if not type_left.conforms_to(self.context.get_type('Int')) or not type_right.conforms_to(self.context.get_type('Int')): - self.errors.append(INVALID_OPERATION % (node.line, node.column, '<', type_left.name, type_right.name)) + self.errors.append(INVALID_OPERATION % (node.line, node.column, type_left.name, '<', type_right.name)) return ErrorType() else: @@ -435,7 +437,7 @@ def visit(self, node, scope): type_right = self.visit(node.right, scope) if not type_left.conforms_to(self.context.get_type('Int')) or not type_right.conforms_to(self.context.get_type('Int')): - self.errors.append(INVALID_OPERATION % (node.line, node.column, '<=', type_left.name, type_right.name)) + self.errors.append(INVALID_OPERATION % (node.line, node.column, type_left.name, '<=', type_right.name)) return ErrorType() else: @@ -454,7 +456,7 @@ def visit(self, node, scope): if type_left.name == 'AUTO_TYPE' or type_right.name == 'AUTO_TYPE': pass elif (type_left == int_type and not type_right.conforms_to(int_type)) or (type_right == int_type and not type_left.conforms_to(int_type)) or (type_left == bool_type and not type_right.conforms_to(bool_type)) or (type_right == bool_type and not type_left.conforms_to(bool_type)) or (type_left == string_type and not type_right.conforms_to(string_type)) or (type_right == string_type and not type_left.conforms_to(string_type)): - self.errors.append(INVALID_OPERATION % (node.line, node.column, '=', type_left.name, type_right.name)) + self.errors.append(INVALID_OPERATION % (node.line, node.column, type_left.name, '=', type_right.name)) return ErrorType() return bool_type \ No newline at end of file From d72b55d7076de57cfe6525da816ac7ba9b99acce Mon Sep 17 00:00:00 2001 From: Ale Date: Sat, 18 Dec 2021 21:59:05 -0800 Subject: [PATCH 19/83] including fixed_tokens --- src/main.py | 2 -- src/utils/COOL_Grammar.py | 2 +- src/utils/COOL_Lexer.py | 22 +++++++++++++++++----- src/utils/ast/AST_Nodes.py | 4 ++-- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/main.py b/src/main.py index f90e0cd20..5e80559a7 100644 --- a/src/main.py +++ b/src/main.py @@ -7,8 +7,6 @@ from utils.semantic_check.type_collector import TypeCollector from utils.semantic_check.type_builder import TypeBuilder from utils.semantic_check.type_checker import TypeChecker -from utils.semantic_check.type_inference import TypeInference -from utils.print_code import PrintCode def main(args): diff --git a/src/utils/COOL_Grammar.py b/src/utils/COOL_Grammar.py index 914f9f0cf..5790cabbe 100644 --- a/src/utils/COOL_Grammar.py +++ b/src/utils/COOL_Grammar.py @@ -49,7 +49,7 @@ def build_COOL_Grammar(): expr %= idx + arrow + expr, lambda h,s: node.AssignNode(s[1],s[3],s[2]) expr %= ifx + expr + then + expr + elsex + expr + fi, lambda h,s: node.IfThenElseNode(s[2],s[4],s[6],s[1]) expr %= whilex + expr + loop + expr + pool, lambda h,s: node.WhileNode(s[2],s[4],s[1]) - expr %= notx + expr, lambda h,s: node.NotNode(s[2]) + expr %= notx + expr, lambda h,s: node.NotNode(s[2],s[1]) expr %= ocur + expr_list + ccur, lambda h,s: node.BlockNode(s[2],s[1]) diff --git a/src/utils/COOL_Lexer.py b/src/utils/COOL_Lexer.py index 3fd1bc052..0075c1398 100644 --- a/src/utils/COOL_Lexer.py +++ b/src/utils/COOL_Lexer.py @@ -14,7 +14,7 @@ def __init__(self, lex, ttype, line, column): self.column = column def __str__(self): - return f'{self.token_type}: {self.lex}' + return f'({self.line}, {self.column}) - {self.token_type}: {self.lex}' ''' El lexer es el resultado de la union de todas las expresiones regulares que forman @@ -22,12 +22,13 @@ def __str__(self): ''' class Lexer: - def __init__(self, table, keywords, ignored_tokens, eof): + def __init__(self, table, keywords, ignored_tokens, tokens_toFix, eof): self.line = 1 self.column = 0 self.table = table self.keywords = keywords self.ignored_tokens = ignored_tokens + self.tokens_toFix = tokens_toFix self.regex = self._build_regex(table) self.errors = [] self.eof = eof @@ -142,11 +143,19 @@ def tokenize(self,text): def _build_regex(sef,table): return re.compile('|'.join([f'(?P<{name}>{regex})' if name != regex else f'({name})' for name,regex in table.items()])) - + def __call__(self, text): - return [Token(lex, ttype, line, column) for lex, ttype, line, column in self.tokenize(text) if ttype not in self.ignored_tokens] + return self.fixed_tokens([Token(lex, ttype, line, column) for lex, ttype, line, column in self.tokenize(text) if ttype not in self.ignored_tokens]) + + def fixed_tokens(self, tokens): + for i, token in enumerate(tokens): + if token.lex in self.tokens_toFix: + token.line = tokens[i + 1].line + token.column = tokens[i + 1].column + + ''' Esta clase guardara las propiedades sintacticas de COOL ''' @@ -205,4 +214,7 @@ def __init__(self): self.ignored_tokens = ['newline','whitespace','tabulation','comment'] - Lexer.__init__(self, self.regexs, self.keywords, self.ignored_tokens, 'eof') \ No newline at end of file + self.tokens_toFix = ['inherits','isvoid','class','while','then','else','loop','case', + 'let','new','not','if','in','of'] + + Lexer.__init__(self, self.regexs, self.keywords, self.ignored_tokens, self.tokens_toFix, 'eof') \ No newline at end of file diff --git a/src/utils/ast/AST_Nodes.py b/src/utils/ast/AST_Nodes.py index 899be306f..c31d90ed2 100644 --- a/src/utils/ast/AST_Nodes.py +++ b/src/utils/ast/AST_Nodes.py @@ -125,8 +125,8 @@ class VariableNode(AtomicNode): class InstantiateNode(AtomicNode): def __init__(self, typex, token): self.lex = typex.lex - self.line = token.line - self.column = token.column + self.line = token.line + 4 + self.column = token.column + 4 class IsVoidNode(AtomicNode): pass class ComplementNode(AtomicNode): From 12dbd4ff769789db3a4a76c73a0f045f30ea7f73 Mon Sep 17 00:00:00 2001 From: Ale Date: Sat, 18 Dec 2021 22:13:44 -0800 Subject: [PATCH 20/83] fixed tokens in ast --- src/main.py | 4 ++-- src/utils/COOL_Lexer.py | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main.py b/src/main.py index 5e80559a7..77550ed4c 100644 --- a/src/main.py +++ b/src/main.py @@ -35,9 +35,9 @@ def main(args): if parser.error: print(parser.error) exit(1) - + # ast - ast = evaluate_reverse_parse(G, derivation, operations, tokens) + ast = evaluate_reverse_parse(G, derivation, operations, lexer.fixed_tokens(tokens)) context = Context() semantic_errors = [] diff --git a/src/utils/COOL_Lexer.py b/src/utils/COOL_Lexer.py index 0075c1398..a3e733f40 100644 --- a/src/utils/COOL_Lexer.py +++ b/src/utils/COOL_Lexer.py @@ -145,13 +145,14 @@ def _build_regex(sef,table): return re.compile('|'.join([f'(?P<{name}>{regex})' if name != regex else f'({name})' for name,regex in table.items()])) def __call__(self, text): - return self.fixed_tokens([Token(lex, ttype, line, column) for lex, ttype, line, column in self.tokenize(text) if ttype not in self.ignored_tokens]) + return [Token(lex, ttype, line, column) for lex, ttype, line, column in self.tokenize(text) if ttype not in self.ignored_tokens] def fixed_tokens(self, tokens): for i, token in enumerate(tokens): if token.lex in self.tokens_toFix: token.line = tokens[i + 1].line token.column = tokens[i + 1].column + return tokens From 7a136143b9b0593ff632a815b59bd327d7420c42 Mon Sep 17 00:00:00 2001 From: Ale Date: Sat, 12 Feb 2022 16:56:17 -0800 Subject: [PATCH 21/83] update errors tags and fixind variables in parents --- src/utils/semantic_check/type_checker.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/utils/semantic_check/type_checker.py b/src/utils/semantic_check/type_checker.py index 89a4b74c4..b63740c0a 100644 --- a/src/utils/semantic_check/type_checker.py +++ b/src/utils/semantic_check/type_checker.py @@ -13,12 +13,13 @@ SELF_TYPE_IN_CASE_BRANCH = '(%s, %s) - TypeError: SELF_TYPE cannot be used as a type of a case branch' INCOMPATIBLE_TYPES_ATTR = '(%s, %s) - TypeError: Inferred type %s of initialization of attribute %s does not conform to declared type %s.' -INCOMPATIBLE_TYPES_COMPLEMENT = '(%s, %s) - TypeError: Argument of %s has type %s instead of %s.' +INCOMPATIBLE_TYPES_ARG = '(%s, %s) - TypeError: Argument of \'%s\' has type %s instead of %s.' +INCOMPATIBLE_TYPES_METH = '(%s, %s) - TypeError: Inferred return type %s of method %s does not conform to declared return type %s.' INCOMPATIBLE_TYPES = '(%s, %s) - TypeError: Cannot convert %s into %s.' WRONG_SIGNATURE = '(%s, %s) - TypeError: Method %s already defined in %s with a different signature.' LOCAL_ALREADY_DEFINED = '(%s, %s) - TypeError: Variable %s is already defined in method %s.' INVALID_OPERATION = '(%s, %s) - TypeError: non-Int arguments: %s %s %s' -VARIABLE_NOT_DEFINED = '(%s, %s) - TypeError: Variable %s is not defined in %s.' +VARIABLE_NOT_DEFINED = '(%s, %s) - NameError: Undeclared identifier %s.' INHERIT_ERROR = '(%s, %s) - TypeError: Class %s cannot inherit from class %s because they form a cycle.' METHOD_PARAMETERS = '(%s, %s) - TypeError: Method %s defined in %s receive %d parameters' @@ -76,6 +77,10 @@ def visit(self, node, scope): self.errors.append(INHERIT_ERROR % (node.line, node.column, self.current_type.name, self.current_type.parent.name)) self.current_type.parent = ErrorType() break + + for attr in current_parent.attributes: + scope.define_variable(attr.name, attr.type) + current_parent = current_parent.parent attrs = [feat for feat in node.features if isinstance(feat, nodes.AttrDeclarationNode)] @@ -149,7 +154,7 @@ def visit(self, node, scope): returnType = ErrorType() if not body_type.conforms_to(returnType): - self.errors.append(INCOMPATIBLE_TYPES % (node.line, node.column, body_type.name, returnType.name)) + self.errors.append(INCOMPATIBLE_TYPES_METH % (node.body_line, node.body_column, body_type.name , node.id, returnType.name )) return @@ -161,7 +166,7 @@ def visit(self, node, scope): type_expr = self.visit(node.expr, scope.create_child()) if var is None: - self.errors.append(VARIABLE_NOT_DEFINED % (node.line, node.column, node.id, self.current_method.name)) + self.errors.append(VARIABLE_NOT_DEFINED % (node.line, node.column, node.id)) elif var.name == 'self': self.errors.append(SELF_IS_READONLY % (node.line, node.column)) @@ -305,7 +310,7 @@ def visit(self, node, scope): typex = self.visit(node.expr, scope) if not typex.conforms_to(self.context.get_type('Bool')): - self.errors.append(INCOMPATIBLE_TYPES % (node.line, node.column, typex.name, 'Bool')) + self.errors.append(INCOMPATIBLE_TYPES_ARG % (node.line, node.column, 'not' ,typex.name, 'Bool')) return ErrorType() return typex @@ -331,7 +336,7 @@ def visit(self, node, scope): var = scope.find_variable(node.lex) if var is None: - self.errors.append(VARIABLE_NOT_DEFINED % (node.line, node.column, node.lex, self.current_method.name)) + self.errors.append(VARIABLE_NOT_DEFINED % (node.line, node.column, node.lex)) return ErrorType() return var.type @@ -360,7 +365,7 @@ def visit(self, node, scope): typex = self.visit(node.lex, scope) if not typex.conforms_to(self.context.get_type('Int')): - self.errors.append(INCOMPATIBLE_TYPES_COMPLEMENT % (node.line, node.column, '~' ,typex.name, 'Int')) + self.errors.append(INCOMPATIBLE_TYPES_ARG % (node.line, node.column, '~' ,typex.name, 'Int')) return ErrorType() return typex From deac2a5cd44acaf60cc5f106ff68b289e987ff8c Mon Sep 17 00:00:00 2001 From: Alejandro Campos Matanzas <74170015+Alexx-4@users.noreply.github.com> Date: Tue, 15 Feb 2022 10:16:10 -0800 Subject: [PATCH 22/83] Update requirements.txt --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 9eb0cad1a..4d792d537 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ pytest pytest-ordering +ply~=3.11 From ce0fabc9e446017eefe06122afce725a2f2d1703 Mon Sep 17 00:00:00 2001 From: Ale Date: Tue, 15 Feb 2022 13:23:38 -0800 Subject: [PATCH 23/83] updating all --- requirements.txt | 2 +- src/.vscode/launch.json | 30 + src/main.py | 20 +- src/tester/01_program.cl | 16 + src/tester/02_program.cl | 15 + src/tester/03_program.cl | 17 + src/tester/04_program.cl | 16 + src/tester/05_program.cl | 16 + src/tester/06_program.cl | 44 ++ src/tester/07_program.cl | 19 + src/tester/08_program.cl | 33 + src/tester/inference/01_program.cl | 16 + src/tester/inference/02_program.cl | 15 + src/tester/inference/03_program.cl | 17 + src/tester/inference/04_program.cl | 16 + src/tester/inference/05_program.cl | 16 + src/tester/inference/06_program.cl | 44 ++ src/tester/inference/07_program.cl | 19 + src/tester/inference/08_program.cl | 33 + src/tester/lexer/comment1.cl | 55 ++ src/tester/lexer/iis1.cl | 111 +++ src/tester/lexer/iis2.cl | 120 +++ src/tester/lexer/iis3.cl | 121 +++ src/tester/lexer/iis4.cl | 120 +++ src/tester/lexer/iis5.cl | 121 +++ src/tester/lexer/iis6.cl | 125 ++++ src/tester/lexer/mixed1.cl | 14 + src/tester/lexer/mixed2.cl | 20 + src/tester/lexer/string1.cl | 6 + src/tester/lexer/string2.cl | 19 + src/tester/lexer/string3.cl | Bin 0 -> 234 bytes src/tester/lexer/string4.cl | 38 + src/tester/parser/assignment1.cl | 37 + src/tester/parser/assignment2.cl | 37 + src/tester/parser/assignment3.cl | 37 + src/tester/parser/attribute1.cl | 34 + src/tester/parser/attribute2.cl | 34 + src/tester/parser/attribute3.cl | 34 + src/tester/parser/block1.cl | 87 +++ src/tester/parser/block2.cl | 87 +++ src/tester/parser/block3.cl | 87 +++ src/tester/parser/block4.cl | 88 +++ src/tester/parser/case1.cl | 91 +++ src/tester/parser/case2.cl | 93 +++ src/tester/parser/case3.cl | 93 +++ src/tester/parser/case4.cl | 93 +++ src/tester/parser/case5.cl | 93 +++ src/tester/parser/case6.cl | 93 +++ src/tester/parser/class1.cl | 20 + src/tester/parser/class2.cl | 20 + src/tester/parser/class3.cl | 34 + src/tester/parser/class4.cl | 36 + src/tester/parser/class5.cl | 34 + src/tester/parser/class6.cl | 34 + src/tester/parser/conditional1.cl | 69 ++ src/tester/parser/conditional2.cl | 69 ++ src/tester/parser/conditional3.cl | 69 ++ src/tester/parser/conditional4.cl | 73 ++ src/tester/parser/conditional5.cl | 73 ++ src/tester/parser/conditional6.cl | 73 ++ src/tester/parser/dispatch1.cl | 45 ++ src/tester/parser/dispatch2.cl | 45 ++ src/tester/parser/dispatch4.cl | 53 ++ src/tester/parser/dispatch5.cl | 53 ++ src/tester/parser/dispatch6.cl | 57 ++ src/tester/parser/dispatch7.cl | 57 ++ src/tester/parser/dispatch8.cl | 57 ++ src/tester/parser/dispatch9.cl | 61 ++ src/tester/parser/let1.cl | 85 +++ src/tester/parser/let2.cl | 85 +++ src/tester/parser/let3.cl | 85 +++ src/tester/parser/let4.cl | 85 +++ src/tester/parser/let5.cl | 85 +++ src/tester/parser/let6.cl | 74 ++ src/tester/parser/let7.cl | 85 +++ src/tester/parser/loop1.cl | 78 ++ src/tester/parser/loop2.cl | 78 ++ src/tester/parser/loop3.cl | 78 ++ src/tester/parser/loop4.cl | 78 ++ src/tester/parser/method1.cl | 34 + src/tester/parser/method2.cl | 34 + src/tester/parser/method3.cl | 34 + src/tester/parser/method4.cl | 34 + src/tester/parser/method5.cl | 34 + src/tester/parser/method6.cl | 33 + src/tester/parser/mixed2.cl | 14 + src/tester/parser/mixed3.cl | 40 + src/tester/parser/mixed4.cl | 21 + src/tester/parser/mixed5.cl | 20 + src/tester/parser/mixed6.cl | 5 + src/tester/parser/operation1.cl | 101 +++ src/tester/parser/operation2.cl | 101 +++ src/tester/parser/operation3.cl | 101 +++ src/tester/parser/operation4.cl | 101 +++ src/tester/parser/program1.cl | 1 + src/tester/parser/program3.cl | 24 + src/tester/semantic/01_program.cl | 16 + src/tester/semantic/arithmetic1.cl | 11 + src/tester/semantic/arithmetic10.cl | 15 + src/tester/semantic/arithmetic10_error.txt | 1 + src/tester/semantic/arithmetic11.cl | 14 + src/tester/semantic/arithmetic11_error.txt | 1 + src/tester/semantic/arithmetic12.cl | 14 + src/tester/semantic/arithmetic12_error.txt | 1 + src/tester/semantic/arithmetic1_error.txt | 1 + src/tester/semantic/arithmetic2.cl | 11 + src/tester/semantic/arithmetic2_error.txt | 1 + src/tester/semantic/arithmetic3.cl | 11 + src/tester/semantic/arithmetic3_error.txt | 1 + src/tester/semantic/arithmetic4.cl | 11 + src/tester/semantic/arithmetic4_error.txt | 1 + src/tester/semantic/arithmetic5.cl | 11 + src/tester/semantic/arithmetic5_error.txt | 1 + src/tester/semantic/arithmetic6.cl | 11 + src/tester/semantic/arithmetic6_error.txt | 1 + src/tester/semantic/arithmetic7.cl | 12 + src/tester/semantic/arithmetic7_error.txt | 1 + src/tester/semantic/arithmetic8.cl | 13 + src/tester/semantic/arithmetic8_error.txt | 1 + src/tester/semantic/arithmetic9.cl | 15 + src/tester/semantic/arithmetic9_error.txt | 1 + src/tester/semantic/assignment1.cl | 7 + src/tester/semantic/assignment1_error.txt | 1 + src/tester/semantic/assignment2.cl | 13 + src/tester/semantic/assignment2_error.txt | 1 + src/tester/semantic/assignment3.cl | 14 + src/tester/semantic/assignment3_error.txt | 1 + src/tester/semantic/attributes1.cl | 13 + src/tester/semantic/attributes1_error.txt | 1 + src/tester/semantic/attributes2.cl | 13 + src/tester/semantic/attributes2_error.txt | 1 + src/tester/semantic/attributes3.cl | 25 + src/tester/semantic/attributes3_error.txt | 1 + src/tester/semantic/attributes4.cl | 39 + src/tester/semantic/attributes4_error.txt | 1 + src/tester/semantic/basics1.cl | 10 + src/tester/semantic/basics1_error.txt | 1 + src/tester/semantic/basics2.cl | 9 + src/tester/semantic/basics2_error.txt | 1 + src/tester/semantic/basics3.cl | 9 + src/tester/semantic/basics3_error.txt | 1 + src/tester/semantic/basics4.cl | 9 + src/tester/semantic/basics4_error.txt | 1 + src/tester/semantic/basics5.cl | 9 + src/tester/semantic/basics5_error.txt | 1 + src/tester/semantic/basics6.cl | 9 + src/tester/semantic/basics6_error.txt | 1 + src/tester/semantic/basics7.cl | 9 + src/tester/semantic/basics7_error.txt | 1 + src/tester/semantic/basics8.cl | 9 + src/tester/semantic/basics8_error.txt | 1 + src/tester/semantic/blocks1.cl | 31 + src/tester/semantic/blocks1_error.txt | 1 + src/tester/semantic/case1.cl | 23 + src/tester/semantic/case1_error.txt | 1 + src/tester/semantic/case2.cl | 23 + src/tester/semantic/case2_error.txt | 1 + src/tester/semantic/case3.cl | 23 + src/tester/semantic/case3_error.txt | 1 + src/tester/semantic/class1.cl | 9 + src/tester/semantic/class1_error.txt | 2 + src/tester/semantic/conditionals1.cl | 14 + src/tester/semantic/conditionals1_error.txt | 1 + src/tester/semantic/conditionals2.cl | 24 + src/tester/semantic/conditionals2_error.txt | 2 + src/tester/semantic/dispatch1.cl | 33 + src/tester/semantic/dispatch1_error.txt | 1 + src/tester/semantic/dispatch2.cl | 34 + src/tester/semantic/dispatch2_error.txt | 1 + src/tester/semantic/dispatch3.cl | 36 + src/tester/semantic/dispatch3_error.txt | 1 + src/tester/semantic/dispatch4.cl | 36 + src/tester/semantic/dispatch4_error.txt | 1 + src/tester/semantic/dispatch5.cl | 31 + src/tester/semantic/dispatch5_error.txt | 1 + src/tester/semantic/dispatch6.cl | 32 + src/tester/semantic/dispatch6_error.txt | 1 + src/tester/semantic/eq1.cl | 17 + src/tester/semantic/eq1_error.txt | 1 + src/tester/semantic/eq2.cl | 17 + src/tester/semantic/eq2_error.txt | 1 + src/tester/semantic/eq3.cl | 17 + src/tester/semantic/eq3_error.txt | 1 + src/tester/semantic/eq4.cl | 17 + src/tester/semantic/eq4_error.txt | 1 + src/tester/semantic/features1.cl | 19 + src/tester/semantic/features1_error.txt | 1 + src/tester/semantic/features2.cl | 19 + src/tester/semantic/features2_error.txt | 1 + src/tester/semantic/features3.cl | 15 + src/tester/semantic/features3_error.txt | 1 + src/tester/semantic/inheritance1.cl | 19 + src/tester/semantic/inheritance1_error.txt | 1 + src/tester/semantic/inheritance2.cl | 19 + src/tester/semantic/inheritance2_error.txt | 1 + src/tester/semantic/inheritance3.cl | 13 + src/tester/semantic/inheritance3_error.txt | 1 + src/tester/semantic/inheritance4.cl | 19 + src/tester/semantic/inheritance4_error.txt | 1 + src/tester/semantic/inheritance5.cl | 21 + src/tester/semantic/inheritance5_error.txt | 1 + src/tester/semantic/isvoid1.cl | 26 + src/tester/semantic/isvoid1_error.txt | 1 + src/tester/semantic/let1.cl | 15 + src/tester/semantic/let1_error.txt | 1 + src/tester/semantic/let2.cl | 15 + src/tester/semantic/let2_error.txt | 1 + src/tester/semantic/let3.cl | 15 + src/tester/semantic/let3_error.txt | 1 + src/tester/semantic/loops1.cl | 8 + src/tester/semantic/loops1_error.txt | 1 + src/tester/semantic/loops2.cl | 9 + src/tester/semantic/loops2_error.txt | 1 + src/tester/semantic/methods1.cl | 12 + src/tester/semantic/methods1_error.txt | 1 + src/tester/semantic/methods2.cl | 12 + src/tester/semantic/methods2_error.txt | 1 + src/tester/semantic/methods3.cl | 14 + src/tester/semantic/methods3_error.txt | 1 + src/tester/semantic/methods4.cl | 19 + src/tester/semantic/methods4_error.txt | 1 + src/tester/semantic/methods5.cl | 20 + src/tester/semantic/methods5_error.txt | 1 + src/tester/semantic/methods6.cl | 27 + src/tester/semantic/methods6_error.txt | 1 + src/tester/semantic/methods7.cl | 12 + src/tester/semantic/methods7_error.txt | 1 + src/tester/semantic/methods8.cl | 12 + src/tester/semantic/methods8_error.txt | 1 + src/tester/semantic/new1.cl | 31 + src/tester/semantic/new1_error.txt | 1 + src/tester/semantic/self1.cl | 11 + src/tester/semantic/self1_error.txt | 1 + src/tester/semantic/self2.cl | 10 + src/tester/semantic/self2_error.txt | 1 + src/tester/semantic/self3.cl | 10 + src/tester/semantic/self3_error.txt | 1 + src/tester/semantic/self4.cl | 10 + src/tester/semantic/self4_error.txt | 1 + src/tests/codegen/arith.cl | 430 +++++++++++ src/tests/codegen/arith_input.txt | 13 + src/tests/codegen/arith_output.txt | 158 ++++ src/tests/codegen/atoi.cl | 121 +++ src/tests/codegen/atoi_input.txt | 0 src/tests/codegen/atoi_output.txt | 1 + src/tests/codegen/book_list.cl | 132 ++++ src/tests/codegen/book_list_input.txt | 0 src/tests/codegen/book_list_output.txt | 7 + src/tests/codegen/cells.cl | 97 +++ src/tests/codegen/cells_input.txt | 0 src/tests/codegen/cells_output.txt | 21 + src/tests/codegen/complex.cl | 52 ++ src/tests/codegen/complex_input.txt | 0 src/tests/codegen/complex_output.txt | 1 + src/tests/codegen/fib.cl | 29 + src/tests/codegen/fib_input.txt | 1 + src/tests/codegen/fib_output.txt | 2 + src/tests/codegen/graph.cl | 381 ++++++++++ src/tests/codegen/graph_input.txt | 5 + src/tests/codegen/graph_output.txt | 7 + src/tests/codegen/hairyscary.cl | 67 ++ src/tests/codegen/hairyscary_input.txt | 0 src/tests/codegen/hairyscary_output.txt | 1 + src/tests/codegen/hello_world.cl | 5 + src/tests/codegen/hello_world_input.txt | 0 src/tests/codegen/hello_world_output.txt | 1 + src/tests/codegen/io.cl | 103 +++ src/tests/codegen/io_input.txt | 0 src/tests/codegen/io_output.txt | 5 + src/tests/codegen/life.cl | 436 +++++++++++ src/tests/codegen/life_input.txt | 66 ++ src/tests/codegen/life_output.txt | 778 ++++++++++++++++++++ src/tests/codegen/list.cl | 141 ++++ src/tests/codegen/list_input.txt | 0 src/tests/codegen/list_output.txt | 5 + src/tests/codegen/new_complex.cl | 79 ++ src/tests/codegen/new_complex_input.txt | 0 src/tests/codegen/new_complex_output.txt | 2 + src/tests/codegen/palindrome.cl | 25 + src/tests/codegen/palindrome_input.txt | 1 + src/tests/codegen/palindrome_output.txt | 2 + src/tests/codegen/primes.cl | 84 +++ src/tests/codegen/primes_input.txt | 0 src/tests/codegen/primes_output.txt | 96 +++ src/tests/codegen/print-cool.cl | 9 + src/tests/codegen/print-cool_input.txt | 0 src/tests/codegen/print-cool_output.txt | 1 + src/tests/codegen/sort-list.cl | 146 ++++ src/tests/codegen/sort-list_input.txt | 1 + src/tests/codegen/sort-list_output.txt | 10 + src/tests/codegen_test.py | 17 + src/tests/conftest.py | 6 + src/tests/lexer/comment1.cl | 55 ++ src/tests/lexer/comment1_error.txt | 1 + src/tests/lexer/iis1.cl | 111 +++ src/tests/lexer/iis1_error.txt | 1 + src/tests/lexer/iis2.cl | 120 +++ src/tests/lexer/iis2_error.txt | 1 + src/tests/lexer/iis3.cl | 121 +++ src/tests/lexer/iis3_error.txt | 1 + src/tests/lexer/iis4.cl | 120 +++ src/tests/lexer/iis4_error.txt | 1 + src/tests/lexer/iis5.cl | 121 +++ src/tests/lexer/iis5_error.txt | 2 + src/tests/lexer/iis6.cl | 125 ++++ src/tests/lexer/iis6_error.txt | 1 + src/tests/lexer/mixed1.cl | 14 + src/tests/lexer/mixed1_error.txt | 1 + src/tests/lexer/mixed2.cl | 20 + src/tests/lexer/mixed2_error.txt | 3 + src/tests/lexer/string1.cl | 6 + src/tests/lexer/string1_error.txt | 2 + src/tests/lexer/string2.cl | 19 + src/tests/lexer/string2_error.txt | 1 + src/tests/lexer/string3.cl | Bin 0 -> 234 bytes src/tests/lexer/string3_error.txt | 1 + src/tests/lexer/string4.cl | 38 + src/tests/lexer/string4_error.txt | 3 + src/tests/lexer_test.py | 13 + src/tests/parser/assignment1.cl | 37 + src/tests/parser/assignment1_error.txt | 1 + src/tests/parser/assignment2.cl | 37 + src/tests/parser/assignment2_error.txt | 1 + src/tests/parser/assignment3.cl | 37 + src/tests/parser/assignment3_error.txt | 1 + src/tests/parser/attribute1.cl | 34 + src/tests/parser/attribute1_error.txt | 1 + src/tests/parser/attribute2.cl | 34 + src/tests/parser/attribute2_error.txt | 1 + src/tests/parser/attribute3.cl | 34 + src/tests/parser/attribute3_error.txt | 1 + src/tests/parser/block1.cl | 87 +++ src/tests/parser/block1_error.txt | 1 + src/tests/parser/block2.cl | 87 +++ src/tests/parser/block2_error.txt | 1 + src/tests/parser/block3.cl | 87 +++ src/tests/parser/block3_error.txt | 1 + src/tests/parser/block4.cl | 88 +++ src/tests/parser/block4_error.txt | 1 + src/tests/parser/case1.cl | 91 +++ src/tests/parser/case1_error.txt | 1 + src/tests/parser/case2.cl | 93 +++ src/tests/parser/case2_error.txt | 1 + src/tests/parser/case3.cl | 93 +++ src/tests/parser/case3_error.txt | 1 + src/tests/parser/case4.cl | 93 +++ src/tests/parser/case4_error.txt | 1 + src/tests/parser/case5.cl | 93 +++ src/tests/parser/case5_error.txt | 1 + src/tests/parser/case6.cl | 93 +++ src/tests/parser/case6_error.txt | 1 + src/tests/parser/class1.cl | 20 + src/tests/parser/class1_error.txt | 1 + src/tests/parser/class2.cl | 20 + src/tests/parser/class2_error.txt | 1 + src/tests/parser/class3.cl | 34 + src/tests/parser/class3_error.txt | 1 + src/tests/parser/class4.cl | 36 + src/tests/parser/class4_error.txt | 1 + src/tests/parser/class5.cl | 34 + src/tests/parser/class5_error.txt | 1 + src/tests/parser/class6.cl | 34 + src/tests/parser/class6_error.txt | 1 + src/tests/parser/conditional1.cl | 69 ++ src/tests/parser/conditional1_error.txt | 1 + src/tests/parser/conditional2.cl | 69 ++ src/tests/parser/conditional2_error.txt | 1 + src/tests/parser/conditional3.cl | 69 ++ src/tests/parser/conditional3_error.txt | 1 + src/tests/parser/conditional4.cl | 73 ++ src/tests/parser/conditional4_error.txt | 1 + src/tests/parser/conditional5.cl | 73 ++ src/tests/parser/conditional5_error.txt | 1 + src/tests/parser/conditional6.cl | 73 ++ src/tests/parser/conditional6_error.txt | 1 + src/tests/parser/dispatch1.cl | 45 ++ src/tests/parser/dispatch1_error.txt | 1 + src/tests/parser/dispatch2.cl | 45 ++ src/tests/parser/dispatch2_error.txt | 1 + src/tests/parser/dispatch3.cl | 45 ++ src/tests/parser/dispatch3_error.txt | 1 + src/tests/parser/dispatch4.cl | 53 ++ src/tests/parser/dispatch4_error.txt | 1 + src/tests/parser/dispatch5.cl | 53 ++ src/tests/parser/dispatch5_error.txt | 1 + src/tests/parser/dispatch6.cl | 57 ++ src/tests/parser/dispatch6_error.txt | 1 + src/tests/parser/dispatch7.cl | 57 ++ src/tests/parser/dispatch7_error.txt | 1 + src/tests/parser/dispatch8.cl | 57 ++ src/tests/parser/dispatch8_error.txt | 1 + src/tests/parser/dispatch9.cl | 61 ++ src/tests/parser/dispatch9_error.txt | 1 + src/tests/parser/let1.cl | 85 +++ src/tests/parser/let1_error.txt | 1 + src/tests/parser/let2.cl | 85 +++ src/tests/parser/let2_error.txt | 1 + src/tests/parser/let3.cl | 85 +++ src/tests/parser/let3_error.txt | 1 + src/tests/parser/let4.cl | 85 +++ src/tests/parser/let4_error.txt | 1 + src/tests/parser/let5.cl | 85 +++ src/tests/parser/let5_error.txt | 1 + src/tests/parser/let6.cl | 74 ++ src/tests/parser/let6_error.txt | 1 + src/tests/parser/let7.cl | 85 +++ src/tests/parser/let7_error.txt | 1 + src/tests/parser/loop1.cl | 78 ++ src/tests/parser/loop1_error.txt | 1 + src/tests/parser/loop2.cl | 78 ++ src/tests/parser/loop2_error.txt | 1 + src/tests/parser/loop3.cl | 78 ++ src/tests/parser/loop3_error.txt | 1 + src/tests/parser/loop4.cl | 78 ++ src/tests/parser/loop4_error.txt | 1 + src/tests/parser/method1.cl | 34 + src/tests/parser/method1_error.txt | 1 + src/tests/parser/method2.cl | 34 + src/tests/parser/method2_error.txt | 1 + src/tests/parser/method3.cl | 34 + src/tests/parser/method3_error.txt | 1 + src/tests/parser/method4.cl | 34 + src/tests/parser/method4_error.txt | 1 + src/tests/parser/method5.cl | 34 + src/tests/parser/method5_error.txt | 1 + src/tests/parser/method6.cl | 33 + src/tests/parser/method6_error.txt | 1 + src/tests/parser/mixed1.cl | 100 +++ src/tests/parser/mixed1_error.txt | 1 + src/tests/parser/mixed2.cl | 14 + src/tests/parser/mixed2_error.txt | 1 + src/tests/parser/mixed3.cl | 40 + src/tests/parser/mixed3_error.txt | 1 + src/tests/parser/mixed4.cl | 21 + src/tests/parser/mixed4_error.txt | 1 + src/tests/parser/mixed5.cl | 20 + src/tests/parser/mixed5_error.txt | 1 + src/tests/parser/mixed6.cl | 5 + src/tests/parser/mixed6_error.txt | 1 + src/tests/parser/operation1.cl | 101 +++ src/tests/parser/operation1_error.txt | 1 + src/tests/parser/operation2.cl | 101 +++ src/tests/parser/operation2_error.txt | 1 + src/tests/parser/operation3.cl | 101 +++ src/tests/parser/operation3_error.txt | 1 + src/tests/parser/operation4.cl | 101 +++ src/tests/parser/operation4_error.txt | 1 + src/tests/parser/program1.cl | 1 + src/tests/parser/program1_error.txt | 1 + src/tests/parser/program2.cl | 20 + src/tests/parser/program2_error.txt | 1 + src/tests/parser/program3.cl | 24 + src/tests/parser/program3_error.txt | 1 + src/tests/parser_test.py | 13 + src/tests/semantic/arithmetic1.cl | 11 + src/tests/semantic/arithmetic10.cl | 15 + src/tests/semantic/arithmetic10_error.txt | 1 + src/tests/semantic/arithmetic11.cl | 14 + src/tests/semantic/arithmetic11_error.txt | 1 + src/tests/semantic/arithmetic12.cl | 14 + src/tests/semantic/arithmetic12_error.txt | 1 + src/tests/semantic/arithmetic1_error.txt | 1 + src/tests/semantic/arithmetic2.cl | 11 + src/tests/semantic/arithmetic2_error.txt | 1 + src/tests/semantic/arithmetic3.cl | 11 + src/tests/semantic/arithmetic3_error.txt | 1 + src/tests/semantic/arithmetic4.cl | 11 + src/tests/semantic/arithmetic4_error.txt | 1 + src/tests/semantic/arithmetic5.cl | 11 + src/tests/semantic/arithmetic5_error.txt | 1 + src/tests/semantic/arithmetic6.cl | 11 + src/tests/semantic/arithmetic6_error.txt | 1 + src/tests/semantic/arithmetic7.cl | 12 + src/tests/semantic/arithmetic7_error.txt | 1 + src/tests/semantic/arithmetic8.cl | 13 + src/tests/semantic/arithmetic8_error.txt | 1 + src/tests/semantic/arithmetic9.cl | 15 + src/tests/semantic/arithmetic9_error.txt | 1 + src/tests/semantic/assignment1.cl | 7 + src/tests/semantic/assignment1_error.txt | 1 + src/tests/semantic/assignment2.cl | 13 + src/tests/semantic/assignment2_error.txt | 1 + src/tests/semantic/assignment3.cl | 14 + src/tests/semantic/assignment3_error.txt | 1 + src/tests/semantic/attributes1.cl | 13 + src/tests/semantic/attributes1_error.txt | 1 + src/tests/semantic/attributes2.cl | 13 + src/tests/semantic/attributes2_error.txt | 1 + src/tests/semantic/attributes3.cl | 25 + src/tests/semantic/attributes3_error.txt | 1 + src/tests/semantic/attributes4.cl | 39 + src/tests/semantic/attributes4_error.txt | 1 + src/tests/semantic/basics1.cl | 10 + src/tests/semantic/basics1_error.txt | 1 + src/tests/semantic/basics2.cl | 9 + src/tests/semantic/basics2_error.txt | 1 + src/tests/semantic/basics3.cl | 9 + src/tests/semantic/basics3_error.txt | 1 + src/tests/semantic/basics4.cl | 9 + src/tests/semantic/basics4_error.txt | 1 + src/tests/semantic/basics5.cl | 9 + src/tests/semantic/basics5_error.txt | 1 + src/tests/semantic/basics6.cl | 9 + src/tests/semantic/basics6_error.txt | 1 + src/tests/semantic/basics7.cl | 9 + src/tests/semantic/basics7_error.txt | 1 + src/tests/semantic/basics8.cl | 9 + src/tests/semantic/basics8_error.txt | 1 + src/tests/semantic/blocks1.cl | 31 + src/tests/semantic/blocks1_error.txt | 1 + src/tests/semantic/case1.cl | 23 + src/tests/semantic/case1_error.txt | 1 + src/tests/semantic/case2.cl | 23 + src/tests/semantic/case2_error.txt | 1 + src/tests/semantic/case3.cl | 23 + src/tests/semantic/case3_error.txt | 1 + src/tests/semantic/class1.cl | 9 + src/tests/semantic/class1_error.txt | 2 + src/tests/semantic/conditionals1.cl | 14 + src/tests/semantic/conditionals1_error.txt | 1 + src/tests/semantic/conditionals2.cl | 24 + src/tests/semantic/conditionals2_error.txt | 2 + src/tests/semantic/dispatch1.cl | 33 + src/tests/semantic/dispatch1_error.txt | 1 + src/tests/semantic/dispatch2.cl | 34 + src/tests/semantic/dispatch2_error.txt | 1 + src/tests/semantic/dispatch3.cl | 36 + src/tests/semantic/dispatch3_error.txt | 1 + src/tests/semantic/dispatch4.cl | 36 + src/tests/semantic/dispatch4_error.txt | 1 + src/tests/semantic/dispatch5.cl | 31 + src/tests/semantic/dispatch5_error.txt | 1 + src/tests/semantic/dispatch6.cl | 32 + src/tests/semantic/dispatch6_error.txt | 1 + src/tests/semantic/eq1.cl | 17 + src/tests/semantic/eq1_error.txt | 1 + src/tests/semantic/eq2.cl | 17 + src/tests/semantic/eq2_error.txt | 1 + src/tests/semantic/eq3.cl | 17 + src/tests/semantic/eq3_error.txt | 1 + src/tests/semantic/eq4.cl | 17 + src/tests/semantic/eq4_error.txt | 1 + src/tests/semantic/features1.cl | 19 + src/tests/semantic/features1_error.txt | 1 + src/tests/semantic/features2.cl | 19 + src/tests/semantic/features2_error.txt | 1 + src/tests/semantic/features3.cl | 15 + src/tests/semantic/features3_error.txt | 1 + src/tests/semantic/inheritance1.cl | 19 + src/tests/semantic/inheritance1_error.txt | 1 + src/tests/semantic/inheritance2.cl | 19 + src/tests/semantic/inheritance2_error.txt | 1 + src/tests/semantic/inheritance3.cl | 13 + src/tests/semantic/inheritance3_error.txt | 1 + src/tests/semantic/inheritance4.cl | 19 + src/tests/semantic/inheritance4_error.txt | 1 + src/tests/semantic/inheritance5.cl | 21 + src/tests/semantic/inheritance5_error.txt | 1 + src/tests/semantic/isvoid1.cl | 26 + src/tests/semantic/isvoid1_error.txt | 1 + src/tests/semantic/let1.cl | 15 + src/tests/semantic/let1_error.txt | 1 + src/tests/semantic/let2.cl | 15 + src/tests/semantic/let2_error.txt | 1 + src/tests/semantic/let3.cl | 15 + src/tests/semantic/let3_error.txt | 1 + src/tests/semantic/loops1.cl | 8 + src/tests/semantic/loops1_error.txt | 1 + src/tests/semantic/loops2.cl | 9 + src/tests/semantic/loops2_error.txt | 1 + src/tests/semantic/methods1.cl | 12 + src/tests/semantic/methods1_error.txt | 1 + src/tests/semantic/methods2.cl | 12 + src/tests/semantic/methods2_error.txt | 1 + src/tests/semantic/methods3.cl | 14 + src/tests/semantic/methods3_error.txt | 1 + src/tests/semantic/methods4.cl | 19 + src/tests/semantic/methods4_error.txt | 1 + src/tests/semantic/methods5.cl | 20 + src/tests/semantic/methods5_error.txt | 1 + src/tests/semantic/methods6.cl | 27 + src/tests/semantic/methods6_error.txt | 1 + src/tests/semantic/methods7.cl | 12 + src/tests/semantic/methods7_error.txt | 1 + src/tests/semantic/methods8.cl | 12 + src/tests/semantic/methods8_error.txt | 1 + src/tests/semantic/new1.cl | 31 + src/tests/semantic/new1_error.txt | 1 + src/tests/semantic/self1.cl | 11 + src/tests/semantic/self1_error.txt | 1 + src/tests/semantic/self2.cl | 10 + src/tests/semantic/self2_error.txt | 1 + src/tests/semantic/self3.cl | 10 + src/tests/semantic/self3_error.txt | 1 + src/tests/semantic/self4.cl | 10 + src/tests/semantic/self4_error.txt | 1 + src/tests/semantic_test.py | 14 + src/tests/utils/__init__.py | 1 + src/tests/utils/utils.py | 91 +++ src/utils/COOL_Grammar.py | 10 +- src/utils/COOL_Lexer.py | 11 +- src/utils/ast/AST_Nodes.py | 61 +- src/utils/print_code.py | 153 ++++ src/utils/semantic_check/type_builder.py | 6 +- src/utils/semantic_check/type_checker.py | 18 +- src/utils/semantic_check/type_collector.py | 8 +- src/utils/semantic_check/type_inference.py | 376 ++++++++++ 607 files changed, 16771 insertions(+), 52 deletions(-) create mode 100644 src/.vscode/launch.json create mode 100644 src/tester/01_program.cl create mode 100644 src/tester/02_program.cl create mode 100644 src/tester/03_program.cl create mode 100644 src/tester/04_program.cl create mode 100644 src/tester/05_program.cl create mode 100644 src/tester/06_program.cl create mode 100644 src/tester/07_program.cl create mode 100644 src/tester/08_program.cl create mode 100644 src/tester/inference/01_program.cl create mode 100644 src/tester/inference/02_program.cl create mode 100644 src/tester/inference/03_program.cl create mode 100644 src/tester/inference/04_program.cl create mode 100644 src/tester/inference/05_program.cl create mode 100644 src/tester/inference/06_program.cl create mode 100644 src/tester/inference/07_program.cl create mode 100644 src/tester/inference/08_program.cl create mode 100644 src/tester/lexer/comment1.cl create mode 100644 src/tester/lexer/iis1.cl create mode 100644 src/tester/lexer/iis2.cl create mode 100644 src/tester/lexer/iis3.cl create mode 100644 src/tester/lexer/iis4.cl create mode 100644 src/tester/lexer/iis5.cl create mode 100644 src/tester/lexer/iis6.cl create mode 100644 src/tester/lexer/mixed1.cl create mode 100644 src/tester/lexer/mixed2.cl create mode 100644 src/tester/lexer/string1.cl create mode 100644 src/tester/lexer/string2.cl create mode 100644 src/tester/lexer/string3.cl create mode 100644 src/tester/lexer/string4.cl create mode 100644 src/tester/parser/assignment1.cl create mode 100644 src/tester/parser/assignment2.cl create mode 100644 src/tester/parser/assignment3.cl create mode 100644 src/tester/parser/attribute1.cl create mode 100644 src/tester/parser/attribute2.cl create mode 100644 src/tester/parser/attribute3.cl create mode 100644 src/tester/parser/block1.cl create mode 100644 src/tester/parser/block2.cl create mode 100644 src/tester/parser/block3.cl create mode 100644 src/tester/parser/block4.cl create mode 100644 src/tester/parser/case1.cl create mode 100644 src/tester/parser/case2.cl create mode 100644 src/tester/parser/case3.cl create mode 100644 src/tester/parser/case4.cl create mode 100644 src/tester/parser/case5.cl create mode 100644 src/tester/parser/case6.cl create mode 100644 src/tester/parser/class1.cl create mode 100644 src/tester/parser/class2.cl create mode 100644 src/tester/parser/class3.cl create mode 100644 src/tester/parser/class4.cl create mode 100644 src/tester/parser/class5.cl create mode 100644 src/tester/parser/class6.cl create mode 100644 src/tester/parser/conditional1.cl create mode 100644 src/tester/parser/conditional2.cl create mode 100644 src/tester/parser/conditional3.cl create mode 100644 src/tester/parser/conditional4.cl create mode 100644 src/tester/parser/conditional5.cl create mode 100644 src/tester/parser/conditional6.cl create mode 100644 src/tester/parser/dispatch1.cl create mode 100644 src/tester/parser/dispatch2.cl create mode 100644 src/tester/parser/dispatch4.cl create mode 100644 src/tester/parser/dispatch5.cl create mode 100644 src/tester/parser/dispatch6.cl create mode 100644 src/tester/parser/dispatch7.cl create mode 100644 src/tester/parser/dispatch8.cl create mode 100644 src/tester/parser/dispatch9.cl create mode 100644 src/tester/parser/let1.cl create mode 100644 src/tester/parser/let2.cl create mode 100644 src/tester/parser/let3.cl create mode 100644 src/tester/parser/let4.cl create mode 100644 src/tester/parser/let5.cl create mode 100644 src/tester/parser/let6.cl create mode 100644 src/tester/parser/let7.cl create mode 100644 src/tester/parser/loop1.cl create mode 100644 src/tester/parser/loop2.cl create mode 100644 src/tester/parser/loop3.cl create mode 100644 src/tester/parser/loop4.cl create mode 100644 src/tester/parser/method1.cl create mode 100644 src/tester/parser/method2.cl create mode 100644 src/tester/parser/method3.cl create mode 100644 src/tester/parser/method4.cl create mode 100644 src/tester/parser/method5.cl create mode 100644 src/tester/parser/method6.cl create mode 100644 src/tester/parser/mixed2.cl create mode 100644 src/tester/parser/mixed3.cl create mode 100644 src/tester/parser/mixed4.cl create mode 100644 src/tester/parser/mixed5.cl create mode 100644 src/tester/parser/mixed6.cl create mode 100644 src/tester/parser/operation1.cl create mode 100644 src/tester/parser/operation2.cl create mode 100644 src/tester/parser/operation3.cl create mode 100644 src/tester/parser/operation4.cl create mode 100644 src/tester/parser/program1.cl create mode 100644 src/tester/parser/program3.cl create mode 100644 src/tester/semantic/01_program.cl create mode 100644 src/tester/semantic/arithmetic1.cl create mode 100644 src/tester/semantic/arithmetic10.cl create mode 100644 src/tester/semantic/arithmetic10_error.txt create mode 100644 src/tester/semantic/arithmetic11.cl create mode 100644 src/tester/semantic/arithmetic11_error.txt create mode 100644 src/tester/semantic/arithmetic12.cl create mode 100644 src/tester/semantic/arithmetic12_error.txt create mode 100644 src/tester/semantic/arithmetic1_error.txt create mode 100644 src/tester/semantic/arithmetic2.cl create mode 100644 src/tester/semantic/arithmetic2_error.txt create mode 100644 src/tester/semantic/arithmetic3.cl create mode 100644 src/tester/semantic/arithmetic3_error.txt create mode 100644 src/tester/semantic/arithmetic4.cl create mode 100644 src/tester/semantic/arithmetic4_error.txt create mode 100644 src/tester/semantic/arithmetic5.cl create mode 100644 src/tester/semantic/arithmetic5_error.txt create mode 100644 src/tester/semantic/arithmetic6.cl create mode 100644 src/tester/semantic/arithmetic6_error.txt create mode 100644 src/tester/semantic/arithmetic7.cl create mode 100644 src/tester/semantic/arithmetic7_error.txt create mode 100644 src/tester/semantic/arithmetic8.cl create mode 100644 src/tester/semantic/arithmetic8_error.txt create mode 100644 src/tester/semantic/arithmetic9.cl create mode 100644 src/tester/semantic/arithmetic9_error.txt create mode 100644 src/tester/semantic/assignment1.cl create mode 100644 src/tester/semantic/assignment1_error.txt create mode 100644 src/tester/semantic/assignment2.cl create mode 100644 src/tester/semantic/assignment2_error.txt create mode 100644 src/tester/semantic/assignment3.cl create mode 100644 src/tester/semantic/assignment3_error.txt create mode 100644 src/tester/semantic/attributes1.cl create mode 100644 src/tester/semantic/attributes1_error.txt create mode 100644 src/tester/semantic/attributes2.cl create mode 100644 src/tester/semantic/attributes2_error.txt create mode 100644 src/tester/semantic/attributes3.cl create mode 100644 src/tester/semantic/attributes3_error.txt create mode 100644 src/tester/semantic/attributes4.cl create mode 100644 src/tester/semantic/attributes4_error.txt create mode 100644 src/tester/semantic/basics1.cl create mode 100644 src/tester/semantic/basics1_error.txt create mode 100644 src/tester/semantic/basics2.cl create mode 100644 src/tester/semantic/basics2_error.txt create mode 100644 src/tester/semantic/basics3.cl create mode 100644 src/tester/semantic/basics3_error.txt create mode 100644 src/tester/semantic/basics4.cl create mode 100644 src/tester/semantic/basics4_error.txt create mode 100644 src/tester/semantic/basics5.cl create mode 100644 src/tester/semantic/basics5_error.txt create mode 100644 src/tester/semantic/basics6.cl create mode 100644 src/tester/semantic/basics6_error.txt create mode 100644 src/tester/semantic/basics7.cl create mode 100644 src/tester/semantic/basics7_error.txt create mode 100644 src/tester/semantic/basics8.cl create mode 100644 src/tester/semantic/basics8_error.txt create mode 100644 src/tester/semantic/blocks1.cl create mode 100644 src/tester/semantic/blocks1_error.txt create mode 100644 src/tester/semantic/case1.cl create mode 100644 src/tester/semantic/case1_error.txt create mode 100644 src/tester/semantic/case2.cl create mode 100644 src/tester/semantic/case2_error.txt create mode 100644 src/tester/semantic/case3.cl create mode 100644 src/tester/semantic/case3_error.txt create mode 100644 src/tester/semantic/class1.cl create mode 100644 src/tester/semantic/class1_error.txt create mode 100644 src/tester/semantic/conditionals1.cl create mode 100644 src/tester/semantic/conditionals1_error.txt create mode 100644 src/tester/semantic/conditionals2.cl create mode 100644 src/tester/semantic/conditionals2_error.txt create mode 100644 src/tester/semantic/dispatch1.cl create mode 100644 src/tester/semantic/dispatch1_error.txt create mode 100644 src/tester/semantic/dispatch2.cl create mode 100644 src/tester/semantic/dispatch2_error.txt create mode 100644 src/tester/semantic/dispatch3.cl create mode 100644 src/tester/semantic/dispatch3_error.txt create mode 100644 src/tester/semantic/dispatch4.cl create mode 100644 src/tester/semantic/dispatch4_error.txt create mode 100644 src/tester/semantic/dispatch5.cl create mode 100644 src/tester/semantic/dispatch5_error.txt create mode 100644 src/tester/semantic/dispatch6.cl create mode 100644 src/tester/semantic/dispatch6_error.txt create mode 100644 src/tester/semantic/eq1.cl create mode 100644 src/tester/semantic/eq1_error.txt create mode 100644 src/tester/semantic/eq2.cl create mode 100644 src/tester/semantic/eq2_error.txt create mode 100644 src/tester/semantic/eq3.cl create mode 100644 src/tester/semantic/eq3_error.txt create mode 100644 src/tester/semantic/eq4.cl create mode 100644 src/tester/semantic/eq4_error.txt create mode 100644 src/tester/semantic/features1.cl create mode 100644 src/tester/semantic/features1_error.txt create mode 100644 src/tester/semantic/features2.cl create mode 100644 src/tester/semantic/features2_error.txt create mode 100644 src/tester/semantic/features3.cl create mode 100644 src/tester/semantic/features3_error.txt create mode 100644 src/tester/semantic/inheritance1.cl create mode 100644 src/tester/semantic/inheritance1_error.txt create mode 100644 src/tester/semantic/inheritance2.cl create mode 100644 src/tester/semantic/inheritance2_error.txt create mode 100644 src/tester/semantic/inheritance3.cl create mode 100644 src/tester/semantic/inheritance3_error.txt create mode 100644 src/tester/semantic/inheritance4.cl create mode 100644 src/tester/semantic/inheritance4_error.txt create mode 100644 src/tester/semantic/inheritance5.cl create mode 100644 src/tester/semantic/inheritance5_error.txt create mode 100644 src/tester/semantic/isvoid1.cl create mode 100644 src/tester/semantic/isvoid1_error.txt create mode 100644 src/tester/semantic/let1.cl create mode 100644 src/tester/semantic/let1_error.txt create mode 100644 src/tester/semantic/let2.cl create mode 100644 src/tester/semantic/let2_error.txt create mode 100644 src/tester/semantic/let3.cl create mode 100644 src/tester/semantic/let3_error.txt create mode 100644 src/tester/semantic/loops1.cl create mode 100644 src/tester/semantic/loops1_error.txt create mode 100644 src/tester/semantic/loops2.cl create mode 100644 src/tester/semantic/loops2_error.txt create mode 100644 src/tester/semantic/methods1.cl create mode 100644 src/tester/semantic/methods1_error.txt create mode 100644 src/tester/semantic/methods2.cl create mode 100644 src/tester/semantic/methods2_error.txt create mode 100644 src/tester/semantic/methods3.cl create mode 100644 src/tester/semantic/methods3_error.txt create mode 100644 src/tester/semantic/methods4.cl create mode 100644 src/tester/semantic/methods4_error.txt create mode 100644 src/tester/semantic/methods5.cl create mode 100644 src/tester/semantic/methods5_error.txt create mode 100644 src/tester/semantic/methods6.cl create mode 100644 src/tester/semantic/methods6_error.txt create mode 100644 src/tester/semantic/methods7.cl create mode 100644 src/tester/semantic/methods7_error.txt create mode 100644 src/tester/semantic/methods8.cl create mode 100644 src/tester/semantic/methods8_error.txt create mode 100644 src/tester/semantic/new1.cl create mode 100644 src/tester/semantic/new1_error.txt create mode 100644 src/tester/semantic/self1.cl create mode 100644 src/tester/semantic/self1_error.txt create mode 100644 src/tester/semantic/self2.cl create mode 100644 src/tester/semantic/self2_error.txt create mode 100644 src/tester/semantic/self3.cl create mode 100644 src/tester/semantic/self3_error.txt create mode 100644 src/tester/semantic/self4.cl create mode 100644 src/tester/semantic/self4_error.txt create mode 100644 src/tests/codegen/arith.cl create mode 100644 src/tests/codegen/arith_input.txt create mode 100644 src/tests/codegen/arith_output.txt create mode 100644 src/tests/codegen/atoi.cl create mode 100644 src/tests/codegen/atoi_input.txt create mode 100644 src/tests/codegen/atoi_output.txt create mode 100644 src/tests/codegen/book_list.cl create mode 100644 src/tests/codegen/book_list_input.txt create mode 100644 src/tests/codegen/book_list_output.txt create mode 100644 src/tests/codegen/cells.cl create mode 100644 src/tests/codegen/cells_input.txt create mode 100644 src/tests/codegen/cells_output.txt create mode 100644 src/tests/codegen/complex.cl create mode 100644 src/tests/codegen/complex_input.txt create mode 100644 src/tests/codegen/complex_output.txt create mode 100644 src/tests/codegen/fib.cl create mode 100644 src/tests/codegen/fib_input.txt create mode 100644 src/tests/codegen/fib_output.txt create mode 100644 src/tests/codegen/graph.cl create mode 100644 src/tests/codegen/graph_input.txt create mode 100644 src/tests/codegen/graph_output.txt create mode 100644 src/tests/codegen/hairyscary.cl create mode 100644 src/tests/codegen/hairyscary_input.txt create mode 100644 src/tests/codegen/hairyscary_output.txt create mode 100644 src/tests/codegen/hello_world.cl create mode 100644 src/tests/codegen/hello_world_input.txt create mode 100644 src/tests/codegen/hello_world_output.txt create mode 100644 src/tests/codegen/io.cl create mode 100644 src/tests/codegen/io_input.txt create mode 100644 src/tests/codegen/io_output.txt create mode 100644 src/tests/codegen/life.cl create mode 100644 src/tests/codegen/life_input.txt create mode 100644 src/tests/codegen/life_output.txt create mode 100644 src/tests/codegen/list.cl create mode 100644 src/tests/codegen/list_input.txt create mode 100644 src/tests/codegen/list_output.txt create mode 100644 src/tests/codegen/new_complex.cl create mode 100644 src/tests/codegen/new_complex_input.txt create mode 100644 src/tests/codegen/new_complex_output.txt create mode 100644 src/tests/codegen/palindrome.cl create mode 100644 src/tests/codegen/palindrome_input.txt create mode 100644 src/tests/codegen/palindrome_output.txt create mode 100644 src/tests/codegen/primes.cl create mode 100644 src/tests/codegen/primes_input.txt create mode 100644 src/tests/codegen/primes_output.txt create mode 100644 src/tests/codegen/print-cool.cl create mode 100644 src/tests/codegen/print-cool_input.txt create mode 100644 src/tests/codegen/print-cool_output.txt create mode 100644 src/tests/codegen/sort-list.cl create mode 100644 src/tests/codegen/sort-list_input.txt create mode 100644 src/tests/codegen/sort-list_output.txt create mode 100644 src/tests/codegen_test.py create mode 100644 src/tests/conftest.py create mode 100644 src/tests/lexer/comment1.cl create mode 100644 src/tests/lexer/comment1_error.txt create mode 100644 src/tests/lexer/iis1.cl create mode 100644 src/tests/lexer/iis1_error.txt create mode 100644 src/tests/lexer/iis2.cl create mode 100644 src/tests/lexer/iis2_error.txt create mode 100644 src/tests/lexer/iis3.cl create mode 100644 src/tests/lexer/iis3_error.txt create mode 100644 src/tests/lexer/iis4.cl create mode 100644 src/tests/lexer/iis4_error.txt create mode 100644 src/tests/lexer/iis5.cl create mode 100644 src/tests/lexer/iis5_error.txt create mode 100644 src/tests/lexer/iis6.cl create mode 100644 src/tests/lexer/iis6_error.txt create mode 100644 src/tests/lexer/mixed1.cl create mode 100644 src/tests/lexer/mixed1_error.txt create mode 100644 src/tests/lexer/mixed2.cl create mode 100644 src/tests/lexer/mixed2_error.txt create mode 100644 src/tests/lexer/string1.cl create mode 100644 src/tests/lexer/string1_error.txt create mode 100644 src/tests/lexer/string2.cl create mode 100644 src/tests/lexer/string2_error.txt create mode 100644 src/tests/lexer/string3.cl create mode 100644 src/tests/lexer/string3_error.txt create mode 100644 src/tests/lexer/string4.cl create mode 100644 src/tests/lexer/string4_error.txt create mode 100644 src/tests/lexer_test.py create mode 100644 src/tests/parser/assignment1.cl create mode 100644 src/tests/parser/assignment1_error.txt create mode 100644 src/tests/parser/assignment2.cl create mode 100644 src/tests/parser/assignment2_error.txt create mode 100644 src/tests/parser/assignment3.cl create mode 100644 src/tests/parser/assignment3_error.txt create mode 100644 src/tests/parser/attribute1.cl create mode 100644 src/tests/parser/attribute1_error.txt create mode 100644 src/tests/parser/attribute2.cl create mode 100644 src/tests/parser/attribute2_error.txt create mode 100644 src/tests/parser/attribute3.cl create mode 100644 src/tests/parser/attribute3_error.txt create mode 100644 src/tests/parser/block1.cl create mode 100644 src/tests/parser/block1_error.txt create mode 100644 src/tests/parser/block2.cl create mode 100644 src/tests/parser/block2_error.txt create mode 100644 src/tests/parser/block3.cl create mode 100644 src/tests/parser/block3_error.txt create mode 100644 src/tests/parser/block4.cl create mode 100644 src/tests/parser/block4_error.txt create mode 100644 src/tests/parser/case1.cl create mode 100644 src/tests/parser/case1_error.txt create mode 100644 src/tests/parser/case2.cl create mode 100644 src/tests/parser/case2_error.txt create mode 100644 src/tests/parser/case3.cl create mode 100644 src/tests/parser/case3_error.txt create mode 100644 src/tests/parser/case4.cl create mode 100644 src/tests/parser/case4_error.txt create mode 100644 src/tests/parser/case5.cl create mode 100644 src/tests/parser/case5_error.txt create mode 100644 src/tests/parser/case6.cl create mode 100644 src/tests/parser/case6_error.txt create mode 100644 src/tests/parser/class1.cl create mode 100644 src/tests/parser/class1_error.txt create mode 100644 src/tests/parser/class2.cl create mode 100644 src/tests/parser/class2_error.txt create mode 100644 src/tests/parser/class3.cl create mode 100644 src/tests/parser/class3_error.txt create mode 100644 src/tests/parser/class4.cl create mode 100644 src/tests/parser/class4_error.txt create mode 100644 src/tests/parser/class5.cl create mode 100644 src/tests/parser/class5_error.txt create mode 100644 src/tests/parser/class6.cl create mode 100644 src/tests/parser/class6_error.txt create mode 100644 src/tests/parser/conditional1.cl create mode 100644 src/tests/parser/conditional1_error.txt create mode 100644 src/tests/parser/conditional2.cl create mode 100644 src/tests/parser/conditional2_error.txt create mode 100644 src/tests/parser/conditional3.cl create mode 100644 src/tests/parser/conditional3_error.txt create mode 100644 src/tests/parser/conditional4.cl create mode 100644 src/tests/parser/conditional4_error.txt create mode 100644 src/tests/parser/conditional5.cl create mode 100644 src/tests/parser/conditional5_error.txt create mode 100644 src/tests/parser/conditional6.cl create mode 100644 src/tests/parser/conditional6_error.txt create mode 100644 src/tests/parser/dispatch1.cl create mode 100644 src/tests/parser/dispatch1_error.txt create mode 100644 src/tests/parser/dispatch2.cl create mode 100644 src/tests/parser/dispatch2_error.txt create mode 100644 src/tests/parser/dispatch3.cl create mode 100644 src/tests/parser/dispatch3_error.txt create mode 100644 src/tests/parser/dispatch4.cl create mode 100644 src/tests/parser/dispatch4_error.txt create mode 100644 src/tests/parser/dispatch5.cl create mode 100644 src/tests/parser/dispatch5_error.txt create mode 100644 src/tests/parser/dispatch6.cl create mode 100644 src/tests/parser/dispatch6_error.txt create mode 100644 src/tests/parser/dispatch7.cl create mode 100644 src/tests/parser/dispatch7_error.txt create mode 100644 src/tests/parser/dispatch8.cl create mode 100644 src/tests/parser/dispatch8_error.txt create mode 100644 src/tests/parser/dispatch9.cl create mode 100644 src/tests/parser/dispatch9_error.txt create mode 100644 src/tests/parser/let1.cl create mode 100644 src/tests/parser/let1_error.txt create mode 100644 src/tests/parser/let2.cl create mode 100644 src/tests/parser/let2_error.txt create mode 100644 src/tests/parser/let3.cl create mode 100644 src/tests/parser/let3_error.txt create mode 100644 src/tests/parser/let4.cl create mode 100644 src/tests/parser/let4_error.txt create mode 100644 src/tests/parser/let5.cl create mode 100644 src/tests/parser/let5_error.txt create mode 100644 src/tests/parser/let6.cl create mode 100644 src/tests/parser/let6_error.txt create mode 100644 src/tests/parser/let7.cl create mode 100644 src/tests/parser/let7_error.txt create mode 100644 src/tests/parser/loop1.cl create mode 100644 src/tests/parser/loop1_error.txt create mode 100644 src/tests/parser/loop2.cl create mode 100644 src/tests/parser/loop2_error.txt create mode 100644 src/tests/parser/loop3.cl create mode 100644 src/tests/parser/loop3_error.txt create mode 100644 src/tests/parser/loop4.cl create mode 100644 src/tests/parser/loop4_error.txt create mode 100644 src/tests/parser/method1.cl create mode 100644 src/tests/parser/method1_error.txt create mode 100644 src/tests/parser/method2.cl create mode 100644 src/tests/parser/method2_error.txt create mode 100644 src/tests/parser/method3.cl create mode 100644 src/tests/parser/method3_error.txt create mode 100644 src/tests/parser/method4.cl create mode 100644 src/tests/parser/method4_error.txt create mode 100644 src/tests/parser/method5.cl create mode 100644 src/tests/parser/method5_error.txt create mode 100644 src/tests/parser/method6.cl create mode 100644 src/tests/parser/method6_error.txt create mode 100644 src/tests/parser/mixed1.cl create mode 100644 src/tests/parser/mixed1_error.txt create mode 100644 src/tests/parser/mixed2.cl create mode 100644 src/tests/parser/mixed2_error.txt create mode 100644 src/tests/parser/mixed3.cl create mode 100644 src/tests/parser/mixed3_error.txt create mode 100644 src/tests/parser/mixed4.cl create mode 100644 src/tests/parser/mixed4_error.txt create mode 100644 src/tests/parser/mixed5.cl create mode 100644 src/tests/parser/mixed5_error.txt create mode 100644 src/tests/parser/mixed6.cl create mode 100644 src/tests/parser/mixed6_error.txt create mode 100644 src/tests/parser/operation1.cl create mode 100644 src/tests/parser/operation1_error.txt create mode 100644 src/tests/parser/operation2.cl create mode 100644 src/tests/parser/operation2_error.txt create mode 100644 src/tests/parser/operation3.cl create mode 100644 src/tests/parser/operation3_error.txt create mode 100644 src/tests/parser/operation4.cl create mode 100644 src/tests/parser/operation4_error.txt create mode 100644 src/tests/parser/program1.cl create mode 100644 src/tests/parser/program1_error.txt create mode 100644 src/tests/parser/program2.cl create mode 100644 src/tests/parser/program2_error.txt create mode 100644 src/tests/parser/program3.cl create mode 100644 src/tests/parser/program3_error.txt create mode 100644 src/tests/parser_test.py create mode 100644 src/tests/semantic/arithmetic1.cl create mode 100644 src/tests/semantic/arithmetic10.cl create mode 100644 src/tests/semantic/arithmetic10_error.txt create mode 100644 src/tests/semantic/arithmetic11.cl create mode 100644 src/tests/semantic/arithmetic11_error.txt create mode 100644 src/tests/semantic/arithmetic12.cl create mode 100644 src/tests/semantic/arithmetic12_error.txt create mode 100644 src/tests/semantic/arithmetic1_error.txt create mode 100644 src/tests/semantic/arithmetic2.cl create mode 100644 src/tests/semantic/arithmetic2_error.txt create mode 100644 src/tests/semantic/arithmetic3.cl create mode 100644 src/tests/semantic/arithmetic3_error.txt create mode 100644 src/tests/semantic/arithmetic4.cl create mode 100644 src/tests/semantic/arithmetic4_error.txt create mode 100644 src/tests/semantic/arithmetic5.cl create mode 100644 src/tests/semantic/arithmetic5_error.txt create mode 100644 src/tests/semantic/arithmetic6.cl create mode 100644 src/tests/semantic/arithmetic6_error.txt create mode 100644 src/tests/semantic/arithmetic7.cl create mode 100644 src/tests/semantic/arithmetic7_error.txt create mode 100644 src/tests/semantic/arithmetic8.cl create mode 100644 src/tests/semantic/arithmetic8_error.txt create mode 100644 src/tests/semantic/arithmetic9.cl create mode 100644 src/tests/semantic/arithmetic9_error.txt create mode 100644 src/tests/semantic/assignment1.cl create mode 100644 src/tests/semantic/assignment1_error.txt create mode 100644 src/tests/semantic/assignment2.cl create mode 100644 src/tests/semantic/assignment2_error.txt create mode 100644 src/tests/semantic/assignment3.cl create mode 100644 src/tests/semantic/assignment3_error.txt create mode 100644 src/tests/semantic/attributes1.cl create mode 100644 src/tests/semantic/attributes1_error.txt create mode 100644 src/tests/semantic/attributes2.cl create mode 100644 src/tests/semantic/attributes2_error.txt create mode 100644 src/tests/semantic/attributes3.cl create mode 100644 src/tests/semantic/attributes3_error.txt create mode 100644 src/tests/semantic/attributes4.cl create mode 100644 src/tests/semantic/attributes4_error.txt create mode 100644 src/tests/semantic/basics1.cl create mode 100644 src/tests/semantic/basics1_error.txt create mode 100644 src/tests/semantic/basics2.cl create mode 100644 src/tests/semantic/basics2_error.txt create mode 100644 src/tests/semantic/basics3.cl create mode 100644 src/tests/semantic/basics3_error.txt create mode 100644 src/tests/semantic/basics4.cl create mode 100644 src/tests/semantic/basics4_error.txt create mode 100644 src/tests/semantic/basics5.cl create mode 100644 src/tests/semantic/basics5_error.txt create mode 100644 src/tests/semantic/basics6.cl create mode 100644 src/tests/semantic/basics6_error.txt create mode 100644 src/tests/semantic/basics7.cl create mode 100644 src/tests/semantic/basics7_error.txt create mode 100644 src/tests/semantic/basics8.cl create mode 100644 src/tests/semantic/basics8_error.txt create mode 100644 src/tests/semantic/blocks1.cl create mode 100644 src/tests/semantic/blocks1_error.txt create mode 100644 src/tests/semantic/case1.cl create mode 100644 src/tests/semantic/case1_error.txt create mode 100644 src/tests/semantic/case2.cl create mode 100644 src/tests/semantic/case2_error.txt create mode 100644 src/tests/semantic/case3.cl create mode 100644 src/tests/semantic/case3_error.txt create mode 100644 src/tests/semantic/class1.cl create mode 100644 src/tests/semantic/class1_error.txt create mode 100644 src/tests/semantic/conditionals1.cl create mode 100644 src/tests/semantic/conditionals1_error.txt create mode 100644 src/tests/semantic/conditionals2.cl create mode 100644 src/tests/semantic/conditionals2_error.txt create mode 100644 src/tests/semantic/dispatch1.cl create mode 100644 src/tests/semantic/dispatch1_error.txt create mode 100644 src/tests/semantic/dispatch2.cl create mode 100644 src/tests/semantic/dispatch2_error.txt create mode 100644 src/tests/semantic/dispatch3.cl create mode 100644 src/tests/semantic/dispatch3_error.txt create mode 100644 src/tests/semantic/dispatch4.cl create mode 100644 src/tests/semantic/dispatch4_error.txt create mode 100644 src/tests/semantic/dispatch5.cl create mode 100644 src/tests/semantic/dispatch5_error.txt create mode 100644 src/tests/semantic/dispatch6.cl create mode 100644 src/tests/semantic/dispatch6_error.txt create mode 100644 src/tests/semantic/eq1.cl create mode 100644 src/tests/semantic/eq1_error.txt create mode 100644 src/tests/semantic/eq2.cl create mode 100644 src/tests/semantic/eq2_error.txt create mode 100644 src/tests/semantic/eq3.cl create mode 100644 src/tests/semantic/eq3_error.txt create mode 100644 src/tests/semantic/eq4.cl create mode 100644 src/tests/semantic/eq4_error.txt create mode 100644 src/tests/semantic/features1.cl create mode 100644 src/tests/semantic/features1_error.txt create mode 100644 src/tests/semantic/features2.cl create mode 100644 src/tests/semantic/features2_error.txt create mode 100644 src/tests/semantic/features3.cl create mode 100644 src/tests/semantic/features3_error.txt create mode 100644 src/tests/semantic/inheritance1.cl create mode 100644 src/tests/semantic/inheritance1_error.txt create mode 100644 src/tests/semantic/inheritance2.cl create mode 100644 src/tests/semantic/inheritance2_error.txt create mode 100644 src/tests/semantic/inheritance3.cl create mode 100644 src/tests/semantic/inheritance3_error.txt create mode 100644 src/tests/semantic/inheritance4.cl create mode 100644 src/tests/semantic/inheritance4_error.txt create mode 100644 src/tests/semantic/inheritance5.cl create mode 100644 src/tests/semantic/inheritance5_error.txt create mode 100644 src/tests/semantic/isvoid1.cl create mode 100644 src/tests/semantic/isvoid1_error.txt create mode 100644 src/tests/semantic/let1.cl create mode 100644 src/tests/semantic/let1_error.txt create mode 100644 src/tests/semantic/let2.cl create mode 100644 src/tests/semantic/let2_error.txt create mode 100644 src/tests/semantic/let3.cl create mode 100644 src/tests/semantic/let3_error.txt create mode 100644 src/tests/semantic/loops1.cl create mode 100644 src/tests/semantic/loops1_error.txt create mode 100644 src/tests/semantic/loops2.cl create mode 100644 src/tests/semantic/loops2_error.txt create mode 100644 src/tests/semantic/methods1.cl create mode 100644 src/tests/semantic/methods1_error.txt create mode 100644 src/tests/semantic/methods2.cl create mode 100644 src/tests/semantic/methods2_error.txt create mode 100644 src/tests/semantic/methods3.cl create mode 100644 src/tests/semantic/methods3_error.txt create mode 100644 src/tests/semantic/methods4.cl create mode 100644 src/tests/semantic/methods4_error.txt create mode 100644 src/tests/semantic/methods5.cl create mode 100644 src/tests/semantic/methods5_error.txt create mode 100644 src/tests/semantic/methods6.cl create mode 100644 src/tests/semantic/methods6_error.txt create mode 100644 src/tests/semantic/methods7.cl create mode 100644 src/tests/semantic/methods7_error.txt create mode 100644 src/tests/semantic/methods8.cl create mode 100644 src/tests/semantic/methods8_error.txt create mode 100644 src/tests/semantic/new1.cl create mode 100644 src/tests/semantic/new1_error.txt create mode 100644 src/tests/semantic/self1.cl create mode 100644 src/tests/semantic/self1_error.txt create mode 100644 src/tests/semantic/self2.cl create mode 100644 src/tests/semantic/self2_error.txt create mode 100644 src/tests/semantic/self3.cl create mode 100644 src/tests/semantic/self3_error.txt create mode 100644 src/tests/semantic/self4.cl create mode 100644 src/tests/semantic/self4_error.txt create mode 100644 src/tests/semantic_test.py create mode 100644 src/tests/utils/__init__.py create mode 100644 src/tests/utils/utils.py create mode 100644 src/utils/print_code.py create mode 100644 src/utils/semantic_check/type_inference.py diff --git a/requirements.txt b/requirements.txt index 9eb0cad1a..46208609f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ pytest -pytest-ordering +pytest-ordering \ No newline at end of file diff --git a/src/.vscode/launch.json b/src/.vscode/launch.json new file mode 100644 index 000000000..0ddbd8f8b --- /dev/null +++ b/src/.vscode/launch.json @@ -0,0 +1,30 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Current File", + "type": "python", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal" + }, + { + "name": "Python: Remote Attach", + "type": "python", + "request": "attach", + "connect": { + "host": "localhost", + "port": 5678 + }, + "pathMappings": [ + { + "localRoot": "${workspaceFolder}", + "remoteRoot": "." + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main.py b/src/main.py index 77550ed4c..7b8464413 100644 --- a/src/main.py +++ b/src/main.py @@ -1,4 +1,5 @@ import argparse +import os from utils.COOL_Grammar import build_COOL_Grammar from utils.COOL_Lexer import COOL_Lexer from utils.parser.COOL_parser import COOL_Parser @@ -8,10 +9,13 @@ from utils.semantic_check.type_builder import TypeBuilder from utils.semantic_check.type_checker import TypeChecker +a = 'arithmetic1.cl' + def main(args): try: - with open(args.file, 'r') as file: + #with open(args.file, 'r') as file: + with open(os.getcwd() + '/tester/semantic/' + args, 'r') as file: code = file.read() except: print(f"(0,0) - CompilerError: file {args.file} not found") @@ -26,7 +30,7 @@ def main(args): if lexer.errors: for error in lexer.errors: print(error) - exit(1) + raise Exception() # parser parser = COOL_Parser(G) @@ -56,10 +60,12 @@ def main(args): print(error) exit(1) -if __name__ == "__main__": +# if __name__ == "__main__": + +# parser = argparse.ArgumentParser(description='description') +# parser.add_argument('-f', '--file', type=str, default='', help='file to read') - parser = argparse.ArgumentParser(description='description') - parser.add_argument('-f', '--file', type=str, default='', help='file to read') +# args = parser.parse_args() +# main(args) - args = parser.parse_args() - main(args) \ No newline at end of file +main('dispatch1.cl') \ No newline at end of file diff --git a/src/tester/01_program.cl b/src/tester/01_program.cl new file mode 100644 index 000000000..ba0d51f47 --- /dev/null +++ b/src/tester/01_program.cl @@ -0,0 +1,16 @@ +class Main { + main (): Object { + 0 + }; +}; + +class Point { + x: AUTO_TYPE; + y: AUTO_TYPE; + + init(x0: Int, y0: Int): AUTO_TYPE {{ + x <- x0; + y <- y0; + self; + }}; +}; \ No newline at end of file diff --git a/src/tester/02_program.cl b/src/tester/02_program.cl new file mode 100644 index 000000000..553bb606a --- /dev/null +++ b/src/tester/02_program.cl @@ -0,0 +1,15 @@ +class Main { + main (): Object { + 0 + }; +}; + +class Ackermann { + ackermann(m: AUTO_TYPE, n: AUTO_TYPE): AUTO_TYPE { + if m = 0 then n + 1 else + if n = 0 then ackermann(m - 1, 1) else + ackermann(m - 1, ackermann(m, n - 1)) + fi + fi + }; +}; \ No newline at end of file diff --git a/src/tester/03_program.cl b/src/tester/03_program.cl new file mode 100644 index 000000000..0f74ed244 --- /dev/null +++ b/src/tester/03_program.cl @@ -0,0 +1,17 @@ +class Main { + main (): Object { + 0 + }; + + f(a: AUTO_TYPE, b: AUTO_TYPE): AUTO_TYPE { + if a = 1 then b else + g(a + 1, b / 1) + fi + }; + + g(a: AUTO_TYPE, b: AUTO_TYPE): AUTO_TYPE { + if b = 1 then a else + f(a / 2, b + 1) + fi + }; +}; \ No newline at end of file diff --git a/src/tester/04_program.cl b/src/tester/04_program.cl new file mode 100644 index 000000000..ab46ef273 --- /dev/null +++ b/src/tester/04_program.cl @@ -0,0 +1,16 @@ +class Main { + main (): Object { + 0 + }; +}; + +class Point { + x: Int; + y: Int; + + init(x0: AUTO_TYPE, y0: AUTO_TYPE): AUTO_TYPE {{ + x <- x0; + y <- y0; + self; + }}; +}; \ No newline at end of file diff --git a/src/tester/05_program.cl b/src/tester/05_program.cl new file mode 100644 index 000000000..38339b055 --- /dev/null +++ b/src/tester/05_program.cl @@ -0,0 +1,16 @@ +class Main { + main (): Object { + 0 + }; + + f (a: AUTO_TYPE, b: AUTO_TYPE, c: AUTO_TYPE, d: AUTO_TYPE): AUTO_TYPE { + { + a <- b; + b <- c; + c <- d; + d <- a; + d + 1; + a; + } + }; +}; \ No newline at end of file diff --git a/src/tester/06_program.cl b/src/tester/06_program.cl new file mode 100644 index 000000000..aec900c57 --- /dev/null +++ b/src/tester/06_program.cl @@ -0,0 +1,44 @@ +class Main inherits IO { + main(): IO { + let vector: AUTO_TYPE <- (new Vector2).init(0, 0) in + vector.print_vector() + }; +}; + +class Vector2 { + x: AUTO_TYPE; + y: AUTO_TYPE; + + init(x_: AUTO_TYPE, y_: AUTO_TYPE): AUTO_TYPE {{ + x <- x_; + y <- y_; + self; + }}; + + + get_x(): AUTO_TYPE { + x + }; + + get_y(): AUTO_TYPE { + y + }; + + add(v: Vector2): AUTO_TYPE { + (new Vector2).init(x + v.get_x(), y + v.get_y()) + }; + + print_vector(): AUTO_TYPE { + let io: IO <- new IO in { + io.out_string("("); + io.out_int(get_x()); + io.out_string("; "); + io.out_int(get_y()); + io.out_string(")\n"); + } + }; + + clone_vector(): AUTO_TYPE { + (new Vector2).init(x, y) + }; +}; \ No newline at end of file diff --git a/src/tester/07_program.cl b/src/tester/07_program.cl new file mode 100644 index 000000000..81a2c38cd --- /dev/null +++ b/src/tester/07_program.cl @@ -0,0 +1,19 @@ +(* This program prints the first 10 numbers of fibonacci *) +class Main { + + main(): Object { + let total: AUTO_TYPE <- 10, + i: AUTO_TYPE <- 1 , + io: AUTO_TYPE <- new IO in + while i <= total loop { + io.out_int(fibonacci(i)); + io.out_string("\n"); + i <- i + 1; + } + pool + }; + + fibonacci (n: AUTO_TYPE): AUTO_TYPE { + if n <= 2 then 1 else fibonacci(n - 1) + fibonacci(n - 2) fi + }; +}; \ No newline at end of file diff --git a/src/tester/08_program.cl b/src/tester/08_program.cl new file mode 100644 index 000000000..5a81c0633 --- /dev/null +++ b/src/tester/08_program.cl @@ -0,0 +1,33 @@ +(* Testing IO *) +class Main inherits IO { + + main(): Object { + let id: AUTO_TYPE, name: AUTO_TYPE, email: AUTO_TYPE in { + out_string("Introduzca su id: "); + id <- self.in_int(); + out_string("Introduzca su nombre: "); + name <- self.in_string(); + out_string("Introduzca su email: "); + email <- self.in_string(); + let user: AUTO_TYPE <- (new User).init(id, name, email) in + out_string("Created user: ".concat(user.get_name()).concat("\n")); + } + }; +}; + +class User { + id: AUTO_TYPE; + name: AUTO_TYPE; + email: AUTO_TYPE; + + init(id_: AUTO_TYPE, name_: AUTO_TYPE, email_: AUTO_TYPE): AUTO_TYPE {{ + id <- id_; + name <- name_; + email <- email_; + self; + }}; + + get_name(): AUTO_TYPE { + name + }; +}; \ No newline at end of file diff --git a/src/tester/inference/01_program.cl b/src/tester/inference/01_program.cl new file mode 100644 index 000000000..ba0d51f47 --- /dev/null +++ b/src/tester/inference/01_program.cl @@ -0,0 +1,16 @@ +class Main { + main (): Object { + 0 + }; +}; + +class Point { + x: AUTO_TYPE; + y: AUTO_TYPE; + + init(x0: Int, y0: Int): AUTO_TYPE {{ + x <- x0; + y <- y0; + self; + }}; +}; \ No newline at end of file diff --git a/src/tester/inference/02_program.cl b/src/tester/inference/02_program.cl new file mode 100644 index 000000000..553bb606a --- /dev/null +++ b/src/tester/inference/02_program.cl @@ -0,0 +1,15 @@ +class Main { + main (): Object { + 0 + }; +}; + +class Ackermann { + ackermann(m: AUTO_TYPE, n: AUTO_TYPE): AUTO_TYPE { + if m = 0 then n + 1 else + if n = 0 then ackermann(m - 1, 1) else + ackermann(m - 1, ackermann(m, n - 1)) + fi + fi + }; +}; \ No newline at end of file diff --git a/src/tester/inference/03_program.cl b/src/tester/inference/03_program.cl new file mode 100644 index 000000000..0f74ed244 --- /dev/null +++ b/src/tester/inference/03_program.cl @@ -0,0 +1,17 @@ +class Main { + main (): Object { + 0 + }; + + f(a: AUTO_TYPE, b: AUTO_TYPE): AUTO_TYPE { + if a = 1 then b else + g(a + 1, b / 1) + fi + }; + + g(a: AUTO_TYPE, b: AUTO_TYPE): AUTO_TYPE { + if b = 1 then a else + f(a / 2, b + 1) + fi + }; +}; \ No newline at end of file diff --git a/src/tester/inference/04_program.cl b/src/tester/inference/04_program.cl new file mode 100644 index 000000000..ab46ef273 --- /dev/null +++ b/src/tester/inference/04_program.cl @@ -0,0 +1,16 @@ +class Main { + main (): Object { + 0 + }; +}; + +class Point { + x: Int; + y: Int; + + init(x0: AUTO_TYPE, y0: AUTO_TYPE): AUTO_TYPE {{ + x <- x0; + y <- y0; + self; + }}; +}; \ No newline at end of file diff --git a/src/tester/inference/05_program.cl b/src/tester/inference/05_program.cl new file mode 100644 index 000000000..38339b055 --- /dev/null +++ b/src/tester/inference/05_program.cl @@ -0,0 +1,16 @@ +class Main { + main (): Object { + 0 + }; + + f (a: AUTO_TYPE, b: AUTO_TYPE, c: AUTO_TYPE, d: AUTO_TYPE): AUTO_TYPE { + { + a <- b; + b <- c; + c <- d; + d <- a; + d + 1; + a; + } + }; +}; \ No newline at end of file diff --git a/src/tester/inference/06_program.cl b/src/tester/inference/06_program.cl new file mode 100644 index 000000000..aec900c57 --- /dev/null +++ b/src/tester/inference/06_program.cl @@ -0,0 +1,44 @@ +class Main inherits IO { + main(): IO { + let vector: AUTO_TYPE <- (new Vector2).init(0, 0) in + vector.print_vector() + }; +}; + +class Vector2 { + x: AUTO_TYPE; + y: AUTO_TYPE; + + init(x_: AUTO_TYPE, y_: AUTO_TYPE): AUTO_TYPE {{ + x <- x_; + y <- y_; + self; + }}; + + + get_x(): AUTO_TYPE { + x + }; + + get_y(): AUTO_TYPE { + y + }; + + add(v: Vector2): AUTO_TYPE { + (new Vector2).init(x + v.get_x(), y + v.get_y()) + }; + + print_vector(): AUTO_TYPE { + let io: IO <- new IO in { + io.out_string("("); + io.out_int(get_x()); + io.out_string("; "); + io.out_int(get_y()); + io.out_string(")\n"); + } + }; + + clone_vector(): AUTO_TYPE { + (new Vector2).init(x, y) + }; +}; \ No newline at end of file diff --git a/src/tester/inference/07_program.cl b/src/tester/inference/07_program.cl new file mode 100644 index 000000000..81a2c38cd --- /dev/null +++ b/src/tester/inference/07_program.cl @@ -0,0 +1,19 @@ +(* This program prints the first 10 numbers of fibonacci *) +class Main { + + main(): Object { + let total: AUTO_TYPE <- 10, + i: AUTO_TYPE <- 1 , + io: AUTO_TYPE <- new IO in + while i <= total loop { + io.out_int(fibonacci(i)); + io.out_string("\n"); + i <- i + 1; + } + pool + }; + + fibonacci (n: AUTO_TYPE): AUTO_TYPE { + if n <= 2 then 1 else fibonacci(n - 1) + fibonacci(n - 2) fi + }; +}; \ No newline at end of file diff --git a/src/tester/inference/08_program.cl b/src/tester/inference/08_program.cl new file mode 100644 index 000000000..5a81c0633 --- /dev/null +++ b/src/tester/inference/08_program.cl @@ -0,0 +1,33 @@ +(* Testing IO *) +class Main inherits IO { + + main(): Object { + let id: AUTO_TYPE, name: AUTO_TYPE, email: AUTO_TYPE in { + out_string("Introduzca su id: "); + id <- self.in_int(); + out_string("Introduzca su nombre: "); + name <- self.in_string(); + out_string("Introduzca su email: "); + email <- self.in_string(); + let user: AUTO_TYPE <- (new User).init(id, name, email) in + out_string("Created user: ".concat(user.get_name()).concat("\n")); + } + }; +}; + +class User { + id: AUTO_TYPE; + name: AUTO_TYPE; + email: AUTO_TYPE; + + init(id_: AUTO_TYPE, name_: AUTO_TYPE, email_: AUTO_TYPE): AUTO_TYPE {{ + id <- id_; + name <- name_; + email <- email_; + self; + }}; + + get_name(): AUTO_TYPE { + name + }; +}; \ No newline at end of file diff --git a/src/tester/lexer/comment1.cl b/src/tester/lexer/comment1.cl new file mode 100644 index 000000000..c2bb9938c --- /dev/null +++ b/src/tester/lexer/comment1.cl @@ -0,0 +1,55 @@ +--Any characters between two dashes "--" and the next newline +--(or EOF, if there is no next newline) are treated as comments + +(*(*(* +Comments may also be written by enclosing +text in (∗ . . . ∗). The latter form of comment may be nested. +Comments cannot cross file boundaries. +*)*)*) + +class Error() { + + (* There was once a comment, + that was quite long. + But, the reader soon discovered that + the comment was indeed longer than + previously assumed. Now, the reader + was in a real dilemma; is the comment + ever gonna end? If I stop reading, will + it end? + He started imagining all sorts of things. + He thought about heisenberg's cat and how + how that relates to the end of the sentence. + He thought to himself "I'm gonna stop reading". + "If I keep reading this comment, I'm gonna know + the fate of this sentence; That will be disastorous." + He knew that such a comment was gonna extend to + another file. It was too awesome to be contained in + a single file. And he would have kept reading too... + if only... + cool wasn't a super-duper-fab-awesomest language; + but cool is that language; + "This comment shall go not cross this file" said cool. + Alas! The reader could read no more. + There was once a comment, + that was quite long. + But, the reader soon discovered that + the comment was indeed longer than + previously assumed. Now, the reader + was in a real dilemma; is the comment + ever gonna end? If I stop reading, will + it end? + He started imagining all sorts of things. + He thought about heisenberg's cat and how + how that relates to the end of the sentence. + He thought to himself "I'm gonna stop reading". + "If I keep reading this comment, I'm gonna know + the fate of this sentence; That will be disastorous." + He knew that such a comment was gonna extend to + another file. It was too awesome to be contained in + a single file. And he would have kept reading too... + if only... + cool wasn't a super-duper-fab-awesomest language; + but cool is that language; + "This comment shall go not cross this file" said cool. + Alas! The reader could read no more. \ No newline at end of file diff --git a/src/tester/lexer/iis1.cl b/src/tester/lexer/iis1.cl new file mode 100644 index 000000000..12cb52beb --- /dev/null +++ b/src/tester/lexer/iis1.cl @@ -0,0 +1,111 @@ +(* Integers, Identifiers, and Special Notation *) + +0007 123 +1 -1 +90 -09 +11113 -4r *a *self* c++ +5! = 120, 2 + 2 = 5 or E = mc2; p + 1 @ p = 1: for x in range(len(b)) +new / <- <<==> {( Int: Objet, Bool; String.string SELF_TYPE isvoid }) +class Class if then else fi testing Testing ~007agent_bond james_007B0N3SS___ +loop pool while tRuE or noT faLsE let in case of ESAC + +(* +#3 INT_CONST 0007 +#3 INT_CONST 123 +#3 '+' +#3 INT_CONST 1 +#3 '-' +#3 INT_CONST 1 +#3 '+' +#3 INT_CONST 90 +#3 '-' +#3 INT_CONST 09 +#3 '+' +#3 INT_CONST 11113 +#3 '-' +#3 INT_CONST 4 +#3 OBJECTID r +#3 '*' +#3 OBJECTID a +#3 '*' +#3 OBJECTID self +#3 '*' +#3 OBJECTID c +#3 '+' +#3 '+' +#4 INT_CONST 5 +#4 ERROR "!" +#4 '=' +#4 INT_CONST 120 +#4 ',' +#4 INT_CONST 2 +#4 '+' +#4 INT_CONST 2 +#4 '=' +#4 INT_CONST 5 +#4 OBJECTID or +#4 TYPEID E +#4 '=' +#4 OBJECTID mc2 +#4 ';' +#4 OBJECTID p +#4 '+' +#4 INT_CONST 1 +#4 '@' +#4 OBJECTID p +#4 '=' +#4 INT_CONST 1 +#4 ':' +#4 OBJECTID for +#4 OBJECTID x +#4 IN +#4 OBJECTID range +#4 '(' +#4 OBJECTID len +#4 '(' +#4 OBJECTID b +#4 ')' +#4 ')' +#5 NEW +#5 '/' +#5 ASSIGN +#5 '<' +#5 LE +#5 DARROW +#5 '{' +#5 '(' +#5 TYPEID Int +#5 ':' +#5 TYPEID Objet +#5 ',' +#5 TYPEID Bool +#5 ';' +#5 TYPEID String +#5 '.' +#5 OBJECTID string +#5 TYPEID SELF_TYPE +#5 ISVOID +#5 '}' +#5 ')' +#6 CLASS +#6 CLASS +#6 IF +#6 THEN +#6 ELSE +#6 FI +#6 OBJECTID testing +#6 TYPEID Testing +#6 '~' +#6 INT_CONST 007 +#6 OBJECTID agent_bond +#6 OBJECTID james_007B0N3SS___ +#7 LOOP +#7 POOL +#7 WHILE +#7 BOOL_CONST true +#7 OBJECTID or +#7 NOT +#7 BOOL_CONST false +#7 LET +#7 IN +#7 CASE +#7 OF +#7 ESAC +*) \ No newline at end of file diff --git a/src/tester/lexer/iis2.cl b/src/tester/lexer/iis2.cl new file mode 100644 index 000000000..9b25715d4 --- /dev/null +++ b/src/tester/lexer/iis2.cl @@ -0,0 +1,120 @@ +(* Integers, Identifiers, and Special Notation *) + +0007 123 +1 -1 +90 -09 +11113 -4r *a *self* c++ +class Class if then else fi testing Testing ~007agent_bond james_007bones___ + + +new / <- <<==> {( Int: Objet, Bool; String.string SELF_TYPE isvoid }) +loop pool while tRuE or noT faLsE let in case of ESAC + +factorial(5) = 120, 2 + 2 = 5? or E = mc2; p + 1 resto p = 1: (@ for x in range(len(b))) + +(* +#3 INT_CONST 0007 +#3 INT_CONST 123 +#3 '+' +#3 INT_CONST 1 +#3 '-' +#3 INT_CONST 1 +#3 '+' +#3 INT_CONST 90 +#3 '-' +#3 INT_CONST 09 +#3 '+' +#3 INT_CONST 11113 +#3 '-' +#3 INT_CONST 4 +#3 OBJECTID r +#3 '*' +#3 OBJECTID a +#3 '*' +#3 OBJECTID self +#3 '*' +#3 OBJECTID c +#3 '+' +#3 '+' +#4 CLASS +#4 CLASS +#4 IF +#4 THEN +#4 ELSE +#4 FI +#4 OBJECTID testing +#4 TYPEID Testing +#4 '~' +#4 INT_CONST 007 +#4 OBJECTID agent_bond +#4 OBJECTID james_007bones___ +#7 NEW +#7 '/' +#7 ASSIGN +#7 '<' +#7 LE +#7 DARROW +#7 '{' +#7 '(' +#7 TYPEID Int +#7 ':' +#7 TYPEID Objet +#7 ',' +#7 TYPEID Bool +#7 ';' +#7 TYPEID String +#7 '.' +#7 OBJECTID string +#7 TYPEID SELF_TYPE +#7 ISVOID +#7 '}' +#7 ')' +#8 LOOP +#8 POOL +#8 WHILE +#8 BOOL_CONST true +#8 OBJECTID or +#8 NOT +#8 BOOL_CONST false +#8 LET +#8 IN +#8 CASE +#8 OF +#8 ESAC +#10 OBJECTID factorial +#10 '(' +#10 INT_CONST 5 +#10 ')' +#10 '=' +#10 INT_CONST 120 +#10 ',' +#10 INT_CONST 2 +#10 '+' +#10 INT_CONST 2 +#10 '=' +#10 INT_CONST 5 +#10 ERROR "?" +#10 OBJECTID or +#10 TYPEID E +#10 '=' +#10 OBJECTID mc2 +#10 ';' +#10 OBJECTID p +#10 '+' +#10 INT_CONST 1 +#10 OBJECTID resto +#10 OBJECTID p +#10 '=' +#10 INT_CONST 1 +#10 ':' +#10 '(' +#10 '@' +#10 OBJECTID for +#10 OBJECTID x +#10 IN +#10 OBJECTID range +#10 '(' +#10 OBJECTID len +#10 '(' +#10 OBJECTID b +#10 ')' +#10 ')' +#10 ')' +*) \ No newline at end of file diff --git a/src/tester/lexer/iis3.cl b/src/tester/lexer/iis3.cl new file mode 100644 index 000000000..0b965ddea --- /dev/null +++ b/src/tester/lexer/iis3.cl @@ -0,0 +1,121 @@ +(* Integers, Identifiers, and Special Notation *) + +factorial(5) = 120, 2 + 2 = 5 or E = mc^2; p + 1 @ p = 1: z for x in range(len(b))) + +loop pool while tRuE or noT faLsE let in case of ESAC + +new / <- <<==> {( Int: Objet, Bool; String.string SELF_TYPE isvoid }) + + +0007 123 +1 -1 +90 -09 +11113 -4r *a *self* c++ +class Class if then else fi testing Testing ~007agent_bond james_007bones___ + +(* +#3 OBJECTID factorial +#3 '(' +#3 INT_CONST 5 +#3 ')' +#3 '=' +#3 INT_CONST 120 +#3 ',' +#3 INT_CONST 2 +#3 '+' +#3 INT_CONST 2 +#3 '=' +#3 INT_CONST 5 +#3 OBJECTID or +#3 TYPEID E +#3 '=' +#3 OBJECTID mc +#3 ERROR "^" +#3 INT_CONST 2 +#3 ';' +#3 OBJECTID p +#3 '+' +#3 INT_CONST 1 +#3 '@' +#3 OBJECTID p +#3 '=' +#3 INT_CONST 1 +#3 ':' +#3 OBJECTID z +#3 OBJECTID for +#3 OBJECTID x +#3 IN +#3 OBJECTID range +#3 '(' +#3 OBJECTID len +#3 '(' +#3 OBJECTID b +#3 ')' +#3 ')' +#3 ')' +#5 LOOP +#5 POOL +#5 WHILE +#5 BOOL_CONST true +#5 OBJECTID or +#5 NOT +#5 BOOL_CONST false +#5 LET +#5 IN +#5 CASE +#5 OF +#5 ESAC +#7 NEW +#7 '/' +#7 ASSIGN +#7 '<' +#7 LE +#7 DARROW +#7 '{' +#7 '(' +#7 TYPEID Int +#7 ':' +#7 TYPEID Objet +#7 ',' +#7 TYPEID Bool +#7 ';' +#7 TYPEID String +#7 '.' +#7 OBJECTID string +#7 TYPEID SELF_TYPE +#7 ISVOID +#7 '}' +#7 ')' +#10 INT_CONST 0007 +#10 INT_CONST 123 +#10 '+' +#10 INT_CONST 1 +#10 '-' +#10 INT_CONST 1 +#10 '+' +#10 INT_CONST 90 +#10 '-' +#10 INT_CONST 09 +#10 '+' +#10 INT_CONST 11113 +#10 '-' +#10 INT_CONST 4 +#10 OBJECTID r +#10 '*' +#10 OBJECTID a +#10 '*' +#10 OBJECTID self +#10 '*' +#10 OBJECTID c +#10 '+' +#10 '+' +#11 CLASS +#11 CLASS +#11 IF +#11 THEN +#11 ELSE +#11 FI +#11 OBJECTID testing +#11 TYPEID Testing +#11 '~' +#11 INT_CONST 007 +#11 OBJECTID agent_bond +#11 OBJECTID james_007bones___ +*) \ No newline at end of file diff --git a/src/tester/lexer/iis4.cl b/src/tester/lexer/iis4.cl new file mode 100644 index 000000000..9e7a9cb62 --- /dev/null +++ b/src/tester/lexer/iis4.cl @@ -0,0 +1,120 @@ +(* Integers, Identifiers, and Special Notation *) + +new / <- <<==> {( Int: Objet, Bool; String.string SELF_TYPE isvoid }) +0007 123 +1 -1 +90 -09 +11113 -4r *a *self* c++ + +factorial(5) = 120, 2 + 2 = 5 or E = mc2; p + 1 % p = 1: @.@ for x in range(len(b))~ + + +loop pool while tRuE or noT faLsE let in case of ESAC +class Class if then else fi testing Testing ~007agent_bond james_007bones___ + +(* +#3 NEW +#3 '/' +#3 ASSIGN +#3 '<' +#3 LE +#3 DARROW +#3 '{' +#3 '(' +#3 TYPEID Int +#3 ':' +#3 TYPEID Objet +#3 ',' +#3 TYPEID Bool +#3 ';' +#3 TYPEID String +#3 '.' +#3 OBJECTID string +#3 TYPEID SELF_TYPE +#3 ISVOID +#3 '}' +#3 ')' +#4 INT_CONST 0007 +#4 INT_CONST 123 +#4 '+' +#4 INT_CONST 1 +#4 '-' +#4 INT_CONST 1 +#4 '+' +#4 INT_CONST 90 +#4 '-' +#4 INT_CONST 09 +#4 '+' +#4 INT_CONST 11113 +#4 '-' +#4 INT_CONST 4 +#4 OBJECTID r +#4 '*' +#4 OBJECTID a +#4 '*' +#4 OBJECTID self +#4 '*' +#4 OBJECTID c +#4 '+' +#4 '+' +#6 OBJECTID factorial +#6 '(' +#6 INT_CONST 5 +#6 ')' +#6 '=' +#6 INT_CONST 120 +#6 ',' +#6 INT_CONST 2 +#6 '+' +#6 INT_CONST 2 +#6 '=' +#6 INT_CONST 5 +#6 OBJECTID or +#6 TYPEID E +#6 '=' +#6 OBJECTID mc2 +#6 ';' +#6 OBJECTID p +#6 '+' +#6 INT_CONST 1 +#6 ERROR "%" +#6 OBJECTID p +#6 '=' +#6 INT_CONST 1 +#6 ':' +#6 '@' +#6 '.' +#6 '@' +#6 OBJECTID for +#6 OBJECTID x +#6 IN +#6 OBJECTID range +#6 '(' +#6 OBJECTID len +#6 '(' +#6 OBJECTID b +#6 ')' +#6 ')' +#6 '~' +#9 LOOP +#9 POOL +#9 WHILE +#9 BOOL_CONST true +#9 OBJECTID or +#9 NOT +#9 BOOL_CONST false +#9 LET +#9 IN +#9 CASE +#9 OF +#9 ESAC +#10 CLASS +#10 CLASS +#10 IF +#10 THEN +#10 ELSE +#10 FI +#10 OBJECTID testing +#10 TYPEID Testing +#10 '~' +#10 INT_CONST 007 +#10 OBJECTID agent_bond +#10 OBJECTID james_007bones___ +*) \ No newline at end of file diff --git a/src/tester/lexer/iis5.cl b/src/tester/lexer/iis5.cl new file mode 100644 index 000000000..d146c0547 --- /dev/null +++ b/src/tester/lexer/iis5.cl @@ -0,0 +1,121 @@ +(* Integers, Identifiers, and Special Notation *) + + +loop pool while tRuE or noT faLsE let in case of ESAC +new / <- <<==> {( Int: Objet, Bool; String.string SELF_TYPE isvoid }) +class Class if then else fi testing Testing ~007agent_bond james_007bones___ + +factorial(5) = 120, 2 + 2 = 5 or E = mc2; p + 1 resto p = 1: [@.@ for x in range(len(b))] + +0007 123 +1 -1 +90 -09 +11113 -4r *a *self* c++ + +(* +#4 LOOP +#4 POOL +#4 WHILE +#4 BOOL_CONST true +#4 OBJECTID or +#4 NOT +#4 BOOL_CONST false +#4 LET +#4 IN +#4 CASE +#4 OF +#4 ESAC +#5 NEW +#5 '/' +#5 ASSIGN +#5 '<' +#5 LE +#5 DARROW +#5 '{' +#5 '(' +#5 TYPEID Int +#5 ':' +#5 TYPEID Objet +#5 ',' +#5 TYPEID Bool +#5 ';' +#5 TYPEID String +#5 '.' +#5 OBJECTID string +#5 TYPEID SELF_TYPE +#5 ISVOID +#5 '}' +#5 ')' +#6 CLASS +#6 CLASS +#6 IF +#6 THEN +#6 ELSE +#6 FI +#6 OBJECTID testing +#6 TYPEID Testing +#6 '~' +#6 INT_CONST 007 +#6 OBJECTID agent_bond +#6 OBJECTID james_007bones___ +#8 OBJECTID factorial +#8 '(' +#8 INT_CONST 5 +#8 ')' +#8 '=' +#8 INT_CONST 120 +#8 ',' +#8 INT_CONST 2 +#8 '+' +#8 INT_CONST 2 +#8 '=' +#8 INT_CONST 5 +#8 OBJECTID or +#8 TYPEID E +#8 '=' +#8 OBJECTID mc2 +#8 ';' +#8 OBJECTID p +#8 '+' +#8 INT_CONST 1 +#8 OBJECTID resto +#8 OBJECTID p +#8 '=' +#8 INT_CONST 1 +#8 ':' +#8 ERROR "[" +#8 '@' +#8 '.' +#8 '@' +#8 OBJECTID for +#8 OBJECTID x +#8 IN +#8 OBJECTID range +#8 '(' +#8 OBJECTID len +#8 '(' +#8 OBJECTID b +#8 ')' +#8 ')' +#8 ERROR "]" +#10 INT_CONST 0007 +#10 INT_CONST 123 +#10 '+' +#10 INT_CONST 1 +#10 '-' +#10 INT_CONST 1 +#10 '+' +#10 INT_CONST 90 +#10 '-' +#10 INT_CONST 09 +#10 '+' +#10 INT_CONST 11113 +#10 '-' +#10 INT_CONST 4 +#10 OBJECTID r +#10 '*' +#10 OBJECTID a +#10 '*' +#10 OBJECTID self +#10 '*' +#10 OBJECTID c +#10 '+' +#10 '+' +*) diff --git a/src/tester/lexer/iis6.cl b/src/tester/lexer/iis6.cl new file mode 100644 index 000000000..1042f132b --- /dev/null +++ b/src/tester/lexer/iis6.cl @@ -0,0 +1,125 @@ +(* Integers, Identifiers, and Special Notation *) + +factorial(5) = 120, 2 + 2 = 5 or E = mc2; p + 1 resto p = 1: {@.@ for x in range(len(b))} + +new / <- <<==> {( Int: Objet, Bool; String.string SELF_TYPE isvoid }) + + +class Class if then else fi testing Testing ~007agent_bond _james_007bones___ + + + +0007 123 +1 -1 +90 -09 +11113 -4r *a *self* c++ +loop pool while tRuE or noT faLsE let in case of ESAC + +(* +#3 OBJECTID factorial +#3 '(' +#3 INT_CONST 5 +#3 ')' +#3 '=' +#3 INT_CONST 120 +#3 ',' +#3 INT_CONST 2 +#3 '+' +#3 INT_CONST 2 +#3 '=' +#3 INT_CONST 5 +#3 OBJECTID or +#3 TYPEID E +#3 '=' +#3 OBJECTID mc2 +#3 ';' +#3 OBJECTID p +#3 '+' +#3 INT_CONST 1 +#3 OBJECTID resto +#3 OBJECTID p +#3 '=' +#3 INT_CONST 1 +#3 ':' +#3 '{' +#3 '@' +#3 '.' +#3 '@' +#3 OBJECTID for +#3 OBJECTID x +#3 IN +#3 OBJECTID range +#3 '(' +#3 OBJECTID len +#3 '(' +#3 OBJECTID b +#3 ')' +#3 ')' +#3 '}' +#5 NEW +#5 '/' +#5 ASSIGN +#5 '<' +#5 LE +#5 DARROW +#5 '{' +#5 '(' +#5 TYPEID Int +#5 ':' +#5 TYPEID Objet +#5 ',' +#5 TYPEID Bool +#5 ';' +#5 TYPEID String +#5 '.' +#5 OBJECTID string +#5 TYPEID SELF_TYPE +#5 ISVOID +#5 '}' +#5 ')' +#8 CLASS +#8 CLASS +#8 IF +#8 THEN +#8 ELSE +#8 FI +#8 OBJECTID testing +#8 TYPEID Testing +#8 '~' +#8 INT_CONST 007 +#8 OBJECTID agent_bond +#8 ERROR "_" +#8 OBJECTID james_007bones___ +#12 INT_CONST 0007 +#12 INT_CONST 123 +#12 '+' +#12 INT_CONST 1 +#12 '-' +#12 INT_CONST 1 +#12 '+' +#12 INT_CONST 90 +#12 '-' +#12 INT_CONST 09 +#12 '+' +#12 INT_CONST 11113 +#12 '-' +#12 INT_CONST 4 +#12 OBJECTID r +#12 '*' +#12 OBJECTID a +#12 '*' +#12 OBJECTID self +#12 '*' +#12 OBJECTID c +#12 '+' +#12 '+' +#13 LOOP +#13 POOL +#13 WHILE +#13 BOOL_CONST true +#13 OBJECTID or +#13 NOT +#13 BOOL_CONST false +#13 LET +#13 IN +#13 CASE +#13 OF +#13 ESAC +*) \ No newline at end of file diff --git a/src/tester/lexer/mixed1.cl b/src/tester/lexer/mixed1.cl new file mode 100644 index 000000000..803d58ef5 --- /dev/null +++ b/src/tester/lexer/mixed1.cl @@ -0,0 +1,14 @@ +"lkjdsafkljdsalfj\u0000dsafdsaf\u0000djafslkjdsalf\nsdajf\" lkjfdsasdkjfl"123 +adsfasklj# +LKldsajf iNhERITS +"lkdsajf" + +(* +#1 STR_CONST "lkjdsafkljdsalfju0000dsafdsafu0000djafslkjdsalf\nsdajf\" lkjfdsasdkjfl" +#1 INT_CONST 123 +#2 OBJECTID adsfasklj +#2 ERROR "#" +#3 TYPEID LKldsajf +#3 INHERITS +#4 STR_CONST "lkdsajf" +*) \ No newline at end of file diff --git a/src/tester/lexer/mixed2.cl b/src/tester/lexer/mixed2.cl new file mode 100644 index 000000000..12039e123 --- /dev/null +++ b/src/tester/lexer/mixed2.cl @@ -0,0 +1,20 @@ +"kjas\"lnnsdj\nfljrdsaf" +@.$.@ +@*%*@ +"alkjfldajf""dasfadsf + +(* +#1 STR_CONST "kjas\"lnnsdj\nfljrdsaf" +#2 '@' +#2 '.' +#2 ERROR "$" +#2 '.' +#2 '@' +#3 '@' +#3 '*' +#3 ERROR "%" +#3 '*' +#3 '@' +#4 STR_CONST "alkjfldajf" +#4 ERROR "Unterminated string constant" +*) \ No newline at end of file diff --git a/src/tester/lexer/string1.cl b/src/tester/lexer/string1.cl new file mode 100644 index 000000000..6c3c00833 --- /dev/null +++ b/src/tester/lexer/string1.cl @@ -0,0 +1,6 @@ +(* A non-escaped newline character may not appear in a string *) + +"This \ +is OK" +"This is not +OK" \ No newline at end of file diff --git a/src/tester/lexer/string2.cl b/src/tester/lexer/string2.cl new file mode 100644 index 000000000..3704b6ae7 --- /dev/null +++ b/src/tester/lexer/string2.cl @@ -0,0 +1,19 @@ +(* A string may not contain EOF *) + +" May the Triforce \ + 0 \ + 0v0 \ + 0vvv0 \ + 0vvvvv0 \ + 0vvvvvvv0 \ + 0vvvvvvvvv0 \ + 0vvvvvvvvvvv0 \ + 000000000000000 \ + 0v0 0v0 \ + 0vvv0 0vvv0 \ + 0vvvvv0 0vvvvv0 \ + 0vvvvvvv0 0vvvvvvv0 \ + 0vvvvvvvvv0 0vvvvvvvvv0 \ + 0vvvvvvvvvvv0 0vvvvvvvvvvv0 \ + 00000000000000000000000000000 \ + be with you! \ No newline at end of file diff --git a/src/tester/lexer/string3.cl b/src/tester/lexer/string3.cl new file mode 100644 index 0000000000000000000000000000000000000000..78abc4972e218bca373ba1750c99a3450cef4ea3 GIT binary patch literal 234 zcmX|4yAH!34D8HToS2dhRoZ?*=Jpd<90*B>0}_xSe_!a!lI8Q=*(aJadZZi|KVhQ- zK4j?NGc6u@9^rRpGmYcJ^ifl$K@ Mi{IIrdU_-I0>Lp*mH+?% literal 0 HcmV?d00001 diff --git a/src/tester/lexer/string4.cl b/src/tester/lexer/string4.cl new file mode 100644 index 000000000..f4d39c027 --- /dev/null +++ b/src/tester/lexer/string4.cl @@ -0,0 +1,38 @@ +class Main { + str <- "The big brown fox + jumped over the fence"; + main() : Object { + { + out_string("Yay! This is the newest shites ); + } + }; +}; + +(* +#1 CLASS +#1 TYPEID Main +#1 '{' +#2 OBJECTID str +#2 ASSIGN +#3 ERROR "Unterminated string constant" +#3 OBJECTID jumped +#3 OBJECTID over +#3 OBJECTID the +#3 OBJECTID fence +#4 ERROR "Unterminated string constant" +#4 OBJECTID main +#4 '(' +#4 ')' +#4 ':' +#4 TYPEID Object +#4 '{' +#5 '{' +#6 OBJECTID out_string +#6 '(' +#7 ERROR "Unterminated string constant" +#7 '}' +#8 '}' +#8 ';' +#9 '}' +#9 ';' +*) \ No newline at end of file diff --git a/src/tester/parser/assignment1.cl b/src/tester/parser/assignment1.cl new file mode 100644 index 000000000..75b4c5bbd --- /dev/null +++ b/src/tester/parser/assignment1.cl @@ -0,0 +1,37 @@ +(* An assignment has the form <- *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(): String { + Test1 <- "Hello World" -- Identifiers begin with a lower case letter + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/assignment2.cl b/src/tester/parser/assignment2.cl new file mode 100644 index 000000000..4efb96487 --- /dev/null +++ b/src/tester/parser/assignment2.cl @@ -0,0 +1,37 @@ +(* An assignment has the form <- *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 - 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(): Int { + test1 <-- ~(1 + 2 + 3 + 4 + 5) -- The left side must be an expression + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/assignment3.cl b/src/tester/parser/assignment3.cl new file mode 100644 index 000000000..ff633f331 --- /dev/null +++ b/src/tester/parser/assignment3.cl @@ -0,0 +1,37 @@ +(* An assignment has the form <- *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(): Bool { + test1 <- true++ -- The left side must be an expression + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/attribute1.cl b/src/tester/parser/attribute1.cl new file mode 100644 index 000000000..063a02c02 --- /dev/null +++ b/src/tester/parser/attribute1.cl @@ -0,0 +1,34 @@ +(* An attribute of class A specifies a variable that is part of the state of objects of class A *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + -- Attributes names must begin with lowercase letters + Test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/attribute2.cl b/src/tester/parser/attribute2.cl new file mode 100644 index 000000000..c05211483 --- /dev/null +++ b/src/tester/parser/attribute2.cl @@ -0,0 +1,34 @@ +(* An attribute of class A specifies a variable that is part of the state of objects of class A *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + -- Type names must begin with uppercase letters + test3: string <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/attribute3.cl b/src/tester/parser/attribute3.cl new file mode 100644 index 000000000..d858ae47c --- /dev/null +++ b/src/tester/parser/attribute3.cl @@ -0,0 +1,34 @@ +(* An attribute of class A specifies a variable that is part of the state of objects of class A *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + -- Expected '<-' not '<=' + test3: String <= "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/block1.cl b/src/tester/parser/block1.cl new file mode 100644 index 000000000..3613d9268 --- /dev/null +++ b/src/tester/parser/block1.cl @@ -0,0 +1,87 @@ +(* A block has the form { ; ... ; } *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + pow: Int <- 1; + count: Int <- 0; + + testing6(a: Int): IO { + { + count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2 -- Missing ";" + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/block2.cl b/src/tester/parser/block2.cl new file mode 100644 index 000000000..f485dd0b1 --- /dev/null +++ b/src/tester/parser/block2.cl @@ -0,0 +1,87 @@ +(* A block has the form { ; ... ; } *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + pow: Int <- 1; + count: Int <- 0; + + testing6(a: Int): IO { + -- Missing "{" + count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/block3.cl b/src/tester/parser/block3.cl new file mode 100644 index 000000000..ae1598c3b --- /dev/null +++ b/src/tester/parser/block3.cl @@ -0,0 +1,87 @@ +(* A block has the form { ; ... ; } *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + pow: Int <- 1; + count: Int <- 0; + + testing6(a: Int): IO { + { + count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + -- Missing "}" + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/block4.cl b/src/tester/parser/block4.cl new file mode 100644 index 000000000..8fd883d02 --- /dev/null +++ b/src/tester/parser/block4.cl @@ -0,0 +1,88 @@ +(* A block has the form { ; ... ; } *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + pow: Int <- 1; + count: Int <- 0; + + testing6(a: Int): IO { + { + count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + true++; -- Only expressions + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/case1.cl b/src/tester/parser/case1.cl new file mode 100644 index 000000000..eb56d8eba --- /dev/null +++ b/src/tester/parser/case1.cl @@ -0,0 +1,91 @@ +(* Case expressions provide runtime type tests on objects *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int <- 0, pow: Int + in { + -- count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; + + testing7(): Object { + case 2 + 2 of + -- Every case expression must have at least one branch + esac + }; +} + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/case2.cl b/src/tester/parser/case2.cl new file mode 100644 index 000000000..f9162e49f --- /dev/null +++ b/src/tester/parser/case2.cl @@ -0,0 +1,93 @@ +(* Case expressions provide runtime type tests on objects *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int <- 0, pow: Int + in { + -- count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; + + testing7(): Object { + case "2 + 2" of + x: Int => new IO.out_string("Es un entero!") -- Missing ";" + y: String => new IO.out_string("Es una cadena!"); + z: Bool => new IO.out_string("Es un booleano!"); + esac + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/case3.cl b/src/tester/parser/case3.cl new file mode 100644 index 000000000..a7eedc18b --- /dev/null +++ b/src/tester/parser/case3.cl @@ -0,0 +1,93 @@ +(* Case expressions provide runtime type tests on objects *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int <- 0, pow: Int + in { + -- count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; + + testing7(): Object { + case 2 + false of + x: Int => new IO.out_string("Es un entero!"); + y: string => new IO.out_string("Es una cadena!"); -- Type identifiers starts with a uppercase letter + z: Bool => new IO.out_string("Es un booleano!"); + esac + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/case4.cl b/src/tester/parser/case4.cl new file mode 100644 index 000000000..25ca3858f --- /dev/null +++ b/src/tester/parser/case4.cl @@ -0,0 +1,93 @@ +(* Case expressions provide runtime type tests on objects *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int <- 0, pow: Int + in { + -- count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; + + testing7(): Object { + case true of + x: Int => new IO.out_string("Es un entero!"); + y: String => new IO.out_string("Es una cadena!"); + Mazinger_Z: Bool => new IO.out_string("Es un booleano!"); -- Identifiers starts with a lowercase letter + esac + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/case5.cl b/src/tester/parser/case5.cl new file mode 100644 index 000000000..b36c663e1 --- /dev/null +++ b/src/tester/parser/case5.cl @@ -0,0 +1,93 @@ +(* Case expressions provide runtime type tests on objects *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int <- 0, pow: Int + in { + -- count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; + + testing7(): Object { + case test2 of + x: Int <- new IO.out_string("Es un entero!"); -- Must be '=>' not '<-'; + y: String => new IO.out_string("Es una cadena!"); + z: Bool => new IO.out_string("Es un booleano!"); + esac + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/case6.cl b/src/tester/parser/case6.cl new file mode 100644 index 000000000..66e7df2ab --- /dev/null +++ b/src/tester/parser/case6.cl @@ -0,0 +1,93 @@ +(* Case expressions provide runtime type tests on objects *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int <- 0, pow: Int + in { + -- count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; + + testing7(): Object { + case 2 + 2 -- Missing "of" + x: Int => new IO.out_string("Es un entero!"); + y: String => new IO.out_string("Es una cadena!"); + z: Bool => new IO.out_string("Es un booleano!"); + esac + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/class1.cl b/src/tester/parser/class1.cl new file mode 100644 index 000000000..f4815e3f4 --- /dev/null +++ b/src/tester/parser/class1.cl @@ -0,0 +1,20 @@ +(* A class is a list of features *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + testing(): Int { + 2 + 2 + }; +}; + +-- Class names must begin with uppercase letters +class alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; diff --git a/src/tester/parser/class2.cl b/src/tester/parser/class2.cl new file mode 100644 index 000000000..f363b032a --- /dev/null +++ b/src/tester/parser/class2.cl @@ -0,0 +1,20 @@ +(* A class is a list of features *) + +CLaSS Main { + main(): Object { + (new Alpha).print() + }; +}; + +CLaSS Test { + testing(): Int { + 2 + 2 + }; +}; + +-- Type names must begin with uppercase letters +CLaSS Alpha iNHeRiTS iO { + print() : Object { + out_string("reached!!\n") + }; +}; diff --git a/src/tester/parser/class3.cl b/src/tester/parser/class3.cl new file mode 100644 index 000000000..0c801372a --- /dev/null +++ b/src/tester/parser/class3.cl @@ -0,0 +1,34 @@ +(* A class is a list of features *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + -- Missing semicolon + testing2(a: Alpha, b: Int): Int { + 2 + 2 + } + + testing3(): String { + "2 + 2" + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; diff --git a/src/tester/parser/class4.cl b/src/tester/parser/class4.cl new file mode 100644 index 000000000..5c286b5e6 --- /dev/null +++ b/src/tester/parser/class4.cl @@ -0,0 +1,36 @@ +(* A class is a list of features *) + +CLaSS Main { + main(): Object { + (new Alpha).print() + }; +}; + +CLaSS Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + -- Only features + 2 + 2; + + testing3(): String { + "2 + 2" + }; +}; + +CLaSS Alpha iNHeRiTS IO { + print() : Object { + out_string("reached!!\n") + }; +}; diff --git a/src/tester/parser/class5.cl b/src/tester/parser/class5.cl new file mode 100644 index 000000000..3f40c36eb --- /dev/null +++ b/src/tester/parser/class5.cl @@ -0,0 +1,34 @@ +(* A class is a list of features *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +-- Missing '{' +class Test + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; diff --git a/src/tester/parser/class6.cl b/src/tester/parser/class6.cl new file mode 100644 index 000000000..8501d2593 --- /dev/null +++ b/src/tester/parser/class6.cl @@ -0,0 +1,34 @@ +(* A class is a list of features *) + +CLaSS Main { + main(): Object { + (new Alpha).print() + }; +}; + +-- Missing '}' +CLaSS Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; +; + +CLaSS Alpha iNHeRiTS IO { + print() : Object { + out_string("reached!!\n") + }; +}; diff --git a/src/tester/parser/conditional1.cl b/src/tester/parser/conditional1.cl new file mode 100644 index 000000000..4d546fc44 --- /dev/null +++ b/src/tester/parser/conditional1.cl @@ -0,0 +1,69 @@ +(* A conditional has the form if then else fi *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + if a.length() < b.length() -- Mising "then" + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + else + if a.length() = b.length() then + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + else + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fi + fi + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/conditional2.cl b/src/tester/parser/conditional2.cl new file mode 100644 index 000000000..4f10c2957 --- /dev/null +++ b/src/tester/parser/conditional2.cl @@ -0,0 +1,69 @@ +(* A conditional has the form if then else fi *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + if a.length() < b.length() then + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + else + if a.length() = b.length() then + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + else + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + -- Missing "fi" + fi + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/conditional3.cl b/src/tester/parser/conditional3.cl new file mode 100644 index 000000000..67e991ade --- /dev/null +++ b/src/tester/parser/conditional3.cl @@ -0,0 +1,69 @@ +(* A conditional has the form if then else fi *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + iF a.length() < b.length() tHen + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + elsE + if a.length() = b.length() then + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + eLseif -- elseif isn't a keyword + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/conditional4.cl b/src/tester/parser/conditional4.cl new file mode 100644 index 000000000..0792fdc85 --- /dev/null +++ b/src/tester/parser/conditional4.cl @@ -0,0 +1,73 @@ +(* A conditional has the form if then else fi *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(): Int { + if true++ then 1 else 0 -- Condition must be an expression + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/conditional5.cl b/src/tester/parser/conditional5.cl new file mode 100644 index 000000000..0c1e1aad0 --- /dev/null +++ b/src/tester/parser/conditional5.cl @@ -0,0 +1,73 @@ +(* A conditional has the form if then else fi *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(): Int { + if true then true++ else 0 -- If branch must be an expression + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/conditional6.cl b/src/tester/parser/conditional6.cl new file mode 100644 index 000000000..02310404a --- /dev/null +++ b/src/tester/parser/conditional6.cl @@ -0,0 +1,73 @@ +(* A conditional has the form if then else fi *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(): Int { + if true then 1 else false++ -- Else branch must be an expression + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/dispatch1.cl b/src/tester/parser/dispatch1.cl new file mode 100644 index 000000000..07d173987 --- /dev/null +++ b/src/tester/parser/dispatch1.cl @@ -0,0 +1,45 @@ +(* There are three forms of dispatch (i.e. method call) in Cool. The three forms differ only in how the called method is selected *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + Test1.testing4(1, 2).testing4(3, 4).testing4(5, 6) -- Objet identifiers begin with a lower case letter + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/dispatch2.cl b/src/tester/parser/dispatch2.cl new file mode 100644 index 000000000..e05385139 --- /dev/null +++ b/src/tester/parser/dispatch2.cl @@ -0,0 +1,45 @@ +(* There are three forms of dispatch (i.e. method call) in Cool. The three forms differ only in how the called method is selected *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13,,) -- Extra comma + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/dispatch4.cl b/src/tester/parser/dispatch4.cl new file mode 100644 index 000000000..34674c7cf --- /dev/null +++ b/src/tester/parser/dispatch4.cl @@ -0,0 +1,53 @@ +(* There are three forms of dispatch (i.e. method call) in Cool. The three forms differ only in how the called method is selected *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + self.testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true++) -- Arguments must be expressions + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/dispatch5.cl b/src/tester/parser/dispatch5.cl new file mode 100644 index 000000000..971b23572 --- /dev/null +++ b/src/tester/parser/dispatch5.cl @@ -0,0 +1,53 @@ +(* There are three forms of dispatch (i.e. method call) in Cool. The three forms differ only in how the called method is selected *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, ,true + fALSE) -- Extra comma + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/dispatch6.cl b/src/tester/parser/dispatch6.cl new file mode 100644 index 000000000..c8d3d5d89 --- /dev/null +++ b/src/tester/parser/dispatch6.cl @@ -0,0 +1,57 @@ +(* There are three forms of dispatch (i.e. method call) in Cool. The three forms differ only in how the called method is selected *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@object.copy() -- Type identifiers begin with a upper case letter + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/dispatch7.cl b/src/tester/parser/dispatch7.cl new file mode 100644 index 000000000..946097167 --- /dev/null +++ b/src/tester/parser/dispatch7.cl @@ -0,0 +1,57 @@ +(* There are three forms of dispatch (i.e. method call) in Cool. The three forms differ only in how the called method is selected *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.Copy() -- Identifiers begin with a lower case letter + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +} \ No newline at end of file diff --git a/src/tester/parser/dispatch8.cl b/src/tester/parser/dispatch8.cl new file mode 100644 index 000000000..df96d9142 --- /dev/null +++ b/src/tester/parser/dispatch8.cl @@ -0,0 +1,57 @@ +(* There are three forms of dispatch (i.e. method call) in Cool. The three forms differ only in how the called method is selected *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy(,) -- Extra comma + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/dispatch9.cl b/src/tester/parser/dispatch9.cl new file mode 100644 index 000000000..e9369540c --- /dev/null +++ b/src/tester/parser/dispatch9.cl @@ -0,0 +1,61 @@ +(* There are three forms of dispatch (i.e. method call) in Cool. The three forms differ only in how the called method is selected *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; + + testing5(): Object { + test1:Object.copy() -- Must be '@' not ':' + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/let1.cl b/src/tester/parser/let1.cl new file mode 100644 index 000000000..576ae383c --- /dev/null +++ b/src/tester/parser/let1.cl @@ -0,0 +1,85 @@ +(* A let expression has the form let : [ <- ], ..., : [ <- ] in *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let Count: Int <- 0, pow: Int <- 1 -- Object identifiers starts with a lowercase letter + in { + -- count <- 0; + -- pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/let2.cl b/src/tester/parser/let2.cl new file mode 100644 index 000000000..4cfaef0f8 --- /dev/null +++ b/src/tester/parser/let2.cl @@ -0,0 +1,85 @@ +(* A let expression has the form let : [ <- ], ..., : [ <- ] in *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int, pow: int <- 1 -- Type identifiers starts with a uppercase letter + in { + count <- 0; + -- pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/let3.cl b/src/tester/parser/let3.cl new file mode 100644 index 000000000..91e567fd8 --- /dev/null +++ b/src/tester/parser/let3.cl @@ -0,0 +1,85 @@ +(* A let expression has the form let : [ <- ], ..., : [ <- ] in *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int, pow: Int, -- Extra comma + in { + count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/let4.cl b/src/tester/parser/let4.cl new file mode 100644 index 000000000..a716c332d --- /dev/null +++ b/src/tester/parser/let4.cl @@ -0,0 +1,85 @@ +(* A let expression has the form let : [ <- ], ..., : [ <- ] in *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int <- true++, pow: Int <- 1 -- Initialization must be an expression + in { + count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/let5.cl b/src/tester/parser/let5.cl new file mode 100644 index 000000000..d974cc138 --- /dev/null +++ b/src/tester/parser/let5.cl @@ -0,0 +1,85 @@ +(* A let expression has the form let : [ <- ], ..., : [ <- ] in *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int = 0, pow: Int -- Must be '<-' not '=' + in { + -- count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/let6.cl b/src/tester/parser/let6.cl new file mode 100644 index 000000000..b6e51d7e1 --- /dev/null +++ b/src/tester/parser/let6.cl @@ -0,0 +1,74 @@ +(* A let expression has the form let : [ <- ], ..., : [ <- ] in *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int <- 0, pow: Int <- 1 + in false++ -- Let body must be an expression + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/let7.cl b/src/tester/parser/let7.cl new file mode 100644 index 000000000..6fd63e6a7 --- /dev/null +++ b/src/tester/parser/let7.cl @@ -0,0 +1,85 @@ +(* A let expression has the form let : [ <- ], ..., : [ <- ] in *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int <- 0, pow: Int + (* Missing "in" *) { + -- count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/loop1.cl b/src/tester/parser/loop1.cl new file mode 100644 index 000000000..7d0d7688f --- /dev/null +++ b/src/tester/parser/loop1.cl @@ -0,0 +1,78 @@ +(* A loop has the form while loop pool *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + count: Int <- 1; + + testing6(): Object { + while count < 1024*1024 + -- Missing "loop" + count <- count * 2 + pool + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/loop2.cl b/src/tester/parser/loop2.cl new file mode 100644 index 000000000..a9613c487 --- /dev/null +++ b/src/tester/parser/loop2.cl @@ -0,0 +1,78 @@ +(* A loop has the form while loop pool *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + count: Int <- 1; + + testing6(): Object { + while count < 1024*1024 + loop + count <- count * 2 + -- Missing "pool" + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/loop3.cl b/src/tester/parser/loop3.cl new file mode 100644 index 000000000..860adb4d1 --- /dev/null +++ b/src/tester/parser/loop3.cl @@ -0,0 +1,78 @@ +(* A loop has the form while loop pool *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + count: Int <- 1; + + testing6(): Object { + while count => 1024*1024 -- Condition must be an expression + loop + count <- count * 2 + pool + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/loop4.cl b/src/tester/parser/loop4.cl new file mode 100644 index 000000000..0a1194e82 --- /dev/null +++ b/src/tester/parser/loop4.cl @@ -0,0 +1,78 @@ +(* A loop has the form while loop pool *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + count: Int <- 1; + + testing6(): Object { + while count < 1024*1024 + loop + count <- true++ -- While body must be an expression + pool + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/method1.cl b/src/tester/parser/method1.cl new file mode 100644 index 000000000..fcfbbcd30 --- /dev/null +++ b/src/tester/parser/method1.cl @@ -0,0 +1,34 @@ +(* A method of class A is a procedure that may manipulate the variables and objects of class A *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + -- Method names must begin with lowercase letters + Testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/method2.cl b/src/tester/parser/method2.cl new file mode 100644 index 000000000..d5bdfd85c --- /dev/null +++ b/src/tester/parser/method2.cl @@ -0,0 +1,34 @@ +(* A method of class A is a procedure that may manipulate the variables and objects of class A *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + -- Parameter names must begin with lowercase letters + testing2(a: Alpha, B: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/method3.cl b/src/tester/parser/method3.cl new file mode 100644 index 000000000..1e5c9eb53 --- /dev/null +++ b/src/tester/parser/method3.cl @@ -0,0 +1,34 @@ +(* A method of class A is a procedure that may manipulate the variables and objects of class A *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + -- Type names must begin with uppercase letters + testing2(a: Alpha, b: int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/method4.cl b/src/tester/parser/method4.cl new file mode 100644 index 000000000..53aba25cb --- /dev/null +++ b/src/tester/parser/method4.cl @@ -0,0 +1,34 @@ +(* A method of class A is a procedure that may manipulate the variables and objects of class A *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + -- Missing paremeter + testing3(x: Int,,): String { + "2 + 2" + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/method5.cl b/src/tester/parser/method5.cl new file mode 100644 index 000000000..13127f664 --- /dev/null +++ b/src/tester/parser/method5.cl @@ -0,0 +1,34 @@ +(* A method of class A is a procedure that may manipulate the variables and objects of class A *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + -- Type names must begin with uppercase letters + testing3(): string { + "2 + 2" + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/method6.cl b/src/tester/parser/method6.cl new file mode 100644 index 000000000..d48cd1293 --- /dev/null +++ b/src/tester/parser/method6.cl @@ -0,0 +1,33 @@ +(* A method of class A is a procedure that may manipulate the variables and objects of class A *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + -- Body can't be empty + testing2(a: Alpha, b: Int): Int { + }; + + testing3(): String { + "2 + 2" + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/mixed2.cl b/src/tester/parser/mixed2.cl new file mode 100644 index 000000000..f5477e0bb --- /dev/null +++ b/src/tester/parser/mixed2.cl @@ -0,0 +1,14 @@ +class Main { + main(): Object { + (new Alpha).print() + }; + +}; + +(* Class names must begin with uppercase letters *) +class alpha inherits IO { + print() : Object { + out_string("reached!!\n"); + }; +}; + diff --git a/src/tester/parser/mixed3.cl b/src/tester/parser/mixed3.cl new file mode 100644 index 000000000..e34edc888 --- /dev/null +++ b/src/tester/parser/mixed3.cl @@ -0,0 +1,40 @@ +class Main inherits IO { + main() : Object { + { + out_string("Enter a number to check if number is prime\n"); + let i : Int <- in_int() in { + if(i <= 1) then { + out_string("Invalid Input\n"); + abort(); + } else { + if (isPrime(i) = 1) then + out_string("Number is prime\n") + else + out_string("Number is composite\n") + fi; + } + fi; + }; + } + }; + + mod(i : Int,, ) : Int { -- Formal list must be comma separated. A comma does not terminate a list of formals. + i - (i/k)*k + }; + + isPrime(i : Int) : Int { + { + let x : Int <- 2, + c : Int <- 1 in + { + while (not (x = i)) loop + if (mod(i, x) = 0) then { + c <- 0; + x <- i; + } else x <- x + 1 fi + pool; + c; + }; + } + }; +}; diff --git a/src/tester/parser/mixed4.cl b/src/tester/parser/mixed4.cl new file mode 100644 index 000000000..e752253be --- /dev/null +++ b/src/tester/parser/mixed4.cl @@ -0,0 +1,21 @@ +class Main inherits IO { + main() : Object { + { + out_string("Enter number of numbers to multiply\n"); + out_int(prod(in_int())); + out_string("\n"); + } + }; + + prod(i : Int) : Int { + let y : Int <- 1 in { + while (not (i = 0) ) loop { + out_string("Enter Number: "); + y <- y * in_int(Main : Int); -- the parser correctly catches the error here + i <- i - 1; + } + pool; + y; + } + }; +}; diff --git a/src/tester/parser/mixed5.cl b/src/tester/parser/mixed5.cl new file mode 100644 index 000000000..41a1f3b00 --- /dev/null +++ b/src/tester/parser/mixed5.cl @@ -0,0 +1,20 @@ +class Main inherits IO { + str <- "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; + main() : Object { + { + out_string("Enter number of numbers to multiply\n"); + out_int(prod(in_int())); + out_string("\n"); + } + }; + prod(i : Int) : Int { + let y : Int <- 1 in { + while (not (i = 0) ) loop { + out_string("Enter Number: "); + y <- y * in_int(); + i <- i - 1; + } + y; + } + }; +}; diff --git a/src/tester/parser/mixed6.cl b/src/tester/parser/mixed6.cl new file mode 100644 index 000000000..5da80da31 --- /dev/null +++ b/src/tester/parser/mixed6.cl @@ -0,0 +1,5 @@ +classs Doom { + i : Int <- 0; + main() : Object { + if i = 0 then out_string("This is da real *h*t") + diff --git a/src/tester/parser/operation1.cl b/src/tester/parser/operation1.cl new file mode 100644 index 000000000..d38eb72d0 --- /dev/null +++ b/src/tester/parser/operation1.cl @@ -0,0 +1,101 @@ +(* Cool has four binary arithmetic operations: +, -, *, /. *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int <- 0, pow: Int + in { + -- count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; + + testing7(): Object { + case 2 + 2 of + x: Int => new IO.out_string("Es un entero!"); + y: String => new IO.out_string("Es una cadena!"); + z: Bool => new IO.out_string("Es un booleano!"); + esac + }; + + a: Int <- 1; + + testing8(x: Int, y: Int): Bool { + let z: Int <- 3, w: Int <- 4 + -- Missing ')' + in isvoid (3 + a * (x / w + new Int) - y - (((if tRue = not faLSe then ~z else 3 <= 4 + "hey".length() fi + a)/(0)*(((4 * 4))))) + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/operation2.cl b/src/tester/parser/operation2.cl new file mode 100644 index 000000000..2dc628359 --- /dev/null +++ b/src/tester/parser/operation2.cl @@ -0,0 +1,101 @@ +(* Cool has four binary arithmetic operations: +, -, *, /. *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int <- 0, pow: Int + in { + -- count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; + + testing7(): Object { + case 2 + 2 of + x: Int => new IO.out_string("Es un entero!"); + y: String => new IO.out_string("Es una cadena!"); + z: Bool => new IO.out_string("Es un booleano!"); + esac + }; + + a: Int <- 1; + + testing8(x: Int, y: Int): Bool { + let z: Int <- 3, w: Int <- 4 + -- Type identifiers starts with a uppercase letter + in isvoid (3 + a * (x / w + new int) - y - (((if tRue = not faLSe then ~z else 3 <= 4 + "hey".length() fi + a))/(0)*(((4 * 4))))) + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/operation3.cl b/src/tester/parser/operation3.cl new file mode 100644 index 000000000..61d6cbfa8 --- /dev/null +++ b/src/tester/parser/operation3.cl @@ -0,0 +1,101 @@ +(* Cool has four binary arithmetic operations: +, -, *, /. *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int <- 0, pow: Int + in { + -- count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; + + testing7(): Object { + case 2 + 2 of + x: Int => new IO.out_string("Es un entero!"); + y: String => new IO.out_string("Es una cadena!"); + z: Bool => new IO.out_string("Es un booleano!"); + esac + }; + + a: Int <- 1; + + testing8(x: Int, y: Int): Bool { + let z: Int <- 3, w: Int <- 4 + -- Object identifiers starts with a lowercase letter + in isvoid (3 + a * (x / w + new Int) - y - (((if tRue = not faLSe then ~Mazinger_Z else 3 <= 4 + "hey".length() fi + a))/(0)*(((4 * 4))))) + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/operation4.cl b/src/tester/parser/operation4.cl new file mode 100644 index 000000000..bae7de5b5 --- /dev/null +++ b/src/tester/parser/operation4.cl @@ -0,0 +1,101 @@ +(* Cool has four binary arithmetic operations: +, -, *, /. *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int <- 0, pow: Int + in { + -- count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; + + testing7(): Object { + case 2 + 2 of + x: Int => new IO.out_string("Es un entero!"); + y: String => new IO.out_string("Es una cadena!"); + z: Bool => new IO.out_string("Es un booleano!"); + esac + }; + + a: Int <- 1; + + testing8(x: Int, y: Int): Bool { + let z: Int <- 3, w: Int <- 4 + -- Double "+" + in isvoid (3 + a * (x / w++ new Int) - y - (((if tRue = not faLSe then ~z else 3 <= 4 + "hey".length() fi + a))/(0)*(((4 * 4))))) + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tester/parser/program1.cl b/src/tester/parser/program1.cl new file mode 100644 index 000000000..8e5cf617f --- /dev/null +++ b/src/tester/parser/program1.cl @@ -0,0 +1 @@ +(* A Cool program can't be empty *) \ No newline at end of file diff --git a/src/tester/parser/program3.cl b/src/tester/parser/program3.cl new file mode 100644 index 000000000..e27889c57 --- /dev/null +++ b/src/tester/parser/program3.cl @@ -0,0 +1,24 @@ +(* Cool programs are sets of classes *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + testing(): Int { + 2 + 2 + }; +}; + +-- Only classes +suma(a: Int, b: Int) int { + a + b +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; diff --git a/src/tester/semantic/01_program.cl b/src/tester/semantic/01_program.cl new file mode 100644 index 000000000..acb44954b --- /dev/null +++ b/src/tester/semantic/01_program.cl @@ -0,0 +1,16 @@ +class Main { + a: Int; + + b: String; + + main () : String { + let a: Int <- "" in 0 + }; + + function_with_errors() : Object { + case a of + x: Int => (new IO).out_int(x); + y: String => (new IO).out_string(x); + esac + }; +}; \ No newline at end of file diff --git a/src/tester/semantic/arithmetic1.cl b/src/tester/semantic/arithmetic1.cl new file mode 100644 index 000000000..bf94eb194 --- /dev/null +++ b/src/tester/semantic/arithmetic1.cl @@ -0,0 +1,11 @@ +--The static types of the two sub-expressions must be Int. + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Int <- let x: Int <- 1 * 2 / 3 - 4 + new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in x <- x + new A.type_name().concat(new B.type_name().concat(new C.type_name())); +}; \ No newline at end of file diff --git a/src/tester/semantic/arithmetic10.cl b/src/tester/semantic/arithmetic10.cl new file mode 100644 index 000000000..bbfe6cdb3 --- /dev/null +++ b/src/tester/semantic/arithmetic10.cl @@ -0,0 +1,15 @@ +(* +The expression ~ is the integer +complement of . The expression must have static type Int and the entire expression +has static type Int. +*) + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Bool <- let x: Bool <- 1 / 2 - 3 + 4 < new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in ~new A.type_name().concat(new B.type_name().concat(new C.type_name())).length(); +}; \ No newline at end of file diff --git a/src/tester/semantic/arithmetic10_error.txt b/src/tester/semantic/arithmetic10_error.txt new file mode 100644 index 000000000..b2be0476f --- /dev/null +++ b/src/tester/semantic/arithmetic10_error.txt @@ -0,0 +1 @@ +(13, 19) - TypeError: Inferred type Int of initialization of attribute test does not conform to declared type Bool. \ No newline at end of file diff --git a/src/tester/semantic/arithmetic11.cl b/src/tester/semantic/arithmetic11.cl new file mode 100644 index 000000000..fc067dc1a --- /dev/null +++ b/src/tester/semantic/arithmetic11.cl @@ -0,0 +1,14 @@ +(* +The expression not is the boolean complement of . The expression + must have static type Bool and the entire expression has static type Bool. +*) + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Bool <- let x: Bool <- 1 / 2 - 3 + 4 < new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in not 1 + new A.type_name().concat(new B.type_name().concat(new C.type_name())).length(); +}; \ No newline at end of file diff --git a/src/tester/semantic/arithmetic11_error.txt b/src/tester/semantic/arithmetic11_error.txt new file mode 100644 index 000000000..bb4b8e1ca --- /dev/null +++ b/src/tester/semantic/arithmetic11_error.txt @@ -0,0 +1 @@ +(13, 24) - TypeError: Argument of 'not' has type Int instead of Bool. \ No newline at end of file diff --git a/src/tester/semantic/arithmetic12.cl b/src/tester/semantic/arithmetic12.cl new file mode 100644 index 000000000..2e012fc41 --- /dev/null +++ b/src/tester/semantic/arithmetic12.cl @@ -0,0 +1,14 @@ +(* +The expression not is the boolean complement of . The expression + must have static type Bool and the entire expression has static type Bool. +*) + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Int <- let x: Bool <- 1 / 2 - 3 + 4 < new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in not 1 < new A.type_name().concat(new B.type_name().concat(new C.type_name())).length(); +}; \ No newline at end of file diff --git a/src/tester/semantic/arithmetic12_error.txt b/src/tester/semantic/arithmetic12_error.txt new file mode 100644 index 000000000..d25eab65e --- /dev/null +++ b/src/tester/semantic/arithmetic12_error.txt @@ -0,0 +1 @@ +(12, 18) - TypeError: Inferred type Bool of initialization of attribute test does not conform to declared type Int. \ No newline at end of file diff --git a/src/tester/semantic/arithmetic1_error.txt b/src/tester/semantic/arithmetic1_error.txt new file mode 100644 index 000000000..a74ebf3da --- /dev/null +++ b/src/tester/semantic/arithmetic1_error.txt @@ -0,0 +1 @@ +(10, 27) - TypeError: non-Int arguments: Int + String diff --git a/src/tester/semantic/arithmetic2.cl b/src/tester/semantic/arithmetic2.cl new file mode 100644 index 000000000..59532573d --- /dev/null +++ b/src/tester/semantic/arithmetic2.cl @@ -0,0 +1,11 @@ +--The static types of the two sub-expressions must be Int. + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Int <- let x: Int <- 1 + 2 * 3 / 4 - new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in x <- x - new A.type_name().concat(new B.type_name().concat(new C.type_name())); +}; \ No newline at end of file diff --git a/src/tester/semantic/arithmetic2_error.txt b/src/tester/semantic/arithmetic2_error.txt new file mode 100644 index 000000000..2c7952af8 --- /dev/null +++ b/src/tester/semantic/arithmetic2_error.txt @@ -0,0 +1 @@ +(10, 27) - TypeError: non-Int arguments: Int - String diff --git a/src/tester/semantic/arithmetic3.cl b/src/tester/semantic/arithmetic3.cl new file mode 100644 index 000000000..b208957f5 --- /dev/null +++ b/src/tester/semantic/arithmetic3.cl @@ -0,0 +1,11 @@ +--The static types of the two sub-expressions must be Int. + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Int <- let x: Int <- 1 - 2 + 3 * 4 / new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in x <- x / new A.type_name().concat(new B.type_name().concat(new C.type_name())); +}; \ No newline at end of file diff --git a/src/tester/semantic/arithmetic3_error.txt b/src/tester/semantic/arithmetic3_error.txt new file mode 100644 index 000000000..81d88331a --- /dev/null +++ b/src/tester/semantic/arithmetic3_error.txt @@ -0,0 +1 @@ +(10, 27) - TypeError: non-Int arguments: Int / String diff --git a/src/tester/semantic/arithmetic4.cl b/src/tester/semantic/arithmetic4.cl new file mode 100644 index 000000000..2c7dd4fc9 --- /dev/null +++ b/src/tester/semantic/arithmetic4.cl @@ -0,0 +1,11 @@ +--The static types of the two sub-expressions must be Int. + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Int <- let x: Int <- 1 / 2 - 3 + 4 * new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in x <- x * new A.type_name().concat(new B.type_name().concat(new C.type_name())); +}; \ No newline at end of file diff --git a/src/tester/semantic/arithmetic4_error.txt b/src/tester/semantic/arithmetic4_error.txt new file mode 100644 index 000000000..1ca6df022 --- /dev/null +++ b/src/tester/semantic/arithmetic4_error.txt @@ -0,0 +1 @@ +(10, 27) - TypeError: non-Int arguments: Int * String \ No newline at end of file diff --git a/src/tester/semantic/arithmetic5.cl b/src/tester/semantic/arithmetic5.cl new file mode 100644 index 000000000..bc08c6e82 --- /dev/null +++ b/src/tester/semantic/arithmetic5.cl @@ -0,0 +1,11 @@ +--The static type of the expression is Int. + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Bool <- let x: Int <- 1 / 2 - 3 + 4 * new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in x <- x * new A.type_name().concat(new B.type_name().concat(new C.type_name())).length(); +}; \ No newline at end of file diff --git a/src/tester/semantic/arithmetic5_error.txt b/src/tester/semantic/arithmetic5_error.txt new file mode 100644 index 000000000..dd5346844 --- /dev/null +++ b/src/tester/semantic/arithmetic5_error.txt @@ -0,0 +1 @@ +(9, 19) - TypeError: Inferred type Int of initialization of attribute test does not conform to declared type Bool. diff --git a/src/tester/semantic/arithmetic6.cl b/src/tester/semantic/arithmetic6.cl new file mode 100644 index 000000000..a0c3d03ff --- /dev/null +++ b/src/tester/semantic/arithmetic6.cl @@ -0,0 +1,11 @@ + --The static types of the two sub-expressions must be Int. + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Bool <- let x: Bool <- 1 / 2 - 3 + 4 <= new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in 1 <= new A.type_name().concat(new B.type_name().concat(new C.type_name())); +}; diff --git a/src/tester/semantic/arithmetic6_error.txt b/src/tester/semantic/arithmetic6_error.txt new file mode 100644 index 000000000..2e43dfc17 --- /dev/null +++ b/src/tester/semantic/arithmetic6_error.txt @@ -0,0 +1 @@ +(10, 22) - TypeError: non-Int arguments: Int <= String diff --git a/src/tester/semantic/arithmetic7.cl b/src/tester/semantic/arithmetic7.cl new file mode 100644 index 000000000..c00c75cde --- /dev/null +++ b/src/tester/semantic/arithmetic7.cl @@ -0,0 +1,12 @@ + --The static types of the two sub-expressions must be Int. + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Bool <- let x: Bool <- 1 / 2 - 3 + 4 < new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in 1 < new A.type_name().concat(new B.type_name().concat(new C.type_name())); +}; + diff --git a/src/tester/semantic/arithmetic7_error.txt b/src/tester/semantic/arithmetic7_error.txt new file mode 100644 index 000000000..6f3537117 --- /dev/null +++ b/src/tester/semantic/arithmetic7_error.txt @@ -0,0 +1 @@ +(10, 22) - TypeError: non-Int arguments: Int < String diff --git a/src/tester/semantic/arithmetic8.cl b/src/tester/semantic/arithmetic8.cl new file mode 100644 index 000000000..3210bdb8a --- /dev/null +++ b/src/tester/semantic/arithmetic8.cl @@ -0,0 +1,13 @@ + --The rules are exactly the same as for the binary arithmetic operations, except that the result is a Bool. + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Int <- let x: Bool <- 1 / 2 - 3 + 4 < new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in 1 < new A.type_name().concat(new B.type_name().concat(new C.type_name())).length(); +}; + + diff --git a/src/tester/semantic/arithmetic8_error.txt b/src/tester/semantic/arithmetic8_error.txt new file mode 100644 index 000000000..ebcaa3797 --- /dev/null +++ b/src/tester/semantic/arithmetic8_error.txt @@ -0,0 +1 @@ +(9, 18) - TypeError: Inferred type Bool of initialization of attribute test does not conform to declared type Int. diff --git a/src/tester/semantic/arithmetic9.cl b/src/tester/semantic/arithmetic9.cl new file mode 100644 index 000000000..95579e134 --- /dev/null +++ b/src/tester/semantic/arithmetic9.cl @@ -0,0 +1,15 @@ +(* +The expression ~ is the integer +complement of . The expression must have static type Int and the entire expression +has static type Int. +*) + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Int <- let x: Bool <- 1 / 2 - 3 + 4 < new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in 1 + ~new A.type_name().concat(new B.type_name().concat(new C.type_name())); +}; \ No newline at end of file diff --git a/src/tester/semantic/arithmetic9_error.txt b/src/tester/semantic/arithmetic9_error.txt new file mode 100644 index 000000000..99fafbbfc --- /dev/null +++ b/src/tester/semantic/arithmetic9_error.txt @@ -0,0 +1 @@ +(14, 25) - TypeError: Argument of '~' has type String instead of Int. \ No newline at end of file diff --git a/src/tester/semantic/assignment1.cl b/src/tester/semantic/assignment1.cl new file mode 100644 index 000000000..19ab70219 --- /dev/null +++ b/src/tester/semantic/assignment1.cl @@ -0,0 +1,7 @@ +--The static type of the expression must conform to the declared type of the identifier + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test: Int <- "String"; +}; diff --git a/src/tester/semantic/assignment1_error.txt b/src/tester/semantic/assignment1_error.txt new file mode 100644 index 000000000..6eb883012 --- /dev/null +++ b/src/tester/semantic/assignment1_error.txt @@ -0,0 +1 @@ +(6, 18) - TypeError: Inferred type String of initialization of attribute test does not conform to declared type Int. diff --git a/src/tester/semantic/assignment2.cl b/src/tester/semantic/assignment2.cl new file mode 100644 index 000000000..cace221ae --- /dev/null +++ b/src/tester/semantic/assignment2.cl @@ -0,0 +1,13 @@ +--The static type of an assignment is the static type of . + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test(a: A): B { a <- new C }; + test2(a: A): D { a <- new C }; +}; diff --git a/src/tester/semantic/assignment2_error.txt b/src/tester/semantic/assignment2_error.txt new file mode 100644 index 000000000..ed10b7f38 --- /dev/null +++ b/src/tester/semantic/assignment2_error.txt @@ -0,0 +1 @@ +(12, 22) - TypeError: Inferred return type C of method test2 does not conform to declared return type D. diff --git a/src/tester/semantic/assignment3.cl b/src/tester/semantic/assignment3.cl new file mode 100644 index 000000000..eba0d69e2 --- /dev/null +++ b/src/tester/semantic/assignment3.cl @@ -0,0 +1,14 @@ +--The static type of an assignment is the static type of . + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + a: A; + b: B <- a <- new C; + d: D <- a <- new C; +}; diff --git a/src/tester/semantic/assignment3_error.txt b/src/tester/semantic/assignment3_error.txt new file mode 100644 index 000000000..bc9a718cc --- /dev/null +++ b/src/tester/semantic/assignment3_error.txt @@ -0,0 +1 @@ +(13, 13) - TypeError: Inferred type C of initialization of attribute d does not conform to declared type D. \ No newline at end of file diff --git a/src/tester/semantic/attributes1.cl b/src/tester/semantic/attributes1.cl new file mode 100644 index 000000000..3fa0440e4 --- /dev/null +++ b/src/tester/semantic/attributes1.cl @@ -0,0 +1,13 @@ +--The static type of the expression must conform to the declared type of the attribute. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + test1: IO <- new Main; + test2: B <- new A; + + main(): IO { out_string("Hello World!")}; +}; \ No newline at end of file diff --git a/src/tester/semantic/attributes1_error.txt b/src/tester/semantic/attributes1_error.txt new file mode 100644 index 000000000..9cb8460c9 --- /dev/null +++ b/src/tester/semantic/attributes1_error.txt @@ -0,0 +1 @@ +(10, 17) - TypeError: Inferred type A of initialization of attribute test2 does not conform to declared type B. diff --git a/src/tester/semantic/attributes2.cl b/src/tester/semantic/attributes2.cl new file mode 100644 index 000000000..7937c2cc8 --- /dev/null +++ b/src/tester/semantic/attributes2.cl @@ -0,0 +1,13 @@ +--The static type of the expression must conform to the declared type of the attribute. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + test1: IO <- new Main; + test2: C <- new D; + + main(): IO { out_string("Hello World!")}; +}; \ No newline at end of file diff --git a/src/tester/semantic/attributes2_error.txt b/src/tester/semantic/attributes2_error.txt new file mode 100644 index 000000000..6d601b7cd --- /dev/null +++ b/src/tester/semantic/attributes2_error.txt @@ -0,0 +1 @@ +(10, 17) - TypeError: Inferred type D of initialization of attribute test2 does not conform to declared type C. diff --git a/src/tester/semantic/attributes3.cl b/src/tester/semantic/attributes3.cl new file mode 100644 index 000000000..8a67decd1 --- /dev/null +++ b/src/tester/semantic/attributes3.cl @@ -0,0 +1,25 @@ +--Attributes are local to the class in which they are defined or inherited. + +class A { + a: Int <- 5; + test(x1: Int, y1: Int): Int { + let x: Int <- x1, y: Int <-y1 in { + x <- x + a; + y <- y + a; + if b then x + y else x - y fi; + } + }; +}; +class B inherits A { + b: Bool <- true; +}; +class C inherits B { + c: String <- "C"; +}; +class D inherits B { + d: IO <- new Main.main(); +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!") }; +}; \ No newline at end of file diff --git a/src/tester/semantic/attributes3_error.txt b/src/tester/semantic/attributes3_error.txt new file mode 100644 index 000000000..6195c816c --- /dev/null +++ b/src/tester/semantic/attributes3_error.txt @@ -0,0 +1 @@ +(9, 16) - NameError: Undeclared identifier b. diff --git a/src/tester/semantic/attributes4.cl b/src/tester/semantic/attributes4.cl new file mode 100644 index 000000000..a7f63adbd --- /dev/null +++ b/src/tester/semantic/attributes4.cl @@ -0,0 +1,39 @@ +--Attributes are local to the class in which they are defined or inherited. + +class A { + a: Int <- 5; +}; +class B inherits A { + b: Bool <- true; + test(x1: Int, y1: Int): Int { + let x: Int <- x1, y: Int <-y1 in { + x <- x + a; + y <- y + a; + if b then x + y else x - y fi; + } + }; +}; +class D inherits B { + d: IO <- new Main.main(); + test3(x1: Int, y1: Int): IO { + let x: Int <- x1, y: Int <-y1, c: String <- "C" in { + x <- x + a; + y <- y + a; + if b then new IO.out_string(c) else d fi; + } + }; +}; +class C inherits B { + c: String <- "C"; + test2(x1: Int, y1: Int): IO { + let x: Int <- x1, y: Int <-y1 in { + x <- x + a; + y <- y + a; + if b then new IO.out_string(c) else d fi; + } + }; +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!") }; +}; \ No newline at end of file diff --git a/src/tester/semantic/attributes4_error.txt b/src/tester/semantic/attributes4_error.txt new file mode 100644 index 000000000..fa5fcfa89 --- /dev/null +++ b/src/tester/semantic/attributes4_error.txt @@ -0,0 +1 @@ +(32, 49) - NameError: Undeclared identifier d. \ No newline at end of file diff --git a/src/tester/semantic/basics1.cl b/src/tester/semantic/basics1.cl new file mode 100644 index 000000000..32ae16564 --- /dev/null +++ b/src/tester/semantic/basics1.cl @@ -0,0 +1,10 @@ +-- It is an error to redefine the IO class. + +class IO { + scan(): String { ":)" }; + print(s: String): IO { new IO }; +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; \ No newline at end of file diff --git a/src/tester/semantic/basics1_error.txt b/src/tester/semantic/basics1_error.txt new file mode 100644 index 000000000..676f5049c --- /dev/null +++ b/src/tester/semantic/basics1_error.txt @@ -0,0 +1 @@ +(3, 7) - SemanticError: Redefinition of basic class IO. diff --git a/src/tester/semantic/basics2.cl b/src/tester/semantic/basics2.cl new file mode 100644 index 000000000..cf2b1cd2f --- /dev/null +++ b/src/tester/semantic/basics2.cl @@ -0,0 +1,9 @@ +-- It is an error to inherit from or redefine Int. + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; + +class A inherits Int { + is_prime(): Bool { false }; +}; diff --git a/src/tester/semantic/basics2_error.txt b/src/tester/semantic/basics2_error.txt new file mode 100644 index 000000000..69a3b6814 --- /dev/null +++ b/src/tester/semantic/basics2_error.txt @@ -0,0 +1 @@ +(7, 18) - SemanticError: Class A cannot inherit class Int. diff --git a/src/tester/semantic/basics3.cl b/src/tester/semantic/basics3.cl new file mode 100644 index 000000000..fef017a8d --- /dev/null +++ b/src/tester/semantic/basics3.cl @@ -0,0 +1,9 @@ +-- It is an error to inherit from or redefine Int. + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; + +class Int { + is_prime(): Bool { false }; +}; \ No newline at end of file diff --git a/src/tester/semantic/basics3_error.txt b/src/tester/semantic/basics3_error.txt new file mode 100644 index 000000000..d8f80cb12 --- /dev/null +++ b/src/tester/semantic/basics3_error.txt @@ -0,0 +1 @@ +(7, 7) - SemanticError: Redefinition of basic class Int. diff --git a/src/tester/semantic/basics4.cl b/src/tester/semantic/basics4.cl new file mode 100644 index 000000000..9266ec79b --- /dev/null +++ b/src/tester/semantic/basics4.cl @@ -0,0 +1,9 @@ +-- It is an error to inherit from or redefine String. + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; + +class A inherits String { + is_palindrome(): Bool { false }; +}; \ No newline at end of file diff --git a/src/tester/semantic/basics4_error.txt b/src/tester/semantic/basics4_error.txt new file mode 100644 index 000000000..d5cd4c3db --- /dev/null +++ b/src/tester/semantic/basics4_error.txt @@ -0,0 +1 @@ +(7, 18) - SemanticError: Class A cannot inherit class String. diff --git a/src/tester/semantic/basics5.cl b/src/tester/semantic/basics5.cl new file mode 100644 index 000000000..bad5eff13 --- /dev/null +++ b/src/tester/semantic/basics5.cl @@ -0,0 +1,9 @@ +-- It is an error to inherit from or redefine String. + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; + +class String { + is_palindrome(): Bool { false }; +}; \ No newline at end of file diff --git a/src/tester/semantic/basics5_error.txt b/src/tester/semantic/basics5_error.txt new file mode 100644 index 000000000..8437accf7 --- /dev/null +++ b/src/tester/semantic/basics5_error.txt @@ -0,0 +1 @@ +(7, 7) - SemanticError: Redefinition of basic class String. diff --git a/src/tester/semantic/basics6.cl b/src/tester/semantic/basics6.cl new file mode 100644 index 000000000..47266ebed --- /dev/null +++ b/src/tester/semantic/basics6.cl @@ -0,0 +1,9 @@ +-- It is an error to inherit from or redefine Bool. + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; + +class A inherits Bool { + xor(b: Bool): Bool { false }; +}; \ No newline at end of file diff --git a/src/tester/semantic/basics6_error.txt b/src/tester/semantic/basics6_error.txt new file mode 100644 index 000000000..b4d22da13 --- /dev/null +++ b/src/tester/semantic/basics6_error.txt @@ -0,0 +1 @@ +(7, 18) - SemanticError: Class A cannot inherit class Bool. diff --git a/src/tester/semantic/basics7.cl b/src/tester/semantic/basics7.cl new file mode 100644 index 000000000..0f30aaec3 --- /dev/null +++ b/src/tester/semantic/basics7.cl @@ -0,0 +1,9 @@ +-- It is an error to inherit from or redefine Bool. + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; + +class Bool { + xor(b: Bool): Bool { false }; +}; \ No newline at end of file diff --git a/src/tester/semantic/basics7_error.txt b/src/tester/semantic/basics7_error.txt new file mode 100644 index 000000000..92660ab9f --- /dev/null +++ b/src/tester/semantic/basics7_error.txt @@ -0,0 +1 @@ +(7, 7) - SemanticError: Redefinition of basic class Bool. diff --git a/src/tester/semantic/basics8.cl b/src/tester/semantic/basics8.cl new file mode 100644 index 000000000..3b9697d4f --- /dev/null +++ b/src/tester/semantic/basics8.cl @@ -0,0 +1,9 @@ +-- It is an error redefine Object. + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; + +class Object { + xor(b: Bool): Bool { false }; +}; \ No newline at end of file diff --git a/src/tester/semantic/basics8_error.txt b/src/tester/semantic/basics8_error.txt new file mode 100644 index 000000000..652f47b30 --- /dev/null +++ b/src/tester/semantic/basics8_error.txt @@ -0,0 +1 @@ +(7, 7) - SemanticError: Redefinition of basic class Object. diff --git a/src/tester/semantic/blocks1.cl b/src/tester/semantic/blocks1.cl new file mode 100644 index 000000000..1e928908b --- /dev/null +++ b/src/tester/semantic/blocks1.cl @@ -0,0 +1,31 @@ +--The static type of a block is the static type of the last expression. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test: B <- { + new A; + { + new B; + { + new C; + { + new D; + { + new E; + { + new F; + }; + }; + }; + }; + }; + }; +}; \ No newline at end of file diff --git a/src/tester/semantic/blocks1_error.txt b/src/tester/semantic/blocks1_error.txt new file mode 100644 index 000000000..2f0e2caf3 --- /dev/null +++ b/src/tester/semantic/blocks1_error.txt @@ -0,0 +1 @@ +(13, 16) - TypeError: Inferred type F of initialization of attribute test does not conform to declared type B. diff --git a/src/tester/semantic/case1.cl b/src/tester/semantic/case1.cl new file mode 100644 index 000000000..82c6a4d61 --- /dev/null +++ b/src/tester/semantic/case1.cl @@ -0,0 +1,23 @@ +--For each branch, let Ti be the static type of . The static type of a case expression is Join 1≤i≤n Ti. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + b: B <- case "true" of + i: Int => New C; + b: Bool => New D; + s: String => New E; + esac; + + test: B <- case 0 of + b: Bool => new F; + i: Int => new E; + esac; +}; diff --git a/src/tester/semantic/case1_error.txt b/src/tester/semantic/case1_error.txt new file mode 100644 index 000000000..f05ce31b9 --- /dev/null +++ b/src/tester/semantic/case1_error.txt @@ -0,0 +1 @@ +(19, 16) - TypeError: Inferred type A of initialization of attribute test does not conform to declared type B. diff --git a/src/tester/semantic/case2.cl b/src/tester/semantic/case2.cl new file mode 100644 index 000000000..ae97b41da --- /dev/null +++ b/src/tester/semantic/case2.cl @@ -0,0 +1,23 @@ +-- The variables declared on each branch of a case must all have distinct types. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + b: B <- case "true" of + i: Int => New C; + b: Bool => New D; + s: String => New E; + esac; + + test: A <- case 0 of + b: Bool => new F; + i: Bool => new E; + esac; +}; \ No newline at end of file diff --git a/src/tester/semantic/case2_error.txt b/src/tester/semantic/case2_error.txt new file mode 100644 index 000000000..302fec38c --- /dev/null +++ b/src/tester/semantic/case2_error.txt @@ -0,0 +1 @@ +(21, 20) - SemanticError: Duplicate branch Bool in case statement. \ No newline at end of file diff --git a/src/tester/semantic/case3.cl b/src/tester/semantic/case3.cl new file mode 100644 index 000000000..da79bbfe6 --- /dev/null +++ b/src/tester/semantic/case3.cl @@ -0,0 +1,23 @@ +-- Missing type + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + b: B <- case "true" of + i: Int => New C; + b: Bool => New D; + s: String => New E; + esac; + + test: A <- case 0 of + b: Bool => new F; + i: Ball => new E; + esac; +}; \ No newline at end of file diff --git a/src/tester/semantic/case3_error.txt b/src/tester/semantic/case3_error.txt new file mode 100644 index 000000000..fea261e5b --- /dev/null +++ b/src/tester/semantic/case3_error.txt @@ -0,0 +1 @@ +(21, 20) - TypeError: Class Ball of case branch is undefined. \ No newline at end of file diff --git a/src/tester/semantic/class1.cl b/src/tester/semantic/class1.cl new file mode 100644 index 000000000..ed83da9d1 --- /dev/null +++ b/src/tester/semantic/class1.cl @@ -0,0 +1,9 @@ +-- Classes may not be redefined. + +class Repeat { + sum(a: Int, b: Int): Int { a + b }; +}; + +class Repeat { + mult(a: Int, b: Int): Int { a * b }; +}; \ No newline at end of file diff --git a/src/tester/semantic/class1_error.txt b/src/tester/semantic/class1_error.txt new file mode 100644 index 000000000..19c507672 --- /dev/null +++ b/src/tester/semantic/class1_error.txt @@ -0,0 +1,2 @@ +(7, 5) - SemanticError: Classes may not be redefined + diff --git a/src/tester/semantic/conditionals1.cl b/src/tester/semantic/conditionals1.cl new file mode 100644 index 000000000..3446a8b0f --- /dev/null +++ b/src/tester/semantic/conditionals1.cl @@ -0,0 +1,14 @@ +--The predicate must have static type Bool. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + a: A <- if new F then new D else new C fi; +}; \ No newline at end of file diff --git a/src/tester/semantic/conditionals1_error.txt b/src/tester/semantic/conditionals1_error.txt new file mode 100644 index 000000000..b86345359 --- /dev/null +++ b/src/tester/semantic/conditionals1_error.txt @@ -0,0 +1 @@ +(13, 16) - TypeError: Predicate of 'if' does not have type Bool. diff --git a/src/tester/semantic/conditionals2.cl b/src/tester/semantic/conditionals2.cl new file mode 100644 index 000000000..9d6313d75 --- /dev/null +++ b/src/tester/semantic/conditionals2.cl @@ -0,0 +1,24 @@ +(* +Let T and F be the static types of the branches of the conditional. Then the static type of the +conditional is T t F. (think: Walk towards Object from each of T and F until the paths meet.) +*) + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + b: B <- if true then + new C + else + if false then new D + else new E fi + fi; + + test: B <- if not true then new F else new E fi; +}; diff --git a/src/tester/semantic/conditionals2_error.txt b/src/tester/semantic/conditionals2_error.txt new file mode 100644 index 000000000..d6f5fc307 --- /dev/null +++ b/src/tester/semantic/conditionals2_error.txt @@ -0,0 +1,2 @@ +(23, 16) - TypeError: Inferred type A of initialization of attribute test does not conform to declared type B. + diff --git a/src/tester/semantic/dispatch1.cl b/src/tester/semantic/dispatch1.cl new file mode 100644 index 000000000..1c0457fa3 --- /dev/null +++ b/src/tester/semantic/dispatch1.cl @@ -0,0 +1,33 @@ +(* +e0 .f(e1, . . . , en ) +Assume e0 has static type A. +Class A must have a method f +*) + +class A inherits IO { + f(x: Int, y: Int): Int { x + y }; + g(x: Int): Int { x + x }; +}; +class B inherits A { + f(a: Int, b: Int): Int { a - b }; +}; +class C inherits B { + ident(m: Int): Int { m }; + f(m: Int, n: Int): Int { m * n }; +}; +class D inherits B { + ident(v: String): IO { new IO.out_string(v) }; + f(v: Int, w: Int): Int { v / w }; + g(v: Int): Int { v + v + v }; + + back(s: String): B { { + out_string(s); + self; + } }; +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test: B <- new D.back("Hello ").back("World!"); +}; \ No newline at end of file diff --git a/src/tester/semantic/dispatch1_error.txt b/src/tester/semantic/dispatch1_error.txt new file mode 100644 index 000000000..7fb22edce --- /dev/null +++ b/src/tester/semantic/dispatch1_error.txt @@ -0,0 +1 @@ +(32, 37) - AttributeError: Dispatch to undefined method back. diff --git a/src/tester/semantic/dispatch2.cl b/src/tester/semantic/dispatch2.cl new file mode 100644 index 000000000..5182912b8 --- /dev/null +++ b/src/tester/semantic/dispatch2.cl @@ -0,0 +1,34 @@ +(* +e0 .f(e1, . . . , en ) +Assume e0 has static type A. +Class A must have a method f +the dispatch and the definition of f must have the same number of arguments +*) + +class A inherits IO { + f(x: Int, y: Int): Int { x + y }; + g(x: Int): Int { x + x }; +}; +class B inherits A { + f(a: Int, b: Int): Int { a - b }; +}; +class C inherits B { + ident(m: Int): Int { m }; + f(m: Int, n: Int): Int { m * n }; +}; +class D inherits B { + ident(v: String): IO { new IO.out_string(v) }; + f(v: Int, w: Int): Int { v / w }; + g(v: Int): Int { v + v + v }; + + back(s: String): B { { + out_string(s); + self; + } }; +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test: Int <- new D.back("Hello ").g(2, 2); +}; \ No newline at end of file diff --git a/src/tester/semantic/dispatch2_error.txt b/src/tester/semantic/dispatch2_error.txt new file mode 100644 index 000000000..a86c35340 --- /dev/null +++ b/src/tester/semantic/dispatch2_error.txt @@ -0,0 +1 @@ +(33, 39) - SemanticError: Method g called with wrong number of arguments. diff --git a/src/tester/semantic/dispatch3.cl b/src/tester/semantic/dispatch3.cl new file mode 100644 index 000000000..ecb1535db --- /dev/null +++ b/src/tester/semantic/dispatch3.cl @@ -0,0 +1,36 @@ +(* +e0 .f(e1, . . . , en ) +Assume e0 has static type A. +Class A must have a method f +the static type of the ith actual parameter must conform to the declared type of the ith formal parameter. +*) + +class A inherits IO { + f(x: Int, y: Int): Int { x + y }; + g(x: Int): Int { x + x }; +}; +class B inherits A { + f(a: Int, b: Int): Int { a - b }; +}; +class C inherits B { + ident(m: Int): Int { m }; + f(m: Int, n: Int): Int { m * n }; +}; +class D inherits B { + ident(v: String): IO { new IO.out_string(v) }; + f(v: Int, w: Int): Int { v / w }; + g(v: Int): Int { v + v + v }; + + back(s: String): B { { + out_string(s); + self; + } }; + + alphabet(a: A, b: B, c: C): D { self }; +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test: B <- new D.alphabet(new D, new D, new D.back("Hello ")).back("World!"); +}; \ No newline at end of file diff --git a/src/tester/semantic/dispatch3_error.txt b/src/tester/semantic/dispatch3_error.txt new file mode 100644 index 000000000..0def5cf03 --- /dev/null +++ b/src/tester/semantic/dispatch3_error.txt @@ -0,0 +1 @@ +(35, 45) - TypeError: In call of method alphabet, type B of parameter c does not conform to declared type C. diff --git a/src/tester/semantic/dispatch4.cl b/src/tester/semantic/dispatch4.cl new file mode 100644 index 000000000..9cadd8332 --- /dev/null +++ b/src/tester/semantic/dispatch4.cl @@ -0,0 +1,36 @@ +(* +e0 .f(e1, . . . , en ) +Assume e0 has static type A. +Class A must have a method f +If f has return type B and B is a class name, then the static type of the dispatch is B. +*) + +class A inherits IO { + f(x: Int, y: Int): Int { x + y }; + g(x: Int): Int { x + x }; +}; +class B inherits A { + f(a: Int, b: Int): Int { a - b }; +}; +class C inherits B { + ident(m: Int): Int { m }; + f(m: Int, n: Int): Int { m * n }; +}; +class D inherits B { + ident(v: String): IO { new IO.out_string(v) }; + f(v: Int, w: Int): Int { v / w }; + g(v: Int): Int { v + v + v }; + + back(s: String): B { { + out_string(s); + self; + } }; + + alphabet(a: A, b: B, c: C): D { self }; +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test: D <- new D.alphabet(new D, new D.back("Hello "), new C).back("World!"); +}; \ No newline at end of file diff --git a/src/tester/semantic/dispatch4_error.txt b/src/tester/semantic/dispatch4_error.txt new file mode 100644 index 000000000..9699f166b --- /dev/null +++ b/src/tester/semantic/dispatch4_error.txt @@ -0,0 +1 @@ +(35, 16) - TypeError: Inferred type B of initialization of attribute test does not conform to declared type D. \ No newline at end of file diff --git a/src/tester/semantic/dispatch5.cl b/src/tester/semantic/dispatch5.cl new file mode 100644 index 000000000..b4437b1b4 --- /dev/null +++ b/src/tester/semantic/dispatch5.cl @@ -0,0 +1,31 @@ +(* +(,...,) is shorthand for self.(,...,). +*) + +class A inherits IO { + f(x: Int, y: Int): Int { x + y }; + g(x: Int): Int { x + x }; +}; +class B inherits A { + f(a: Int, b: Int): Int { a - b }; +}; +class C inherits B { + ident(m: Int): Int { m }; + f(m: Int, n: Int): Int { m * n }; + sum(m: Int, n: Int, p: Int): Int { m + n + p }; +}; +class D inherits B { + ident(v: String): IO { new IO.out_string(v) }; + f(v: Int, w: Int): Int { v / w }; + + back(s: String): B { { + out_string(s); + g(2); + sum(1, 2, 3); + self; + } }; +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; \ No newline at end of file diff --git a/src/tester/semantic/dispatch5_error.txt b/src/tester/semantic/dispatch5_error.txt new file mode 100644 index 000000000..d26bf34a1 --- /dev/null +++ b/src/tester/semantic/dispatch5_error.txt @@ -0,0 +1 @@ +(24, 9) - AttributeError: Dispatch to undefined method sum. diff --git a/src/tester/semantic/dispatch6.cl b/src/tester/semantic/dispatch6.cl new file mode 100644 index 000000000..fcc033f2c --- /dev/null +++ b/src/tester/semantic/dispatch6.cl @@ -0,0 +1,32 @@ +(* +e@B.f() invokes the method +f in class B on the object that is the value of e. For this form of dispatch, the static type to the left of +“@”must conform to the type specified to the right of “@”. +*) + +class A { + f(x: Int, y: Int): Int { x + y }; + g(x: Int): Int { x + x }; +}; +class B inherits A { + f(a: Int, b: Int): Int { a - b }; + sum(m: Int, n: Int, p: Int): Int { m + n + p }; +}; +class C inherits B { + ident(m: Int): Int { m }; + f(m: Int, n: Int): Int { m * n }; +}; +class D inherits B { + ident(v: String): IO { new IO.out_string(v) }; + f(v: Int, w: Int): Int { v / w }; + g(v: Int): Int { v + v + v }; + sum(v: Int, w: Int, z: Int): Int { v - w - z }; +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + a: A <- new D; + b: Int <- new D@B.sum(1, 2, 3); + test: Int <- a@B.sum(1, 2, 3); +}; diff --git a/src/tester/semantic/dispatch6_error.txt b/src/tester/semantic/dispatch6_error.txt new file mode 100644 index 000000000..ae9184b2f --- /dev/null +++ b/src/tester/semantic/dispatch6_error.txt @@ -0,0 +1 @@ +(31, 18) - TypeError: Expression type A does not conform to declared static dispatch type B. diff --git a/src/tester/semantic/eq1.cl b/src/tester/semantic/eq1.cl new file mode 100644 index 000000000..88f2a7ffe --- /dev/null +++ b/src/tester/semantic/eq1.cl @@ -0,0 +1,17 @@ +(* +The comparison = is a special +case. If either or has static type Int, Bool, or String, then the other must have the +same static type. Any other types, including SELF TYPE, may be freely compared. +*) + +class A { }; +class B inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + x: Bool <- 1 = 2; + test: Bool <- 1 = new A; + y: Bool <- "1" = "2"; + z: Bool <- true = not false; +}; \ No newline at end of file diff --git a/src/tester/semantic/eq1_error.txt b/src/tester/semantic/eq1_error.txt new file mode 100644 index 000000000..f81425683 --- /dev/null +++ b/src/tester/semantic/eq1_error.txt @@ -0,0 +1 @@ +(14, 21) - TypeError: Illegal comparison with a basic type. diff --git a/src/tester/semantic/eq2.cl b/src/tester/semantic/eq2.cl new file mode 100644 index 000000000..d76852780 --- /dev/null +++ b/src/tester/semantic/eq2.cl @@ -0,0 +1,17 @@ +(* +The comparison = is a special +case. If either or has static type Int, Bool, or String, then the other must have the +same static type. Any other types, including SELF TYPE, may be freely compared. +*) + +class A { }; +class B inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + x: Bool <- 1 = 2; + y: Bool <- "1" = "2"; + test: Bool <- "1" = new B; + z: Bool <- true = not false; +}; diff --git a/src/tester/semantic/eq2_error.txt b/src/tester/semantic/eq2_error.txt new file mode 100644 index 000000000..a44ab0d51 --- /dev/null +++ b/src/tester/semantic/eq2_error.txt @@ -0,0 +1 @@ +(15, 23) - TypeError: Illegal comparison with a basic type. diff --git a/src/tester/semantic/eq3.cl b/src/tester/semantic/eq3.cl new file mode 100644 index 000000000..4dad693ee --- /dev/null +++ b/src/tester/semantic/eq3.cl @@ -0,0 +1,17 @@ +(* +The comparison = is a special +case. If either or has static type Int, Bool, or String, then the other must have the +same static type. Any other types, including SELF TYPE, may be freely compared. +*) + +class A { }; +class B inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + x: Bool <- 1 = 2; + y: Bool <- "1" = "2"; + z: Bool <- true = not false; + test: Bool <- "true" = not false; +}; diff --git a/src/tester/semantic/eq3_error.txt b/src/tester/semantic/eq3_error.txt new file mode 100644 index 000000000..c4e27eb8a --- /dev/null +++ b/src/tester/semantic/eq3_error.txt @@ -0,0 +1 @@ +(16, 26) - TypeError: Illegal comparison with a basic type. diff --git a/src/tester/semantic/eq4.cl b/src/tester/semantic/eq4.cl new file mode 100644 index 000000000..11afc119f --- /dev/null +++ b/src/tester/semantic/eq4.cl @@ -0,0 +1,17 @@ +(* +The comparison = is a special +case. If either or has static type Int, Bool, or String, then the other must have the +same static type. Any other types, including SELF TYPE, may be freely compared. The result is a Bool. +*) + +class A { }; +class B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + x: Bool <- 1 = 2; + y: Bool <- "1" = "2"; + z: Bool <- new A = new B; + test: Int <- new A = new B; +}; diff --git a/src/tester/semantic/eq4_error.txt b/src/tester/semantic/eq4_error.txt new file mode 100644 index 000000000..3ead21d0e --- /dev/null +++ b/src/tester/semantic/eq4_error.txt @@ -0,0 +1 @@ +(16, 18) - TypeError: Inferred type Bool of initialization of attribute test does not conform to declared type Int. diff --git a/src/tester/semantic/features1.cl b/src/tester/semantic/features1.cl new file mode 100644 index 000000000..66f650f4a --- /dev/null +++ b/src/tester/semantic/features1.cl @@ -0,0 +1,19 @@ +(* +No method name may be defined multiple times in +a class, and no attribute name may be defined multiple times in a class, but a method and an attribute +may have the same name. +*) + +class Main inherits IO { + main(): IO { out_string("hi!") }; + + main: IO <- out_string("bye!"); +}; + +class A { + x: Int <- 3; + + x(): Int { 3 }; + + x: String <- ":)"; +}; \ No newline at end of file diff --git a/src/tester/semantic/features1_error.txt b/src/tester/semantic/features1_error.txt new file mode 100644 index 000000000..40033e9b3 --- /dev/null +++ b/src/tester/semantic/features1_error.txt @@ -0,0 +1 @@ +(18, 5) - SemanticError: Attribute x is multiply defined in class. \ No newline at end of file diff --git a/src/tester/semantic/features2.cl b/src/tester/semantic/features2.cl new file mode 100644 index 000000000..5b1f7e9df --- /dev/null +++ b/src/tester/semantic/features2.cl @@ -0,0 +1,19 @@ +(* +No method name may be defined multiple times in +a class, and no attribute name may be defined multiple times in a class, but a method and an attribute +may have the same name. +*) + +class Main inherits IO { + main(): IO { out_string("hi!") }; + + main: IO <- out_string("bye!"); +}; + +class A { + x: Int <- 3; + + x(): String { "3" }; + + x(): String { ":)" }; +}; \ No newline at end of file diff --git a/src/tester/semantic/features2_error.txt b/src/tester/semantic/features2_error.txt new file mode 100644 index 000000000..117e06042 --- /dev/null +++ b/src/tester/semantic/features2_error.txt @@ -0,0 +1 @@ +(18, 5) - SemanticError: Method x is multiply defined. \ No newline at end of file diff --git a/src/tester/semantic/features3.cl b/src/tester/semantic/features3.cl new file mode 100644 index 000000000..3e75c88bb --- /dev/null +++ b/src/tester/semantic/features3.cl @@ -0,0 +1,15 @@ +-- Missing type + +class Main inherits IO { + main(): IO { not a+b}; + + main: IO <- out_string("bye!"); +}; + +class A { + x: Int <- 3; + + x(): Int { 3 }; + + c: Cadena; +}; \ No newline at end of file diff --git a/src/tester/semantic/features3_error.txt b/src/tester/semantic/features3_error.txt new file mode 100644 index 000000000..53f1abe26 --- /dev/null +++ b/src/tester/semantic/features3_error.txt @@ -0,0 +1 @@ +(14, 8) - TypeError: Class Cadena of attribute c is undefined. \ No newline at end of file diff --git a/src/tester/semantic/inheritance1.cl b/src/tester/semantic/inheritance1.cl new file mode 100644 index 000000000..1d92da307 --- /dev/null +++ b/src/tester/semantic/inheritance1.cl @@ -0,0 +1,19 @@ +--It is illegal to redefine attribute names. + +class Main inherits IO { + main(): IO { out_string("hi!") }; + + main: IO <- out_string("bye!"); +}; + +class A { + x: Int <- 3; + + x(): String { ":)" }; +}; + +class B inherits A { + x: Int; + + div(a: Int, b: Int): Int { a / b}; +}; \ No newline at end of file diff --git a/src/tester/semantic/inheritance1_error.txt b/src/tester/semantic/inheritance1_error.txt new file mode 100644 index 000000000..ec5b504e6 --- /dev/null +++ b/src/tester/semantic/inheritance1_error.txt @@ -0,0 +1 @@ +(16, 5) - SemanticError: Attribute x is an attribute of an inherited class. \ No newline at end of file diff --git a/src/tester/semantic/inheritance2.cl b/src/tester/semantic/inheritance2.cl new file mode 100644 index 000000000..d453eca09 --- /dev/null +++ b/src/tester/semantic/inheritance2.cl @@ -0,0 +1,19 @@ +--If C inherits from P, then P must have a class definition somewhere in the program. + +class Main inherits IO { + main(): IO { out_string("hi!") }; + + main: IO <- out_string("bye!"); +}; + +class Alo { + x: Int <- 3; + + x(): String { "3" }; +}; + +class B inherits A { + div(a: Int, b: Int): Int { a / b}; + + x: String <- "2"; +}; \ No newline at end of file diff --git a/src/tester/semantic/inheritance2_error.txt b/src/tester/semantic/inheritance2_error.txt new file mode 100644 index 000000000..1ec7669b5 --- /dev/null +++ b/src/tester/semantic/inheritance2_error.txt @@ -0,0 +1 @@ +(15, 18) - TypeError: Class B inherits from an undefined class A. \ No newline at end of file diff --git a/src/tester/semantic/inheritance3.cl b/src/tester/semantic/inheritance3.cl new file mode 100644 index 000000000..3ff170dec --- /dev/null +++ b/src/tester/semantic/inheritance3.cl @@ -0,0 +1,13 @@ +--The parent-child relation on classes defines a graph. This graph may not contain cycles. + +class Main inherits IO { + main(): IO { out_string("hi!") }; + + main: IO <- out_string("bye!"); +}; + +class A inherits A { + x: Int <- 3; + + x(): String { ":)" }; +}; \ No newline at end of file diff --git a/src/tester/semantic/inheritance3_error.txt b/src/tester/semantic/inheritance3_error.txt new file mode 100644 index 000000000..d17ca7f49 --- /dev/null +++ b/src/tester/semantic/inheritance3_error.txt @@ -0,0 +1 @@ +(9, 18) - SemanticError: Class A, or an ancestor of A, is involved in an inheritance cycle. \ No newline at end of file diff --git a/src/tester/semantic/inheritance4.cl b/src/tester/semantic/inheritance4.cl new file mode 100644 index 000000000..c985484ba --- /dev/null +++ b/src/tester/semantic/inheritance4.cl @@ -0,0 +1,19 @@ +--The parent-child relation on classes defines a graph. This graph may not contain cycles. + +class Main inherits IO { + main(): IO { out_string("hi!") }; + + main: IO <- out_string("bye!"); +}; + +class A inherits B { + x: Int <- 3; + + x(): String { ":)" }; +}; + +class B inherits A { + y: Int <- 2; + + div(a: Int, b: Int): Int { a / b}; +}; \ No newline at end of file diff --git a/src/tester/semantic/inheritance4_error.txt b/src/tester/semantic/inheritance4_error.txt new file mode 100644 index 000000000..b437ec667 --- /dev/null +++ b/src/tester/semantic/inheritance4_error.txt @@ -0,0 +1 @@ +(15, 18) - SemanticError: Class B, or an ancestor of B, is involved in an inheritance cycle. \ No newline at end of file diff --git a/src/tester/semantic/inheritance5.cl b/src/tester/semantic/inheritance5.cl new file mode 100644 index 000000000..f6ed885c8 --- /dev/null +++ b/src/tester/semantic/inheritance5.cl @@ -0,0 +1,21 @@ +--The parent-child relation on classes defines a graph. This graph may not contain cycles. + +class Main inherits IO { + main(): IO { out_string("hi!") }; + + main: IO <- out_string("bye!"); +}; + +class A inherits B { + x: Int <- 3; + + x(): String { ":)" }; +}; + +class B inherits C { + y: Int <- 2; + + div(a: Int, b: Int): Int { a / b}; +}; + +class C inherits A { }; \ No newline at end of file diff --git a/src/tester/semantic/inheritance5_error.txt b/src/tester/semantic/inheritance5_error.txt new file mode 100644 index 000000000..da72ba547 --- /dev/null +++ b/src/tester/semantic/inheritance5_error.txt @@ -0,0 +1 @@ +(21, 18) - SemanticError: Class C, or an ancestor of C, is involved in an inheritance cycle. \ No newline at end of file diff --git a/src/tester/semantic/isvoid1.cl b/src/tester/semantic/isvoid1.cl new file mode 100644 index 000000000..072720d85 --- /dev/null +++ b/src/tester/semantic/isvoid1.cl @@ -0,0 +1,26 @@ +--evaluates to true if expr is void and evaluates to false if expr is not void. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + b: B <- if isvoid new F then + new C + else + if false then new D + else new E fi + fi; + + test: B <- isvoid if isvoid new F then + new C + else + if false then new D + else new E fi + fi; +}; \ No newline at end of file diff --git a/src/tester/semantic/isvoid1_error.txt b/src/tester/semantic/isvoid1_error.txt new file mode 100644 index 000000000..0922de909 --- /dev/null +++ b/src/tester/semantic/isvoid1_error.txt @@ -0,0 +1 @@ +(20, 16) - TypeError: Inferred type Bool of initialization of attribute test does not conform to declared type B. diff --git a/src/tester/semantic/let1.cl b/src/tester/semantic/let1.cl new file mode 100644 index 000000000..26ef63026 --- /dev/null +++ b/src/tester/semantic/let1.cl @@ -0,0 +1,15 @@ +--The type of an initialization expression must conform to the declared type of the identifier. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + b: B <- let a: Bool, a: Int <- 5, a: String, a: A <- new F, b: B <- new E in b; + test: B <- let a: Bool, a: Int <- 5, a: String, a: A <- new F, b: C <- new E in b; +}; \ No newline at end of file diff --git a/src/tester/semantic/let1_error.txt b/src/tester/semantic/let1_error.txt new file mode 100644 index 000000000..16ecf780c --- /dev/null +++ b/src/tester/semantic/let1_error.txt @@ -0,0 +1 @@ +(14, 76) - TypeError: Inferred type E of initialization of b does not conform to identifier's declared type C. diff --git a/src/tester/semantic/let2.cl b/src/tester/semantic/let2.cl new file mode 100644 index 000000000..c5956ead3 --- /dev/null +++ b/src/tester/semantic/let2.cl @@ -0,0 +1,15 @@ +--The type of let is the type of the body. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + b: B <- let a: Bool, a: Int <- 5, a: String, a: A <- new F, b: B <- new E in b; + test: B <- let a: Bool, a: Int <- 5, a: String, a: A <- new F, b: A <- new E in b; +}; \ No newline at end of file diff --git a/src/tester/semantic/let2_error.txt b/src/tester/semantic/let2_error.txt new file mode 100644 index 000000000..b1e8a365d --- /dev/null +++ b/src/tester/semantic/let2_error.txt @@ -0,0 +1 @@ +(14, 16) - TypeError: Inferred type A of initialization of attribute test does not conform to declared type B. diff --git a/src/tester/semantic/let3.cl b/src/tester/semantic/let3.cl new file mode 100644 index 000000000..8c0670ab8 --- /dev/null +++ b/src/tester/semantic/let3.cl @@ -0,0 +1,15 @@ +-- Missing type + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + b: B <- let a: Bool, a: Int <- 5, a: String, a: A <- new F, b: B <- new E in b; + test: B <- let a: Bool, a: Int <- 5, a: String, a: A <- new F, b: Cadena in new B; +}; \ No newline at end of file diff --git a/src/tester/semantic/let3_error.txt b/src/tester/semantic/let3_error.txt new file mode 100644 index 000000000..39c5315d8 --- /dev/null +++ b/src/tester/semantic/let3_error.txt @@ -0,0 +1 @@ +(14, 71) - TypeError: Class Cadena of let-bound identifier b is undefined. \ No newline at end of file diff --git a/src/tester/semantic/loops1.cl b/src/tester/semantic/loops1.cl new file mode 100644 index 000000000..de3a624d2 --- /dev/null +++ b/src/tester/semantic/loops1.cl @@ -0,0 +1,8 @@ +--The predicate must have static type Bool. + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + i: Int <- 1; + test: Object <- while "true" loop i <- i + 1 pool; +}; \ No newline at end of file diff --git a/src/tester/semantic/loops1_error.txt b/src/tester/semantic/loops1_error.txt new file mode 100644 index 000000000..b160214b4 --- /dev/null +++ b/src/tester/semantic/loops1_error.txt @@ -0,0 +1 @@ +(7, 27) - TypeError: Loop condition does not have type Bool. \ No newline at end of file diff --git a/src/tester/semantic/loops2.cl b/src/tester/semantic/loops2.cl new file mode 100644 index 000000000..dea69fa14 --- /dev/null +++ b/src/tester/semantic/loops2.cl @@ -0,0 +1,9 @@ +--The static type of a loop expression is Object. + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + i: Int <- 1; + test: Object <- while not false loop i <- i + 1 pool; + test2: Int <- while not false loop i <- i + 1 pool; +}; diff --git a/src/tester/semantic/loops2_error.txt b/src/tester/semantic/loops2_error.txt new file mode 100644 index 000000000..9711cdf6a --- /dev/null +++ b/src/tester/semantic/loops2_error.txt @@ -0,0 +1 @@ +(8, 19) - TypeError: Inferred type Object of initialization of attribute test2 does not conform to declared type Int. diff --git a/src/tester/semantic/methods1.cl b/src/tester/semantic/methods1.cl new file mode 100644 index 000000000..d12031970 --- /dev/null +++ b/src/tester/semantic/methods1.cl @@ -0,0 +1,12 @@ +--The identifiers used in the formal parameter list must be distinct + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test(a: A, a: B): Int { 4 }; +}; \ No newline at end of file diff --git a/src/tester/semantic/methods1_error.txt b/src/tester/semantic/methods1_error.txt new file mode 100644 index 000000000..06ab88a92 --- /dev/null +++ b/src/tester/semantic/methods1_error.txt @@ -0,0 +1 @@ +(11, 16) - SemanticError: Formal parameter a is multiply defined. diff --git a/src/tester/semantic/methods2.cl b/src/tester/semantic/methods2.cl new file mode 100644 index 000000000..3865f0e13 --- /dev/null +++ b/src/tester/semantic/methods2.cl @@ -0,0 +1,12 @@ +--The type of the method body must conform to the declared return type. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test(a: A, b: B): C { new D }; +}; \ No newline at end of file diff --git a/src/tester/semantic/methods2_error.txt b/src/tester/semantic/methods2_error.txt new file mode 100644 index 000000000..f7e4a330d --- /dev/null +++ b/src/tester/semantic/methods2_error.txt @@ -0,0 +1 @@ +(11, 27) - TypeError: Inferred return type D of method test does not conform to declared return type C. diff --git a/src/tester/semantic/methods3.cl b/src/tester/semantic/methods3.cl new file mode 100644 index 000000000..b92faeb97 --- /dev/null +++ b/src/tester/semantic/methods3.cl @@ -0,0 +1,14 @@ +--A formal parameter hides any definition of an attribute of the same name. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + a: C <- new C; + test(a: D): D { a }; + test2(a: B): C { a }; +}; \ No newline at end of file diff --git a/src/tester/semantic/methods3_error.txt b/src/tester/semantic/methods3_error.txt new file mode 100644 index 000000000..1165b7595 --- /dev/null +++ b/src/tester/semantic/methods3_error.txt @@ -0,0 +1 @@ +(13, 22) - TypeError: Inferred return type B of method test2 does not conform to declared return type C. diff --git a/src/tester/semantic/methods4.cl b/src/tester/semantic/methods4.cl new file mode 100644 index 000000000..be8fa36ef --- /dev/null +++ b/src/tester/semantic/methods4.cl @@ -0,0 +1,19 @@ +(* +The rule is +simple: If a class C inherits a method f from an ancestor class P, then C may override the inherited +definition of f provided the number of arguments, the types of the formal parameters, and the return +type are exactly the same in both definitions. +*) + +class A { + f(x: Int, y: Int): Int { x + y }; +}; +class B inherits A { + f(x: Int, y: Object): Int { x }; +}; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; \ No newline at end of file diff --git a/src/tester/semantic/methods4_error.txt b/src/tester/semantic/methods4_error.txt new file mode 100644 index 000000000..9f1486dec --- /dev/null +++ b/src/tester/semantic/methods4_error.txt @@ -0,0 +1 @@ +(12, 15) - SemanticError: In redefined method f, parameter type Object is different from original type Int. diff --git a/src/tester/semantic/methods5.cl b/src/tester/semantic/methods5.cl new file mode 100644 index 000000000..3905dfdd6 --- /dev/null +++ b/src/tester/semantic/methods5.cl @@ -0,0 +1,20 @@ +(* +The rule is +simple: If a class C inherits a method f from an ancestor class P, then C may override the inherited +definition of f provided the number of arguments, the types of the formal parameters, and the return +type are exactly the same in both definitions. +*) + +class A { + f(x: Int, y: Int): Int { x + y }; +}; +class B inherits A { + f(a: Int, b: Int): Object { a - b }; +}; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; + diff --git a/src/tester/semantic/methods5_error.txt b/src/tester/semantic/methods5_error.txt new file mode 100644 index 000000000..8b6bdf36e --- /dev/null +++ b/src/tester/semantic/methods5_error.txt @@ -0,0 +1 @@ +(12, 24) - SemanticError: In redefined method f, return type Object is different from original return type Int. diff --git a/src/tester/semantic/methods6.cl b/src/tester/semantic/methods6.cl new file mode 100644 index 000000000..dd2b73da6 --- /dev/null +++ b/src/tester/semantic/methods6.cl @@ -0,0 +1,27 @@ +(* +The rule is +simple: If a class C inherits a method f from an ancestor class P, then C may override the inherited +definition of f provided the number of arguments, the types of the formal parameters, and the return +type are exactly the same in both definitions. +*) + +class A { + f(x: Int, y: Int): Int { x + y }; + g(x: Int): Int { x + x }; +}; +class B inherits A { + f(a: Int, b: Int): Int { a - b }; +}; +class C inherits B { + ident(m: Int): Int { m }; + f(m: Int, n: Int): Int { m * n }; +}; +class D inherits B { + ident(v: String): IO { new IO.out_string(v) }; + f(v: Int, w: Int): Int { v / w }; + g(v: Int, w: Int, z: Int): Int { v + w + z }; +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; \ No newline at end of file diff --git a/src/tester/semantic/methods6_error.txt b/src/tester/semantic/methods6_error.txt new file mode 100644 index 000000000..8e32663b9 --- /dev/null +++ b/src/tester/semantic/methods6_error.txt @@ -0,0 +1 @@ +(22, 5) - SemanticError: Incompatible number of formal parameters in redefined method g. diff --git a/src/tester/semantic/methods7.cl b/src/tester/semantic/methods7.cl new file mode 100644 index 000000000..e5a01f682 --- /dev/null +++ b/src/tester/semantic/methods7.cl @@ -0,0 +1,12 @@ +-- Missing type + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test(a: A, b: Ball): Int { 4 }; +}; \ No newline at end of file diff --git a/src/tester/semantic/methods7_error.txt b/src/tester/semantic/methods7_error.txt new file mode 100644 index 000000000..472cbd9d1 --- /dev/null +++ b/src/tester/semantic/methods7_error.txt @@ -0,0 +1 @@ +(11, 19) - TypeError: Class Ball of formal parameter b is undefined. \ No newline at end of file diff --git a/src/tester/semantic/methods8.cl b/src/tester/semantic/methods8.cl new file mode 100644 index 000000000..3fccab54c --- /dev/null +++ b/src/tester/semantic/methods8.cl @@ -0,0 +1,12 @@ +-- Missing type + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test(a: A, b: B): Integrer { 4 }; +}; \ No newline at end of file diff --git a/src/tester/semantic/methods8_error.txt b/src/tester/semantic/methods8_error.txt new file mode 100644 index 000000000..dc9302ec0 --- /dev/null +++ b/src/tester/semantic/methods8_error.txt @@ -0,0 +1 @@ +(11, 23) - TypeError: Undefined return type Integrer in method test. \ No newline at end of file diff --git a/src/tester/semantic/new1.cl b/src/tester/semantic/new1.cl new file mode 100644 index 000000000..d007fc03d --- /dev/null +++ b/src/tester/semantic/new1.cl @@ -0,0 +1,31 @@ +-- Missing type + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test: F <- { + new A; + { + new Ball; + { + new C; + { + new D; + { + new E; + { + new F; + }; + }; + }; + }; + }; + }; +}; \ No newline at end of file diff --git a/src/tester/semantic/new1_error.txt b/src/tester/semantic/new1_error.txt new file mode 100644 index 000000000..612a3d427 --- /dev/null +++ b/src/tester/semantic/new1_error.txt @@ -0,0 +1 @@ +(16, 17) - TypeError: 'new' used with undefined class Ball. \ No newline at end of file diff --git a/src/tester/semantic/self1.cl b/src/tester/semantic/self1.cl new file mode 100644 index 000000000..3387fd263 --- /dev/null +++ b/src/tester/semantic/self1.cl @@ -0,0 +1,11 @@ +(* +But it is an error to assign to self or to bind self in a let, a +case, or as a formal parameter. It is also illegal to have attributes named self. +*) + + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test(a: Main): IO { self <- a }; +}; diff --git a/src/tester/semantic/self1_error.txt b/src/tester/semantic/self1_error.txt new file mode 100644 index 000000000..6beb3cda2 --- /dev/null +++ b/src/tester/semantic/self1_error.txt @@ -0,0 +1 @@ +(10, 30) - SemanticError: Cannot assign to 'self'. diff --git a/src/tester/semantic/self2.cl b/src/tester/semantic/self2.cl new file mode 100644 index 000000000..2e6921a92 --- /dev/null +++ b/src/tester/semantic/self2.cl @@ -0,0 +1,10 @@ +(* +But it is an error to assign to self or to bind self in a let, a +case, or as a formal parameter. It is also illegal to have attributes named self. +*) + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test(): IO { let self: Main <- new Main in self }; +}; diff --git a/src/tester/semantic/self2_error.txt b/src/tester/semantic/self2_error.txt new file mode 100644 index 000000000..20c883c91 --- /dev/null +++ b/src/tester/semantic/self2_error.txt @@ -0,0 +1 @@ +(9, 22) - SemanticError: 'self' cannot be bound in a 'let' expression. diff --git a/src/tester/semantic/self3.cl b/src/tester/semantic/self3.cl new file mode 100644 index 000000000..81709b4b5 --- /dev/null +++ b/src/tester/semantic/self3.cl @@ -0,0 +1,10 @@ +(* +But it is an error to assign to self or to bind self in a let, a +case, or as a formal parameter. It is also illegal to have attributes named self. +*) + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test(self: IO): IO { self }; +}; diff --git a/src/tester/semantic/self3_error.txt b/src/tester/semantic/self3_error.txt new file mode 100644 index 000000000..0ae382007 --- /dev/null +++ b/src/tester/semantic/self3_error.txt @@ -0,0 +1 @@ +(9, 10) - SemanticError: 'self' cannot be the name of a formal parameter. diff --git a/src/tester/semantic/self4.cl b/src/tester/semantic/self4.cl new file mode 100644 index 000000000..7c2b960cb --- /dev/null +++ b/src/tester/semantic/self4.cl @@ -0,0 +1,10 @@ +(* +But it is an error to assign to self or to bind self in a let, a +case, or as a formal parameter. It is also illegal to have attributes named self. +*) + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + self: IO <- self; +}; \ No newline at end of file diff --git a/src/tester/semantic/self4_error.txt b/src/tester/semantic/self4_error.txt new file mode 100644 index 000000000..c19ca400f --- /dev/null +++ b/src/tester/semantic/self4_error.txt @@ -0,0 +1 @@ +(9, 5) - SemanticError: 'self' cannot be the name of an attribute. diff --git a/src/tests/codegen/arith.cl b/src/tests/codegen/arith.cl new file mode 100644 index 000000000..af5951cf7 --- /dev/null +++ b/src/tests/codegen/arith.cl @@ -0,0 +1,430 @@ +(* + * A contribution from Anne Sheets (sheets@cory) + * + * Tests the arithmetic operations and various other things + *) + +class A { + + var : Int <- 0; + + value() : Int { var }; + + set_var(num : Int) : A{ + { + var <- num; + self; + } + }; + + method1(num : Int) : A { -- same + self + }; + + method2(num1 : Int, num2 : Int) : A { -- plus + (let x : Int in + { + x <- num1 + num2; + (new B).set_var(x); + } + ) + }; + + method3(num : Int) : A { -- negate + (let x : Int in + { + x <- ~num; + (new C).set_var(x); + } + ) + }; + + method4(num1 : Int, num2 : Int) : A { -- diff + if num2 < num1 then + (let x : Int in + { + x <- num1 - num2; + (new D).set_var(x); + } + ) + else + (let x : Int in + { + x <- num2 - num1; + (new D).set_var(x); + } + ) + fi + }; + + method5(num : Int) : A { -- factorial + (let x : Int <- 1 in + { + (let y : Int <- 1 in + while y <= num loop + { + x <- x * y; + y <- y + 1; + } + pool + ); + (new E).set_var(x); + } + ) + }; + +}; + +class B inherits A { -- B is a number squared + + method5(num : Int) : A { -- square + (let x : Int in + { + x <- num * num; + (new E).set_var(x); + } + ) + }; + +}; + +class C inherits B { + + method6(num : Int) : A { -- negate + (let x : Int in + { + x <- ~num; + (new A).set_var(x); + } + ) + }; + + method5(num : Int) : A { -- cube + (let x : Int in + { + x <- num * num * num; + (new E).set_var(x); + } + ) + }; + +}; + +class D inherits B { + + method7(num : Int) : Bool { -- divisible by 3 + (let x : Int <- num in + if x < 0 then method7(~x) else + if 0 = x then true else + if 1 = x then false else + if 2 = x then false else + method7(x - 3) + fi fi fi fi + ) + }; + +}; + +class E inherits D { + + method6(num : Int) : A { -- division + (let x : Int in + { + x <- num / 8; + (new A).set_var(x); + } + ) + }; + +}; + +(* The following code is from atoi.cl in ~cs164/examples *) + +(* + The class A2I provides integer-to-string and string-to-integer +conversion routines. To use these routines, either inherit them +in the class where needed, have a dummy variable bound to +something of type A2I, or simpl write (new A2I).method(argument). +*) + + +(* + c2i Converts a 1-character string to an integer. Aborts + if the string is not "0" through "9" +*) +class A2I { + + c2i(char : String) : Int { + if char = "0" then 0 else + if char = "1" then 1 else + if char = "2" then 2 else + if char = "3" then 3 else + if char = "4" then 4 else + if char = "5" then 5 else + if char = "6" then 6 else + if char = "7" then 7 else + if char = "8" then 8 else + if char = "9" then 9 else + { abort(); 0; } (* the 0 is needed to satisfy the + typchecker *) + fi fi fi fi fi fi fi fi fi fi + }; + +(* + i2c is the inverse of c2i. +*) + i2c(i : Int) : String { + if i = 0 then "0" else + if i = 1 then "1" else + if i = 2 then "2" else + if i = 3 then "3" else + if i = 4 then "4" else + if i = 5 then "5" else + if i = 6 then "6" else + if i = 7 then "7" else + if i = 8 then "8" else + if i = 9 then "9" else + { abort(); ""; } -- the "" is needed to satisfy the typchecker + fi fi fi fi fi fi fi fi fi fi + }; + +(* + a2i converts an ASCII string into an integer. The empty string +is converted to 0. Signed and unsigned strings are handled. The +method aborts if the string does not represent an integer. Very +long strings of digits produce strange answers because of arithmetic +overflow. + +*) + a2i(s : String) : Int { + if s.length() = 0 then 0 else + if s.substr(0,1) = "-" then ~a2i_aux(s.substr(1,s.length()-1)) else + if s.substr(0,1) = "+" then a2i_aux(s.substr(1,s.length()-1)) else + a2i_aux(s) + fi fi fi + }; + +(* a2i_aux converts the usigned portion of the string. As a + programming example, this method is written iteratively. *) + + + a2i_aux(s : String) : Int { + (let int : Int <- 0 in + { + (let j : Int <- s.length() in + (let i : Int <- 0 in + while i < j loop + { + int <- int * 10 + c2i(s.substr(i,1)); + i <- i + 1; + } + pool + ) + ); + int; + } + ) + }; + +(* i2a converts an integer to a string. Positive and negative + numbers are handled correctly. *) + + i2a(i : Int) : String { + if i = 0 then "0" else + if 0 < i then i2a_aux(i) else + "-".concat(i2a_aux(i * ~1)) + fi fi + }; + +(* i2a_aux is an example using recursion. *) + + i2a_aux(i : Int) : String { + if i = 0 then "" else + (let next : Int <- i / 10 in + i2a_aux(next).concat(i2c(i - next * 10)) + ) + fi + }; + +}; + +class Main inherits IO { + + char : String; + avar : A; + a_var : A; + flag : Bool <- true; + + + menu() : String { + { + out_string("\n\tTo add a number to "); + print(avar); + out_string("...enter a:\n"); + out_string("\tTo negate "); + print(avar); + out_string("...enter b:\n"); + out_string("\tTo find the difference between "); + print(avar); + out_string("and another number...enter c:\n"); + out_string("\tTo find the factorial of "); + print(avar); + out_string("...enter d:\n"); + out_string("\tTo square "); + print(avar); + out_string("...enter e:\n"); + out_string("\tTo cube "); + print(avar); + out_string("...enter f:\n"); + out_string("\tTo find out if "); + print(avar); + out_string("is a multiple of 3...enter g:\n"); + out_string("\tTo divide "); + print(avar); + out_string("by 8...enter h:\n"); + out_string("\tTo get a new number...enter j:\n"); + out_string("\tTo quit...enter q:\n\n"); + in_string(); + } + }; + + prompt() : String { + { + out_string("\n"); + out_string("Please enter a number... "); + in_string(); + } + }; + + get_int() : Int { + { + (let z : A2I <- new A2I in + (let s : String <- prompt() in + z.a2i(s) + ) + ); + } + }; + + is_even(num : Int) : Bool { + (let x : Int <- num in + if x < 0 then is_even(~x) else + if 0 = x then true else + if 1 = x then false else + is_even(x - 2) + fi fi fi + ) + }; + + class_type(var : A) : IO { + case var of + a : A => out_string("Class type is now A\n"); + b : B => out_string("Class type is now B\n"); + c : C => out_string("Class type is now C\n"); + d : D => out_string("Class type is now D\n"); + e : E => out_string("Class type is now E\n"); + o : Object => out_string("Oooops\n"); + esac + }; + + print(var : A) : IO { + (let z : A2I <- new A2I in + { + out_string(z.i2a(var.value())); + out_string(" "); + } + ) + }; + + main() : Object { + { + avar <- (new A); + while flag loop + { + -- avar <- (new A).set_var(get_int()); + out_string("number "); + print(avar); + if is_even(avar.value()) then + out_string("is even!\n") + else + out_string("is odd!\n") + fi; + -- print(avar); -- prints out answer + class_type(avar); + char <- menu(); + if char = "a" then -- add + { + a_var <- (new A).set_var(get_int()); + avar <- (new B).method2(avar.value(), a_var.value()); + } else + if char = "b" then -- negate + case avar of + c : C => avar <- c.method6(c.value()); + a : A => avar <- a.method3(a.value()); + o : Object => { + out_string("Oooops\n"); + abort(); 0; + }; + esac else + if char = "c" then -- diff + { + a_var <- (new A).set_var(get_int()); + avar <- (new D).method4(avar.value(), a_var.value()); + } else + if char = "d" then avar <- (new C)@A.method5(avar.value()) else + -- factorial + if char = "e" then avar <- (new C)@B.method5(avar.value()) else + -- square + if char = "f" then avar <- (new C)@C.method5(avar.value()) else + -- cube + if char = "g" then -- multiple of 3? + if ((new D).method7(avar.value())) + then -- avar <- (new A).method1(avar.value()) + { + out_string("number "); + print(avar); + out_string("is divisible by 3.\n"); + } + else -- avar <- (new A).set_var(0) + { + out_string("number "); + print(avar); + out_string("is not divisible by 3.\n"); + } + fi else + if char = "h" then + (let x : A in + { + x <- (new E).method6(avar.value()); + (let r : Int <- (avar.value() - (x.value() * 8)) in + { + out_string("number "); + print(avar); + out_string("is equal to "); + print(x); + out_string("times 8 with a remainder of "); + (let a : A2I <- new A2I in + { + out_string(a.i2a(r)); + out_string("\n"); + } + ); -- end let a: + } + ); -- end let r: + avar <- x; + } + ) -- end let x: + else + if char = "j" then avar <- (new A) + else + if char = "q" then flag <- false + else + avar <- (new A).method1(avar.value()) -- divide/8 + fi fi fi fi fi fi fi fi fi fi; + } + pool; + } + }; + +}; + diff --git a/src/tests/codegen/arith_input.txt b/src/tests/codegen/arith_input.txt new file mode 100644 index 000000000..83e05b1ea --- /dev/null +++ b/src/tests/codegen/arith_input.txt @@ -0,0 +1,13 @@ +a +1 +b +c +0 +d +e +f +g +h +j +5 +q diff --git a/src/tests/codegen/arith_output.txt b/src/tests/codegen/arith_output.txt new file mode 100644 index 000000000..44b4ce73e --- /dev/null +++ b/src/tests/codegen/arith_output.txt @@ -0,0 +1,158 @@ +number 0 is even! +Class type is now A + + To add a number to 0 ...enter a: + To negate 0 ...enter b: + To find the difference between 0 and another number...enter c: + To find the factorial of 0 ...enter d: + To square 0 ...enter e: + To cube 0 ...enter f: + To find out if 0 is a multiple of 3...enter g: + To divide 0 by 8...enter h: + To get a new number...enter j: + To quit...enter q: + + +Please enter a number... number 1 is odd! +Class type is now B + + To add a number to 1 ...enter a: + To negate 1 ...enter b: + To find the difference between 1 and another number...enter c: + To find the factorial of 1 ...enter d: + To square 1 ...enter e: + To cube 1 ...enter f: + To find out if 1 is a multiple of 3...enter g: + To divide 1 by 8...enter h: + To get a new number...enter j: + To quit...enter q: + +number -1 is odd! +Class type is now C + + To add a number to -1 ...enter a: + To negate -1 ...enter b: + To find the difference between -1 and another number...enter c: + To find the factorial of -1 ...enter d: + To square -1 ...enter e: + To cube -1 ...enter f: + To find out if -1 is a multiple of 3...enter g: + To divide -1 by 8...enter h: + To get a new number...enter j: + To quit...enter q: + + +Please enter a number... number 1 is odd! +Class type is now D + + To add a number to 1 ...enter a: + To negate 1 ...enter b: + To find the difference between 1 and another number...enter c: + To find the factorial of 1 ...enter d: + To square 1 ...enter e: + To cube 1 ...enter f: + To find out if 1 is a multiple of 3...enter g: + To divide 1 by 8...enter h: + To get a new number...enter j: + To quit...enter q: + +number 1 is odd! +Class type is now E + + To add a number to 1 ...enter a: + To negate 1 ...enter b: + To find the difference between 1 and another number...enter c: + To find the factorial of 1 ...enter d: + To square 1 ...enter e: + To cube 1 ...enter f: + To find out if 1 is a multiple of 3...enter g: + To divide 1 by 8...enter h: + To get a new number...enter j: + To quit...enter q: + +number 1 is odd! +Class type is now E + + To add a number to 1 ...enter a: + To negate 1 ...enter b: + To find the difference between 1 and another number...enter c: + To find the factorial of 1 ...enter d: + To square 1 ...enter e: + To cube 1 ...enter f: + To find out if 1 is a multiple of 3...enter g: + To divide 1 by 8...enter h: + To get a new number...enter j: + To quit...enter q: + +number 1 is odd! +Class type is now E + + To add a number to 1 ...enter a: + To negate 1 ...enter b: + To find the difference between 1 and another number...enter c: + To find the factorial of 1 ...enter d: + To square 1 ...enter e: + To cube 1 ...enter f: + To find out if 1 is a multiple of 3...enter g: + To divide 1 by 8...enter h: + To get a new number...enter j: + To quit...enter q: + +number 1 is not divisible by 3. +number 1 is odd! +Class type is now E + + To add a number to 1 ...enter a: + To negate 1 ...enter b: + To find the difference between 1 and another number...enter c: + To find the factorial of 1 ...enter d: + To square 1 ...enter e: + To cube 1 ...enter f: + To find out if 1 is a multiple of 3...enter g: + To divide 1 by 8...enter h: + To get a new number...enter j: + To quit...enter q: + +number 1 is equal to 0 times 8 with a remainder of 1 +number 0 is even! +Class type is now A + + To add a number to 0 ...enter a: + To negate 0 ...enter b: + To find the difference between 0 and another number...enter c: + To find the factorial of 0 ...enter d: + To square 0 ...enter e: + To cube 0 ...enter f: + To find out if 0 is a multiple of 3...enter g: + To divide 0 by 8...enter h: + To get a new number...enter j: + To quit...enter q: + +number 0 is even! +Class type is now A + + To add a number to 0 ...enter a: + To negate 0 ...enter b: + To find the difference between 0 and another number...enter c: + To find the factorial of 0 ...enter d: + To square 0 ...enter e: + To cube 0 ...enter f: + To find out if 0 is a multiple of 3...enter g: + To divide 0 by 8...enter h: + To get a new number...enter j: + To quit...enter q: + +number 0 is even! +Class type is now A + + To add a number to 0 ...enter a: + To negate 0 ...enter b: + To find the difference between 0 and another number...enter c: + To find the factorial of 0 ...enter d: + To square 0 ...enter e: + To cube 0 ...enter f: + To find out if 0 is a multiple of 3...enter g: + To divide 0 by 8...enter h: + To get a new number...enter j: + To quit...enter q: + diff --git a/src/tests/codegen/atoi.cl b/src/tests/codegen/atoi.cl new file mode 100644 index 000000000..f4125a2f8 --- /dev/null +++ b/src/tests/codegen/atoi.cl @@ -0,0 +1,121 @@ +(* + The class A2I provides integer-to-string and string-to-integer +conversion routines. To use these routines, either inherit them +in the class where needed, have a dummy variable bound to +something of type A2I, or simpl write (new A2I).method(argument). +*) + + +(* + c2i Converts a 1-character string to an integer. Aborts + if the string is not "0" through "9" +*) +class A2I { + + c2i(char : String) : Int { + if char = "0" then 0 else + if char = "1" then 1 else + if char = "2" then 2 else + if char = "3" then 3 else + if char = "4" then 4 else + if char = "5" then 5 else + if char = "6" then 6 else + if char = "7" then 7 else + if char = "8" then 8 else + if char = "9" then 9 else + { abort(); 0; } -- the 0 is needed to satisfy the typchecker + fi fi fi fi fi fi fi fi fi fi + }; + +(* + i2c is the inverse of c2i. +*) + i2c(i : Int) : String { + if i = 0 then "0" else + if i = 1 then "1" else + if i = 2 then "2" else + if i = 3 then "3" else + if i = 4 then "4" else + if i = 5 then "5" else + if i = 6 then "6" else + if i = 7 then "7" else + if i = 8 then "8" else + if i = 9 then "9" else + { abort(); ""; } -- the "" is needed to satisfy the typchecker + fi fi fi fi fi fi fi fi fi fi + }; + +(* + a2i converts an ASCII string into an integer. The empty string +is converted to 0. Signed and unsigned strings are handled. The +method aborts if the string does not represent an integer. Very +long strings of digits produce strange answers because of arithmetic +overflow. + +*) + a2i(s : String) : Int { + if s.length() = 0 then 0 else + if s.substr(0,1) = "-" then ~a2i_aux(s.substr(1,s.length()-1)) else + if s.substr(0,1) = "+" then a2i_aux(s.substr(1,s.length()-1)) else + a2i_aux(s) + fi fi fi + }; + +(* + a2i_aux converts the usigned portion of the string. As a programming +example, this method is written iteratively. +*) + a2i_aux(s : String) : Int { + (let int : Int <- 0 in + { + (let j : Int <- s.length() in + (let i : Int <- 0 in + while i < j loop + { + int <- int * 10 + c2i(s.substr(i,1)); + i <- i + 1; + } + pool + ) + ); + int; + } + ) + }; + +(* + i2a converts an integer to a string. Positive and negative +numbers are handled correctly. +*) + i2a(i : Int) : String { + if i = 0 then "0" else + if 0 < i then i2a_aux(i) else + "-".concat(i2a_aux(i * ~1)) + fi fi + }; + +(* + i2a_aux is an example using recursion. +*) + i2a_aux(i : Int) : String { + if i = 0 then "" else + (let next : Int <- i / 10 in + i2a_aux(next).concat(i2c(i - next * 10)) + ) + fi + }; + +}; + +class Main inherits IO { + main () : Object { + let a : Int <- (new A2I).a2i("678987"), + b : String <- (new A2I).i2a(678987) in + { + out_int(a) ; + out_string(" == ") ; + out_string(b) ; + out_string("\n"); + } + } ; +} ; diff --git a/src/tests/codegen/atoi_input.txt b/src/tests/codegen/atoi_input.txt new file mode 100644 index 000000000..e69de29bb diff --git a/src/tests/codegen/atoi_output.txt b/src/tests/codegen/atoi_output.txt new file mode 100644 index 000000000..51b815a48 --- /dev/null +++ b/src/tests/codegen/atoi_output.txt @@ -0,0 +1 @@ +678987 == 678987 diff --git a/src/tests/codegen/book_list.cl b/src/tests/codegen/book_list.cl new file mode 100644 index 000000000..025ea1695 --- /dev/null +++ b/src/tests/codegen/book_list.cl @@ -0,0 +1,132 @@ +-- example of static and dynamic type differing for a dispatch + +Class Book inherits IO { + title : String; + author : String; + + initBook(title_p : String, author_p : String) : Book { + { + title <- title_p; + author <- author_p; + self; + } + }; + + print() : Book { + { + out_string("title: ").out_string(title).out_string("\n"); + out_string("author: ").out_string(author).out_string("\n"); + self; + } + }; +}; + +Class Article inherits Book { + per_title : String; + + initArticle(title_p : String, author_p : String, + per_title_p : String) : Article { + { + initBook(title_p, author_p); + per_title <- per_title_p; + self; + } + }; + + print() : Book { + { + self@Book.print(); + out_string("periodical: ").out_string(per_title).out_string("\n"); + self; + } + }; +}; + +Class BookList inherits IO { + (* Since abort "returns" type Object, we have to add + an expression of type Bool here to satisfy the typechecker. + This code is unreachable, since abort() halts the program. + *) + isNil() : Bool { { abort(); true; } }; + + cons(hd : Book) : Cons { + (let new_cell : Cons <- new Cons in + new_cell.init(hd,self) + ) + }; + + (* Since abort "returns" type Object, we have to add + an expression of type Book here to satisfy the typechecker. + This code is unreachable, since abort() halts the program. + *) + car() : Book { { abort(); new Book; } }; + + (* Since abort "returns" type Object, we have to add + an expression of type BookList here to satisfy the typechecker. + This code is unreachable, since abort() halts the program. + *) + cdr() : BookList { { abort(); new BookList; } }; + + print_list() : Object { abort() }; +}; + +Class Cons inherits BookList { + xcar : Book; -- We keep the car and cdr in attributes. + xcdr : BookList; -- Because methods and features must have different names, + -- we use xcar and xcdr for the attributes and reserve + -- car and cdr for the features. + + isNil() : Bool { false }; + + init(hd : Book, tl : BookList) : Cons { + { + xcar <- hd; + xcdr <- tl; + self; + } + }; + + car() : Book { xcar }; + + cdr() : BookList { xcdr }; + + print_list() : Object { + { + case xcar.print() of + dummy : Book => out_string("- dynamic type was Book -\n"); + dummy : Article => out_string("- dynamic type was Article -\n"); + esac; + xcdr.print_list(); + } + }; +}; + +Class Nil inherits BookList { + isNil() : Bool { true }; + + print_list() : Object { true }; +}; + + +Class Main { + + books : BookList; + + main() : Object { + (let a_book : Book <- + (new Book).initBook("Compilers, Principles, Techniques, and Tools", + "Aho, Sethi, and Ullman") + in + (let an_article : Article <- + (new Article).initArticle("The Top 100 CD_ROMs", + "Ulanoff", + "PC Magazine") + in + { + books <- (new Nil).cons(a_book).cons(an_article); + books.print_list(); + } + ) -- end let an_article + ) -- end let a_book + }; +}; diff --git a/src/tests/codegen/book_list_input.txt b/src/tests/codegen/book_list_input.txt new file mode 100644 index 000000000..e69de29bb diff --git a/src/tests/codegen/book_list_output.txt b/src/tests/codegen/book_list_output.txt new file mode 100644 index 000000000..3408320b2 --- /dev/null +++ b/src/tests/codegen/book_list_output.txt @@ -0,0 +1,7 @@ +title: The Top 100 CD_ROMs +author: Ulanoff +periodical: PC Magazine +- dynamic type was Article - +title: Compilers, Principles, Techniques, and Tools +author: Aho, Sethi, and Ullman +- dynamic type was Book - diff --git a/src/tests/codegen/cells.cl b/src/tests/codegen/cells.cl new file mode 100644 index 000000000..9fd6741bb --- /dev/null +++ b/src/tests/codegen/cells.cl @@ -0,0 +1,97 @@ +(* models one-dimensional cellular automaton on a circle of finite radius + arrays are faked as Strings, + X's respresent live cells, dots represent dead cells, + no error checking is done *) +class CellularAutomaton inherits IO { + population_map : String; + + init(map : String) : CellularAutomaton { + { + population_map <- map; + self; + } + }; + + print() : CellularAutomaton { + { + out_string(population_map.concat("\n")); + self; + } + }; + + num_cells() : Int { + population_map.length() + }; + + cell(position : Int) : String { + population_map.substr(position, 1) + }; + + cell_left_neighbor(position : Int) : String { + if position = 0 then + cell(num_cells() - 1) + else + cell(position - 1) + fi + }; + + cell_right_neighbor(position : Int) : String { + if position = num_cells() - 1 then + cell(0) + else + cell(position + 1) + fi + }; + + (* a cell will live if exactly 1 of itself and it's immediate + neighbors are alive *) + cell_at_next_evolution(position : Int) : String { + if (if cell(position) = "X" then 1 else 0 fi + + if cell_left_neighbor(position) = "X" then 1 else 0 fi + + if cell_right_neighbor(position) = "X" then 1 else 0 fi + = 1) + then + "X" + else + "." + fi + }; + + evolve() : CellularAutomaton { + (let position : Int in + (let num : Int <- num_cells() in + (let temp : String in + { + while position < num loop + { + temp <- temp.concat(cell_at_next_evolution(position)); + position <- position + 1; + } + pool; + population_map <- temp; + self; + } + ) ) ) + }; +}; + +class Main { + cells : CellularAutomaton; + + main() : Main { + { + cells <- (new CellularAutomaton).init(" X "); + cells.print(); + (let countdown : Int <- 20 in + while 0 < countdown loop + { + cells.evolve(); + cells.print(); + countdown <- countdown - 1; + } + pool + ); + self; + } + }; +}; diff --git a/src/tests/codegen/cells_input.txt b/src/tests/codegen/cells_input.txt new file mode 100644 index 000000000..e69de29bb diff --git a/src/tests/codegen/cells_output.txt b/src/tests/codegen/cells_output.txt new file mode 100644 index 000000000..6304902cc --- /dev/null +++ b/src/tests/codegen/cells_output.txt @@ -0,0 +1,21 @@ + X +........XXX........ +.......X...X....... +......XXX.XXX...... +.....X.......X..... +....XXX.....XXX.... +...X...X...X...X... +..XXX.XXX.XXX.XXX.. +.X...............X. +XXX.............XXX +...X...........X... +..XXX.........XXX.. +.X...X.......X...X. +XXX.XXX.....XXX.XXX +.......X...X....... +......XXX.XXX...... +.....X.......X..... +....XXX.....XXX.... +...X...X...X...X... +..XXX.XXX.XXX.XXX.. +.X...............X. diff --git a/src/tests/codegen/complex.cl b/src/tests/codegen/complex.cl new file mode 100644 index 000000000..0b7aa44e9 --- /dev/null +++ b/src/tests/codegen/complex.cl @@ -0,0 +1,52 @@ +class Main inherits IO { + main() : IO { + (let c : Complex <- (new Complex).init(1, 1) in + if c.reflect_X().reflect_Y() = c.reflect_0() + then out_string("=)\n") + else out_string("=(\n") + fi + ) + }; +}; + +class Complex inherits IO { + x : Int; + y : Int; + + init(a : Int, b : Int) : Complex { + { + x = a; + y = b; + self; + } + }; + + print() : Object { + if y = 0 + then out_int(x) + else out_int(x).out_string("+").out_int(y).out_string("I") + fi + }; + + reflect_0() : Complex { + { + x = ~x; + y = ~y; + self; + } + }; + + reflect_X() : Complex { + { + y = ~y; + self; + } + }; + + reflect_Y() : Complex { + { + x = ~x; + self; + } + }; +}; diff --git a/src/tests/codegen/complex_input.txt b/src/tests/codegen/complex_input.txt new file mode 100644 index 000000000..e69de29bb diff --git a/src/tests/codegen/complex_output.txt b/src/tests/codegen/complex_output.txt new file mode 100644 index 000000000..18b77c1fc --- /dev/null +++ b/src/tests/codegen/complex_output.txt @@ -0,0 +1 @@ +=) diff --git a/src/tests/codegen/fib.cl b/src/tests/codegen/fib.cl new file mode 100644 index 000000000..08ceaede8 --- /dev/null +++ b/src/tests/codegen/fib.cl @@ -0,0 +1,29 @@ +class Main inherits IO { + -- the class has features. Only methods in this case. + main(): Object { + { + out_string("Enter n to find nth fibonacci number!\n"); + out_int(fib(in_int())); + out_string("\n"); + } + }; + + fib(i : Int) : Int { -- list of formals. And the return type of the method. + let a : Int <- 1, + b : Int <- 0, + c : Int <- 0 + in + { + while (not (i = 0)) loop -- expressions are nested. + { + c <- a + b; + i <- i - 1; + b <- a; + a <- c; + } + pool; + c; + } + }; + +}; diff --git a/src/tests/codegen/fib_input.txt b/src/tests/codegen/fib_input.txt new file mode 100644 index 000000000..f599e28b8 --- /dev/null +++ b/src/tests/codegen/fib_input.txt @@ -0,0 +1 @@ +10 diff --git a/src/tests/codegen/fib_output.txt b/src/tests/codegen/fib_output.txt new file mode 100644 index 000000000..d402da6af --- /dev/null +++ b/src/tests/codegen/fib_output.txt @@ -0,0 +1,2 @@ +Enter n to find nth fibonacci number! +89 diff --git a/src/tests/codegen/graph.cl b/src/tests/codegen/graph.cl new file mode 100644 index 000000000..8e511358c --- /dev/null +++ b/src/tests/codegen/graph.cl @@ -0,0 +1,381 @@ +(* + * Cool program reading descriptions of weighted directed graphs + * from stdin. It builds up a graph objects with a list of vertices + * and a list of edges. Every vertice has a list of outgoing edges. + * + * INPUT FORMAT + * Every line has the form vertice successor* + * Where vertice is an int, and successor is vertice,weight + * + * An empty line or EOF terminates the input. + * + * The list of vertices and the edge list is printed out by the Main + * class. + * + * TEST + * Once compiled, the file g1.graph can be fed to the program. + * The output should look like this: + +nautilus.CS.Berkeley.EDU 53# spim -file graph.s (new Bar); + n : Foo => (new Razz); + n : Bar => n; + esac; + + b : Int <- a.doh() + g.doh() + doh() + printh(); + + doh() : Int { (let i : Int <- h in { h <- h + 2; i; } ) }; + +}; + +class Bar inherits Razz { + + c : Int <- doh(); + + d : Object <- printh(); +}; + + +class Razz inherits Foo { + + e : Bar <- case self of + n : Razz => (new Bar); + n : Bar => n; + esac; + + f : Int <- a@Bazz.doh() + g.doh() + e.doh() + doh() + printh(); + +}; + +class Bazz inherits IO { + + h : Int <- 1; + + g : Foo <- case self of + n : Bazz => (new Foo); + n : Razz => (new Bar); + n : Foo => (new Razz); + n : Bar => n; + esac; + + i : Object <- printh(); + + printh() : Int { { out_int(h); 0; } }; + + doh() : Int { (let i: Int <- h in { h <- h + 1; i; } ) }; +}; + +(* scary . . . *) +class Main { + a : Bazz <- new Bazz; + b : Foo <- new Foo; + c : Razz <- new Razz; + d : Bar <- new Bar; + + main(): String { "do nothing" }; + +}; + + + + + diff --git a/src/tests/codegen/hairyscary_input.txt b/src/tests/codegen/hairyscary_input.txt new file mode 100644 index 000000000..e69de29bb diff --git a/src/tests/codegen/hairyscary_output.txt b/src/tests/codegen/hairyscary_output.txt new file mode 100644 index 000000000..8985c22f2 --- /dev/null +++ b/src/tests/codegen/hairyscary_output.txt @@ -0,0 +1 @@ +17141611714163171416511714161171416317141653117141611714163171416511714161171416317141653171416117141631714165171416 \ No newline at end of file diff --git a/src/tests/codegen/hello_world.cl b/src/tests/codegen/hello_world.cl new file mode 100644 index 000000000..0c818f908 --- /dev/null +++ b/src/tests/codegen/hello_world.cl @@ -0,0 +1,5 @@ +class Main inherits IO { + main(): IO { + out_string("Hello, World.\n") + }; +}; diff --git a/src/tests/codegen/hello_world_input.txt b/src/tests/codegen/hello_world_input.txt new file mode 100644 index 000000000..e69de29bb diff --git a/src/tests/codegen/hello_world_output.txt b/src/tests/codegen/hello_world_output.txt new file mode 100644 index 000000000..349db2bfe --- /dev/null +++ b/src/tests/codegen/hello_world_output.txt @@ -0,0 +1 @@ +Hello, World. diff --git a/src/tests/codegen/io.cl b/src/tests/codegen/io.cl new file mode 100644 index 000000000..7f0de869e --- /dev/null +++ b/src/tests/codegen/io.cl @@ -0,0 +1,103 @@ +(* + * The IO class is predefined and has 4 methods: + * + * out_string(s : String) : SELF_TYPE + * out_int(i : Int) : SELF_TYPE + * in_string() : String + * in_int() : Int + * + * The out operations print their argument to the terminal. The + * in_string method reads an entire line from the terminal and returns a + * string not containing the new line. The in_int method also reads + * an entire line from the terminal and returns the integer + * corresponding to the first non blank word on the line. If that + * word is not an integer, it returns 0. + * + * + * Because our language is object oriented, we need an object of type + * IO in order to call any of these methods. + * + * There are basically two ways of getting access to IO in a class C. + * + * 1) Define C to Inherit from IO. This way the IO methods become + * methods of C, and they can be called using the abbreviated + * dispatch, i.e. + * + * class C inherits IO is + * ... + * out_string("Hello world\n") + * ... + * end; + * + * 2) If your class C does not directly or indirectly inherit from + * IO, the best way to access IO is through an initialized + * attribute of type IO. + * + * class C inherits Foo is + * io : IO <- new IO; + * ... + * io.out_string("Hello world\n"); + * ... + * end; + * + * Approach 1) is most often used, in particular when you need IO + * functions in the Main class. + * + *) + + +class A { + + -- Let's assume that we don't want A to not inherit from IO. + + io : IO <- new IO; + + out_a() : Object { io.out_string("A: Hello world\n") }; + +}; + + +class B inherits A { + + -- B does not have to an extra attribute, since it inherits io from A. + + out_b() : Object { io.out_string("B: Hello world\n") }; + +}; + + +class C inherits IO { + + -- Now the IO methods are part of C. + + out_c() : Object { out_string("C: Hello world\n") }; + + -- Note that out_string(...) is just a shorthand for self.out_string(...) + +}; + + +class D inherits C { + + -- Inherits IO methods from C. + + out_d() : Object { out_string("D: Hello world\n") }; + +}; + + +class Main inherits IO { + + -- Same case as class C. + + main() : Object { + { + (new A).out_a(); + (new B).out_b(); + (new C).out_c(); + (new D).out_d(); + out_string("Done.\n"); + } + }; + +}; diff --git a/src/tests/codegen/io_input.txt b/src/tests/codegen/io_input.txt new file mode 100644 index 000000000..e69de29bb diff --git a/src/tests/codegen/io_output.txt b/src/tests/codegen/io_output.txt new file mode 100644 index 000000000..f846f596d --- /dev/null +++ b/src/tests/codegen/io_output.txt @@ -0,0 +1,5 @@ +A: Hello world +B: Hello world +C: Hello world +D: Hello world +Done. diff --git a/src/tests/codegen/life.cl b/src/tests/codegen/life.cl new file mode 100644 index 000000000..b83d97957 --- /dev/null +++ b/src/tests/codegen/life.cl @@ -0,0 +1,436 @@ +(* The Game of Life + Tendo Kayiira, Summer '95 + With code taken from /private/cool/class/examples/cells.cl + + This introduction was taken off the internet. It gives a brief + description of the Game Of Life. It also gives the rules by which + this particular game follows. + + Introduction + + John Conway's Game of Life is a mathematical amusement, but it + is also much more: an insight into how a system of simple + cellualar automata can create complex, odd, and often aesthetically + pleasing patterns. It is played on a cartesian grid of cells + which are either 'on' or 'off' The game gets it's name from the + similarity between the behaviour of these cells and the behaviour + of living organisms. + + The Rules + + The playfield is a cartesian grid of arbitrary size. Each cell in + this grid can be in an 'on' state or an 'off' state. On each 'turn' + (called a generation,) the state of each cell changes simultaneously + depending on it's state and the state of all cells adjacent to it. + + For 'on' cells, + If the cell has 0 or 1 neighbours which are 'on', the cell turns + 'off'. ('dies of loneliness') + If the cell has 2 or 3 neighbours which are 'on', the cell stays + 'on'. (nothing happens to that cell) + If the cell has 4, 5, 6, 7, 8, or 9 neighbours which are 'on', + the cell turns 'off'. ('dies of overcrowding') + + For 'off' cells, + If the cell has 0, 1, 2, 4, 5, 6, 7, 8, or 9 neighbours which + are 'on', the cell stays 'off'. (nothing happens to that cell) + If the cell has 3 neighbours which are 'on', the cell turns + 'on'. (3 neighbouring 'alive' cells 'give birth' to a fourth.) + + Repeat for as many generations as desired. + + *) + + +class Board inherits IO { + + rows : Int; + columns : Int; + board_size : Int; + + size_of_board(initial : String) : Int { + initial.length() + }; + + board_init(start : String) : Board { + (let size :Int <- size_of_board(start) in + { + if size = 15 then + { + rows <- 3; + columns <- 5; + board_size <- size; + } + else if size = 16 then + { + rows <- 4; + columns <- 4; + board_size <- size; + } + else if size = 20 then + { + rows <- 4; + columns <- 5; + board_size <- size; + } + else if size = 21 then + { + rows <- 3; + columns <- 7; + board_size <- size; + } + else if size = 25 then + { + rows <- 5; + columns <- 5; + board_size <- size; + } + else if size = 28 then + { + rows <- 7; + columns <- 4; + board_size <- size; + } + else -- If none of the above fit, then just give + { -- the configuration of the most common board + rows <- 5; + columns <- 5; + board_size <- size; + } + fi fi fi fi fi fi; + self; + } + ) + }; + +}; + + + +class CellularAutomaton inherits Board { + population_map : String; + + init(map : String) : CellularAutomaton { + { + population_map <- map; + board_init(map); + self; + } + }; + + + + + print() : CellularAutomaton { + + (let i : Int <- 0 in + (let num : Int <- board_size in + { + out_string("\n"); + while i < num loop + { + out_string(population_map.substr(i,columns)); + out_string("\n"); + i <- i + columns; + } + pool; + out_string("\n"); + self; + } + ) ) + }; + + num_cells() : Int { + population_map.length() + }; + + cell(position : Int) : String { + if board_size - 1 < position then + " " + else + population_map.substr(position, 1) + fi + }; + + north(position : Int): String { + if (position - columns) < 0 then + " " + else + cell(position - columns) + fi + }; + + south(position : Int): String { + if board_size < (position + columns) then + " " + else + cell(position + columns) + fi + }; + + east(position : Int): String { + if (((position + 1) /columns ) * columns) = (position + 1) then + " " + else + cell(position + 1) + fi + }; + + west(position : Int): String { + if position = 0 then + " " + else + if ((position / columns) * columns) = position then + " " + else + cell(position - 1) + fi fi + }; + + northwest(position : Int): String { + if (position - columns) < 0 then + " " + else if ((position / columns) * columns) = position then + " " + else + north(position - 1) + fi fi + }; + + northeast(position : Int): String { + if (position - columns) < 0 then + " " + else if (((position + 1) /columns ) * columns) = (position + 1) then + " " + else + north(position + 1) + fi fi + }; + + southeast(position : Int): String { + if board_size < (position + columns) then + " " + else if (((position + 1) /columns ) * columns) = (position + 1) then + " " + else + south(position + 1) + fi fi + }; + + southwest(position : Int): String { + if board_size < (position + columns) then + " " + else if ((position / columns) * columns) = position then + " " + else + south(position - 1) + fi fi + }; + + neighbors(position: Int): Int { + { + if north(position) = "X" then 1 else 0 fi + + if south(position) = "X" then 1 else 0 fi + + if east(position) = "X" then 1 else 0 fi + + if west(position) = "X" then 1 else 0 fi + + if northeast(position) = "X" then 1 else 0 fi + + if northwest(position) = "X" then 1 else 0 fi + + if southeast(position) = "X" then 1 else 0 fi + + if southwest(position) = "X" then 1 else 0 fi; + } + }; + + +(* A cell will live if 2 or 3 of it's neighbors are alive. It dies + otherwise. A cell is born if only 3 of it's neighbors are alive. *) + + cell_at_next_evolution(position : Int) : String { + + if neighbors(position) = 3 then + "X" + else + if neighbors(position) = 2 then + if cell(position) = "X" then + "X" + else + "-" + fi + else + "-" + fi fi + }; + + + evolve() : CellularAutomaton { + (let position : Int <- 0 in + (let num : Int <- num_cells() in + (let temp : String in + { + while position < num loop + { + temp <- temp.concat(cell_at_next_evolution(position)); + position <- position + 1; + } + pool; + population_map <- temp; + self; + } + ) ) ) + }; + +(* This is where the background pattern is detremined by the user. More + patterns can be added as long as whoever adds keeps the board either + 3x5, 4x5, 5x5, 3x7, 7x4, 4x4 with the row first then column. *) + option(): String { + { + (let num : Int in + { + out_string("\nPlease chose a number:\n"); + out_string("\t1: A cross\n"); + out_string("\t2: A slash from the upper left to lower right\n"); + out_string("\t3: A slash from the upper right to lower left\n"); + out_string("\t4: An X\n"); + out_string("\t5: A greater than sign \n"); + out_string("\t6: A less than sign\n"); + out_string("\t7: Two greater than signs\n"); + out_string("\t8: Two less than signs\n"); + out_string("\t9: A 'V'\n"); + out_string("\t10: An inverse 'V'\n"); + out_string("\t11: Numbers 9 and 10 combined\n"); + out_string("\t12: A full grid\n"); + out_string("\t13: A 'T'\n"); + out_string("\t14: A plus '+'\n"); + out_string("\t15: A 'W'\n"); + out_string("\t16: An 'M'\n"); + out_string("\t17: An 'E'\n"); + out_string("\t18: A '3'\n"); + out_string("\t19: An 'O'\n"); + out_string("\t20: An '8'\n"); + out_string("\t21: An 'S'\n"); + out_string("Your choice => "); + num <- in_int(); + out_string("\n"); + if num = 1 then + " XX XXXX XXXX XX " + else if num = 2 then + " X X X X X " + else if num = 3 then + "X X X X X" + else if num = 4 then + "X X X X X X X X X" + else if num = 5 then + "X X X X X " + else if num = 6 then + " X X X X X" + else if num = 7 then + "X X X XX X " + else if num = 8 then + " X XX X X X " + else if num = 9 then + "X X X X X " + else if num = 10 then + " X X X X X" + else if num = 11 then + "X X X X X X X X" + else if num = 12 then + "XXXXXXXXXXXXXXXXXXXXXXXXX" + else if num = 13 then + "XXXXX X X X X " + else if num = 14 then + " X X XXXXX X X " + else if num = 15 then + "X X X X X X X " + else if num = 16 then + " X X X X X X X" + else if num = 17 then + "XXXXX X XXXXX X XXXX" + else if num = 18 then + "XXX X X X X XXXX " + else if num = 19 then + " XX X XX X XX " + else if num = 20 then + " XX X XX X XX X XX X XX " + else if num = 21 then + " XXXX X XX X XXXX " + else + " " + fi fi fi fi fi fi fi fi fi fi fi fi fi fi fi fi fi fi fi fi fi; + } + ); + } + }; + + + + + prompt() : Bool { + { + (let ans : String in + { + out_string("Would you like to continue with the next generation? \n"); + out_string("Please use lowercase y or n for your answer [y]: "); + ans <- in_string(); + out_string("\n"); + if ans = "n" then + false + else + true + fi; + } + ); + } + }; + + + prompt2() : Bool { + (let ans : String in + { + out_string("\n\n"); + out_string("Would you like to choose a background pattern? \n"); + out_string("Please use lowercase y or n for your answer [n]: "); + ans <- in_string(); + if ans = "y" then + true + else + false + fi; + } + ) + }; + + +}; + +class Main inherits CellularAutomaton { + cells : CellularAutomaton; + + main() : Main { + { + (let continue : Bool in + (let choice : String in + { + out_string("Welcome to the Game of Life.\n"); + out_string("There are many initial states to choose from. \n"); + while prompt2() loop + { + continue <- true; + choice <- option(); + cells <- (new CellularAutomaton).init(choice); + cells.print(); + while continue loop + if prompt() then + { + cells.evolve(); + cells.print(); + } + else + continue <- false + fi + pool; + } + pool; + self; + } ) ); } + }; +}; + diff --git a/src/tests/codegen/life_input.txt b/src/tests/codegen/life_input.txt new file mode 100644 index 000000000..07e016726 --- /dev/null +++ b/src/tests/codegen/life_input.txt @@ -0,0 +1,66 @@ +y +1 +n +y +2 +n +y +3 +n +y +4 +n +y +5 +n +y +6 +n +y +7 +n +y +8 +n +y +9 +n +y +10 +n +y +11 +n +y +12 +n +y +13 +n +y +14 +n +y +15 +n +y +16 +n +y +17 +n +y +18 +n +y +19 +n +y +20 +n +y +21 +y +y +n +n \ No newline at end of file diff --git a/src/tests/codegen/life_output.txt b/src/tests/codegen/life_output.txt new file mode 100644 index 000000000..5a9b9f73d --- /dev/null +++ b/src/tests/codegen/life_output.txt @@ -0,0 +1,778 @@ +Welcome to the Game of Life. +There are many initial states to choose from. + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + + XX +XXXX +XXXX + XX + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + + X + X + X + X +X + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + +X + X + X + X + X + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + +X X + X X + X + X X +X X + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + +X + X + X + X +X + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + + X + X + X + X + X + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + +X X + X X +X X + + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + + X X +X X + X X + + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + +X X + X X + X + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + + X + X X +X X + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + +X X X + X X +X X X + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + +XXXXX +XXXXX +XXXXX +XXXXX +XXXXX + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + +XXXXX + X + X + X + X + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + + X + X +XXXXX + X + X + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + +X X + X X X + X X + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + + X X + X X X +X X + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + +XXXX +X +X +XXXX +X +X +XXXX + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + +XXX + X + X + X + X + X +XXX + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + + XX +X X +X X + XX + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + + XX +X X +X X + XX +X X +X X + XX + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: +Please chose a number: + 1: A cross + 2: A slash from the upper left to lower right + 3: A slash from the upper right to lower left + 4: An X + 5: A greater than sign + 6: A less than sign + 7: Two greater than signs + 8: Two less than signs + 9: A 'V' + 10: An inverse 'V' + 11: Numbers 9 and 10 combined + 12: A full grid + 13: A 'T' + 14: A plus '+' + 15: A 'W' + 16: An 'M' + 17: An 'E' + 18: A '3' + 19: An 'O' + 20: An '8' + 21: An 'S' +Your choice => + + XXX +X +X + XX + X + X +XXX + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + +-XX- +X-X- +X--- +-XX- +---X +-X-X +-XX- + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + +-XX- +X-X- +X-X- +-XX- +-X-X +-X-X +-XX- + +Would you like to continue with the next generation? +Please use lowercase y or n for your answer [y]: + + +Would you like to choose a background pattern? +Please use lowercase y or n for your answer [n]: \ No newline at end of file diff --git a/src/tests/codegen/list.cl b/src/tests/codegen/list.cl new file mode 100644 index 000000000..e8bbcb844 --- /dev/null +++ b/src/tests/codegen/list.cl @@ -0,0 +1,141 @@ +(* + * This file shows how to implement a list data type for lists of integers. + * It makes use of INHERITANCE and DYNAMIC DISPATCH. + * + * The List class has 4 operations defined on List objects. If 'l' is + * a list, then the methods dispatched on 'l' have the following effects: + * + * isNil() : Bool Returns true if 'l' is empty, false otherwise. + * head() : Int Returns the integer at the head of 'l'. + * If 'l' is empty, execution aborts. + * tail() : List Returns the remainder of the 'l', + * i.e. without the first element. + * cons(i : Int) : List Return a new list containing i as the + * first element, followed by the + * elements in 'l'. + * + * There are 2 kinds of lists, the empty list and a non-empty + * list. We can think of the non-empty list as a specialization of + * the empty list. + * The class List defines the operations on empty list. The class + * Cons inherits from List and redefines things to handle non-empty + * lists. + *) + + +class List { + -- Define operations on empty lists. + + isNil() : Bool { true }; + + -- Since abort() has return type Object and head() has return type + -- Int, we need to have an Int as the result of the method body, + -- even though abort() never returns. + + head() : Int { { abort(); 0; } }; + + -- As for head(), the self is just to make sure the return type of + -- tail() is correct. + + tail() : List { { abort(); self; } }; + + -- When we cons and element onto the empty list we get a non-empty + -- list. The (new Cons) expression creates a new list cell of class + -- Cons, which is initialized by a dispatch to init(). + -- The result of init() is an element of class Cons, but it + -- conforms to the return type List, because Cons is a subclass of + -- List. + + cons(i : Int) : List { + (new Cons).init(i, self) + }; + +}; + + +(* + * Cons inherits all operations from List. We can reuse only the cons + * method though, because adding an element to the front of an emtpy + * list is the same as adding it to the front of a non empty + * list. All other methods have to be redefined, since the behaviour + * for them is different from the empty list. + * + * Cons needs two attributes to hold the integer of this list + * cell and to hold the rest of the list. + * + * The init() method is used by the cons() method to initialize the + * cell. + *) + +class Cons inherits List { + + car : Int; -- The element in this list cell + + cdr : List; -- The rest of the list + + isNil() : Bool { false }; + + head() : Int { car }; + + tail() : List { cdr }; + + init(i : Int, rest : List) : List { + { + car <- i; + cdr <- rest; + self; + } + }; + +}; + + + +(* + * The Main class shows how to use the List class. It creates a small + * list and then repeatedly prints out its elements and takes off the + * first element of the list. + *) + +class Main inherits IO { + + mylist : List; + + -- Print all elements of the list. Calls itself recursively with + -- the tail of the list, until the end of the list is reached. + + print_list(l : List) : Object { + if l.isNil() then out_string("\n") + else { + out_int(l.head()); + out_string(" "); + print_list(l.tail()); + } + fi + }; + + -- Note how the dynamic dispatch mechanism is responsible to end + -- the while loop. As long as mylist is bound to an object of + -- dynamic type Cons, the dispatch to isNil calls the isNil method of + -- the Cons class, which returns false. However when we reach the + -- end of the list, mylist gets bound to the object that was + -- created by the (new List) expression. This object is of dynamic type + -- List, and thus the method isNil in the List class is called and + -- returns true. + + main() : Object { + { + mylist <- new List.cons(1).cons(2).cons(3).cons(4).cons(5); + while (not mylist.isNil()) loop + { + print_list(mylist); + mylist <- mylist.tail(); + } + pool; + } + }; + +}; + + + diff --git a/src/tests/codegen/list_input.txt b/src/tests/codegen/list_input.txt new file mode 100644 index 000000000..e69de29bb diff --git a/src/tests/codegen/list_output.txt b/src/tests/codegen/list_output.txt new file mode 100644 index 000000000..fca724903 --- /dev/null +++ b/src/tests/codegen/list_output.txt @@ -0,0 +1,5 @@ +5 4 3 2 1 +4 3 2 1 +3 2 1 +2 1 +1 diff --git a/src/tests/codegen/new_complex.cl b/src/tests/codegen/new_complex.cl new file mode 100644 index 000000000..a4fe714ce --- /dev/null +++ b/src/tests/codegen/new_complex.cl @@ -0,0 +1,79 @@ +class Main inherits IO { + main() : IO { + (let c : Complex <- (new Complex).init(1, 1) in + { + -- trivially equal (see CoolAid) + if c.reflect_X() = c.reflect_0() + then out_string("=)\n") + else out_string("=(\n") + fi; + -- equal + if c.reflect_X().reflect_Y().equal(c.reflect_0()) + then out_string("=)\n") + else out_string("=(\n") + fi; + } + ) + }; +}; + +class Complex inherits IO { + x : Int; + y : Int; + + init(a : Int, b : Int) : Complex { + { + x = a; + y = b; + self; + } + }; + + print() : Object { + if y = 0 + then out_int(x) + else out_int(x).out_string("+").out_int(y).out_string("I") + fi + }; + + reflect_0() : Complex { + { + x = ~x; + y = ~y; + self; + } + }; + + reflect_X() : Complex { + { + y = ~y; + self; + } + }; + + reflect_Y() : Complex { + { + x = ~x; + self; + } + }; + + equal(d : Complex) : Bool { + if x = d.x_value() + then + if y = d.y_value() + then true + else false + fi + else false + fi + }; + + x_value() : Int { + x + }; + + y_value() : Int { + y + }; +}; diff --git a/src/tests/codegen/new_complex_input.txt b/src/tests/codegen/new_complex_input.txt new file mode 100644 index 000000000..e69de29bb diff --git a/src/tests/codegen/new_complex_output.txt b/src/tests/codegen/new_complex_output.txt new file mode 100644 index 000000000..0e8da112c --- /dev/null +++ b/src/tests/codegen/new_complex_output.txt @@ -0,0 +1,2 @@ +=) +=) diff --git a/src/tests/codegen/palindrome.cl b/src/tests/codegen/palindrome.cl new file mode 100644 index 000000000..7f24789f9 --- /dev/null +++ b/src/tests/codegen/palindrome.cl @@ -0,0 +1,25 @@ +class Main inherits IO { + pal(s : String) : Bool { + if s.length() = 0 + then true + else if s.length() = 1 + then true + else if s.substr(0, 1) = s.substr(s.length() - 1, 1) + then pal(s.substr(1, s.length() -2)) + else false + fi fi fi + }; + + i : Int; + + main() : IO { + { + i <- ~1; + out_string("enter a string\n"); + if pal(in_string()) + then out_string("that was a palindrome\n") + else out_string("that was not a palindrome\n") + fi; + } + }; +}; diff --git a/src/tests/codegen/palindrome_input.txt b/src/tests/codegen/palindrome_input.txt new file mode 100644 index 000000000..8e1b64142 --- /dev/null +++ b/src/tests/codegen/palindrome_input.txt @@ -0,0 +1 @@ +anitalabalatina diff --git a/src/tests/codegen/palindrome_output.txt b/src/tests/codegen/palindrome_output.txt new file mode 100644 index 000000000..7a0095959 --- /dev/null +++ b/src/tests/codegen/palindrome_output.txt @@ -0,0 +1,2 @@ +enter a string +that was a palindrome diff --git a/src/tests/codegen/primes.cl b/src/tests/codegen/primes.cl new file mode 100644 index 000000000..ea9533298 --- /dev/null +++ b/src/tests/codegen/primes.cl @@ -0,0 +1,84 @@ + +(* + * methodless-primes.cl + * + * Designed by Jesse H. Willett, jhw@cory, 11103234, with + * Istvan Siposs, isiposs@cory, 12342921. + * + * This program generates primes in order without using any methods. + * Actually, it does use three methods: those of IO to print out each + * prime, and abort() to halt the program. These methods are incidental, + * however, to the information-processing functionality of the program. We + * could regard the attribute 'out's sequential values as our output, and + * the string "halt" as our terminate signal. + * + * Naturally, using Cool this way is a real waste, basically reducing it + * to assembly without the benefit of compilation. + * + * There could even be a subroutine-like construction, in that different + * code could be in the assign fields of attributes of other classes, + * and it could be executed by calling 'new Sub', but no parameters + * could be passed to the subroutine, and it could only return itself. + * but returning itself would be useless since we couldn't call methods + * and the only operators we have are for Int and Bool, which do nothing + * interesting when we initialize them! + *) + +class Main inherits IO { + + main() : Int { -- main() is an atrophied method so we can parse. + 0 + }; + + out : Int <- -- out is our 'output'. Its values are the primes. + { + out_string("2 is trivially prime.\n"); + 2; + }; + + testee : Int <- out; -- testee is a number to be tested for primeness. + + divisor : Int; -- divisor is a number which may factor testee. + + stop : Int <- 500; -- stop is an arbitrary value limiting testee. + + m : Object <- -- m supplants the main method. + while true loop + { + + testee <- testee + 1; + divisor <- 2; + + while + if testee < divisor * divisor + then false -- can stop if divisor > sqrt(testee). + else if testee - divisor*(testee/divisor) = 0 + then false -- can stop if divisor divides testee. + else true + fi fi + loop + divisor <- divisor + 1 + pool; + + if testee < divisor * divisor -- which reason did we stop for? + then -- testee has no factors less than sqrt(testee). + { + out <- testee; -- we could think of out itself as the output. + out_int(out); + out_string(" is prime.\n"); + } + else -- the loop halted on testee/divisor = 0, testee isn't prime. + 0 -- testee isn't prime, do nothing. + fi; + + if stop <= testee then + "halt".abort() -- we could think of "halt" as SIGTERM. + else + "continue" + fi; + + } + pool; + +}; (* end of Main *) + diff --git a/src/tests/codegen/primes_input.txt b/src/tests/codegen/primes_input.txt new file mode 100644 index 000000000..e69de29bb diff --git a/src/tests/codegen/primes_output.txt b/src/tests/codegen/primes_output.txt new file mode 100644 index 000000000..a4d0fcb3f --- /dev/null +++ b/src/tests/codegen/primes_output.txt @@ -0,0 +1,96 @@ +2 is trivially prime. +3 is prime. +5 is prime. +7 is prime. +11 is prime. +13 is prime. +17 is prime. +19 is prime. +23 is prime. +29 is prime. +31 is prime. +37 is prime. +41 is prime. +43 is prime. +47 is prime. +53 is prime. +59 is prime. +61 is prime. +67 is prime. +71 is prime. +73 is prime. +79 is prime. +83 is prime. +89 is prime. +97 is prime. +101 is prime. +103 is prime. +107 is prime. +109 is prime. +113 is prime. +127 is prime. +131 is prime. +137 is prime. +139 is prime. +149 is prime. +151 is prime. +157 is prime. +163 is prime. +167 is prime. +173 is prime. +179 is prime. +181 is prime. +191 is prime. +193 is prime. +197 is prime. +199 is prime. +211 is prime. +223 is prime. +227 is prime. +229 is prime. +233 is prime. +239 is prime. +241 is prime. +251 is prime. +257 is prime. +263 is prime. +269 is prime. +271 is prime. +277 is prime. +281 is prime. +283 is prime. +293 is prime. +307 is prime. +311 is prime. +313 is prime. +317 is prime. +331 is prime. +337 is prime. +347 is prime. +349 is prime. +353 is prime. +359 is prime. +367 is prime. +373 is prime. +379 is prime. +383 is prime. +389 is prime. +397 is prime. +401 is prime. +409 is prime. +419 is prime. +421 is prime. +431 is prime. +433 is prime. +439 is prime. +443 is prime. +449 is prime. +457 is prime. +461 is prime. +463 is prime. +467 is prime. +479 is prime. +487 is prime. +491 is prime. +499 is prime. +Abort called from class String diff --git a/src/tests/codegen/print-cool.cl b/src/tests/codegen/print-cool.cl new file mode 100644 index 000000000..8d7a336f3 --- /dev/null +++ b/src/tests/codegen/print-cool.cl @@ -0,0 +1,9 @@ +class Main inherits IO { + main() : IO { + { + out_string((new Object).type_name().substr(4,1)). + out_string((isvoid self).type_name().substr(1,3)); -- demonstrates the dispatch rules. + out_string("\n"); + } + }; +}; diff --git a/src/tests/codegen/print-cool_input.txt b/src/tests/codegen/print-cool_input.txt new file mode 100644 index 000000000..e69de29bb diff --git a/src/tests/codegen/print-cool_output.txt b/src/tests/codegen/print-cool_output.txt new file mode 100644 index 000000000..2b58f8985 --- /dev/null +++ b/src/tests/codegen/print-cool_output.txt @@ -0,0 +1 @@ +cool diff --git a/src/tests/codegen/sort-list.cl b/src/tests/codegen/sort-list.cl new file mode 100644 index 000000000..d49d56c4b --- /dev/null +++ b/src/tests/codegen/sort-list.cl @@ -0,0 +1,146 @@ +(* + This file presents a fairly large example of Cool programming. The +class List defines the names of standard list operations ala Scheme: +car, cdr, cons, isNil, rev, sort, rcons (add an element to the end of +the list), and print_list. In the List class most of these functions +are just stubs that abort if ever called. The classes Nil and Cons +inherit from List and define the same operations, but now as +appropriate to the empty list (for the Nil class) and for cons cells (for +the Cons class). + +The Main class puts all of this code through the following silly +test exercise: + + 1. prompt for a number N + 2. generate a list of numbers 0..N-1 + 3. reverse the list + 4. sort the list + 5. print the sorted list + +Because the sort used is a quadratic space insertion sort, sorting +moderately large lists can be quite slow. +*) + +Class List inherits IO { + (* Since abort() returns Object, we need something of + type Bool at the end of the block to satisfy the typechecker. + This code is unreachable, since abort() halts the program. *) + isNil() : Bool { { abort(); true; } }; + + cons(hd : Int) : Cons { + (let new_cell : Cons <- new Cons in + new_cell.init(hd,self) + ) + }; + + (* + Since abort "returns" type Object, we have to add + an expression of type Int here to satisfy the typechecker. + This code is, of course, unreachable. + *) + car() : Int { { abort(); new Int; } }; + + cdr() : List { { abort(); new List; } }; + + rev() : List { cdr() }; + + sort() : List { cdr() }; + + insert(i : Int) : List { cdr() }; + + rcons(i : Int) : List { cdr() }; + + print_list() : Object { abort() }; +}; + +Class Cons inherits List { + xcar : Int; -- We keep the car in cdr in attributes. + xcdr : List; + + isNil() : Bool { false }; + + init(hd : Int, tl : List) : Cons { + { + xcar <- hd; + xcdr <- tl; + self; + } + }; + + car() : Int { xcar }; + + cdr() : List { xcdr }; + + rev() : List { (xcdr.rev()).rcons(xcar) }; + + sort() : List { (xcdr.sort()).insert(xcar) }; + + insert(i : Int) : List { + if i < xcar then + (new Cons).init(i,self) + else + (new Cons).init(xcar,xcdr.insert(i)) + fi + }; + + + rcons(i : Int) : List { (new Cons).init(xcar, xcdr.rcons(i)) }; + + print_list() : Object { + { + out_int(xcar); + out_string("\n"); + xcdr.print_list(); + } + }; +}; + +Class Nil inherits List { + isNil() : Bool { true }; + + rev() : List { self }; + + sort() : List { self }; + + insert(i : Int) : List { rcons(i) }; + + rcons(i : Int) : List { (new Cons).init(i,self) }; + + print_list() : Object { true }; + +}; + + +Class Main inherits IO { + + l : List; + + (* iota maps its integer argument n into the list 0..n-1 *) + iota(i : Int) : List { + { + l <- new Nil; + (let j : Int <- 0 in + while j < i + loop + { + l <- (new Cons).init(j,l); + j <- j + 1; + } + pool + ); + l; + } + }; + + main() : Object { + { + out_string("How many numbers to sort? "); + iota(in_int()).rev().sort().print_list(); + } + }; +}; + + + + + diff --git a/src/tests/codegen/sort-list_input.txt b/src/tests/codegen/sort-list_input.txt new file mode 100644 index 000000000..f599e28b8 --- /dev/null +++ b/src/tests/codegen/sort-list_input.txt @@ -0,0 +1 @@ +10 diff --git a/src/tests/codegen/sort-list_output.txt b/src/tests/codegen/sort-list_output.txt new file mode 100644 index 000000000..9878d57ea --- /dev/null +++ b/src/tests/codegen/sort-list_output.txt @@ -0,0 +1,10 @@ +How many numbers to sort? 0 +1 +2 +3 +4 +5 +6 +7 +8 +9 diff --git a/src/tests/codegen_test.py b/src/tests/codegen_test.py new file mode 100644 index 000000000..48df768ff --- /dev/null +++ b/src/tests/codegen_test.py @@ -0,0 +1,17 @@ +import pytest +import os +from utils import compare_outputs + +tests_dir = __file__.rpartition('/')[0] + '/codegen/' +tests = [(file) for file in os.listdir(tests_dir) if file.endswith('.cl')] + +# @pytest.mark.lexer +# @pytest.mark.parser +# @pytest.mark.semantic +@pytest.mark.codegen +@pytest.mark.ok +@pytest.mark.run(order=4) +@pytest.mark.parametrize("cool_file", tests) +def test_codegen(compiler_path, cool_file): + compare_outputs(compiler_path, tests_dir + cool_file, tests_dir + cool_file[:-3] + '_input.txt',\ + tests_dir + cool_file[:-3] + '_output.txt') \ No newline at end of file diff --git a/src/tests/conftest.py b/src/tests/conftest.py new file mode 100644 index 000000000..1f44eeb72 --- /dev/null +++ b/src/tests/conftest.py @@ -0,0 +1,6 @@ +import pytest +import os + +@pytest.fixture +def compiler_path(): + return os.path.abspath('./coolc.sh') \ No newline at end of file diff --git a/src/tests/lexer/comment1.cl b/src/tests/lexer/comment1.cl new file mode 100644 index 000000000..69533f23c --- /dev/null +++ b/src/tests/lexer/comment1.cl @@ -0,0 +1,55 @@ +--Any characters between two dashes “--” and the next newline +--(or EOF, if there is no next newline) are treated as comments + +(*(*(* +Comments may also be written by enclosing +text in (∗ . . . ∗). The latter form of comment may be nested. +Comments cannot cross file boundaries. +*)*)*) + +class Error() { + + (* There was once a comment, + that was quite long. + But, the reader soon discovered that + the comment was indeed longer than + previously assumed. Now, the reader + was in a real dilemma; is the comment + ever gonna end? If I stop reading, will + it end? + He started imagining all sorts of things. + He thought about heisenberg's cat and how + how that relates to the end of the sentence. + He thought to himself "I'm gonna stop reading". + "If I keep reading this comment, I'm gonna know + the fate of this sentence; That will be disastorous." + He knew that such a comment was gonna extend to + another file. It was too awesome to be contained in + a single file. And he would have kept reading too... + if only... + cool wasn't a super-duper-fab-awesomest language; + but cool is that language; + "This comment shall go not cross this file" said cool. + Alas! The reader could read no more. + There was once a comment, + that was quite long. + But, the reader soon discovered that + the comment was indeed longer than + previously assumed. Now, the reader + was in a real dilemma; is the comment + ever gonna end? If I stop reading, will + it end? + He started imagining all sorts of things. + He thought about heisenberg's cat and how + how that relates to the end of the sentence. + He thought to himself "I'm gonna stop reading". + "If I keep reading this comment, I'm gonna know + the fate of this sentence; That will be disastorous." + He knew that such a comment was gonna extend to + another file. It was too awesome to be contained in + a single file. And he would have kept reading too... + if only... + cool wasn't a super-duper-fab-awesomest language; + but cool is that language; + "This comment shall go not cross this file" said cool. + Alas! The reader could read no more. \ No newline at end of file diff --git a/src/tests/lexer/comment1_error.txt b/src/tests/lexer/comment1_error.txt new file mode 100644 index 000000000..9fd7b8d67 --- /dev/null +++ b/src/tests/lexer/comment1_error.txt @@ -0,0 +1 @@ +(55, 46) - LexicographicError: EOF in comment diff --git a/src/tests/lexer/iis1.cl b/src/tests/lexer/iis1.cl new file mode 100644 index 000000000..12cb52beb --- /dev/null +++ b/src/tests/lexer/iis1.cl @@ -0,0 +1,111 @@ +(* Integers, Identifiers, and Special Notation *) + +0007 123 +1 -1 +90 -09 +11113 -4r *a *self* c++ +5! = 120, 2 + 2 = 5 or E = mc2; p + 1 @ p = 1: for x in range(len(b)) +new / <- <<==> {( Int: Objet, Bool; String.string SELF_TYPE isvoid }) +class Class if then else fi testing Testing ~007agent_bond james_007B0N3SS___ +loop pool while tRuE or noT faLsE let in case of ESAC + +(* +#3 INT_CONST 0007 +#3 INT_CONST 123 +#3 '+' +#3 INT_CONST 1 +#3 '-' +#3 INT_CONST 1 +#3 '+' +#3 INT_CONST 90 +#3 '-' +#3 INT_CONST 09 +#3 '+' +#3 INT_CONST 11113 +#3 '-' +#3 INT_CONST 4 +#3 OBJECTID r +#3 '*' +#3 OBJECTID a +#3 '*' +#3 OBJECTID self +#3 '*' +#3 OBJECTID c +#3 '+' +#3 '+' +#4 INT_CONST 5 +#4 ERROR "!" +#4 '=' +#4 INT_CONST 120 +#4 ',' +#4 INT_CONST 2 +#4 '+' +#4 INT_CONST 2 +#4 '=' +#4 INT_CONST 5 +#4 OBJECTID or +#4 TYPEID E +#4 '=' +#4 OBJECTID mc2 +#4 ';' +#4 OBJECTID p +#4 '+' +#4 INT_CONST 1 +#4 '@' +#4 OBJECTID p +#4 '=' +#4 INT_CONST 1 +#4 ':' +#4 OBJECTID for +#4 OBJECTID x +#4 IN +#4 OBJECTID range +#4 '(' +#4 OBJECTID len +#4 '(' +#4 OBJECTID b +#4 ')' +#4 ')' +#5 NEW +#5 '/' +#5 ASSIGN +#5 '<' +#5 LE +#5 DARROW +#5 '{' +#5 '(' +#5 TYPEID Int +#5 ':' +#5 TYPEID Objet +#5 ',' +#5 TYPEID Bool +#5 ';' +#5 TYPEID String +#5 '.' +#5 OBJECTID string +#5 TYPEID SELF_TYPE +#5 ISVOID +#5 '}' +#5 ')' +#6 CLASS +#6 CLASS +#6 IF +#6 THEN +#6 ELSE +#6 FI +#6 OBJECTID testing +#6 TYPEID Testing +#6 '~' +#6 INT_CONST 007 +#6 OBJECTID agent_bond +#6 OBJECTID james_007B0N3SS___ +#7 LOOP +#7 POOL +#7 WHILE +#7 BOOL_CONST true +#7 OBJECTID or +#7 NOT +#7 BOOL_CONST false +#7 LET +#7 IN +#7 CASE +#7 OF +#7 ESAC +*) \ No newline at end of file diff --git a/src/tests/lexer/iis1_error.txt b/src/tests/lexer/iis1_error.txt new file mode 100644 index 000000000..9e6d66cac --- /dev/null +++ b/src/tests/lexer/iis1_error.txt @@ -0,0 +1 @@ +(4, 2) - LexicographicError: ERROR "!" diff --git a/src/tests/lexer/iis2.cl b/src/tests/lexer/iis2.cl new file mode 100644 index 000000000..9b25715d4 --- /dev/null +++ b/src/tests/lexer/iis2.cl @@ -0,0 +1,120 @@ +(* Integers, Identifiers, and Special Notation *) + +0007 123 +1 -1 +90 -09 +11113 -4r *a *self* c++ +class Class if then else fi testing Testing ~007agent_bond james_007bones___ + + +new / <- <<==> {( Int: Objet, Bool; String.string SELF_TYPE isvoid }) +loop pool while tRuE or noT faLsE let in case of ESAC + +factorial(5) = 120, 2 + 2 = 5? or E = mc2; p + 1 resto p = 1: (@ for x in range(len(b))) + +(* +#3 INT_CONST 0007 +#3 INT_CONST 123 +#3 '+' +#3 INT_CONST 1 +#3 '-' +#3 INT_CONST 1 +#3 '+' +#3 INT_CONST 90 +#3 '-' +#3 INT_CONST 09 +#3 '+' +#3 INT_CONST 11113 +#3 '-' +#3 INT_CONST 4 +#3 OBJECTID r +#3 '*' +#3 OBJECTID a +#3 '*' +#3 OBJECTID self +#3 '*' +#3 OBJECTID c +#3 '+' +#3 '+' +#4 CLASS +#4 CLASS +#4 IF +#4 THEN +#4 ELSE +#4 FI +#4 OBJECTID testing +#4 TYPEID Testing +#4 '~' +#4 INT_CONST 007 +#4 OBJECTID agent_bond +#4 OBJECTID james_007bones___ +#7 NEW +#7 '/' +#7 ASSIGN +#7 '<' +#7 LE +#7 DARROW +#7 '{' +#7 '(' +#7 TYPEID Int +#7 ':' +#7 TYPEID Objet +#7 ',' +#7 TYPEID Bool +#7 ';' +#7 TYPEID String +#7 '.' +#7 OBJECTID string +#7 TYPEID SELF_TYPE +#7 ISVOID +#7 '}' +#7 ')' +#8 LOOP +#8 POOL +#8 WHILE +#8 BOOL_CONST true +#8 OBJECTID or +#8 NOT +#8 BOOL_CONST false +#8 LET +#8 IN +#8 CASE +#8 OF +#8 ESAC +#10 OBJECTID factorial +#10 '(' +#10 INT_CONST 5 +#10 ')' +#10 '=' +#10 INT_CONST 120 +#10 ',' +#10 INT_CONST 2 +#10 '+' +#10 INT_CONST 2 +#10 '=' +#10 INT_CONST 5 +#10 ERROR "?" +#10 OBJECTID or +#10 TYPEID E +#10 '=' +#10 OBJECTID mc2 +#10 ';' +#10 OBJECTID p +#10 '+' +#10 INT_CONST 1 +#10 OBJECTID resto +#10 OBJECTID p +#10 '=' +#10 INT_CONST 1 +#10 ':' +#10 '(' +#10 '@' +#10 OBJECTID for +#10 OBJECTID x +#10 IN +#10 OBJECTID range +#10 '(' +#10 OBJECTID len +#10 '(' +#10 OBJECTID b +#10 ')' +#10 ')' +#10 ')' +*) \ No newline at end of file diff --git a/src/tests/lexer/iis2_error.txt b/src/tests/lexer/iis2_error.txt new file mode 100644 index 000000000..922391a9d --- /dev/null +++ b/src/tests/lexer/iis2_error.txt @@ -0,0 +1 @@ +(10, 30) - LexicographicError: ERROR "?" diff --git a/src/tests/lexer/iis3.cl b/src/tests/lexer/iis3.cl new file mode 100644 index 000000000..0b965ddea --- /dev/null +++ b/src/tests/lexer/iis3.cl @@ -0,0 +1,121 @@ +(* Integers, Identifiers, and Special Notation *) + +factorial(5) = 120, 2 + 2 = 5 or E = mc^2; p + 1 @ p = 1: z for x in range(len(b))) + +loop pool while tRuE or noT faLsE let in case of ESAC + +new / <- <<==> {( Int: Objet, Bool; String.string SELF_TYPE isvoid }) + + +0007 123 +1 -1 +90 -09 +11113 -4r *a *self* c++ +class Class if then else fi testing Testing ~007agent_bond james_007bones___ + +(* +#3 OBJECTID factorial +#3 '(' +#3 INT_CONST 5 +#3 ')' +#3 '=' +#3 INT_CONST 120 +#3 ',' +#3 INT_CONST 2 +#3 '+' +#3 INT_CONST 2 +#3 '=' +#3 INT_CONST 5 +#3 OBJECTID or +#3 TYPEID E +#3 '=' +#3 OBJECTID mc +#3 ERROR "^" +#3 INT_CONST 2 +#3 ';' +#3 OBJECTID p +#3 '+' +#3 INT_CONST 1 +#3 '@' +#3 OBJECTID p +#3 '=' +#3 INT_CONST 1 +#3 ':' +#3 OBJECTID z +#3 OBJECTID for +#3 OBJECTID x +#3 IN +#3 OBJECTID range +#3 '(' +#3 OBJECTID len +#3 '(' +#3 OBJECTID b +#3 ')' +#3 ')' +#3 ')' +#5 LOOP +#5 POOL +#5 WHILE +#5 BOOL_CONST true +#5 OBJECTID or +#5 NOT +#5 BOOL_CONST false +#5 LET +#5 IN +#5 CASE +#5 OF +#5 ESAC +#7 NEW +#7 '/' +#7 ASSIGN +#7 '<' +#7 LE +#7 DARROW +#7 '{' +#7 '(' +#7 TYPEID Int +#7 ':' +#7 TYPEID Objet +#7 ',' +#7 TYPEID Bool +#7 ';' +#7 TYPEID String +#7 '.' +#7 OBJECTID string +#7 TYPEID SELF_TYPE +#7 ISVOID +#7 '}' +#7 ')' +#10 INT_CONST 0007 +#10 INT_CONST 123 +#10 '+' +#10 INT_CONST 1 +#10 '-' +#10 INT_CONST 1 +#10 '+' +#10 INT_CONST 90 +#10 '-' +#10 INT_CONST 09 +#10 '+' +#10 INT_CONST 11113 +#10 '-' +#10 INT_CONST 4 +#10 OBJECTID r +#10 '*' +#10 OBJECTID a +#10 '*' +#10 OBJECTID self +#10 '*' +#10 OBJECTID c +#10 '+' +#10 '+' +#11 CLASS +#11 CLASS +#11 IF +#11 THEN +#11 ELSE +#11 FI +#11 OBJECTID testing +#11 TYPEID Testing +#11 '~' +#11 INT_CONST 007 +#11 OBJECTID agent_bond +#11 OBJECTID james_007bones___ +*) \ No newline at end of file diff --git a/src/tests/lexer/iis3_error.txt b/src/tests/lexer/iis3_error.txt new file mode 100644 index 000000000..b001b6a71 --- /dev/null +++ b/src/tests/lexer/iis3_error.txt @@ -0,0 +1 @@ +(3, 40) - LexicographicError: ERROR "^" diff --git a/src/tests/lexer/iis4.cl b/src/tests/lexer/iis4.cl new file mode 100644 index 000000000..9e7a9cb62 --- /dev/null +++ b/src/tests/lexer/iis4.cl @@ -0,0 +1,120 @@ +(* Integers, Identifiers, and Special Notation *) + +new / <- <<==> {( Int: Objet, Bool; String.string SELF_TYPE isvoid }) +0007 123 +1 -1 +90 -09 +11113 -4r *a *self* c++ + +factorial(5) = 120, 2 + 2 = 5 or E = mc2; p + 1 % p = 1: @.@ for x in range(len(b))~ + + +loop pool while tRuE or noT faLsE let in case of ESAC +class Class if then else fi testing Testing ~007agent_bond james_007bones___ + +(* +#3 NEW +#3 '/' +#3 ASSIGN +#3 '<' +#3 LE +#3 DARROW +#3 '{' +#3 '(' +#3 TYPEID Int +#3 ':' +#3 TYPEID Objet +#3 ',' +#3 TYPEID Bool +#3 ';' +#3 TYPEID String +#3 '.' +#3 OBJECTID string +#3 TYPEID SELF_TYPE +#3 ISVOID +#3 '}' +#3 ')' +#4 INT_CONST 0007 +#4 INT_CONST 123 +#4 '+' +#4 INT_CONST 1 +#4 '-' +#4 INT_CONST 1 +#4 '+' +#4 INT_CONST 90 +#4 '-' +#4 INT_CONST 09 +#4 '+' +#4 INT_CONST 11113 +#4 '-' +#4 INT_CONST 4 +#4 OBJECTID r +#4 '*' +#4 OBJECTID a +#4 '*' +#4 OBJECTID self +#4 '*' +#4 OBJECTID c +#4 '+' +#4 '+' +#6 OBJECTID factorial +#6 '(' +#6 INT_CONST 5 +#6 ')' +#6 '=' +#6 INT_CONST 120 +#6 ',' +#6 INT_CONST 2 +#6 '+' +#6 INT_CONST 2 +#6 '=' +#6 INT_CONST 5 +#6 OBJECTID or +#6 TYPEID E +#6 '=' +#6 OBJECTID mc2 +#6 ';' +#6 OBJECTID p +#6 '+' +#6 INT_CONST 1 +#6 ERROR "%" +#6 OBJECTID p +#6 '=' +#6 INT_CONST 1 +#6 ':' +#6 '@' +#6 '.' +#6 '@' +#6 OBJECTID for +#6 OBJECTID x +#6 IN +#6 OBJECTID range +#6 '(' +#6 OBJECTID len +#6 '(' +#6 OBJECTID b +#6 ')' +#6 ')' +#6 '~' +#9 LOOP +#9 POOL +#9 WHILE +#9 BOOL_CONST true +#9 OBJECTID or +#9 NOT +#9 BOOL_CONST false +#9 LET +#9 IN +#9 CASE +#9 OF +#9 ESAC +#10 CLASS +#10 CLASS +#10 IF +#10 THEN +#10 ELSE +#10 FI +#10 OBJECTID testing +#10 TYPEID Testing +#10 '~' +#10 INT_CONST 007 +#10 OBJECTID agent_bond +#10 OBJECTID james_007bones___ +*) \ No newline at end of file diff --git a/src/tests/lexer/iis4_error.txt b/src/tests/lexer/iis4_error.txt new file mode 100644 index 000000000..f24076a8c --- /dev/null +++ b/src/tests/lexer/iis4_error.txt @@ -0,0 +1 @@ +(6, 49) - LexicographicError: ERROR "!" diff --git a/src/tests/lexer/iis5.cl b/src/tests/lexer/iis5.cl new file mode 100644 index 000000000..d146c0547 --- /dev/null +++ b/src/tests/lexer/iis5.cl @@ -0,0 +1,121 @@ +(* Integers, Identifiers, and Special Notation *) + + +loop pool while tRuE or noT faLsE let in case of ESAC +new / <- <<==> {( Int: Objet, Bool; String.string SELF_TYPE isvoid }) +class Class if then else fi testing Testing ~007agent_bond james_007bones___ + +factorial(5) = 120, 2 + 2 = 5 or E = mc2; p + 1 resto p = 1: [@.@ for x in range(len(b))] + +0007 123 +1 -1 +90 -09 +11113 -4r *a *self* c++ + +(* +#4 LOOP +#4 POOL +#4 WHILE +#4 BOOL_CONST true +#4 OBJECTID or +#4 NOT +#4 BOOL_CONST false +#4 LET +#4 IN +#4 CASE +#4 OF +#4 ESAC +#5 NEW +#5 '/' +#5 ASSIGN +#5 '<' +#5 LE +#5 DARROW +#5 '{' +#5 '(' +#5 TYPEID Int +#5 ':' +#5 TYPEID Objet +#5 ',' +#5 TYPEID Bool +#5 ';' +#5 TYPEID String +#5 '.' +#5 OBJECTID string +#5 TYPEID SELF_TYPE +#5 ISVOID +#5 '}' +#5 ')' +#6 CLASS +#6 CLASS +#6 IF +#6 THEN +#6 ELSE +#6 FI +#6 OBJECTID testing +#6 TYPEID Testing +#6 '~' +#6 INT_CONST 007 +#6 OBJECTID agent_bond +#6 OBJECTID james_007bones___ +#8 OBJECTID factorial +#8 '(' +#8 INT_CONST 5 +#8 ')' +#8 '=' +#8 INT_CONST 120 +#8 ',' +#8 INT_CONST 2 +#8 '+' +#8 INT_CONST 2 +#8 '=' +#8 INT_CONST 5 +#8 OBJECTID or +#8 TYPEID E +#8 '=' +#8 OBJECTID mc2 +#8 ';' +#8 OBJECTID p +#8 '+' +#8 INT_CONST 1 +#8 OBJECTID resto +#8 OBJECTID p +#8 '=' +#8 INT_CONST 1 +#8 ':' +#8 ERROR "[" +#8 '@' +#8 '.' +#8 '@' +#8 OBJECTID for +#8 OBJECTID x +#8 IN +#8 OBJECTID range +#8 '(' +#8 OBJECTID len +#8 '(' +#8 OBJECTID b +#8 ')' +#8 ')' +#8 ERROR "]" +#10 INT_CONST 0007 +#10 INT_CONST 123 +#10 '+' +#10 INT_CONST 1 +#10 '-' +#10 INT_CONST 1 +#10 '+' +#10 INT_CONST 90 +#10 '-' +#10 INT_CONST 09 +#10 '+' +#10 INT_CONST 11113 +#10 '-' +#10 INT_CONST 4 +#10 OBJECTID r +#10 '*' +#10 OBJECTID a +#10 '*' +#10 OBJECTID self +#10 '*' +#10 OBJECTID c +#10 '+' +#10 '+' +*) diff --git a/src/tests/lexer/iis5_error.txt b/src/tests/lexer/iis5_error.txt new file mode 100644 index 000000000..b3dbadcb6 --- /dev/null +++ b/src/tests/lexer/iis5_error.txt @@ -0,0 +1,2 @@ +(8, 62) - LexicographicError: ERROR "[" +(8, 89) - LexicographicError: ERROR "]" diff --git a/src/tests/lexer/iis6.cl b/src/tests/lexer/iis6.cl new file mode 100644 index 000000000..1042f132b --- /dev/null +++ b/src/tests/lexer/iis6.cl @@ -0,0 +1,125 @@ +(* Integers, Identifiers, and Special Notation *) + +factorial(5) = 120, 2 + 2 = 5 or E = mc2; p + 1 resto p = 1: {@.@ for x in range(len(b))} + +new / <- <<==> {( Int: Objet, Bool; String.string SELF_TYPE isvoid }) + + +class Class if then else fi testing Testing ~007agent_bond _james_007bones___ + + + +0007 123 +1 -1 +90 -09 +11113 -4r *a *self* c++ +loop pool while tRuE or noT faLsE let in case of ESAC + +(* +#3 OBJECTID factorial +#3 '(' +#3 INT_CONST 5 +#3 ')' +#3 '=' +#3 INT_CONST 120 +#3 ',' +#3 INT_CONST 2 +#3 '+' +#3 INT_CONST 2 +#3 '=' +#3 INT_CONST 5 +#3 OBJECTID or +#3 TYPEID E +#3 '=' +#3 OBJECTID mc2 +#3 ';' +#3 OBJECTID p +#3 '+' +#3 INT_CONST 1 +#3 OBJECTID resto +#3 OBJECTID p +#3 '=' +#3 INT_CONST 1 +#3 ':' +#3 '{' +#3 '@' +#3 '.' +#3 '@' +#3 OBJECTID for +#3 OBJECTID x +#3 IN +#3 OBJECTID range +#3 '(' +#3 OBJECTID len +#3 '(' +#3 OBJECTID b +#3 ')' +#3 ')' +#3 '}' +#5 NEW +#5 '/' +#5 ASSIGN +#5 '<' +#5 LE +#5 DARROW +#5 '{' +#5 '(' +#5 TYPEID Int +#5 ':' +#5 TYPEID Objet +#5 ',' +#5 TYPEID Bool +#5 ';' +#5 TYPEID String +#5 '.' +#5 OBJECTID string +#5 TYPEID SELF_TYPE +#5 ISVOID +#5 '}' +#5 ')' +#8 CLASS +#8 CLASS +#8 IF +#8 THEN +#8 ELSE +#8 FI +#8 OBJECTID testing +#8 TYPEID Testing +#8 '~' +#8 INT_CONST 007 +#8 OBJECTID agent_bond +#8 ERROR "_" +#8 OBJECTID james_007bones___ +#12 INT_CONST 0007 +#12 INT_CONST 123 +#12 '+' +#12 INT_CONST 1 +#12 '-' +#12 INT_CONST 1 +#12 '+' +#12 INT_CONST 90 +#12 '-' +#12 INT_CONST 09 +#12 '+' +#12 INT_CONST 11113 +#12 '-' +#12 INT_CONST 4 +#12 OBJECTID r +#12 '*' +#12 OBJECTID a +#12 '*' +#12 OBJECTID self +#12 '*' +#12 OBJECTID c +#12 '+' +#12 '+' +#13 LOOP +#13 POOL +#13 WHILE +#13 BOOL_CONST true +#13 OBJECTID or +#13 NOT +#13 BOOL_CONST false +#13 LET +#13 IN +#13 CASE +#13 OF +#13 ESAC +*) \ No newline at end of file diff --git a/src/tests/lexer/iis6_error.txt b/src/tests/lexer/iis6_error.txt new file mode 100644 index 000000000..d7fad9c79 --- /dev/null +++ b/src/tests/lexer/iis6_error.txt @@ -0,0 +1 @@ +(8, 60) - LexicographicError: ERROR "_" diff --git a/src/tests/lexer/mixed1.cl b/src/tests/lexer/mixed1.cl new file mode 100644 index 000000000..803d58ef5 --- /dev/null +++ b/src/tests/lexer/mixed1.cl @@ -0,0 +1,14 @@ +"lkjdsafkljdsalfj\u0000dsafdsaf\u0000djafslkjdsalf\nsdajf\" lkjfdsasdkjfl"123 +adsfasklj# +LKldsajf iNhERITS +"lkdsajf" + +(* +#1 STR_CONST "lkjdsafkljdsalfju0000dsafdsafu0000djafslkjdsalf\nsdajf\" lkjfdsasdkjfl" +#1 INT_CONST 123 +#2 OBJECTID adsfasklj +#2 ERROR "#" +#3 TYPEID LKldsajf +#3 INHERITS +#4 STR_CONST "lkdsajf" +*) \ No newline at end of file diff --git a/src/tests/lexer/mixed1_error.txt b/src/tests/lexer/mixed1_error.txt new file mode 100644 index 000000000..99af5fbdc --- /dev/null +++ b/src/tests/lexer/mixed1_error.txt @@ -0,0 +1 @@ +(2, 10) - LexicographicError: ERROR "#" diff --git a/src/tests/lexer/mixed2.cl b/src/tests/lexer/mixed2.cl new file mode 100644 index 000000000..12039e123 --- /dev/null +++ b/src/tests/lexer/mixed2.cl @@ -0,0 +1,20 @@ +"kjas\"lnnsdj\nfljrdsaf" +@.$.@ +@*%*@ +"alkjfldajf""dasfadsf + +(* +#1 STR_CONST "kjas\"lnnsdj\nfljrdsaf" +#2 '@' +#2 '.' +#2 ERROR "$" +#2 '.' +#2 '@' +#3 '@' +#3 '*' +#3 ERROR "%" +#3 '*' +#3 '@' +#4 STR_CONST "alkjfldajf" +#4 ERROR "Unterminated string constant" +*) \ No newline at end of file diff --git a/src/tests/lexer/mixed2_error.txt b/src/tests/lexer/mixed2_error.txt new file mode 100644 index 000000000..097dc2a07 --- /dev/null +++ b/src/tests/lexer/mixed2_error.txt @@ -0,0 +1,3 @@ +(2, 3) - LexicographicError: ERROR "$" +(3, 3) - LexicographicError: ERROR "%" +(4, 22) - LexicographicError: Unterminated string constant diff --git a/src/tests/lexer/string1.cl b/src/tests/lexer/string1.cl new file mode 100644 index 000000000..6c3c00833 --- /dev/null +++ b/src/tests/lexer/string1.cl @@ -0,0 +1,6 @@ +(* A non-escaped newline character may not appear in a string *) + +"This \ +is OK" +"This is not +OK" \ No newline at end of file diff --git a/src/tests/lexer/string1_error.txt b/src/tests/lexer/string1_error.txt new file mode 100644 index 000000000..078c12bbb --- /dev/null +++ b/src/tests/lexer/string1_error.txt @@ -0,0 +1,2 @@ +(5, 13) - LexicographicError: Unterminated string constant +(6, 4) - LexicographicError: EOF in string constant \ No newline at end of file diff --git a/src/tests/lexer/string2.cl b/src/tests/lexer/string2.cl new file mode 100644 index 000000000..3704b6ae7 --- /dev/null +++ b/src/tests/lexer/string2.cl @@ -0,0 +1,19 @@ +(* A string may not contain EOF *) + +" May the Triforce \ + 0 \ + 0v0 \ + 0vvv0 \ + 0vvvvv0 \ + 0vvvvvvv0 \ + 0vvvvvvvvv0 \ + 0vvvvvvvvvvv0 \ + 000000000000000 \ + 0v0 0v0 \ + 0vvv0 0vvv0 \ + 0vvvvv0 0vvvvv0 \ + 0vvvvvvv0 0vvvvvvv0 \ + 0vvvvvvvvv0 0vvvvvvvvv0 \ + 0vvvvvvvvvvv0 0vvvvvvvvvvv0 \ + 00000000000000000000000000000 \ + be with you! \ No newline at end of file diff --git a/src/tests/lexer/string2_error.txt b/src/tests/lexer/string2_error.txt new file mode 100644 index 000000000..7fbbcb526 --- /dev/null +++ b/src/tests/lexer/string2_error.txt @@ -0,0 +1 @@ +(19, 29) - LexicographicError: EOF in string constant \ No newline at end of file diff --git a/src/tests/lexer/string3.cl b/src/tests/lexer/string3.cl new file mode 100644 index 0000000000000000000000000000000000000000..78abc4972e218bca373ba1750c99a3450cef4ea3 GIT binary patch literal 234 zcmX|4yAH!34D8HToS2dhRoZ?*=Jpd<90*B>0}_xSe_!a!lI8Q=*(aJadZZi|KVhQ- zK4j?NGc6u@9^rRpGmYcJ^ifl$K@ Mi{IIrdU_-I0>Lp*mH+?% literal 0 HcmV?d00001 diff --git a/src/tests/lexer/string3_error.txt b/src/tests/lexer/string3_error.txt new file mode 100644 index 000000000..35695d07e --- /dev/null +++ b/src/tests/lexer/string3_error.txt @@ -0,0 +1 @@ +(8, 4) - LexicographicError: String contains null character \ No newline at end of file diff --git a/src/tests/lexer/string4.cl b/src/tests/lexer/string4.cl new file mode 100644 index 000000000..f4d39c027 --- /dev/null +++ b/src/tests/lexer/string4.cl @@ -0,0 +1,38 @@ +class Main { + str <- "The big brown fox + jumped over the fence"; + main() : Object { + { + out_string("Yay! This is the newest shites ); + } + }; +}; + +(* +#1 CLASS +#1 TYPEID Main +#1 '{' +#2 OBJECTID str +#2 ASSIGN +#3 ERROR "Unterminated string constant" +#3 OBJECTID jumped +#3 OBJECTID over +#3 OBJECTID the +#3 OBJECTID fence +#4 ERROR "Unterminated string constant" +#4 OBJECTID main +#4 '(' +#4 ')' +#4 ':' +#4 TYPEID Object +#4 '{' +#5 '{' +#6 OBJECTID out_string +#6 '(' +#7 ERROR "Unterminated string constant" +#7 '}' +#8 '}' +#8 ';' +#9 '}' +#9 ';' +*) \ No newline at end of file diff --git a/src/tests/lexer/string4_error.txt b/src/tests/lexer/string4_error.txt new file mode 100644 index 000000000..5ab0ea847 --- /dev/null +++ b/src/tests/lexer/string4_error.txt @@ -0,0 +1,3 @@ +(2, 30) - LexicographicError: Unterminated string constant +(3, 36) - LexicographicError: Unterminated string constant +(6, 58) - LexicographicError: Unterminated string constant \ No newline at end of file diff --git a/src/tests/lexer_test.py b/src/tests/lexer_test.py new file mode 100644 index 000000000..2a27223d3 --- /dev/null +++ b/src/tests/lexer_test.py @@ -0,0 +1,13 @@ +import pytest +import os +from utils import compare_errors + +tests_dir = __file__.rpartition('/')[0] + '/lexer/' +tests = [(file) for file in os.listdir(tests_dir) if file.endswith('.cl')] + +@pytest.mark.lexer +@pytest.mark.error +@pytest.mark.run(order=1) +@pytest.mark.parametrize("cool_file", tests) +def test_lexer_errors(compiler_path, cool_file): + compare_errors(compiler_path, tests_dir + cool_file, tests_dir + cool_file[:-3] + '_error.txt') \ No newline at end of file diff --git a/src/tests/parser/assignment1.cl b/src/tests/parser/assignment1.cl new file mode 100644 index 000000000..75b4c5bbd --- /dev/null +++ b/src/tests/parser/assignment1.cl @@ -0,0 +1,37 @@ +(* An assignment has the form <- *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(): String { + Test1 <- "Hello World" -- Identifiers begin with a lower case letter + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/assignment1_error.txt b/src/tests/parser/assignment1_error.txt new file mode 100644 index 000000000..cef0d3946 --- /dev/null +++ b/src/tests/parser/assignment1_error.txt @@ -0,0 +1 @@ +(29, 9) - SyntacticError: ERROR at or near "Test1" \ No newline at end of file diff --git a/src/tests/parser/assignment2.cl b/src/tests/parser/assignment2.cl new file mode 100644 index 000000000..4efb96487 --- /dev/null +++ b/src/tests/parser/assignment2.cl @@ -0,0 +1,37 @@ +(* An assignment has the form <- *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 - 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(): Int { + test1 <-- ~(1 + 2 + 3 + 4 + 5) -- The left side must be an expression + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/assignment2_error.txt b/src/tests/parser/assignment2_error.txt new file mode 100644 index 000000000..dc611c159 --- /dev/null +++ b/src/tests/parser/assignment2_error.txt @@ -0,0 +1 @@ +(29, 17) - SyntacticError: ERROR at or near "-" \ No newline at end of file diff --git a/src/tests/parser/assignment3.cl b/src/tests/parser/assignment3.cl new file mode 100644 index 000000000..ff633f331 --- /dev/null +++ b/src/tests/parser/assignment3.cl @@ -0,0 +1,37 @@ +(* An assignment has the form <- *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(): Bool { + test1 <- true++ -- The left side must be an expression + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/assignment3_error.txt b/src/tests/parser/assignment3_error.txt new file mode 100644 index 000000000..a69ac3a81 --- /dev/null +++ b/src/tests/parser/assignment3_error.txt @@ -0,0 +1 @@ +(29, 23) - SyntacticError: ERROR at or near "+" \ No newline at end of file diff --git a/src/tests/parser/attribute1.cl b/src/tests/parser/attribute1.cl new file mode 100644 index 000000000..063a02c02 --- /dev/null +++ b/src/tests/parser/attribute1.cl @@ -0,0 +1,34 @@ +(* An attribute of class A specifies a variable that is part of the state of objects of class A *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + -- Attributes names must begin with lowercase letters + Test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/attribute1_error.txt b/src/tests/parser/attribute1_error.txt new file mode 100644 index 000000000..a4e9eb060 --- /dev/null +++ b/src/tests/parser/attribute1_error.txt @@ -0,0 +1 @@ +(17, 5) - SyntacticError: ERROR at or near "Test2" \ No newline at end of file diff --git a/src/tests/parser/attribute2.cl b/src/tests/parser/attribute2.cl new file mode 100644 index 000000000..c05211483 --- /dev/null +++ b/src/tests/parser/attribute2.cl @@ -0,0 +1,34 @@ +(* An attribute of class A specifies a variable that is part of the state of objects of class A *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + -- Type names must begin with uppercase letters + test3: string <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/attribute2_error.txt b/src/tests/parser/attribute2_error.txt new file mode 100644 index 000000000..b02a52ee1 --- /dev/null +++ b/src/tests/parser/attribute2_error.txt @@ -0,0 +1 @@ +(19, 12) - SyntacticError: ERROR at or near "string" \ No newline at end of file diff --git a/src/tests/parser/attribute3.cl b/src/tests/parser/attribute3.cl new file mode 100644 index 000000000..d858ae47c --- /dev/null +++ b/src/tests/parser/attribute3.cl @@ -0,0 +1,34 @@ +(* An attribute of class A specifies a variable that is part of the state of objects of class A *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + -- Expected '<-' not '<=' + test3: String <= "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/attribute3_error.txt b/src/tests/parser/attribute3_error.txt new file mode 100644 index 000000000..71f5bc0b7 --- /dev/null +++ b/src/tests/parser/attribute3_error.txt @@ -0,0 +1 @@ +(19, 19) - SyntacticError: ERROR at or near "<=" \ No newline at end of file diff --git a/src/tests/parser/block1.cl b/src/tests/parser/block1.cl new file mode 100644 index 000000000..3613d9268 --- /dev/null +++ b/src/tests/parser/block1.cl @@ -0,0 +1,87 @@ +(* A block has the form { ; ... ; } *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + pow: Int <- 1; + count: Int <- 0; + + testing6(a: Int): IO { + { + count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2 -- Missing ";" + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/block1_error.txt b/src/tests/parser/block1_error.txt new file mode 100644 index 000000000..c78fb0b96 --- /dev/null +++ b/src/tests/parser/block1_error.txt @@ -0,0 +1 @@ +(56, 17) - SyntacticError: ERROR at or near "}" \ No newline at end of file diff --git a/src/tests/parser/block2.cl b/src/tests/parser/block2.cl new file mode 100644 index 000000000..f485dd0b1 --- /dev/null +++ b/src/tests/parser/block2.cl @@ -0,0 +1,87 @@ +(* A block has the form { ; ... ; } *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + pow: Int <- 1; + count: Int <- 0; + + testing6(a: Int): IO { + -- Missing "{" + count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/block2_error.txt b/src/tests/parser/block2_error.txt new file mode 100644 index 000000000..f85f4303c --- /dev/null +++ b/src/tests/parser/block2_error.txt @@ -0,0 +1 @@ +(49, 23) - SyntacticError: ERROR at or near ";" \ No newline at end of file diff --git a/src/tests/parser/block3.cl b/src/tests/parser/block3.cl new file mode 100644 index 000000000..ae1598c3b --- /dev/null +++ b/src/tests/parser/block3.cl @@ -0,0 +1,87 @@ +(* A block has the form { ; ... ; } *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + pow: Int <- 1; + count: Int <- 0; + + testing6(a: Int): IO { + { + count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + -- Missing "}" + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/block3_error.txt b/src/tests/parser/block3_error.txt new file mode 100644 index 000000000..cda9949a2 --- /dev/null +++ b/src/tests/parser/block3_error.txt @@ -0,0 +1 @@ +(57, 13) - SyntacticError: ERROR at or near "pool" \ No newline at end of file diff --git a/src/tests/parser/block4.cl b/src/tests/parser/block4.cl new file mode 100644 index 000000000..8fd883d02 --- /dev/null +++ b/src/tests/parser/block4.cl @@ -0,0 +1,88 @@ +(* A block has the form { ; ... ; } *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + pow: Int <- 1; + count: Int <- 0; + + testing6(a: Int): IO { + { + count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + true++; -- Only expressions + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/block4_error.txt b/src/tests/parser/block4_error.txt new file mode 100644 index 000000000..ddbeb32ef --- /dev/null +++ b/src/tests/parser/block4_error.txt @@ -0,0 +1 @@ +(56, 26) - SyntacticError: ERROR at or near "+" \ No newline at end of file diff --git a/src/tests/parser/case1.cl b/src/tests/parser/case1.cl new file mode 100644 index 000000000..c2f508809 --- /dev/null +++ b/src/tests/parser/case1.cl @@ -0,0 +1,91 @@ +(* Case expressions provide runtime type tests on objects *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int <- 0, pow: Int + in { + -- count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; + + testing7(): Object { + case 2 + 2 of + -- Every case expression must have at least one branch + esac + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/case1_error.txt b/src/tests/parser/case1_error.txt new file mode 100644 index 000000000..61fca14f7 --- /dev/null +++ b/src/tests/parser/case1_error.txt @@ -0,0 +1 @@ +(63, 9) - SyntacticError: ERROR at or near ESAC \ No newline at end of file diff --git a/src/tests/parser/case2.cl b/src/tests/parser/case2.cl new file mode 100644 index 000000000..f9162e49f --- /dev/null +++ b/src/tests/parser/case2.cl @@ -0,0 +1,93 @@ +(* Case expressions provide runtime type tests on objects *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int <- 0, pow: Int + in { + -- count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; + + testing7(): Object { + case "2 + 2" of + x: Int => new IO.out_string("Es un entero!") -- Missing ";" + y: String => new IO.out_string("Es una cadena!"); + z: Bool => new IO.out_string("Es un booleano!"); + esac + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/case2_error.txt b/src/tests/parser/case2_error.txt new file mode 100644 index 000000000..40b030dd9 --- /dev/null +++ b/src/tests/parser/case2_error.txt @@ -0,0 +1 @@ +(63, 13) - SyntacticError: ERROR at or near "y" \ No newline at end of file diff --git a/src/tests/parser/case3.cl b/src/tests/parser/case3.cl new file mode 100644 index 000000000..a7eedc18b --- /dev/null +++ b/src/tests/parser/case3.cl @@ -0,0 +1,93 @@ +(* Case expressions provide runtime type tests on objects *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int <- 0, pow: Int + in { + -- count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; + + testing7(): Object { + case 2 + false of + x: Int => new IO.out_string("Es un entero!"); + y: string => new IO.out_string("Es una cadena!"); -- Type identifiers starts with a uppercase letter + z: Bool => new IO.out_string("Es un booleano!"); + esac + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/case3_error.txt b/src/tests/parser/case3_error.txt new file mode 100644 index 000000000..f25c5c563 --- /dev/null +++ b/src/tests/parser/case3_error.txt @@ -0,0 +1 @@ +(63, 16) - SyntacticError: ERROR at or near "string" \ No newline at end of file diff --git a/src/tests/parser/case4.cl b/src/tests/parser/case4.cl new file mode 100644 index 000000000..25ca3858f --- /dev/null +++ b/src/tests/parser/case4.cl @@ -0,0 +1,93 @@ +(* Case expressions provide runtime type tests on objects *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int <- 0, pow: Int + in { + -- count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; + + testing7(): Object { + case true of + x: Int => new IO.out_string("Es un entero!"); + y: String => new IO.out_string("Es una cadena!"); + Mazinger_Z: Bool => new IO.out_string("Es un booleano!"); -- Identifiers starts with a lowercase letter + esac + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/case4_error.txt b/src/tests/parser/case4_error.txt new file mode 100644 index 000000000..c5a16ddec --- /dev/null +++ b/src/tests/parser/case4_error.txt @@ -0,0 +1 @@ +(64, 13) - SyntacticError: ERROR at or near "Mazinger_Z" \ No newline at end of file diff --git a/src/tests/parser/case5.cl b/src/tests/parser/case5.cl new file mode 100644 index 000000000..b36c663e1 --- /dev/null +++ b/src/tests/parser/case5.cl @@ -0,0 +1,93 @@ +(* Case expressions provide runtime type tests on objects *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int <- 0, pow: Int + in { + -- count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; + + testing7(): Object { + case test2 of + x: Int <- new IO.out_string("Es un entero!"); -- Must be '=>' not '<-'; + y: String => new IO.out_string("Es una cadena!"); + z: Bool => new IO.out_string("Es un booleano!"); + esac + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/case5_error.txt b/src/tests/parser/case5_error.txt new file mode 100644 index 000000000..fc6ec0eda --- /dev/null +++ b/src/tests/parser/case5_error.txt @@ -0,0 +1 @@ +(62, 20) - SyntacticError: ERROR at or near ASSIGN \ No newline at end of file diff --git a/src/tests/parser/case6.cl b/src/tests/parser/case6.cl new file mode 100644 index 000000000..66e7df2ab --- /dev/null +++ b/src/tests/parser/case6.cl @@ -0,0 +1,93 @@ +(* Case expressions provide runtime type tests on objects *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int <- 0, pow: Int + in { + -- count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; + + testing7(): Object { + case 2 + 2 -- Missing "of" + x: Int => new IO.out_string("Es un entero!"); + y: String => new IO.out_string("Es una cadena!"); + z: Bool => new IO.out_string("Es un booleano!"); + esac + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/case6_error.txt b/src/tests/parser/case6_error.txt new file mode 100644 index 000000000..2ae2f723b --- /dev/null +++ b/src/tests/parser/case6_error.txt @@ -0,0 +1 @@ +(62, 13) - SyntacticError: ERROR at or near "x" \ No newline at end of file diff --git a/src/tests/parser/class1.cl b/src/tests/parser/class1.cl new file mode 100644 index 000000000..f4815e3f4 --- /dev/null +++ b/src/tests/parser/class1.cl @@ -0,0 +1,20 @@ +(* A class is a list of features *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + testing(): Int { + 2 + 2 + }; +}; + +-- Class names must begin with uppercase letters +class alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; diff --git a/src/tests/parser/class1_error.txt b/src/tests/parser/class1_error.txt new file mode 100644 index 000000000..acaa52a6e --- /dev/null +++ b/src/tests/parser/class1_error.txt @@ -0,0 +1 @@ +(16, 7) - SyntacticError: ERROR at or near "alpha" \ No newline at end of file diff --git a/src/tests/parser/class2.cl b/src/tests/parser/class2.cl new file mode 100644 index 000000000..f363b032a --- /dev/null +++ b/src/tests/parser/class2.cl @@ -0,0 +1,20 @@ +(* A class is a list of features *) + +CLaSS Main { + main(): Object { + (new Alpha).print() + }; +}; + +CLaSS Test { + testing(): Int { + 2 + 2 + }; +}; + +-- Type names must begin with uppercase letters +CLaSS Alpha iNHeRiTS iO { + print() : Object { + out_string("reached!!\n") + }; +}; diff --git a/src/tests/parser/class2_error.txt b/src/tests/parser/class2_error.txt new file mode 100644 index 000000000..59d065913 --- /dev/null +++ b/src/tests/parser/class2_error.txt @@ -0,0 +1 @@ +(16, 22) - SyntacticError: ERROR at or near "iO" \ No newline at end of file diff --git a/src/tests/parser/class3.cl b/src/tests/parser/class3.cl new file mode 100644 index 000000000..0c801372a --- /dev/null +++ b/src/tests/parser/class3.cl @@ -0,0 +1,34 @@ +(* A class is a list of features *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + -- Missing semicolon + testing2(a: Alpha, b: Int): Int { + 2 + 2 + } + + testing3(): String { + "2 + 2" + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; diff --git a/src/tests/parser/class3_error.txt b/src/tests/parser/class3_error.txt new file mode 100644 index 000000000..bc2f946b2 --- /dev/null +++ b/src/tests/parser/class3_error.txt @@ -0,0 +1 @@ +(25, 5) - SyntacticError: ERROR at or near "testing3" \ No newline at end of file diff --git a/src/tests/parser/class4.cl b/src/tests/parser/class4.cl new file mode 100644 index 000000000..5c286b5e6 --- /dev/null +++ b/src/tests/parser/class4.cl @@ -0,0 +1,36 @@ +(* A class is a list of features *) + +CLaSS Main { + main(): Object { + (new Alpha).print() + }; +}; + +CLaSS Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + -- Only features + 2 + 2; + + testing3(): String { + "2 + 2" + }; +}; + +CLaSS Alpha iNHeRiTS IO { + print() : Object { + out_string("reached!!\n") + }; +}; diff --git a/src/tests/parser/class4_error.txt b/src/tests/parser/class4_error.txt new file mode 100644 index 000000000..1007f033d --- /dev/null +++ b/src/tests/parser/class4_error.txt @@ -0,0 +1 @@ +(25, 5) - SyntacticError: ERROR at or near "2" \ No newline at end of file diff --git a/src/tests/parser/class5.cl b/src/tests/parser/class5.cl new file mode 100644 index 000000000..3f40c36eb --- /dev/null +++ b/src/tests/parser/class5.cl @@ -0,0 +1,34 @@ +(* A class is a list of features *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +-- Missing '{' +class Test + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; diff --git a/src/tests/parser/class5_error.txt b/src/tests/parser/class5_error.txt new file mode 100644 index 000000000..400e4d614 --- /dev/null +++ b/src/tests/parser/class5_error.txt @@ -0,0 +1 @@ +(11, 5) - SyntacticError: ERROR at or near "test1" \ No newline at end of file diff --git a/src/tests/parser/class6.cl b/src/tests/parser/class6.cl new file mode 100644 index 000000000..8501d2593 --- /dev/null +++ b/src/tests/parser/class6.cl @@ -0,0 +1,34 @@ +(* A class is a list of features *) + +CLaSS Main { + main(): Object { + (new Alpha).print() + }; +}; + +-- Missing '}' +CLaSS Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; +; + +CLaSS Alpha iNHeRiTS IO { + print() : Object { + out_string("reached!!\n") + }; +}; diff --git a/src/tests/parser/class6_error.txt b/src/tests/parser/class6_error.txt new file mode 100644 index 000000000..73574c94c --- /dev/null +++ b/src/tests/parser/class6_error.txt @@ -0,0 +1 @@ +(28, 1) - SyntacticError: ERROR at or near ";" \ No newline at end of file diff --git a/src/tests/parser/conditional1.cl b/src/tests/parser/conditional1.cl new file mode 100644 index 000000000..4d546fc44 --- /dev/null +++ b/src/tests/parser/conditional1.cl @@ -0,0 +1,69 @@ +(* A conditional has the form if then else fi *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + if a.length() < b.length() -- Mising "then" + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + else + if a.length() = b.length() then + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + else + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fi + fi + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/conditional1_error.txt b/src/tests/parser/conditional1_error.txt new file mode 100644 index 000000000..ee533fd84 --- /dev/null +++ b/src/tests/parser/conditional1_error.txt @@ -0,0 +1 @@ +(34, 13) - SyntacticError: ERROR at or near NEW \ No newline at end of file diff --git a/src/tests/parser/conditional2.cl b/src/tests/parser/conditional2.cl new file mode 100644 index 000000000..4f10c2957 --- /dev/null +++ b/src/tests/parser/conditional2.cl @@ -0,0 +1,69 @@ +(* A conditional has the form if then else fi *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + if a.length() < b.length() then + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + else + if a.length() = b.length() then + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + else + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + -- Missing "fi" + fi + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/conditional2_error.txt b/src/tests/parser/conditional2_error.txt new file mode 100644 index 000000000..c72f78d7e --- /dev/null +++ b/src/tests/parser/conditional2_error.txt @@ -0,0 +1 @@ +(42, 5) - SyntacticError: ERROR at or near "}" \ No newline at end of file diff --git a/src/tests/parser/conditional3.cl b/src/tests/parser/conditional3.cl new file mode 100644 index 000000000..67e991ade --- /dev/null +++ b/src/tests/parser/conditional3.cl @@ -0,0 +1,69 @@ +(* A conditional has the form if then else fi *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + iF a.length() < b.length() tHen + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + elsE + if a.length() = b.length() then + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + eLseif -- elseif isn't a keyword + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/conditional3_error.txt b/src/tests/parser/conditional3_error.txt new file mode 100644 index 000000000..ad95552b5 --- /dev/null +++ b/src/tests/parser/conditional3_error.txt @@ -0,0 +1 @@ +(38, 13) - SyntacticError: ERROR at or near "eLseif" \ No newline at end of file diff --git a/src/tests/parser/conditional4.cl b/src/tests/parser/conditional4.cl new file mode 100644 index 000000000..0792fdc85 --- /dev/null +++ b/src/tests/parser/conditional4.cl @@ -0,0 +1,73 @@ +(* A conditional has the form if then else fi *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(): Int { + if true++ then 1 else 0 -- Condition must be an expression + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/conditional4_error.txt b/src/tests/parser/conditional4_error.txt new file mode 100644 index 000000000..f5511445b --- /dev/null +++ b/src/tests/parser/conditional4_error.txt @@ -0,0 +1 @@ +(45, 17) - SyntacticError: ERROR at or near "+" \ No newline at end of file diff --git a/src/tests/parser/conditional5.cl b/src/tests/parser/conditional5.cl new file mode 100644 index 000000000..0c1e1aad0 --- /dev/null +++ b/src/tests/parser/conditional5.cl @@ -0,0 +1,73 @@ +(* A conditional has the form if then else fi *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(): Int { + if true then true++ else 0 -- If branch must be an expression + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/conditional5_error.txt b/src/tests/parser/conditional5_error.txt new file mode 100644 index 000000000..b3214010d --- /dev/null +++ b/src/tests/parser/conditional5_error.txt @@ -0,0 +1 @@ +(45, 27) - SyntacticError: ERROR at or near "+" \ No newline at end of file diff --git a/src/tests/parser/conditional6.cl b/src/tests/parser/conditional6.cl new file mode 100644 index 000000000..02310404a --- /dev/null +++ b/src/tests/parser/conditional6.cl @@ -0,0 +1,73 @@ +(* A conditional has the form if then else fi *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(): Int { + if true then 1 else false++ -- Else branch must be an expression + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/conditional6_error.txt b/src/tests/parser/conditional6_error.txt new file mode 100644 index 000000000..968b78ad9 --- /dev/null +++ b/src/tests/parser/conditional6_error.txt @@ -0,0 +1 @@ +(45, 35) - SyntacticError: ERROR at or near "+" \ No newline at end of file diff --git a/src/tests/parser/dispatch1.cl b/src/tests/parser/dispatch1.cl new file mode 100644 index 000000000..2ca394716 --- /dev/null +++ b/src/tests/parser/dispatch1.cl @@ -0,0 +1,45 @@ +(* There are three forms of dispatch (i.e. method call) in Cool. The three forms differ only in how the called method is selected *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + Test1.testing4(1, 2).testing4(3, 4).testing4(5, 6) -- Objet identifiers begin with a lower case letter + }; +} + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/dispatch1_error.txt b/src/tests/parser/dispatch1_error.txt new file mode 100644 index 000000000..ba8e9e84c --- /dev/null +++ b/src/tests/parser/dispatch1_error.txt @@ -0,0 +1 @@ +(37, 9) - SyntacticError: ERROR at or near "Test1" \ No newline at end of file diff --git a/src/tests/parser/dispatch2.cl b/src/tests/parser/dispatch2.cl new file mode 100644 index 000000000..0b57467a1 --- /dev/null +++ b/src/tests/parser/dispatch2.cl @@ -0,0 +1,45 @@ +(* There are three forms of dispatch (i.e. method call) in Cool. The three forms differ only in how the called method is selected *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13,) -- Extra comma + }; +} + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/dispatch2_error.txt b/src/tests/parser/dispatch2_error.txt new file mode 100644 index 000000000..134e266b2 --- /dev/null +++ b/src/tests/parser/dispatch2_error.txt @@ -0,0 +1 @@ +(37, 84) - SyntacticError: ERROR at or near ")" \ No newline at end of file diff --git a/src/tests/parser/dispatch3.cl b/src/tests/parser/dispatch3.cl new file mode 100644 index 000000000..9f1a5afff --- /dev/null +++ b/src/tests/parser/dispatch3.cl @@ -0,0 +1,45 @@ +(* There are three forms of dispatch (i.e. method call) in Cool. The three forms differ only in how the called method is selected *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).Testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) -- Identifiers begin with a lower case letter + }; +} + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/dispatch3_error.txt b/src/tests/parser/dispatch3_error.txt new file mode 100644 index 000000000..86d2d5142 --- /dev/null +++ b/src/tests/parser/dispatch3_error.txt @@ -0,0 +1 @@ +(37, 38) - SyntacticError: ERROR at or near "Testing4" \ No newline at end of file diff --git a/src/tests/parser/dispatch4.cl b/src/tests/parser/dispatch4.cl new file mode 100644 index 000000000..d1efc469d --- /dev/null +++ b/src/tests/parser/dispatch4.cl @@ -0,0 +1,53 @@ +(* There are three forms of dispatch (i.e. method call) in Cool. The three forms differ only in how the called method is selected *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + self.testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true++) -- Arguments must be expressions + }; +} + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/dispatch4_error.txt b/src/tests/parser/dispatch4_error.txt new file mode 100644 index 000000000..d03bb4c53 --- /dev/null +++ b/src/tests/parser/dispatch4_error.txt @@ -0,0 +1 @@ +(45, 81) - SyntacticError: ERROR at or near "+" \ No newline at end of file diff --git a/src/tests/parser/dispatch5.cl b/src/tests/parser/dispatch5.cl new file mode 100644 index 000000000..63a5afa79 --- /dev/null +++ b/src/tests/parser/dispatch5.cl @@ -0,0 +1,53 @@ +(* There are three forms of dispatch (i.e. method call) in Cool. The three forms differ only in how the called method is selected *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, ,true + fALSE) -- Extra comma + }; +} + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/dispatch5_error.txt b/src/tests/parser/dispatch5_error.txt new file mode 100644 index 000000000..3fc39c625 --- /dev/null +++ b/src/tests/parser/dispatch5_error.txt @@ -0,0 +1 @@ +(45, 71) - SyntacticError: ERROR at or near "," \ No newline at end of file diff --git a/src/tests/parser/dispatch6.cl b/src/tests/parser/dispatch6.cl new file mode 100644 index 000000000..0a953e2e6 --- /dev/null +++ b/src/tests/parser/dispatch6.cl @@ -0,0 +1,57 @@ +(* There are three forms of dispatch (i.e. method call) in Cool. The three forms differ only in how the called method is selected *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@object.copy() -- Type identifiers begin with a upper case letter + }; +} + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/dispatch6_error.txt b/src/tests/parser/dispatch6_error.txt new file mode 100644 index 000000000..543f3a38c --- /dev/null +++ b/src/tests/parser/dispatch6_error.txt @@ -0,0 +1 @@ +(49, 15) - SyntacticError: ERROR at or near "object" \ No newline at end of file diff --git a/src/tests/parser/dispatch7.cl b/src/tests/parser/dispatch7.cl new file mode 100644 index 000000000..3ecac4d0f --- /dev/null +++ b/src/tests/parser/dispatch7.cl @@ -0,0 +1,57 @@ +(* There are three forms of dispatch (i.e. method call) in Cool. The three forms differ only in how the called method is selected *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.Copy() -- Identifiers begin with a lower case letter + }; +} + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/dispatch7_error.txt b/src/tests/parser/dispatch7_error.txt new file mode 100644 index 000000000..27235d118 --- /dev/null +++ b/src/tests/parser/dispatch7_error.txt @@ -0,0 +1 @@ +(49, 22) - SyntacticError: ERROR at or near "Copy" \ No newline at end of file diff --git a/src/tests/parser/dispatch8.cl b/src/tests/parser/dispatch8.cl new file mode 100644 index 000000000..eef0455ef --- /dev/null +++ b/src/tests/parser/dispatch8.cl @@ -0,0 +1,57 @@ +(* There are three forms of dispatch (i.e. method call) in Cool. The three forms differ only in how the called method is selected *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy(,) -- Extra comma + }; +} + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/dispatch8_error.txt b/src/tests/parser/dispatch8_error.txt new file mode 100644 index 000000000..04704520a --- /dev/null +++ b/src/tests/parser/dispatch8_error.txt @@ -0,0 +1 @@ +(49, 27) - SyntacticError: ERROR at or near "," \ No newline at end of file diff --git a/src/tests/parser/dispatch9.cl b/src/tests/parser/dispatch9.cl new file mode 100644 index 000000000..5fdef22d6 --- /dev/null +++ b/src/tests/parser/dispatch9.cl @@ -0,0 +1,61 @@ +(* There are three forms of dispatch (i.e. method call) in Cool. The three forms differ only in how the called method is selected *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; + + testing5(): Object { + test1:Object.copy() -- Must be '@' not ':' + }; +} + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/dispatch9_error.txt b/src/tests/parser/dispatch9_error.txt new file mode 100644 index 000000000..eb0b3397d --- /dev/null +++ b/src/tests/parser/dispatch9_error.txt @@ -0,0 +1 @@ +(53, 14) - SyntacticError: ERROR at or near ":" \ No newline at end of file diff --git a/src/tests/parser/let1.cl b/src/tests/parser/let1.cl new file mode 100644 index 000000000..576ae383c --- /dev/null +++ b/src/tests/parser/let1.cl @@ -0,0 +1,85 @@ +(* A let expression has the form let : [ <- ], ..., : [ <- ] in *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let Count: Int <- 0, pow: Int <- 1 -- Object identifiers starts with a lowercase letter + in { + -- count <- 0; + -- pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/let1_error.txt b/src/tests/parser/let1_error.txt new file mode 100644 index 000000000..8b7fe63d1 --- /dev/null +++ b/src/tests/parser/let1_error.txt @@ -0,0 +1 @@ +(45, 13) - SyntacticError: ERROR at or near "Count" \ No newline at end of file diff --git a/src/tests/parser/let2.cl b/src/tests/parser/let2.cl new file mode 100644 index 000000000..4cfaef0f8 --- /dev/null +++ b/src/tests/parser/let2.cl @@ -0,0 +1,85 @@ +(* A let expression has the form let : [ <- ], ..., : [ <- ] in *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int, pow: int <- 1 -- Type identifiers starts with a uppercase letter + in { + count <- 0; + -- pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/let2_error.txt b/src/tests/parser/let2_error.txt new file mode 100644 index 000000000..6fb3f8e9c --- /dev/null +++ b/src/tests/parser/let2_error.txt @@ -0,0 +1 @@ +(45, 30) - SyntacticError: ERROR at or near "int" \ No newline at end of file diff --git a/src/tests/parser/let3.cl b/src/tests/parser/let3.cl new file mode 100644 index 000000000..91e567fd8 --- /dev/null +++ b/src/tests/parser/let3.cl @@ -0,0 +1,85 @@ +(* A let expression has the form let : [ <- ], ..., : [ <- ] in *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int, pow: Int, -- Extra comma + in { + count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/let3_error.txt b/src/tests/parser/let3_error.txt new file mode 100644 index 000000000..71fa08812 --- /dev/null +++ b/src/tests/parser/let3_error.txt @@ -0,0 +1 @@ +(46, 9) - SyntacticError: ERROR at or near IN \ No newline at end of file diff --git a/src/tests/parser/let4.cl b/src/tests/parser/let4.cl new file mode 100644 index 000000000..a716c332d --- /dev/null +++ b/src/tests/parser/let4.cl @@ -0,0 +1,85 @@ +(* A let expression has the form let : [ <- ], ..., : [ <- ] in *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int <- true++, pow: Int <- 1 -- Initialization must be an expression + in { + count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/let4_error.txt b/src/tests/parser/let4_error.txt new file mode 100644 index 000000000..e12c7478c --- /dev/null +++ b/src/tests/parser/let4_error.txt @@ -0,0 +1 @@ +(45, 32) - SyntacticError: ERROR at or near "+" \ No newline at end of file diff --git a/src/tests/parser/let5.cl b/src/tests/parser/let5.cl new file mode 100644 index 000000000..d974cc138 --- /dev/null +++ b/src/tests/parser/let5.cl @@ -0,0 +1,85 @@ +(* A let expression has the form let : [ <- ], ..., : [ <- ] in *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int = 0, pow: Int -- Must be '<-' not '=' + in { + -- count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/let5_error.txt b/src/tests/parser/let5_error.txt new file mode 100644 index 000000000..e561f846c --- /dev/null +++ b/src/tests/parser/let5_error.txt @@ -0,0 +1 @@ +(45, 24) - SyntacticError: ERROR at or near "=" \ No newline at end of file diff --git a/src/tests/parser/let6.cl b/src/tests/parser/let6.cl new file mode 100644 index 000000000..b6e51d7e1 --- /dev/null +++ b/src/tests/parser/let6.cl @@ -0,0 +1,74 @@ +(* A let expression has the form let : [ <- ], ..., : [ <- ] in *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int <- 0, pow: Int <- 1 + in false++ -- Let body must be an expression + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/let6_error.txt b/src/tests/parser/let6_error.txt new file mode 100644 index 000000000..7a77928b9 --- /dev/null +++ b/src/tests/parser/let6_error.txt @@ -0,0 +1 @@ +(46, 18) - SyntacticError: ERROR at or near "+" \ No newline at end of file diff --git a/src/tests/parser/let7.cl b/src/tests/parser/let7.cl new file mode 100644 index 000000000..6fd63e6a7 --- /dev/null +++ b/src/tests/parser/let7.cl @@ -0,0 +1,85 @@ +(* A let expression has the form let : [ <- ], ..., : [ <- ] in *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int <- 0, pow: Int + (* Missing "in" *) { + -- count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/let7_error.txt b/src/tests/parser/let7_error.txt new file mode 100644 index 000000000..654b1ce60 --- /dev/null +++ b/src/tests/parser/let7_error.txt @@ -0,0 +1 @@ +(46, 28) - SyntacticError: ERROR at or near "{" \ No newline at end of file diff --git a/src/tests/parser/loop1.cl b/src/tests/parser/loop1.cl new file mode 100644 index 000000000..7d0d7688f --- /dev/null +++ b/src/tests/parser/loop1.cl @@ -0,0 +1,78 @@ +(* A loop has the form while loop pool *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + count: Int <- 1; + + testing6(): Object { + while count < 1024*1024 + -- Missing "loop" + count <- count * 2 + pool + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/loop1_error.txt b/src/tests/parser/loop1_error.txt new file mode 100644 index 000000000..94248ff00 --- /dev/null +++ b/src/tests/parser/loop1_error.txt @@ -0,0 +1 @@ +(49, 13) - SyntacticError: ERROR at or near "count" \ No newline at end of file diff --git a/src/tests/parser/loop2.cl b/src/tests/parser/loop2.cl new file mode 100644 index 000000000..a9613c487 --- /dev/null +++ b/src/tests/parser/loop2.cl @@ -0,0 +1,78 @@ +(* A loop has the form while loop pool *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + count: Int <- 1; + + testing6(): Object { + while count < 1024*1024 + loop + count <- count * 2 + -- Missing "pool" + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/loop2_error.txt b/src/tests/parser/loop2_error.txt new file mode 100644 index 000000000..6447101f8 --- /dev/null +++ b/src/tests/parser/loop2_error.txt @@ -0,0 +1 @@ +(51, 5) - SyntacticError: ERROR at or near "}" \ No newline at end of file diff --git a/src/tests/parser/loop3.cl b/src/tests/parser/loop3.cl new file mode 100644 index 000000000..860adb4d1 --- /dev/null +++ b/src/tests/parser/loop3.cl @@ -0,0 +1,78 @@ +(* A loop has the form while loop pool *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + count: Int <- 1; + + testing6(): Object { + while count => 1024*1024 -- Condition must be an expression + loop + count <- count * 2 + pool + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/loop3_error.txt b/src/tests/parser/loop3_error.txt new file mode 100644 index 000000000..3da8bcde0 --- /dev/null +++ b/src/tests/parser/loop3_error.txt @@ -0,0 +1 @@ +(47, 21) - SyntacticError: ERROR at or near DARROW \ No newline at end of file diff --git a/src/tests/parser/loop4.cl b/src/tests/parser/loop4.cl new file mode 100644 index 000000000..0a1194e82 --- /dev/null +++ b/src/tests/parser/loop4.cl @@ -0,0 +1,78 @@ +(* A loop has the form while loop pool *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + count: Int <- 1; + + testing6(): Object { + while count < 1024*1024 + loop + count <- true++ -- While body must be an expression + pool + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/loop4_error.txt b/src/tests/parser/loop4_error.txt new file mode 100644 index 000000000..c39f35fe1 --- /dev/null +++ b/src/tests/parser/loop4_error.txt @@ -0,0 +1 @@ +(49, 27) - SyntacticError: ERROR at or near "+" \ No newline at end of file diff --git a/src/tests/parser/method1.cl b/src/tests/parser/method1.cl new file mode 100644 index 000000000..fcfbbcd30 --- /dev/null +++ b/src/tests/parser/method1.cl @@ -0,0 +1,34 @@ +(* A method of class A is a procedure that may manipulate the variables and objects of class A *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + -- Method names must begin with lowercase letters + Testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/method1_error.txt b/src/tests/parser/method1_error.txt new file mode 100644 index 000000000..0eff41999 --- /dev/null +++ b/src/tests/parser/method1_error.txt @@ -0,0 +1 @@ +(21, 5) - SyntacticError: ERROR at or near "Testing2" \ No newline at end of file diff --git a/src/tests/parser/method2.cl b/src/tests/parser/method2.cl new file mode 100644 index 000000000..d5bdfd85c --- /dev/null +++ b/src/tests/parser/method2.cl @@ -0,0 +1,34 @@ +(* A method of class A is a procedure that may manipulate the variables and objects of class A *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + -- Parameter names must begin with lowercase letters + testing2(a: Alpha, B: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/method2_error.txt b/src/tests/parser/method2_error.txt new file mode 100644 index 000000000..1843fb7b4 --- /dev/null +++ b/src/tests/parser/method2_error.txt @@ -0,0 +1 @@ +(21, 24) - SyntacticError: ERROR at or near "B" \ No newline at end of file diff --git a/src/tests/parser/method3.cl b/src/tests/parser/method3.cl new file mode 100644 index 000000000..1e5c9eb53 --- /dev/null +++ b/src/tests/parser/method3.cl @@ -0,0 +1,34 @@ +(* A method of class A is a procedure that may manipulate the variables and objects of class A *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + -- Type names must begin with uppercase letters + testing2(a: Alpha, b: int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/method3_error.txt b/src/tests/parser/method3_error.txt new file mode 100644 index 000000000..dbecf552e --- /dev/null +++ b/src/tests/parser/method3_error.txt @@ -0,0 +1 @@ +(21, 27) - SyntacticError: ERROR at or near "int" \ No newline at end of file diff --git a/src/tests/parser/method4.cl b/src/tests/parser/method4.cl new file mode 100644 index 000000000..019ada276 --- /dev/null +++ b/src/tests/parser/method4.cl @@ -0,0 +1,34 @@ +(* A method of class A is a procedure that may manipulate the variables and objects of class A *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + -- Missing paremeter + testing3(x: Int,): String { + "2 + 2" + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/method4_error.txt b/src/tests/parser/method4_error.txt new file mode 100644 index 000000000..6421cee2b --- /dev/null +++ b/src/tests/parser/method4_error.txt @@ -0,0 +1 @@ +(25, 21) - SyntacticError: ERROR at or near ")" \ No newline at end of file diff --git a/src/tests/parser/method5.cl b/src/tests/parser/method5.cl new file mode 100644 index 000000000..13127f664 --- /dev/null +++ b/src/tests/parser/method5.cl @@ -0,0 +1,34 @@ +(* A method of class A is a procedure that may manipulate the variables and objects of class A *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + -- Type names must begin with uppercase letters + testing3(): string { + "2 + 2" + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/method5_error.txt b/src/tests/parser/method5_error.txt new file mode 100644 index 000000000..9bda07041 --- /dev/null +++ b/src/tests/parser/method5_error.txt @@ -0,0 +1 @@ +(25, 17) - SyntacticError: ERROR at or near "string" \ No newline at end of file diff --git a/src/tests/parser/method6.cl b/src/tests/parser/method6.cl new file mode 100644 index 000000000..d48cd1293 --- /dev/null +++ b/src/tests/parser/method6.cl @@ -0,0 +1,33 @@ +(* A method of class A is a procedure that may manipulate the variables and objects of class A *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + -- Body can't be empty + testing2(a: Alpha, b: Int): Int { + }; + + testing3(): String { + "2 + 2" + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/method6_error.txt b/src/tests/parser/method6_error.txt new file mode 100644 index 000000000..e7d5de400 --- /dev/null +++ b/src/tests/parser/method6_error.txt @@ -0,0 +1 @@ +(22, 5) - SyntacticError: ERROR at or near "}" \ No newline at end of file diff --git a/src/tests/parser/mixed1.cl b/src/tests/parser/mixed1.cl new file mode 100644 index 000000000..a27879513 --- /dev/null +++ b/src/tests/parser/mixed1.cl @@ -0,0 +1,100 @@ +(* Cool has four binary arithmetic operations: +, -, *, /. *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int <- 0, pow: Int + in { + -- count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; + + testing7(): Object { + case 2 + 2 of + x: Int => new IO.out_string("Es un entero!"); + y: String => new IO.out_string("Es una cadena!"); + z: Bool => new IO.out_string("Es un booleano!"); + esac + }; + + a: Int <- 1; + + testing8(x: Int, y: Int): Bool { + let z: Int <- 3, w: Int <- 4 + in isvoid (3 + a * (x / w + new Int) - y - (((if tRue = not faLSe then ~z else 3 <= 4 + "hey".length() fi + a))/(0)*(((4 * 4))))) + }; +}-- Mising ";" + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/mixed1_error.txt b/src/tests/parser/mixed1_error.txt new file mode 100644 index 000000000..d5b0ff8bb --- /dev/null +++ b/src/tests/parser/mixed1_error.txt @@ -0,0 +1 @@ +(76, 1) - SyntacticError: ERROR at or near CLASS \ No newline at end of file diff --git a/src/tests/parser/mixed2.cl b/src/tests/parser/mixed2.cl new file mode 100644 index 000000000..f5477e0bb --- /dev/null +++ b/src/tests/parser/mixed2.cl @@ -0,0 +1,14 @@ +class Main { + main(): Object { + (new Alpha).print() + }; + +}; + +(* Class names must begin with uppercase letters *) +class alpha inherits IO { + print() : Object { + out_string("reached!!\n"); + }; +}; + diff --git a/src/tests/parser/mixed2_error.txt b/src/tests/parser/mixed2_error.txt new file mode 100644 index 000000000..b5613c52a --- /dev/null +++ b/src/tests/parser/mixed2_error.txt @@ -0,0 +1 @@ +(9, 7) - SyntacticError: ERROR at or near "alpha" \ No newline at end of file diff --git a/src/tests/parser/mixed3.cl b/src/tests/parser/mixed3.cl new file mode 100644 index 000000000..1bdcad743 --- /dev/null +++ b/src/tests/parser/mixed3.cl @@ -0,0 +1,40 @@ +class Main inherits IO { + main() : Object { + { + out_string("Enter a number to check if number is prime\n"); + let i : Int <- in_int() in { + if(i <= 1) then { + out_string("Invalid Input\n"); + abort(); + } else { + if (isPrime(i) = 1) then + out_string("Number is prime\n") + else + out_string("Number is composite\n") + fi; + } + fi; + }; + } + }; + + mod(i : Int, ) : Int { -- Formal list must be comma separated. A comma does not terminate a list of formals. + i - (i/k)*k + }; + + isPrime(i : Int) : Int { + { + let x : Int <- 2, + c : Int <- 1 in + { + while (not (x = i)) loop + if (mod(i, x) = 0) then { + c <- 0; + x <- i; + } else x <- x + 1 fi + pool; + c; + }; + } + }; +}; diff --git a/src/tests/parser/mixed3_error.txt b/src/tests/parser/mixed3_error.txt new file mode 100644 index 000000000..159bdca63 --- /dev/null +++ b/src/tests/parser/mixed3_error.txt @@ -0,0 +1 @@ +(21, 18) - SyntacticError: ERROR at or near ")" \ No newline at end of file diff --git a/src/tests/parser/mixed4.cl b/src/tests/parser/mixed4.cl new file mode 100644 index 000000000..e752253be --- /dev/null +++ b/src/tests/parser/mixed4.cl @@ -0,0 +1,21 @@ +class Main inherits IO { + main() : Object { + { + out_string("Enter number of numbers to multiply\n"); + out_int(prod(in_int())); + out_string("\n"); + } + }; + + prod(i : Int) : Int { + let y : Int <- 1 in { + while (not (i = 0) ) loop { + out_string("Enter Number: "); + y <- y * in_int(Main : Int); -- the parser correctly catches the error here + i <- i - 1; + } + pool; + y; + } + }; +}; diff --git a/src/tests/parser/mixed4_error.txt b/src/tests/parser/mixed4_error.txt new file mode 100644 index 000000000..2349f28a5 --- /dev/null +++ b/src/tests/parser/mixed4_error.txt @@ -0,0 +1 @@ +(14, 41) - SyntacticError: ERROR at or near "Main" \ No newline at end of file diff --git a/src/tests/parser/mixed5.cl b/src/tests/parser/mixed5.cl new file mode 100644 index 000000000..c9176a890 --- /dev/null +++ b/src/tests/parser/mixed5.cl @@ -0,0 +1,20 @@ +class Main inherits IO { + str <- "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; + main() : Object { + { + out_string("Enter number of numbers to multiply\n"); + out_int(prod(in_int())); + out_string("\n"); + } + }; + prod(i : Int) : Int { + let y : Int <- 1 in { + while (not (i = 0) ) loop { + out_string("Enter Number: "); + y <- y * in_int(); + i <- i - 1; + } + y; + } + }; +} diff --git a/src/tests/parser/mixed5_error.txt b/src/tests/parser/mixed5_error.txt new file mode 100644 index 000000000..443037eca --- /dev/null +++ b/src/tests/parser/mixed5_error.txt @@ -0,0 +1 @@ +(2, 9) - SyntacticError: ERROR at or near ASSIGN \ No newline at end of file diff --git a/src/tests/parser/mixed6.cl b/src/tests/parser/mixed6.cl new file mode 100644 index 000000000..5da80da31 --- /dev/null +++ b/src/tests/parser/mixed6.cl @@ -0,0 +1,5 @@ +classs Doom { + i : Int <- 0; + main() : Object { + if i = 0 then out_string("This is da real *h*t") + diff --git a/src/tests/parser/mixed6_error.txt b/src/tests/parser/mixed6_error.txt new file mode 100644 index 000000000..af75ca925 --- /dev/null +++ b/src/tests/parser/mixed6_error.txt @@ -0,0 +1 @@ +(1, 1) - SyntacticError: ERROR at or near "classs" \ No newline at end of file diff --git a/src/tests/parser/operation1.cl b/src/tests/parser/operation1.cl new file mode 100644 index 000000000..d38eb72d0 --- /dev/null +++ b/src/tests/parser/operation1.cl @@ -0,0 +1,101 @@ +(* Cool has four binary arithmetic operations: +, -, *, /. *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int <- 0, pow: Int + in { + -- count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; + + testing7(): Object { + case 2 + 2 of + x: Int => new IO.out_string("Es un entero!"); + y: String => new IO.out_string("Es una cadena!"); + z: Bool => new IO.out_string("Es un booleano!"); + esac + }; + + a: Int <- 1; + + testing8(x: Int, y: Int): Bool { + let z: Int <- 3, w: Int <- 4 + -- Missing ')' + in isvoid (3 + a * (x / w + new Int) - y - (((if tRue = not faLSe then ~z else 3 <= 4 + "hey".length() fi + a)/(0)*(((4 * 4))))) + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/operation1_error.txt b/src/tests/parser/operation1_error.txt new file mode 100644 index 000000000..b30202399 --- /dev/null +++ b/src/tests/parser/operation1_error.txt @@ -0,0 +1 @@ +(74, 5) - SyntacticError: ERROR at or near "}" \ No newline at end of file diff --git a/src/tests/parser/operation2.cl b/src/tests/parser/operation2.cl new file mode 100644 index 000000000..2dc628359 --- /dev/null +++ b/src/tests/parser/operation2.cl @@ -0,0 +1,101 @@ +(* Cool has four binary arithmetic operations: +, -, *, /. *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int <- 0, pow: Int + in { + -- count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; + + testing7(): Object { + case 2 + 2 of + x: Int => new IO.out_string("Es un entero!"); + y: String => new IO.out_string("Es una cadena!"); + z: Bool => new IO.out_string("Es un booleano!"); + esac + }; + + a: Int <- 1; + + testing8(x: Int, y: Int): Bool { + let z: Int <- 3, w: Int <- 4 + -- Type identifiers starts with a uppercase letter + in isvoid (3 + a * (x / w + new int) - y - (((if tRue = not faLSe then ~z else 3 <= 4 + "hey".length() fi + a))/(0)*(((4 * 4))))) + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/operation2_error.txt b/src/tests/parser/operation2_error.txt new file mode 100644 index 000000000..37b458f3a --- /dev/null +++ b/src/tests/parser/operation2_error.txt @@ -0,0 +1 @@ +(73, 41) - SyntacticError: ERROR at or near "int" \ No newline at end of file diff --git a/src/tests/parser/operation3.cl b/src/tests/parser/operation3.cl new file mode 100644 index 000000000..61d6cbfa8 --- /dev/null +++ b/src/tests/parser/operation3.cl @@ -0,0 +1,101 @@ +(* Cool has four binary arithmetic operations: +, -, *, /. *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int <- 0, pow: Int + in { + -- count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; + + testing7(): Object { + case 2 + 2 of + x: Int => new IO.out_string("Es un entero!"); + y: String => new IO.out_string("Es una cadena!"); + z: Bool => new IO.out_string("Es un booleano!"); + esac + }; + + a: Int <- 1; + + testing8(x: Int, y: Int): Bool { + let z: Int <- 3, w: Int <- 4 + -- Object identifiers starts with a lowercase letter + in isvoid (3 + a * (x / w + new Int) - y - (((if tRue = not faLSe then ~Mazinger_Z else 3 <= 4 + "hey".length() fi + a))/(0)*(((4 * 4))))) + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/operation3_error.txt b/src/tests/parser/operation3_error.txt new file mode 100644 index 000000000..6b266f3f3 --- /dev/null +++ b/src/tests/parser/operation3_error.txt @@ -0,0 +1 @@ +(73, 81) - SyntacticError: ERROR at or near "Mazinger_Z" \ No newline at end of file diff --git a/src/tests/parser/operation4.cl b/src/tests/parser/operation4.cl new file mode 100644 index 000000000..bae7de5b5 --- /dev/null +++ b/src/tests/parser/operation4.cl @@ -0,0 +1,101 @@ +(* Cool has four binary arithmetic operations: +, -, *, /. *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + test1: Object; + + testing1(): Int { + 2 + 2 + }; + + test2: Int <- 1; + + test3: String <- "1"; + + testing2(a: Alpha, b: Int): Int { + 2 + 2 + }; + + testing3(): String { + "2 + 2" + }; + + testing4(x: Int, y: Int): Test { + self + }; + + testing5(a: String, b: String): IO { + If a.length() < b.length() THeN + new IO.out_string("La cadena \"".concat(b).concat("\" es mas larga que la cadena \"").concat(a).concat("\".")) + eLSe + if a.length() = b.length() THeN + new IO.out_string("La cadena \"".concat(a).concat("\" mide igual que la cadena \"").concat(b).concat("\".")) + ElsE + new IO.out_string("La cadena \"".concat(a).concat("\" es mas larga que la cadena \"").concat(b).concat("\".")) + fI + Fi + }; + + testing6(a: Int): IO { + let count: Int <- 0, pow: Int + in { + -- count <- 0; + pow <- 1; + while pow < a + loop + { + count <- count + 1; + pow <- pow * 2; + } + pool; + new IO.out_string("El logaritmo en base 2 de ").out_int(a).out_string(" es ").out_int(count); + } + }; + + testing7(): Object { + case 2 + 2 of + x: Int => new IO.out_string("Es un entero!"); + y: String => new IO.out_string("Es una cadena!"); + z: Bool => new IO.out_string("Es un booleano!"); + esac + }; + + a: Int <- 1; + + testing8(x: Int, y: Int): Bool { + let z: Int <- 3, w: Int <- 4 + -- Double "+" + in isvoid (3 + a * (x / w++ new Int) - y - (((if tRue = not faLSe then ~z else 3 <= 4 + "hey".length() fi + a))/(0)*(((4 * 4))))) + }; +}; + +class Test2 { + test1: Test <- new Test; + + testing1(): Test { + test1.testing4(1 + 1, 1 + 2).testing4(2 + 3, 3 + 5).testing4(5 + 8, 8 + 13) + }; + + testing2(x: Int, y: Int): Test2 { + self + }; + + testing3(): Test2 { + testing2(1 + 1, 1 + 2).testing2(2 + 3, 3 + 5).testing2(5 + 8, true + fALSE) + }; + + testing4(): Object { + test1@Object.copy() + }; +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; \ No newline at end of file diff --git a/src/tests/parser/operation4_error.txt b/src/tests/parser/operation4_error.txt new file mode 100644 index 000000000..e0ebb0985 --- /dev/null +++ b/src/tests/parser/operation4_error.txt @@ -0,0 +1 @@ +(73, 35) - SyntacticError: ERROR at or near "+" \ No newline at end of file diff --git a/src/tests/parser/program1.cl b/src/tests/parser/program1.cl new file mode 100644 index 000000000..8e5cf617f --- /dev/null +++ b/src/tests/parser/program1.cl @@ -0,0 +1 @@ +(* A Cool program can't be empty *) \ No newline at end of file diff --git a/src/tests/parser/program1_error.txt b/src/tests/parser/program1_error.txt new file mode 100644 index 000000000..de00ac46b --- /dev/null +++ b/src/tests/parser/program1_error.txt @@ -0,0 +1 @@ +(0, 0) - SyntacticError: ERROR at or near EOF \ No newline at end of file diff --git a/src/tests/parser/program2.cl b/src/tests/parser/program2.cl new file mode 100644 index 000000000..f8b16779c --- /dev/null +++ b/src/tests/parser/program2.cl @@ -0,0 +1,20 @@ +(* Cool programs are sets of classes *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +-- Missing semicolon +class Test { + testing(): Int { + 2 + 2 + }; +} + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; diff --git a/src/tests/parser/program2_error.txt b/src/tests/parser/program2_error.txt new file mode 100644 index 000000000..94ba8df65 --- /dev/null +++ b/src/tests/parser/program2_error.txt @@ -0,0 +1 @@ +(16, 1) - SyntacticError: ERROR at or near CLASS \ No newline at end of file diff --git a/src/tests/parser/program3.cl b/src/tests/parser/program3.cl new file mode 100644 index 000000000..e27889c57 --- /dev/null +++ b/src/tests/parser/program3.cl @@ -0,0 +1,24 @@ +(* Cool programs are sets of classes *) + +class Main { + main(): Object { + (new Alpha).print() + }; +}; + +class Test { + testing(): Int { + 2 + 2 + }; +}; + +-- Only classes +suma(a: Int, b: Int) int { + a + b +}; + +class Alpha inherits IO { + print() : Object { + out_string("reached!!\n") + }; +}; diff --git a/src/tests/parser/program3_error.txt b/src/tests/parser/program3_error.txt new file mode 100644 index 000000000..dd3b3947a --- /dev/null +++ b/src/tests/parser/program3_error.txt @@ -0,0 +1 @@ +(16, 1) - SyntacticError: ERROR at or near "suma" \ No newline at end of file diff --git a/src/tests/parser_test.py b/src/tests/parser_test.py new file mode 100644 index 000000000..129c0f20a --- /dev/null +++ b/src/tests/parser_test.py @@ -0,0 +1,13 @@ +import pytest +import os +from utils import compare_errors + +tests_dir = __file__.rpartition('/')[0] + '/parser/' +tests = [(file) for file in os.listdir(tests_dir) if file.endswith('.cl')] + +@pytest.mark.parser +@pytest.mark.error +@pytest.mark.run(order=2) +@pytest.mark.parametrize("cool_file", tests) +def test_parser_errors(compiler_path, cool_file): + compare_errors(compiler_path, tests_dir + cool_file, tests_dir + cool_file[:-3] + '_error.txt') \ No newline at end of file diff --git a/src/tests/semantic/arithmetic1.cl b/src/tests/semantic/arithmetic1.cl new file mode 100644 index 000000000..bf94eb194 --- /dev/null +++ b/src/tests/semantic/arithmetic1.cl @@ -0,0 +1,11 @@ +--The static types of the two sub-expressions must be Int. + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Int <- let x: Int <- 1 * 2 / 3 - 4 + new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in x <- x + new A.type_name().concat(new B.type_name().concat(new C.type_name())); +}; \ No newline at end of file diff --git a/src/tests/semantic/arithmetic10.cl b/src/tests/semantic/arithmetic10.cl new file mode 100644 index 000000000..bbfe6cdb3 --- /dev/null +++ b/src/tests/semantic/arithmetic10.cl @@ -0,0 +1,15 @@ +(* +The expression ~ is the integer +complement of . The expression must have static type Int and the entire expression +has static type Int. +*) + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Bool <- let x: Bool <- 1 / 2 - 3 + 4 < new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in ~new A.type_name().concat(new B.type_name().concat(new C.type_name())).length(); +}; \ No newline at end of file diff --git a/src/tests/semantic/arithmetic10_error.txt b/src/tests/semantic/arithmetic10_error.txt new file mode 100644 index 000000000..b2be0476f --- /dev/null +++ b/src/tests/semantic/arithmetic10_error.txt @@ -0,0 +1 @@ +(13, 19) - TypeError: Inferred type Int of initialization of attribute test does not conform to declared type Bool. \ No newline at end of file diff --git a/src/tests/semantic/arithmetic11.cl b/src/tests/semantic/arithmetic11.cl new file mode 100644 index 000000000..fc067dc1a --- /dev/null +++ b/src/tests/semantic/arithmetic11.cl @@ -0,0 +1,14 @@ +(* +The expression not is the boolean complement of . The expression + must have static type Bool and the entire expression has static type Bool. +*) + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Bool <- let x: Bool <- 1 / 2 - 3 + 4 < new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in not 1 + new A.type_name().concat(new B.type_name().concat(new C.type_name())).length(); +}; \ No newline at end of file diff --git a/src/tests/semantic/arithmetic11_error.txt b/src/tests/semantic/arithmetic11_error.txt new file mode 100644 index 000000000..bb4b8e1ca --- /dev/null +++ b/src/tests/semantic/arithmetic11_error.txt @@ -0,0 +1 @@ +(13, 24) - TypeError: Argument of 'not' has type Int instead of Bool. \ No newline at end of file diff --git a/src/tests/semantic/arithmetic12.cl b/src/tests/semantic/arithmetic12.cl new file mode 100644 index 000000000..2e012fc41 --- /dev/null +++ b/src/tests/semantic/arithmetic12.cl @@ -0,0 +1,14 @@ +(* +The expression not is the boolean complement of . The expression + must have static type Bool and the entire expression has static type Bool. +*) + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Int <- let x: Bool <- 1 / 2 - 3 + 4 < new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in not 1 < new A.type_name().concat(new B.type_name().concat(new C.type_name())).length(); +}; \ No newline at end of file diff --git a/src/tests/semantic/arithmetic12_error.txt b/src/tests/semantic/arithmetic12_error.txt new file mode 100644 index 000000000..d25eab65e --- /dev/null +++ b/src/tests/semantic/arithmetic12_error.txt @@ -0,0 +1 @@ +(12, 18) - TypeError: Inferred type Bool of initialization of attribute test does not conform to declared type Int. \ No newline at end of file diff --git a/src/tests/semantic/arithmetic1_error.txt b/src/tests/semantic/arithmetic1_error.txt new file mode 100644 index 000000000..a74ebf3da --- /dev/null +++ b/src/tests/semantic/arithmetic1_error.txt @@ -0,0 +1 @@ +(10, 27) - TypeError: non-Int arguments: Int + String diff --git a/src/tests/semantic/arithmetic2.cl b/src/tests/semantic/arithmetic2.cl new file mode 100644 index 000000000..59532573d --- /dev/null +++ b/src/tests/semantic/arithmetic2.cl @@ -0,0 +1,11 @@ +--The static types of the two sub-expressions must be Int. + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Int <- let x: Int <- 1 + 2 * 3 / 4 - new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in x <- x - new A.type_name().concat(new B.type_name().concat(new C.type_name())); +}; \ No newline at end of file diff --git a/src/tests/semantic/arithmetic2_error.txt b/src/tests/semantic/arithmetic2_error.txt new file mode 100644 index 000000000..2c7952af8 --- /dev/null +++ b/src/tests/semantic/arithmetic2_error.txt @@ -0,0 +1 @@ +(10, 27) - TypeError: non-Int arguments: Int - String diff --git a/src/tests/semantic/arithmetic3.cl b/src/tests/semantic/arithmetic3.cl new file mode 100644 index 000000000..b208957f5 --- /dev/null +++ b/src/tests/semantic/arithmetic3.cl @@ -0,0 +1,11 @@ +--The static types of the two sub-expressions must be Int. + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Int <- let x: Int <- 1 - 2 + 3 * 4 / new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in x <- x / new A.type_name().concat(new B.type_name().concat(new C.type_name())); +}; \ No newline at end of file diff --git a/src/tests/semantic/arithmetic3_error.txt b/src/tests/semantic/arithmetic3_error.txt new file mode 100644 index 000000000..81d88331a --- /dev/null +++ b/src/tests/semantic/arithmetic3_error.txt @@ -0,0 +1 @@ +(10, 27) - TypeError: non-Int arguments: Int / String diff --git a/src/tests/semantic/arithmetic4.cl b/src/tests/semantic/arithmetic4.cl new file mode 100644 index 000000000..2c7dd4fc9 --- /dev/null +++ b/src/tests/semantic/arithmetic4.cl @@ -0,0 +1,11 @@ +--The static types of the two sub-expressions must be Int. + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Int <- let x: Int <- 1 / 2 - 3 + 4 * new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in x <- x * new A.type_name().concat(new B.type_name().concat(new C.type_name())); +}; \ No newline at end of file diff --git a/src/tests/semantic/arithmetic4_error.txt b/src/tests/semantic/arithmetic4_error.txt new file mode 100644 index 000000000..1ca6df022 --- /dev/null +++ b/src/tests/semantic/arithmetic4_error.txt @@ -0,0 +1 @@ +(10, 27) - TypeError: non-Int arguments: Int * String \ No newline at end of file diff --git a/src/tests/semantic/arithmetic5.cl b/src/tests/semantic/arithmetic5.cl new file mode 100644 index 000000000..bc08c6e82 --- /dev/null +++ b/src/tests/semantic/arithmetic5.cl @@ -0,0 +1,11 @@ +--The static type of the expression is Int. + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Bool <- let x: Int <- 1 / 2 - 3 + 4 * new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in x <- x * new A.type_name().concat(new B.type_name().concat(new C.type_name())).length(); +}; \ No newline at end of file diff --git a/src/tests/semantic/arithmetic5_error.txt b/src/tests/semantic/arithmetic5_error.txt new file mode 100644 index 000000000..dd5346844 --- /dev/null +++ b/src/tests/semantic/arithmetic5_error.txt @@ -0,0 +1 @@ +(9, 19) - TypeError: Inferred type Int of initialization of attribute test does not conform to declared type Bool. diff --git a/src/tests/semantic/arithmetic6.cl b/src/tests/semantic/arithmetic6.cl new file mode 100644 index 000000000..a0c3d03ff --- /dev/null +++ b/src/tests/semantic/arithmetic6.cl @@ -0,0 +1,11 @@ + --The static types of the two sub-expressions must be Int. + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Bool <- let x: Bool <- 1 / 2 - 3 + 4 <= new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in 1 <= new A.type_name().concat(new B.type_name().concat(new C.type_name())); +}; diff --git a/src/tests/semantic/arithmetic6_error.txt b/src/tests/semantic/arithmetic6_error.txt new file mode 100644 index 000000000..2e43dfc17 --- /dev/null +++ b/src/tests/semantic/arithmetic6_error.txt @@ -0,0 +1 @@ +(10, 22) - TypeError: non-Int arguments: Int <= String diff --git a/src/tests/semantic/arithmetic7.cl b/src/tests/semantic/arithmetic7.cl new file mode 100644 index 000000000..c00c75cde --- /dev/null +++ b/src/tests/semantic/arithmetic7.cl @@ -0,0 +1,12 @@ + --The static types of the two sub-expressions must be Int. + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Bool <- let x: Bool <- 1 / 2 - 3 + 4 < new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in 1 < new A.type_name().concat(new B.type_name().concat(new C.type_name())); +}; + diff --git a/src/tests/semantic/arithmetic7_error.txt b/src/tests/semantic/arithmetic7_error.txt new file mode 100644 index 000000000..6f3537117 --- /dev/null +++ b/src/tests/semantic/arithmetic7_error.txt @@ -0,0 +1 @@ +(10, 22) - TypeError: non-Int arguments: Int < String diff --git a/src/tests/semantic/arithmetic8.cl b/src/tests/semantic/arithmetic8.cl new file mode 100644 index 000000000..3210bdb8a --- /dev/null +++ b/src/tests/semantic/arithmetic8.cl @@ -0,0 +1,13 @@ + --The rules are exactly the same as for the binary arithmetic operations, except that the result is a Bool. + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Int <- let x: Bool <- 1 / 2 - 3 + 4 < new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in 1 < new A.type_name().concat(new B.type_name().concat(new C.type_name())).length(); +}; + + diff --git a/src/tests/semantic/arithmetic8_error.txt b/src/tests/semantic/arithmetic8_error.txt new file mode 100644 index 000000000..ebcaa3797 --- /dev/null +++ b/src/tests/semantic/arithmetic8_error.txt @@ -0,0 +1 @@ +(9, 18) - TypeError: Inferred type Bool of initialization of attribute test does not conform to declared type Int. diff --git a/src/tests/semantic/arithmetic9.cl b/src/tests/semantic/arithmetic9.cl new file mode 100644 index 000000000..95579e134 --- /dev/null +++ b/src/tests/semantic/arithmetic9.cl @@ -0,0 +1,15 @@ +(* +The expression ~ is the integer +complement of . The expression must have static type Int and the entire expression +has static type Int. +*) + +class A { }; +class B inherits A { }; +class C inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + test: Int <- let x: Bool <- 1 / 2 - 3 + 4 < new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + in 1 + ~new A.type_name().concat(new B.type_name().concat(new C.type_name())); +}; \ No newline at end of file diff --git a/src/tests/semantic/arithmetic9_error.txt b/src/tests/semantic/arithmetic9_error.txt new file mode 100644 index 000000000..99fafbbfc --- /dev/null +++ b/src/tests/semantic/arithmetic9_error.txt @@ -0,0 +1 @@ +(14, 25) - TypeError: Argument of '~' has type String instead of Int. \ No newline at end of file diff --git a/src/tests/semantic/assignment1.cl b/src/tests/semantic/assignment1.cl new file mode 100644 index 000000000..19ab70219 --- /dev/null +++ b/src/tests/semantic/assignment1.cl @@ -0,0 +1,7 @@ +--The static type of the expression must conform to the declared type of the identifier + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test: Int <- "String"; +}; diff --git a/src/tests/semantic/assignment1_error.txt b/src/tests/semantic/assignment1_error.txt new file mode 100644 index 000000000..6eb883012 --- /dev/null +++ b/src/tests/semantic/assignment1_error.txt @@ -0,0 +1 @@ +(6, 18) - TypeError: Inferred type String of initialization of attribute test does not conform to declared type Int. diff --git a/src/tests/semantic/assignment2.cl b/src/tests/semantic/assignment2.cl new file mode 100644 index 000000000..cace221ae --- /dev/null +++ b/src/tests/semantic/assignment2.cl @@ -0,0 +1,13 @@ +--The static type of an assignment is the static type of . + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test(a: A): B { a <- new C }; + test2(a: A): D { a <- new C }; +}; diff --git a/src/tests/semantic/assignment2_error.txt b/src/tests/semantic/assignment2_error.txt new file mode 100644 index 000000000..ed10b7f38 --- /dev/null +++ b/src/tests/semantic/assignment2_error.txt @@ -0,0 +1 @@ +(12, 22) - TypeError: Inferred return type C of method test2 does not conform to declared return type D. diff --git a/src/tests/semantic/assignment3.cl b/src/tests/semantic/assignment3.cl new file mode 100644 index 000000000..eba0d69e2 --- /dev/null +++ b/src/tests/semantic/assignment3.cl @@ -0,0 +1,14 @@ +--The static type of an assignment is the static type of . + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + a: A; + b: B <- a <- new C; + d: D <- a <- new C; +}; diff --git a/src/tests/semantic/assignment3_error.txt b/src/tests/semantic/assignment3_error.txt new file mode 100644 index 000000000..bc9a718cc --- /dev/null +++ b/src/tests/semantic/assignment3_error.txt @@ -0,0 +1 @@ +(13, 13) - TypeError: Inferred type C of initialization of attribute d does not conform to declared type D. \ No newline at end of file diff --git a/src/tests/semantic/attributes1.cl b/src/tests/semantic/attributes1.cl new file mode 100644 index 000000000..3fa0440e4 --- /dev/null +++ b/src/tests/semantic/attributes1.cl @@ -0,0 +1,13 @@ +--The static type of the expression must conform to the declared type of the attribute. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + test1: IO <- new Main; + test2: B <- new A; + + main(): IO { out_string("Hello World!")}; +}; \ No newline at end of file diff --git a/src/tests/semantic/attributes1_error.txt b/src/tests/semantic/attributes1_error.txt new file mode 100644 index 000000000..9cb8460c9 --- /dev/null +++ b/src/tests/semantic/attributes1_error.txt @@ -0,0 +1 @@ +(10, 17) - TypeError: Inferred type A of initialization of attribute test2 does not conform to declared type B. diff --git a/src/tests/semantic/attributes2.cl b/src/tests/semantic/attributes2.cl new file mode 100644 index 000000000..7937c2cc8 --- /dev/null +++ b/src/tests/semantic/attributes2.cl @@ -0,0 +1,13 @@ +--The static type of the expression must conform to the declared type of the attribute. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + test1: IO <- new Main; + test2: C <- new D; + + main(): IO { out_string("Hello World!")}; +}; \ No newline at end of file diff --git a/src/tests/semantic/attributes2_error.txt b/src/tests/semantic/attributes2_error.txt new file mode 100644 index 000000000..6d601b7cd --- /dev/null +++ b/src/tests/semantic/attributes2_error.txt @@ -0,0 +1 @@ +(10, 17) - TypeError: Inferred type D of initialization of attribute test2 does not conform to declared type C. diff --git a/src/tests/semantic/attributes3.cl b/src/tests/semantic/attributes3.cl new file mode 100644 index 000000000..8a67decd1 --- /dev/null +++ b/src/tests/semantic/attributes3.cl @@ -0,0 +1,25 @@ +--Attributes are local to the class in which they are defined or inherited. + +class A { + a: Int <- 5; + test(x1: Int, y1: Int): Int { + let x: Int <- x1, y: Int <-y1 in { + x <- x + a; + y <- y + a; + if b then x + y else x - y fi; + } + }; +}; +class B inherits A { + b: Bool <- true; +}; +class C inherits B { + c: String <- "C"; +}; +class D inherits B { + d: IO <- new Main.main(); +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!") }; +}; \ No newline at end of file diff --git a/src/tests/semantic/attributes3_error.txt b/src/tests/semantic/attributes3_error.txt new file mode 100644 index 000000000..6195c816c --- /dev/null +++ b/src/tests/semantic/attributes3_error.txt @@ -0,0 +1 @@ +(9, 16) - NameError: Undeclared identifier b. diff --git a/src/tests/semantic/attributes4.cl b/src/tests/semantic/attributes4.cl new file mode 100644 index 000000000..a7f63adbd --- /dev/null +++ b/src/tests/semantic/attributes4.cl @@ -0,0 +1,39 @@ +--Attributes are local to the class in which they are defined or inherited. + +class A { + a: Int <- 5; +}; +class B inherits A { + b: Bool <- true; + test(x1: Int, y1: Int): Int { + let x: Int <- x1, y: Int <-y1 in { + x <- x + a; + y <- y + a; + if b then x + y else x - y fi; + } + }; +}; +class D inherits B { + d: IO <- new Main.main(); + test3(x1: Int, y1: Int): IO { + let x: Int <- x1, y: Int <-y1, c: String <- "C" in { + x <- x + a; + y <- y + a; + if b then new IO.out_string(c) else d fi; + } + }; +}; +class C inherits B { + c: String <- "C"; + test2(x1: Int, y1: Int): IO { + let x: Int <- x1, y: Int <-y1 in { + x <- x + a; + y <- y + a; + if b then new IO.out_string(c) else d fi; + } + }; +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!") }; +}; \ No newline at end of file diff --git a/src/tests/semantic/attributes4_error.txt b/src/tests/semantic/attributes4_error.txt new file mode 100644 index 000000000..fa5fcfa89 --- /dev/null +++ b/src/tests/semantic/attributes4_error.txt @@ -0,0 +1 @@ +(32, 49) - NameError: Undeclared identifier d. \ No newline at end of file diff --git a/src/tests/semantic/basics1.cl b/src/tests/semantic/basics1.cl new file mode 100644 index 000000000..32ae16564 --- /dev/null +++ b/src/tests/semantic/basics1.cl @@ -0,0 +1,10 @@ +-- It is an error to redefine the IO class. + +class IO { + scan(): String { ":)" }; + print(s: String): IO { new IO }; +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; \ No newline at end of file diff --git a/src/tests/semantic/basics1_error.txt b/src/tests/semantic/basics1_error.txt new file mode 100644 index 000000000..676f5049c --- /dev/null +++ b/src/tests/semantic/basics1_error.txt @@ -0,0 +1 @@ +(3, 7) - SemanticError: Redefinition of basic class IO. diff --git a/src/tests/semantic/basics2.cl b/src/tests/semantic/basics2.cl new file mode 100644 index 000000000..cf2b1cd2f --- /dev/null +++ b/src/tests/semantic/basics2.cl @@ -0,0 +1,9 @@ +-- It is an error to inherit from or redefine Int. + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; + +class A inherits Int { + is_prime(): Bool { false }; +}; diff --git a/src/tests/semantic/basics2_error.txt b/src/tests/semantic/basics2_error.txt new file mode 100644 index 000000000..69a3b6814 --- /dev/null +++ b/src/tests/semantic/basics2_error.txt @@ -0,0 +1 @@ +(7, 18) - SemanticError: Class A cannot inherit class Int. diff --git a/src/tests/semantic/basics3.cl b/src/tests/semantic/basics3.cl new file mode 100644 index 000000000..fef017a8d --- /dev/null +++ b/src/tests/semantic/basics3.cl @@ -0,0 +1,9 @@ +-- It is an error to inherit from or redefine Int. + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; + +class Int { + is_prime(): Bool { false }; +}; \ No newline at end of file diff --git a/src/tests/semantic/basics3_error.txt b/src/tests/semantic/basics3_error.txt new file mode 100644 index 000000000..d8f80cb12 --- /dev/null +++ b/src/tests/semantic/basics3_error.txt @@ -0,0 +1 @@ +(7, 7) - SemanticError: Redefinition of basic class Int. diff --git a/src/tests/semantic/basics4.cl b/src/tests/semantic/basics4.cl new file mode 100644 index 000000000..9266ec79b --- /dev/null +++ b/src/tests/semantic/basics4.cl @@ -0,0 +1,9 @@ +-- It is an error to inherit from or redefine String. + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; + +class A inherits String { + is_palindrome(): Bool { false }; +}; \ No newline at end of file diff --git a/src/tests/semantic/basics4_error.txt b/src/tests/semantic/basics4_error.txt new file mode 100644 index 000000000..d5cd4c3db --- /dev/null +++ b/src/tests/semantic/basics4_error.txt @@ -0,0 +1 @@ +(7, 18) - SemanticError: Class A cannot inherit class String. diff --git a/src/tests/semantic/basics5.cl b/src/tests/semantic/basics5.cl new file mode 100644 index 000000000..bad5eff13 --- /dev/null +++ b/src/tests/semantic/basics5.cl @@ -0,0 +1,9 @@ +-- It is an error to inherit from or redefine String. + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; + +class String { + is_palindrome(): Bool { false }; +}; \ No newline at end of file diff --git a/src/tests/semantic/basics5_error.txt b/src/tests/semantic/basics5_error.txt new file mode 100644 index 000000000..8437accf7 --- /dev/null +++ b/src/tests/semantic/basics5_error.txt @@ -0,0 +1 @@ +(7, 7) - SemanticError: Redefinition of basic class String. diff --git a/src/tests/semantic/basics6.cl b/src/tests/semantic/basics6.cl new file mode 100644 index 000000000..47266ebed --- /dev/null +++ b/src/tests/semantic/basics6.cl @@ -0,0 +1,9 @@ +-- It is an error to inherit from or redefine Bool. + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; + +class A inherits Bool { + xor(b: Bool): Bool { false }; +}; \ No newline at end of file diff --git a/src/tests/semantic/basics6_error.txt b/src/tests/semantic/basics6_error.txt new file mode 100644 index 000000000..b4d22da13 --- /dev/null +++ b/src/tests/semantic/basics6_error.txt @@ -0,0 +1 @@ +(7, 18) - SemanticError: Class A cannot inherit class Bool. diff --git a/src/tests/semantic/basics7.cl b/src/tests/semantic/basics7.cl new file mode 100644 index 000000000..0f30aaec3 --- /dev/null +++ b/src/tests/semantic/basics7.cl @@ -0,0 +1,9 @@ +-- It is an error to inherit from or redefine Bool. + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; + +class Bool { + xor(b: Bool): Bool { false }; +}; \ No newline at end of file diff --git a/src/tests/semantic/basics7_error.txt b/src/tests/semantic/basics7_error.txt new file mode 100644 index 000000000..92660ab9f --- /dev/null +++ b/src/tests/semantic/basics7_error.txt @@ -0,0 +1 @@ +(7, 7) - SemanticError: Redefinition of basic class Bool. diff --git a/src/tests/semantic/basics8.cl b/src/tests/semantic/basics8.cl new file mode 100644 index 000000000..3b9697d4f --- /dev/null +++ b/src/tests/semantic/basics8.cl @@ -0,0 +1,9 @@ +-- It is an error redefine Object. + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; + +class Object { + xor(b: Bool): Bool { false }; +}; \ No newline at end of file diff --git a/src/tests/semantic/basics8_error.txt b/src/tests/semantic/basics8_error.txt new file mode 100644 index 000000000..652f47b30 --- /dev/null +++ b/src/tests/semantic/basics8_error.txt @@ -0,0 +1 @@ +(7, 7) - SemanticError: Redefinition of basic class Object. diff --git a/src/tests/semantic/blocks1.cl b/src/tests/semantic/blocks1.cl new file mode 100644 index 000000000..1e928908b --- /dev/null +++ b/src/tests/semantic/blocks1.cl @@ -0,0 +1,31 @@ +--The static type of a block is the static type of the last expression. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test: B <- { + new A; + { + new B; + { + new C; + { + new D; + { + new E; + { + new F; + }; + }; + }; + }; + }; + }; +}; \ No newline at end of file diff --git a/src/tests/semantic/blocks1_error.txt b/src/tests/semantic/blocks1_error.txt new file mode 100644 index 000000000..2f0e2caf3 --- /dev/null +++ b/src/tests/semantic/blocks1_error.txt @@ -0,0 +1 @@ +(13, 16) - TypeError: Inferred type F of initialization of attribute test does not conform to declared type B. diff --git a/src/tests/semantic/case1.cl b/src/tests/semantic/case1.cl new file mode 100644 index 000000000..82c6a4d61 --- /dev/null +++ b/src/tests/semantic/case1.cl @@ -0,0 +1,23 @@ +--For each branch, let Ti be the static type of . The static type of a case expression is Join 1≤i≤n Ti. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + b: B <- case "true" of + i: Int => New C; + b: Bool => New D; + s: String => New E; + esac; + + test: B <- case 0 of + b: Bool => new F; + i: Int => new E; + esac; +}; diff --git a/src/tests/semantic/case1_error.txt b/src/tests/semantic/case1_error.txt new file mode 100644 index 000000000..f05ce31b9 --- /dev/null +++ b/src/tests/semantic/case1_error.txt @@ -0,0 +1 @@ +(19, 16) - TypeError: Inferred type A of initialization of attribute test does not conform to declared type B. diff --git a/src/tests/semantic/case2.cl b/src/tests/semantic/case2.cl new file mode 100644 index 000000000..ae97b41da --- /dev/null +++ b/src/tests/semantic/case2.cl @@ -0,0 +1,23 @@ +-- The variables declared on each branch of a case must all have distinct types. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + b: B <- case "true" of + i: Int => New C; + b: Bool => New D; + s: String => New E; + esac; + + test: A <- case 0 of + b: Bool => new F; + i: Bool => new E; + esac; +}; \ No newline at end of file diff --git a/src/tests/semantic/case2_error.txt b/src/tests/semantic/case2_error.txt new file mode 100644 index 000000000..302fec38c --- /dev/null +++ b/src/tests/semantic/case2_error.txt @@ -0,0 +1 @@ +(21, 20) - SemanticError: Duplicate branch Bool in case statement. \ No newline at end of file diff --git a/src/tests/semantic/case3.cl b/src/tests/semantic/case3.cl new file mode 100644 index 000000000..da79bbfe6 --- /dev/null +++ b/src/tests/semantic/case3.cl @@ -0,0 +1,23 @@ +-- Missing type + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + b: B <- case "true" of + i: Int => New C; + b: Bool => New D; + s: String => New E; + esac; + + test: A <- case 0 of + b: Bool => new F; + i: Ball => new E; + esac; +}; \ No newline at end of file diff --git a/src/tests/semantic/case3_error.txt b/src/tests/semantic/case3_error.txt new file mode 100644 index 000000000..fea261e5b --- /dev/null +++ b/src/tests/semantic/case3_error.txt @@ -0,0 +1 @@ +(21, 20) - TypeError: Class Ball of case branch is undefined. \ No newline at end of file diff --git a/src/tests/semantic/class1.cl b/src/tests/semantic/class1.cl new file mode 100644 index 000000000..ed83da9d1 --- /dev/null +++ b/src/tests/semantic/class1.cl @@ -0,0 +1,9 @@ +-- Classes may not be redefined. + +class Repeat { + sum(a: Int, b: Int): Int { a + b }; +}; + +class Repeat { + mult(a: Int, b: Int): Int { a * b }; +}; \ No newline at end of file diff --git a/src/tests/semantic/class1_error.txt b/src/tests/semantic/class1_error.txt new file mode 100644 index 000000000..19c507672 --- /dev/null +++ b/src/tests/semantic/class1_error.txt @@ -0,0 +1,2 @@ +(7, 5) - SemanticError: Classes may not be redefined + diff --git a/src/tests/semantic/conditionals1.cl b/src/tests/semantic/conditionals1.cl new file mode 100644 index 000000000..3446a8b0f --- /dev/null +++ b/src/tests/semantic/conditionals1.cl @@ -0,0 +1,14 @@ +--The predicate must have static type Bool. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + a: A <- if new F then new D else new C fi; +}; \ No newline at end of file diff --git a/src/tests/semantic/conditionals1_error.txt b/src/tests/semantic/conditionals1_error.txt new file mode 100644 index 000000000..b86345359 --- /dev/null +++ b/src/tests/semantic/conditionals1_error.txt @@ -0,0 +1 @@ +(13, 16) - TypeError: Predicate of 'if' does not have type Bool. diff --git a/src/tests/semantic/conditionals2.cl b/src/tests/semantic/conditionals2.cl new file mode 100644 index 000000000..9d6313d75 --- /dev/null +++ b/src/tests/semantic/conditionals2.cl @@ -0,0 +1,24 @@ +(* +Let T and F be the static types of the branches of the conditional. Then the static type of the +conditional is T t F. (think: Walk towards Object from each of T and F until the paths meet.) +*) + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + b: B <- if true then + new C + else + if false then new D + else new E fi + fi; + + test: B <- if not true then new F else new E fi; +}; diff --git a/src/tests/semantic/conditionals2_error.txt b/src/tests/semantic/conditionals2_error.txt new file mode 100644 index 000000000..d6f5fc307 --- /dev/null +++ b/src/tests/semantic/conditionals2_error.txt @@ -0,0 +1,2 @@ +(23, 16) - TypeError: Inferred type A of initialization of attribute test does not conform to declared type B. + diff --git a/src/tests/semantic/dispatch1.cl b/src/tests/semantic/dispatch1.cl new file mode 100644 index 000000000..1c0457fa3 --- /dev/null +++ b/src/tests/semantic/dispatch1.cl @@ -0,0 +1,33 @@ +(* +e0 .f(e1, . . . , en ) +Assume e0 has static type A. +Class A must have a method f +*) + +class A inherits IO { + f(x: Int, y: Int): Int { x + y }; + g(x: Int): Int { x + x }; +}; +class B inherits A { + f(a: Int, b: Int): Int { a - b }; +}; +class C inherits B { + ident(m: Int): Int { m }; + f(m: Int, n: Int): Int { m * n }; +}; +class D inherits B { + ident(v: String): IO { new IO.out_string(v) }; + f(v: Int, w: Int): Int { v / w }; + g(v: Int): Int { v + v + v }; + + back(s: String): B { { + out_string(s); + self; + } }; +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test: B <- new D.back("Hello ").back("World!"); +}; \ No newline at end of file diff --git a/src/tests/semantic/dispatch1_error.txt b/src/tests/semantic/dispatch1_error.txt new file mode 100644 index 000000000..7fb22edce --- /dev/null +++ b/src/tests/semantic/dispatch1_error.txt @@ -0,0 +1 @@ +(32, 37) - AttributeError: Dispatch to undefined method back. diff --git a/src/tests/semantic/dispatch2.cl b/src/tests/semantic/dispatch2.cl new file mode 100644 index 000000000..5182912b8 --- /dev/null +++ b/src/tests/semantic/dispatch2.cl @@ -0,0 +1,34 @@ +(* +e0 .f(e1, . . . , en ) +Assume e0 has static type A. +Class A must have a method f +the dispatch and the definition of f must have the same number of arguments +*) + +class A inherits IO { + f(x: Int, y: Int): Int { x + y }; + g(x: Int): Int { x + x }; +}; +class B inherits A { + f(a: Int, b: Int): Int { a - b }; +}; +class C inherits B { + ident(m: Int): Int { m }; + f(m: Int, n: Int): Int { m * n }; +}; +class D inherits B { + ident(v: String): IO { new IO.out_string(v) }; + f(v: Int, w: Int): Int { v / w }; + g(v: Int): Int { v + v + v }; + + back(s: String): B { { + out_string(s); + self; + } }; +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test: Int <- new D.back("Hello ").g(2, 2); +}; \ No newline at end of file diff --git a/src/tests/semantic/dispatch2_error.txt b/src/tests/semantic/dispatch2_error.txt new file mode 100644 index 000000000..a86c35340 --- /dev/null +++ b/src/tests/semantic/dispatch2_error.txt @@ -0,0 +1 @@ +(33, 39) - SemanticError: Method g called with wrong number of arguments. diff --git a/src/tests/semantic/dispatch3.cl b/src/tests/semantic/dispatch3.cl new file mode 100644 index 000000000..ecb1535db --- /dev/null +++ b/src/tests/semantic/dispatch3.cl @@ -0,0 +1,36 @@ +(* +e0 .f(e1, . . . , en ) +Assume e0 has static type A. +Class A must have a method f +the static type of the ith actual parameter must conform to the declared type of the ith formal parameter. +*) + +class A inherits IO { + f(x: Int, y: Int): Int { x + y }; + g(x: Int): Int { x + x }; +}; +class B inherits A { + f(a: Int, b: Int): Int { a - b }; +}; +class C inherits B { + ident(m: Int): Int { m }; + f(m: Int, n: Int): Int { m * n }; +}; +class D inherits B { + ident(v: String): IO { new IO.out_string(v) }; + f(v: Int, w: Int): Int { v / w }; + g(v: Int): Int { v + v + v }; + + back(s: String): B { { + out_string(s); + self; + } }; + + alphabet(a: A, b: B, c: C): D { self }; +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test: B <- new D.alphabet(new D, new D, new D.back("Hello ")).back("World!"); +}; \ No newline at end of file diff --git a/src/tests/semantic/dispatch3_error.txt b/src/tests/semantic/dispatch3_error.txt new file mode 100644 index 000000000..0def5cf03 --- /dev/null +++ b/src/tests/semantic/dispatch3_error.txt @@ -0,0 +1 @@ +(35, 45) - TypeError: In call of method alphabet, type B of parameter c does not conform to declared type C. diff --git a/src/tests/semantic/dispatch4.cl b/src/tests/semantic/dispatch4.cl new file mode 100644 index 000000000..9cadd8332 --- /dev/null +++ b/src/tests/semantic/dispatch4.cl @@ -0,0 +1,36 @@ +(* +e0 .f(e1, . . . , en ) +Assume e0 has static type A. +Class A must have a method f +If f has return type B and B is a class name, then the static type of the dispatch is B. +*) + +class A inherits IO { + f(x: Int, y: Int): Int { x + y }; + g(x: Int): Int { x + x }; +}; +class B inherits A { + f(a: Int, b: Int): Int { a - b }; +}; +class C inherits B { + ident(m: Int): Int { m }; + f(m: Int, n: Int): Int { m * n }; +}; +class D inherits B { + ident(v: String): IO { new IO.out_string(v) }; + f(v: Int, w: Int): Int { v / w }; + g(v: Int): Int { v + v + v }; + + back(s: String): B { { + out_string(s); + self; + } }; + + alphabet(a: A, b: B, c: C): D { self }; +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test: D <- new D.alphabet(new D, new D.back("Hello "), new C).back("World!"); +}; \ No newline at end of file diff --git a/src/tests/semantic/dispatch4_error.txt b/src/tests/semantic/dispatch4_error.txt new file mode 100644 index 000000000..9699f166b --- /dev/null +++ b/src/tests/semantic/dispatch4_error.txt @@ -0,0 +1 @@ +(35, 16) - TypeError: Inferred type B of initialization of attribute test does not conform to declared type D. \ No newline at end of file diff --git a/src/tests/semantic/dispatch5.cl b/src/tests/semantic/dispatch5.cl new file mode 100644 index 000000000..b4437b1b4 --- /dev/null +++ b/src/tests/semantic/dispatch5.cl @@ -0,0 +1,31 @@ +(* +(,...,) is shorthand for self.(,...,). +*) + +class A inherits IO { + f(x: Int, y: Int): Int { x + y }; + g(x: Int): Int { x + x }; +}; +class B inherits A { + f(a: Int, b: Int): Int { a - b }; +}; +class C inherits B { + ident(m: Int): Int { m }; + f(m: Int, n: Int): Int { m * n }; + sum(m: Int, n: Int, p: Int): Int { m + n + p }; +}; +class D inherits B { + ident(v: String): IO { new IO.out_string(v) }; + f(v: Int, w: Int): Int { v / w }; + + back(s: String): B { { + out_string(s); + g(2); + sum(1, 2, 3); + self; + } }; +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; \ No newline at end of file diff --git a/src/tests/semantic/dispatch5_error.txt b/src/tests/semantic/dispatch5_error.txt new file mode 100644 index 000000000..d26bf34a1 --- /dev/null +++ b/src/tests/semantic/dispatch5_error.txt @@ -0,0 +1 @@ +(24, 9) - AttributeError: Dispatch to undefined method sum. diff --git a/src/tests/semantic/dispatch6.cl b/src/tests/semantic/dispatch6.cl new file mode 100644 index 000000000..fcc033f2c --- /dev/null +++ b/src/tests/semantic/dispatch6.cl @@ -0,0 +1,32 @@ +(* +e@B.f() invokes the method +f in class B on the object that is the value of e. For this form of dispatch, the static type to the left of +“@”must conform to the type specified to the right of “@”. +*) + +class A { + f(x: Int, y: Int): Int { x + y }; + g(x: Int): Int { x + x }; +}; +class B inherits A { + f(a: Int, b: Int): Int { a - b }; + sum(m: Int, n: Int, p: Int): Int { m + n + p }; +}; +class C inherits B { + ident(m: Int): Int { m }; + f(m: Int, n: Int): Int { m * n }; +}; +class D inherits B { + ident(v: String): IO { new IO.out_string(v) }; + f(v: Int, w: Int): Int { v / w }; + g(v: Int): Int { v + v + v }; + sum(v: Int, w: Int, z: Int): Int { v - w - z }; +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + a: A <- new D; + b: Int <- new D@B.sum(1, 2, 3); + test: Int <- a@B.sum(1, 2, 3); +}; diff --git a/src/tests/semantic/dispatch6_error.txt b/src/tests/semantic/dispatch6_error.txt new file mode 100644 index 000000000..ae9184b2f --- /dev/null +++ b/src/tests/semantic/dispatch6_error.txt @@ -0,0 +1 @@ +(31, 18) - TypeError: Expression type A does not conform to declared static dispatch type B. diff --git a/src/tests/semantic/eq1.cl b/src/tests/semantic/eq1.cl new file mode 100644 index 000000000..88f2a7ffe --- /dev/null +++ b/src/tests/semantic/eq1.cl @@ -0,0 +1,17 @@ +(* +The comparison = is a special +case. If either or has static type Int, Bool, or String, then the other must have the +same static type. Any other types, including SELF TYPE, may be freely compared. +*) + +class A { }; +class B inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + x: Bool <- 1 = 2; + test: Bool <- 1 = new A; + y: Bool <- "1" = "2"; + z: Bool <- true = not false; +}; \ No newline at end of file diff --git a/src/tests/semantic/eq1_error.txt b/src/tests/semantic/eq1_error.txt new file mode 100644 index 000000000..f81425683 --- /dev/null +++ b/src/tests/semantic/eq1_error.txt @@ -0,0 +1 @@ +(14, 21) - TypeError: Illegal comparison with a basic type. diff --git a/src/tests/semantic/eq2.cl b/src/tests/semantic/eq2.cl new file mode 100644 index 000000000..d76852780 --- /dev/null +++ b/src/tests/semantic/eq2.cl @@ -0,0 +1,17 @@ +(* +The comparison = is a special +case. If either or has static type Int, Bool, or String, then the other must have the +same static type. Any other types, including SELF TYPE, may be freely compared. +*) + +class A { }; +class B inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + x: Bool <- 1 = 2; + y: Bool <- "1" = "2"; + test: Bool <- "1" = new B; + z: Bool <- true = not false; +}; diff --git a/src/tests/semantic/eq2_error.txt b/src/tests/semantic/eq2_error.txt new file mode 100644 index 000000000..a44ab0d51 --- /dev/null +++ b/src/tests/semantic/eq2_error.txt @@ -0,0 +1 @@ +(15, 23) - TypeError: Illegal comparison with a basic type. diff --git a/src/tests/semantic/eq3.cl b/src/tests/semantic/eq3.cl new file mode 100644 index 000000000..4dad693ee --- /dev/null +++ b/src/tests/semantic/eq3.cl @@ -0,0 +1,17 @@ +(* +The comparison = is a special +case. If either or has static type Int, Bool, or String, then the other must have the +same static type. Any other types, including SELF TYPE, may be freely compared. +*) + +class A { }; +class B inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + x: Bool <- 1 = 2; + y: Bool <- "1" = "2"; + z: Bool <- true = not false; + test: Bool <- "true" = not false; +}; diff --git a/src/tests/semantic/eq3_error.txt b/src/tests/semantic/eq3_error.txt new file mode 100644 index 000000000..c4e27eb8a --- /dev/null +++ b/src/tests/semantic/eq3_error.txt @@ -0,0 +1 @@ +(16, 26) - TypeError: Illegal comparison with a basic type. diff --git a/src/tests/semantic/eq4.cl b/src/tests/semantic/eq4.cl new file mode 100644 index 000000000..11afc119f --- /dev/null +++ b/src/tests/semantic/eq4.cl @@ -0,0 +1,17 @@ +(* +The comparison = is a special +case. If either or has static type Int, Bool, or String, then the other must have the +same static type. Any other types, including SELF TYPE, may be freely compared. The result is a Bool. +*) + +class A { }; +class B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + x: Bool <- 1 = 2; + y: Bool <- "1" = "2"; + z: Bool <- new A = new B; + test: Int <- new A = new B; +}; diff --git a/src/tests/semantic/eq4_error.txt b/src/tests/semantic/eq4_error.txt new file mode 100644 index 000000000..3ead21d0e --- /dev/null +++ b/src/tests/semantic/eq4_error.txt @@ -0,0 +1 @@ +(16, 18) - TypeError: Inferred type Bool of initialization of attribute test does not conform to declared type Int. diff --git a/src/tests/semantic/features1.cl b/src/tests/semantic/features1.cl new file mode 100644 index 000000000..66f650f4a --- /dev/null +++ b/src/tests/semantic/features1.cl @@ -0,0 +1,19 @@ +(* +No method name may be defined multiple times in +a class, and no attribute name may be defined multiple times in a class, but a method and an attribute +may have the same name. +*) + +class Main inherits IO { + main(): IO { out_string("hi!") }; + + main: IO <- out_string("bye!"); +}; + +class A { + x: Int <- 3; + + x(): Int { 3 }; + + x: String <- ":)"; +}; \ No newline at end of file diff --git a/src/tests/semantic/features1_error.txt b/src/tests/semantic/features1_error.txt new file mode 100644 index 000000000..40033e9b3 --- /dev/null +++ b/src/tests/semantic/features1_error.txt @@ -0,0 +1 @@ +(18, 5) - SemanticError: Attribute x is multiply defined in class. \ No newline at end of file diff --git a/src/tests/semantic/features2.cl b/src/tests/semantic/features2.cl new file mode 100644 index 000000000..5b1f7e9df --- /dev/null +++ b/src/tests/semantic/features2.cl @@ -0,0 +1,19 @@ +(* +No method name may be defined multiple times in +a class, and no attribute name may be defined multiple times in a class, but a method and an attribute +may have the same name. +*) + +class Main inherits IO { + main(): IO { out_string("hi!") }; + + main: IO <- out_string("bye!"); +}; + +class A { + x: Int <- 3; + + x(): String { "3" }; + + x(): String { ":)" }; +}; \ No newline at end of file diff --git a/src/tests/semantic/features2_error.txt b/src/tests/semantic/features2_error.txt new file mode 100644 index 000000000..117e06042 --- /dev/null +++ b/src/tests/semantic/features2_error.txt @@ -0,0 +1 @@ +(18, 5) - SemanticError: Method x is multiply defined. \ No newline at end of file diff --git a/src/tests/semantic/features3.cl b/src/tests/semantic/features3.cl new file mode 100644 index 000000000..a892d011d --- /dev/null +++ b/src/tests/semantic/features3.cl @@ -0,0 +1,15 @@ +-- Missing type + +class Main inherits IO { + main(): IO { out_string("hi!") }; + + main: IO <- out_string("bye!"); +}; + +class A { + x: Int <- 3; + + x(): Int { 3 }; + + c: Cadena; +}; \ No newline at end of file diff --git a/src/tests/semantic/features3_error.txt b/src/tests/semantic/features3_error.txt new file mode 100644 index 000000000..53f1abe26 --- /dev/null +++ b/src/tests/semantic/features3_error.txt @@ -0,0 +1 @@ +(14, 8) - TypeError: Class Cadena of attribute c is undefined. \ No newline at end of file diff --git a/src/tests/semantic/inheritance1.cl b/src/tests/semantic/inheritance1.cl new file mode 100644 index 000000000..1d92da307 --- /dev/null +++ b/src/tests/semantic/inheritance1.cl @@ -0,0 +1,19 @@ +--It is illegal to redefine attribute names. + +class Main inherits IO { + main(): IO { out_string("hi!") }; + + main: IO <- out_string("bye!"); +}; + +class A { + x: Int <- 3; + + x(): String { ":)" }; +}; + +class B inherits A { + x: Int; + + div(a: Int, b: Int): Int { a / b}; +}; \ No newline at end of file diff --git a/src/tests/semantic/inheritance1_error.txt b/src/tests/semantic/inheritance1_error.txt new file mode 100644 index 000000000..ec5b504e6 --- /dev/null +++ b/src/tests/semantic/inheritance1_error.txt @@ -0,0 +1 @@ +(16, 5) - SemanticError: Attribute x is an attribute of an inherited class. \ No newline at end of file diff --git a/src/tests/semantic/inheritance2.cl b/src/tests/semantic/inheritance2.cl new file mode 100644 index 000000000..d453eca09 --- /dev/null +++ b/src/tests/semantic/inheritance2.cl @@ -0,0 +1,19 @@ +--If C inherits from P, then P must have a class definition somewhere in the program. + +class Main inherits IO { + main(): IO { out_string("hi!") }; + + main: IO <- out_string("bye!"); +}; + +class Alo { + x: Int <- 3; + + x(): String { "3" }; +}; + +class B inherits A { + div(a: Int, b: Int): Int { a / b}; + + x: String <- "2"; +}; \ No newline at end of file diff --git a/src/tests/semantic/inheritance2_error.txt b/src/tests/semantic/inheritance2_error.txt new file mode 100644 index 000000000..1ec7669b5 --- /dev/null +++ b/src/tests/semantic/inheritance2_error.txt @@ -0,0 +1 @@ +(15, 18) - TypeError: Class B inherits from an undefined class A. \ No newline at end of file diff --git a/src/tests/semantic/inheritance3.cl b/src/tests/semantic/inheritance3.cl new file mode 100644 index 000000000..3ff170dec --- /dev/null +++ b/src/tests/semantic/inheritance3.cl @@ -0,0 +1,13 @@ +--The parent-child relation on classes defines a graph. This graph may not contain cycles. + +class Main inherits IO { + main(): IO { out_string("hi!") }; + + main: IO <- out_string("bye!"); +}; + +class A inherits A { + x: Int <- 3; + + x(): String { ":)" }; +}; \ No newline at end of file diff --git a/src/tests/semantic/inheritance3_error.txt b/src/tests/semantic/inheritance3_error.txt new file mode 100644 index 000000000..d17ca7f49 --- /dev/null +++ b/src/tests/semantic/inheritance3_error.txt @@ -0,0 +1 @@ +(9, 18) - SemanticError: Class A, or an ancestor of A, is involved in an inheritance cycle. \ No newline at end of file diff --git a/src/tests/semantic/inheritance4.cl b/src/tests/semantic/inheritance4.cl new file mode 100644 index 000000000..c985484ba --- /dev/null +++ b/src/tests/semantic/inheritance4.cl @@ -0,0 +1,19 @@ +--The parent-child relation on classes defines a graph. This graph may not contain cycles. + +class Main inherits IO { + main(): IO { out_string("hi!") }; + + main: IO <- out_string("bye!"); +}; + +class A inherits B { + x: Int <- 3; + + x(): String { ":)" }; +}; + +class B inherits A { + y: Int <- 2; + + div(a: Int, b: Int): Int { a / b}; +}; \ No newline at end of file diff --git a/src/tests/semantic/inheritance4_error.txt b/src/tests/semantic/inheritance4_error.txt new file mode 100644 index 000000000..b437ec667 --- /dev/null +++ b/src/tests/semantic/inheritance4_error.txt @@ -0,0 +1 @@ +(15, 18) - SemanticError: Class B, or an ancestor of B, is involved in an inheritance cycle. \ No newline at end of file diff --git a/src/tests/semantic/inheritance5.cl b/src/tests/semantic/inheritance5.cl new file mode 100644 index 000000000..f6ed885c8 --- /dev/null +++ b/src/tests/semantic/inheritance5.cl @@ -0,0 +1,21 @@ +--The parent-child relation on classes defines a graph. This graph may not contain cycles. + +class Main inherits IO { + main(): IO { out_string("hi!") }; + + main: IO <- out_string("bye!"); +}; + +class A inherits B { + x: Int <- 3; + + x(): String { ":)" }; +}; + +class B inherits C { + y: Int <- 2; + + div(a: Int, b: Int): Int { a / b}; +}; + +class C inherits A { }; \ No newline at end of file diff --git a/src/tests/semantic/inheritance5_error.txt b/src/tests/semantic/inheritance5_error.txt new file mode 100644 index 000000000..da72ba547 --- /dev/null +++ b/src/tests/semantic/inheritance5_error.txt @@ -0,0 +1 @@ +(21, 18) - SemanticError: Class C, or an ancestor of C, is involved in an inheritance cycle. \ No newline at end of file diff --git a/src/tests/semantic/isvoid1.cl b/src/tests/semantic/isvoid1.cl new file mode 100644 index 000000000..072720d85 --- /dev/null +++ b/src/tests/semantic/isvoid1.cl @@ -0,0 +1,26 @@ +--evaluates to true if expr is void and evaluates to false if expr is not void. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + b: B <- if isvoid new F then + new C + else + if false then new D + else new E fi + fi; + + test: B <- isvoid if isvoid new F then + new C + else + if false then new D + else new E fi + fi; +}; \ No newline at end of file diff --git a/src/tests/semantic/isvoid1_error.txt b/src/tests/semantic/isvoid1_error.txt new file mode 100644 index 000000000..0922de909 --- /dev/null +++ b/src/tests/semantic/isvoid1_error.txt @@ -0,0 +1 @@ +(20, 16) - TypeError: Inferred type Bool of initialization of attribute test does not conform to declared type B. diff --git a/src/tests/semantic/let1.cl b/src/tests/semantic/let1.cl new file mode 100644 index 000000000..26ef63026 --- /dev/null +++ b/src/tests/semantic/let1.cl @@ -0,0 +1,15 @@ +--The type of an initialization expression must conform to the declared type of the identifier. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + b: B <- let a: Bool, a: Int <- 5, a: String, a: A <- new F, b: B <- new E in b; + test: B <- let a: Bool, a: Int <- 5, a: String, a: A <- new F, b: C <- new E in b; +}; \ No newline at end of file diff --git a/src/tests/semantic/let1_error.txt b/src/tests/semantic/let1_error.txt new file mode 100644 index 000000000..16ecf780c --- /dev/null +++ b/src/tests/semantic/let1_error.txt @@ -0,0 +1 @@ +(14, 76) - TypeError: Inferred type E of initialization of b does not conform to identifier's declared type C. diff --git a/src/tests/semantic/let2.cl b/src/tests/semantic/let2.cl new file mode 100644 index 000000000..c5956ead3 --- /dev/null +++ b/src/tests/semantic/let2.cl @@ -0,0 +1,15 @@ +--The type of let is the type of the body. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + b: B <- let a: Bool, a: Int <- 5, a: String, a: A <- new F, b: B <- new E in b; + test: B <- let a: Bool, a: Int <- 5, a: String, a: A <- new F, b: A <- new E in b; +}; \ No newline at end of file diff --git a/src/tests/semantic/let2_error.txt b/src/tests/semantic/let2_error.txt new file mode 100644 index 000000000..b1e8a365d --- /dev/null +++ b/src/tests/semantic/let2_error.txt @@ -0,0 +1 @@ +(14, 16) - TypeError: Inferred type A of initialization of attribute test does not conform to declared type B. diff --git a/src/tests/semantic/let3.cl b/src/tests/semantic/let3.cl new file mode 100644 index 000000000..8c0670ab8 --- /dev/null +++ b/src/tests/semantic/let3.cl @@ -0,0 +1,15 @@ +-- Missing type + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + b: B <- let a: Bool, a: Int <- 5, a: String, a: A <- new F, b: B <- new E in b; + test: B <- let a: Bool, a: Int <- 5, a: String, a: A <- new F, b: Cadena in new B; +}; \ No newline at end of file diff --git a/src/tests/semantic/let3_error.txt b/src/tests/semantic/let3_error.txt new file mode 100644 index 000000000..39c5315d8 --- /dev/null +++ b/src/tests/semantic/let3_error.txt @@ -0,0 +1 @@ +(14, 71) - TypeError: Class Cadena of let-bound identifier b is undefined. \ No newline at end of file diff --git a/src/tests/semantic/loops1.cl b/src/tests/semantic/loops1.cl new file mode 100644 index 000000000..de3a624d2 --- /dev/null +++ b/src/tests/semantic/loops1.cl @@ -0,0 +1,8 @@ +--The predicate must have static type Bool. + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + i: Int <- 1; + test: Object <- while "true" loop i <- i + 1 pool; +}; \ No newline at end of file diff --git a/src/tests/semantic/loops1_error.txt b/src/tests/semantic/loops1_error.txt new file mode 100644 index 000000000..b160214b4 --- /dev/null +++ b/src/tests/semantic/loops1_error.txt @@ -0,0 +1 @@ +(7, 27) - TypeError: Loop condition does not have type Bool. \ No newline at end of file diff --git a/src/tests/semantic/loops2.cl b/src/tests/semantic/loops2.cl new file mode 100644 index 000000000..dea69fa14 --- /dev/null +++ b/src/tests/semantic/loops2.cl @@ -0,0 +1,9 @@ +--The static type of a loop expression is Object. + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + i: Int <- 1; + test: Object <- while not false loop i <- i + 1 pool; + test2: Int <- while not false loop i <- i + 1 pool; +}; diff --git a/src/tests/semantic/loops2_error.txt b/src/tests/semantic/loops2_error.txt new file mode 100644 index 000000000..9711cdf6a --- /dev/null +++ b/src/tests/semantic/loops2_error.txt @@ -0,0 +1 @@ +(8, 19) - TypeError: Inferred type Object of initialization of attribute test2 does not conform to declared type Int. diff --git a/src/tests/semantic/methods1.cl b/src/tests/semantic/methods1.cl new file mode 100644 index 000000000..d12031970 --- /dev/null +++ b/src/tests/semantic/methods1.cl @@ -0,0 +1,12 @@ +--The identifiers used in the formal parameter list must be distinct + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test(a: A, a: B): Int { 4 }; +}; \ No newline at end of file diff --git a/src/tests/semantic/methods1_error.txt b/src/tests/semantic/methods1_error.txt new file mode 100644 index 000000000..06ab88a92 --- /dev/null +++ b/src/tests/semantic/methods1_error.txt @@ -0,0 +1 @@ +(11, 16) - SemanticError: Formal parameter a is multiply defined. diff --git a/src/tests/semantic/methods2.cl b/src/tests/semantic/methods2.cl new file mode 100644 index 000000000..3865f0e13 --- /dev/null +++ b/src/tests/semantic/methods2.cl @@ -0,0 +1,12 @@ +--The type of the method body must conform to the declared return type. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test(a: A, b: B): C { new D }; +}; \ No newline at end of file diff --git a/src/tests/semantic/methods2_error.txt b/src/tests/semantic/methods2_error.txt new file mode 100644 index 000000000..f7e4a330d --- /dev/null +++ b/src/tests/semantic/methods2_error.txt @@ -0,0 +1 @@ +(11, 27) - TypeError: Inferred return type D of method test does not conform to declared return type C. diff --git a/src/tests/semantic/methods3.cl b/src/tests/semantic/methods3.cl new file mode 100644 index 000000000..b92faeb97 --- /dev/null +++ b/src/tests/semantic/methods3.cl @@ -0,0 +1,14 @@ +--A formal parameter hides any definition of an attribute of the same name. + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + a: C <- new C; + test(a: D): D { a }; + test2(a: B): C { a }; +}; \ No newline at end of file diff --git a/src/tests/semantic/methods3_error.txt b/src/tests/semantic/methods3_error.txt new file mode 100644 index 000000000..1165b7595 --- /dev/null +++ b/src/tests/semantic/methods3_error.txt @@ -0,0 +1 @@ +(13, 22) - TypeError: Inferred return type B of method test2 does not conform to declared return type C. diff --git a/src/tests/semantic/methods4.cl b/src/tests/semantic/methods4.cl new file mode 100644 index 000000000..be8fa36ef --- /dev/null +++ b/src/tests/semantic/methods4.cl @@ -0,0 +1,19 @@ +(* +The rule is +simple: If a class C inherits a method f from an ancestor class P, then C may override the inherited +definition of f provided the number of arguments, the types of the formal parameters, and the return +type are exactly the same in both definitions. +*) + +class A { + f(x: Int, y: Int): Int { x + y }; +}; +class B inherits A { + f(x: Int, y: Object): Int { x }; +}; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; \ No newline at end of file diff --git a/src/tests/semantic/methods4_error.txt b/src/tests/semantic/methods4_error.txt new file mode 100644 index 000000000..9f1486dec --- /dev/null +++ b/src/tests/semantic/methods4_error.txt @@ -0,0 +1 @@ +(12, 15) - SemanticError: In redefined method f, parameter type Object is different from original type Int. diff --git a/src/tests/semantic/methods5.cl b/src/tests/semantic/methods5.cl new file mode 100644 index 000000000..3905dfdd6 --- /dev/null +++ b/src/tests/semantic/methods5.cl @@ -0,0 +1,20 @@ +(* +The rule is +simple: If a class C inherits a method f from an ancestor class P, then C may override the inherited +definition of f provided the number of arguments, the types of the formal parameters, and the return +type are exactly the same in both definitions. +*) + +class A { + f(x: Int, y: Int): Int { x + y }; +}; +class B inherits A { + f(a: Int, b: Int): Object { a - b }; +}; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; + diff --git a/src/tests/semantic/methods5_error.txt b/src/tests/semantic/methods5_error.txt new file mode 100644 index 000000000..8b6bdf36e --- /dev/null +++ b/src/tests/semantic/methods5_error.txt @@ -0,0 +1 @@ +(12, 24) - SemanticError: In redefined method f, return type Object is different from original return type Int. diff --git a/src/tests/semantic/methods6.cl b/src/tests/semantic/methods6.cl new file mode 100644 index 000000000..dd2b73da6 --- /dev/null +++ b/src/tests/semantic/methods6.cl @@ -0,0 +1,27 @@ +(* +The rule is +simple: If a class C inherits a method f from an ancestor class P, then C may override the inherited +definition of f provided the number of arguments, the types of the formal parameters, and the return +type are exactly the same in both definitions. +*) + +class A { + f(x: Int, y: Int): Int { x + y }; + g(x: Int): Int { x + x }; +}; +class B inherits A { + f(a: Int, b: Int): Int { a - b }; +}; +class C inherits B { + ident(m: Int): Int { m }; + f(m: Int, n: Int): Int { m * n }; +}; +class D inherits B { + ident(v: String): IO { new IO.out_string(v) }; + f(v: Int, w: Int): Int { v / w }; + g(v: Int, w: Int, z: Int): Int { v + w + z }; +}; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; +}; \ No newline at end of file diff --git a/src/tests/semantic/methods6_error.txt b/src/tests/semantic/methods6_error.txt new file mode 100644 index 000000000..8e32663b9 --- /dev/null +++ b/src/tests/semantic/methods6_error.txt @@ -0,0 +1 @@ +(22, 5) - SemanticError: Incompatible number of formal parameters in redefined method g. diff --git a/src/tests/semantic/methods7.cl b/src/tests/semantic/methods7.cl new file mode 100644 index 000000000..e5a01f682 --- /dev/null +++ b/src/tests/semantic/methods7.cl @@ -0,0 +1,12 @@ +-- Missing type + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test(a: A, b: Ball): Int { 4 }; +}; \ No newline at end of file diff --git a/src/tests/semantic/methods7_error.txt b/src/tests/semantic/methods7_error.txt new file mode 100644 index 000000000..472cbd9d1 --- /dev/null +++ b/src/tests/semantic/methods7_error.txt @@ -0,0 +1 @@ +(11, 19) - TypeError: Class Ball of formal parameter b is undefined. \ No newline at end of file diff --git a/src/tests/semantic/methods8.cl b/src/tests/semantic/methods8.cl new file mode 100644 index 000000000..3fccab54c --- /dev/null +++ b/src/tests/semantic/methods8.cl @@ -0,0 +1,12 @@ +-- Missing type + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test(a: A, b: B): Integrer { 4 }; +}; \ No newline at end of file diff --git a/src/tests/semantic/methods8_error.txt b/src/tests/semantic/methods8_error.txt new file mode 100644 index 000000000..dc9302ec0 --- /dev/null +++ b/src/tests/semantic/methods8_error.txt @@ -0,0 +1 @@ +(11, 23) - TypeError: Undefined return type Integrer in method test. \ No newline at end of file diff --git a/src/tests/semantic/new1.cl b/src/tests/semantic/new1.cl new file mode 100644 index 000000000..d007fc03d --- /dev/null +++ b/src/tests/semantic/new1.cl @@ -0,0 +1,31 @@ +-- Missing type + +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; +class E inherits B { }; +class F inherits A { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test: F <- { + new A; + { + new Ball; + { + new C; + { + new D; + { + new E; + { + new F; + }; + }; + }; + }; + }; + }; +}; \ No newline at end of file diff --git a/src/tests/semantic/new1_error.txt b/src/tests/semantic/new1_error.txt new file mode 100644 index 000000000..612a3d427 --- /dev/null +++ b/src/tests/semantic/new1_error.txt @@ -0,0 +1 @@ +(16, 17) - TypeError: 'new' used with undefined class Ball. \ No newline at end of file diff --git a/src/tests/semantic/self1.cl b/src/tests/semantic/self1.cl new file mode 100644 index 000000000..3387fd263 --- /dev/null +++ b/src/tests/semantic/self1.cl @@ -0,0 +1,11 @@ +(* +But it is an error to assign to self or to bind self in a let, a +case, or as a formal parameter. It is also illegal to have attributes named self. +*) + + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test(a: Main): IO { self <- a }; +}; diff --git a/src/tests/semantic/self1_error.txt b/src/tests/semantic/self1_error.txt new file mode 100644 index 000000000..6beb3cda2 --- /dev/null +++ b/src/tests/semantic/self1_error.txt @@ -0,0 +1 @@ +(10, 30) - SemanticError: Cannot assign to 'self'. diff --git a/src/tests/semantic/self2.cl b/src/tests/semantic/self2.cl new file mode 100644 index 000000000..2e6921a92 --- /dev/null +++ b/src/tests/semantic/self2.cl @@ -0,0 +1,10 @@ +(* +But it is an error to assign to self or to bind self in a let, a +case, or as a formal parameter. It is also illegal to have attributes named self. +*) + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test(): IO { let self: Main <- new Main in self }; +}; diff --git a/src/tests/semantic/self2_error.txt b/src/tests/semantic/self2_error.txt new file mode 100644 index 000000000..20c883c91 --- /dev/null +++ b/src/tests/semantic/self2_error.txt @@ -0,0 +1 @@ +(9, 22) - SemanticError: 'self' cannot be bound in a 'let' expression. diff --git a/src/tests/semantic/self3.cl b/src/tests/semantic/self3.cl new file mode 100644 index 000000000..81709b4b5 --- /dev/null +++ b/src/tests/semantic/self3.cl @@ -0,0 +1,10 @@ +(* +But it is an error to assign to self or to bind self in a let, a +case, or as a formal parameter. It is also illegal to have attributes named self. +*) + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test(self: IO): IO { self }; +}; diff --git a/src/tests/semantic/self3_error.txt b/src/tests/semantic/self3_error.txt new file mode 100644 index 000000000..0ae382007 --- /dev/null +++ b/src/tests/semantic/self3_error.txt @@ -0,0 +1 @@ +(9, 10) - SemanticError: 'self' cannot be the name of a formal parameter. diff --git a/src/tests/semantic/self4.cl b/src/tests/semantic/self4.cl new file mode 100644 index 000000000..7c2b960cb --- /dev/null +++ b/src/tests/semantic/self4.cl @@ -0,0 +1,10 @@ +(* +But it is an error to assign to self or to bind self in a let, a +case, or as a formal parameter. It is also illegal to have attributes named self. +*) + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + self: IO <- self; +}; \ No newline at end of file diff --git a/src/tests/semantic/self4_error.txt b/src/tests/semantic/self4_error.txt new file mode 100644 index 000000000..c19ca400f --- /dev/null +++ b/src/tests/semantic/self4_error.txt @@ -0,0 +1 @@ +(9, 5) - SemanticError: 'self' cannot be the name of an attribute. diff --git a/src/tests/semantic_test.py b/src/tests/semantic_test.py new file mode 100644 index 000000000..cac9cd78b --- /dev/null +++ b/src/tests/semantic_test.py @@ -0,0 +1,14 @@ +import pytest +import os +from utils import compare_errors, first_error_only_line + +tests_dir = __file__.rpartition('/')[0] + '/semantic/' +tests = [(file) for file in os.listdir(tests_dir) if file.endswith('.cl')] + +@pytest.mark.semantic +@pytest.mark.error +@pytest.mark.run(order=3) +@pytest.mark.parametrize("cool_file", tests) +def test_semantic_errors(compiler_path, cool_file): + compare_errors(compiler_path, tests_dir + cool_file, tests_dir + cool_file[:-3] + '_error.txt', \ + cmp=first_error_only_line) \ No newline at end of file diff --git a/src/tests/utils/__init__.py b/src/tests/utils/__init__.py new file mode 100644 index 000000000..90f60fdd8 --- /dev/null +++ b/src/tests/utils/__init__.py @@ -0,0 +1 @@ +from .utils import * \ No newline at end of file diff --git a/src/tests/utils/utils.py b/src/tests/utils/utils.py new file mode 100644 index 000000000..961cf7cbc --- /dev/null +++ b/src/tests/utils/utils.py @@ -0,0 +1,91 @@ +import subprocess +import re + + +COMPILER_TIMEOUT = 'El compilador tarda mucho en responder.' +SPIM_TIMEOUT = 'El spim tarda mucho en responder.' +TEST_MUST_FAIL = 'El test %s debe fallar al compilar' +TEST_MUST_COMPILE = 'El test %s debe compilar' +BAD_ERROR_FORMAT = '''El error no esta en formato: (,) - : + o no se encuentra en la 3ra linea\n\n%s''' +UNEXPECTED_ERROR = 'Se esperaba un %s en (%d, %d). Su error fue un %s en (%d, %d)' +UNEXPECTED_OUTPUT = 'La salida de %s no es la esperada:\n%s\nEsperada:\n%s' + +ERROR_FORMAT = r'^\s*\(\s*(\d+)\s*,\s*(\d+)\s*\)\s*-\s*(\w+)\s*:(.*)$' + +def parse_error(error: str): + merror = re.fullmatch(ERROR_FORMAT, error) + assert merror, BAD_ERROR_FORMAT % error + + return (t(x) for t, x in zip([int, int, str, str], merror.groups())) + + +def first_error(compiler_output: list, errors: list): + line, column, error_type, _ = parse_error(errors[0]) + + oline, ocolumn, oerror_type, _ = parse_error(compiler_output[0]) + + assert line == oline and column == ocolumn and error_type == oerror_type,\ + UNEXPECTED_ERROR % (error_type, line, column, oerror_type, oline, ocolumn) + +def first_error_only_line(compiler_output: list, errors: list): + line, column, error_type, _ = parse_error(errors[0]) + + oline, ocolumn, oerror_type, _ = parse_error(compiler_output[0]) + + assert line == oline and error_type == oerror_type,\ + UNEXPECTED_ERROR % (error_type, line, column, oerror_type, oline, ocolumn) + + +def get_file_name(path: str): + try: + return path[path.rindex('/') + 1:] + except ValueError: + return path + +def compare_errors(compiler_path: str, cool_file_path: str, error_file_path: str, cmp=first_error, timeout=100): + try: + sp = subprocess.run(['bash', compiler_path, cool_file_path], capture_output=True, timeout=timeout) + return_code, output = sp.returncode, sp.stdout.decode() + except subprocess.TimeoutExpired: + assert False, COMPILER_TIMEOUT + + assert return_code == 1, TEST_MUST_FAIL % get_file_name(cool_file_path) + + fd = open(error_file_path, 'r') + errors = fd.read().split('\n') + fd.close() + + # checking the errors of compiler + compiler_output = output.split('\n') + cmp(compiler_output[2:], errors) + +SPIM_HEADER = r'''^SPIM Version .+ of .+ +Copyright .+\, James R\. Larus\. +All Rights Reserved\. +See the file README for a full copyright notice\. +(?:Loaded: .+\n)*''' +def compare_outputs(compiler_path: str, cool_file_path: str, input_file_path: str, output_file_path: str, timeout=100): + try: + sp = subprocess.run(['bash', compiler_path, cool_file_path], capture_output=True, timeout=timeout) + assert sp.returncode == 0, TEST_MUST_COMPILE % get_file_name(cool_file_path) + except subprocess.TimeoutExpired: + assert False, COMPILER_TIMEOUT + + spim_file = cool_file_path[:-2] + 'mips' + + try: + fd = open(input_file_path, 'rb') + sp = subprocess.run(['spim', '-file', spim_file], input=fd.read(), capture_output=True, timeout=timeout) + fd.close() + mo = re.match(SPIM_HEADER, sp.stdout.decode()) + if mo: + output = mo.string[mo.end():] + except subprocess.TimeoutExpired: + assert False, SPIM_TIMEOUT + + fd = open(output_file_path, 'r') + eoutput = fd.read() + fd.close() + + assert output == eoutput, UNEXPECTED_OUTPUT % (spim_file, repr(output), repr(eoutput)) diff --git a/src/utils/COOL_Grammar.py b/src/utils/COOL_Grammar.py index 5790cabbe..2fe488dcb 100644 --- a/src/utils/COOL_Grammar.py +++ b/src/utils/COOL_Grammar.py @@ -28,17 +28,17 @@ def build_COOL_Grammar(): class_list %= def_class + semi, lambda h,s: [s[1]] class_list %= def_class + semi + class_list, lambda h,s: [s[1]] + s[3] - def_class %= classx + typex + ocur + feature_list + ccur, lambda h,s: node.ClassDeclarationNode(s[2],s[4]) - def_class %= classx + typex + inherits + typex + ocur + feature_list + ccur, lambda h,s: node.ClassDeclarationNode(s[2],s[6],s[4]) + def_class %= classx + typex + ocur + feature_list + ccur, lambda h,s: node.ClassDeclarationNode(s[2],s[4],s[1]) + def_class %= classx + typex + inherits + typex + ocur + feature_list + ccur, lambda h,s: node.ClassDeclarationNode(s[2],s[6],s[1],s[4]) feature_list %= def_attr + semi + feature_list, lambda h,s: [s[1]] + s[3] feature_list %= def_meth + semi + feature_list, lambda h,s: [s[1]] + s[3] feature_list %= G.Epsilon, lambda h,s: [] def_attr %= idx + colon + typex, lambda h,s: node.AttrDeclarationNode(s[1],s[3]) - def_attr %= idx + colon + typex + arrow + expr, lambda h,s: node.AttrDeclarationNode(s[1],s[3],s[5]) + def_attr %= idx + colon + typex + arrow + expr, lambda h,s: node.AttrDeclarationNode(s[1],s[3],s[4],s[5]) - def_meth %= idx + opar + param_list + cpar + colon + typex + ocur + expr + ccur, lambda h,s: node.MethDeclarationNode(s[1],s[3],s[6],s[8]) + def_meth %= idx + opar + param_list + cpar + colon + typex + ocur + expr + ccur, lambda h,s: node.MethDeclarationNode(s[1],s[3],s[6],s[8],s[7]) param_list %= param, lambda h,s: [s[1]] param_list %= param + comma + param_list, lambda h,s: [s[1]] + s[3] @@ -84,7 +84,7 @@ def build_COOL_Grammar(): term %= factor, lambda h,s: s[1] factor %= isvoid + factor, lambda h,s: node.IsVoidNode(s[2]) - factor %= tilde + factor, lambda h,s: node.ComplementNode(s[2]) + factor %= tilde + factor, lambda h,s: node.ComplementNode(s[2], s[1]) factor %= atom, lambda h,s: s[1] atom %= true, lambda h,s: node.ConstantBoolNode(s[1]) diff --git a/src/utils/COOL_Lexer.py b/src/utils/COOL_Lexer.py index a3e733f40..dc241493d 100644 --- a/src/utils/COOL_Lexer.py +++ b/src/utils/COOL_Lexer.py @@ -12,6 +12,7 @@ def __init__(self, lex, ttype, line, column): self.token_type = ttype self.line = line self.column = column + self.next_token = None def __str__(self): return f'({self.line}, {self.column}) - {self.token_type}: {self.lex}' @@ -135,7 +136,7 @@ def tokenize(self,text): token_type = match.lastgroup if lexeme.lower() not in self.keywords and match.lastgroup is not None else match.group().lower() - yield lexeme, token_type, self.line, self.column - len(lexeme) + 1 if lexeme[:2] != '(*' and lexeme[0] != '"' else self.column + yield lexeme, token_type, self.line, self.column - len(lexeme) + 1 text = text[match.end():] if lexeme[:2] != '(*' and lexeme[0] != '"' else text @@ -148,10 +149,8 @@ def __call__(self, text): return [Token(lex, ttype, line, column) for lex, ttype, line, column in self.tokenize(text) if ttype not in self.ignored_tokens] def fixed_tokens(self, tokens): - for i, token in enumerate(tokens): - if token.lex in self.tokens_toFix: - token.line = tokens[i + 1].line - token.column = tokens[i + 1].column + for i, token in enumerate(tokens[:(len(tokens) - 1)]): + token.next_token = tokens[i+1] return tokens @@ -216,6 +215,6 @@ def __init__(self): self.ignored_tokens = ['newline','whitespace','tabulation','comment'] self.tokens_toFix = ['inherits','isvoid','class','while','then','else','loop','case', - 'let','new','not','if','in','of'] + 'let','new','not','if','in','of', '<-'] Lexer.__init__(self, self.regexs, self.keywords, self.ignored_tokens, self.tokens_toFix, 'eof') \ No newline at end of file diff --git a/src/utils/ast/AST_Nodes.py b/src/utils/ast/AST_Nodes.py index c31d90ed2..41f76e6a3 100644 --- a/src/utils/ast/AST_Nodes.py +++ b/src/utils/ast/AST_Nodes.py @@ -19,27 +19,32 @@ class ExpressionNode(Node): class ClassDeclarationNode(DeclarationNode): - def __init__(self, token, features, parent=None): - self.id = token.lex - self.line = token.line - self.column = token.column + def __init__(self, idx, features, token, parent=None): + self.id = idx.lex + self.line = idx.line + self.column = idx.column + self.classt_line = token.line + self.classt_column = token.column + 4 self.parent = parent.lex if parent else parent + self.parent_column = parent.column if parent else None self.features = features class MethDeclarationNode(DeclarationNode): - def __init__(self, token, params, return_type, body): - self.id = token.lex - self.line = token.line - self.column = token.column + def __init__(self, idx, params, return_type, body, ocurToken): + self.id = idx.lex + self.line = idx.line + self.column = idx.column + self.body_line = ocurToken.next_token.line + self.body_column = ocurToken.next_token.column self.params = [[item.lex if isinstance(item, Token) else item for item in _list] for _list in params] self.type = return_type.lex self.body = body class AttrDeclarationNode(DeclarationNode): - def __init__(self, token, typex, expr = None): - self.id = token.lex - self.line = expr.line if expr else token.line - self.column = expr.column if expr else token.column + def __init__(self, idx, typex, arrowToken = None, expr = None): + self.id = idx.lex + self.line = arrowToken.next_token.line if expr else typex.line + self.column = arrowToken.next_token.column if expr else typex.column self.type = typex.lex self.expr = expr @@ -64,8 +69,8 @@ def __init__(self, if_expr, then_expr, else_expr,token): self.if_expr = if_expr self.then_expr = then_expr self.else_expr = else_expr - self.line = token.line - self.column = token.column + self.line = token.next_token.line + self.column = token.next_token.column class WhileNode(ExpressionNode): def __init__(self, conditional_expr, loop_expr, token): @@ -90,21 +95,26 @@ def __init__(self, identifiers, in_expr, token): class CaseNode(ExpressionNode): def __init__(self, predicate, branches, token): self.predicate = predicate - self.branches = [tuple([item.lex if isinstance(item, Token) else item for item in _list]) for _list in branches] + self.branches = [] + self.branchesPos = [] + for branch in branches: + self.branches.append(tuple([item.lex if isinstance(item, Token) else item for item in branch])) + _,typex,_ = branch + self.branchesPos.append((typex.line,typex.column)) self.line = token.line self.column = token.column class NotNode(ExpressionNode): def __init__(self, expr, token): self.expr = expr - self.line = token.line + 4 - self.column = token.column + 4 + self.line = token.next_token.line + self.column = token.next_token.column class AtomicNode(ExpressionNode): - def __init__(self, token): - self.lex = token.lex if isinstance(token, Token) else token - self.line = token.line - self.column = token.column + def __init__(self, expr): + self.lex = expr.lex if isinstance(expr, Token) else expr + self.line = expr.line + self.column = expr.column class BinaryNode(ExpressionNode): def __init__(self, left, right, token): @@ -125,12 +135,15 @@ class VariableNode(AtomicNode): class InstantiateNode(AtomicNode): def __init__(self, typex, token): self.lex = typex.lex - self.line = token.line + 4 - self.column = token.column + 4 + self.line = token.next_token.line + self.column = token.next_token.column class IsVoidNode(AtomicNode): pass class ComplementNode(AtomicNode): - pass + def __init__(self, expr, token): + self.lex = expr.lex if isinstance(expr, Token) else expr + self.line = token.next_token.line + self.column = token.next_token.column class PlusNode(BinaryNode): diff --git a/src/utils/print_code.py b/src/utils/print_code.py new file mode 100644 index 000000000..1ff4ac195 --- /dev/null +++ b/src/utils/print_code.py @@ -0,0 +1,153 @@ +import cmp.visitor as visitor +from utils.ast.AST_Nodes import ast_nodes as nodes + +class PrintCode: + @visitor.on('node') + def visit(self, node, tabs = 0): + pass + + @visitor.when(nodes.ProgramNode) + def visit(self, node, tabs = 0): + return '\n'.join(self.visit(dec, tabs) for dec in node.declarations) + + + @visitor.when(nodes.ClassDeclarationNode) + def visit(self, node, tabs = 0): + parent = '' if node.parent is None else f'inherits {node.parent}' + ans = '\t' * tabs + f'class {node.id} {parent}' + features = '\n'.join(self.visit(feat, tabs + 1) for feat in node.features) + return f'{ans} {{\n{features}\n}};' + + + @visitor.when(nodes.AttrDeclarationNode) + def visit(self, node, tabs = 0): + expr = '' if node.expr is None else f'<- {self.visit(node.expr)}' + return '\t' * tabs + f'{node.id}: {node.type} {expr};' + + + @visitor.when(nodes.MethDeclarationNode) + def visit(self, node, tabs = 0): + params = ', '.join(': '.join(param) for param in node.params) + ans = '\t' * tabs + f'{node.id} ({params}): {node.type}' + body = self.visit(node.body, tabs + 1) + return f'{ans} {{\n{body}\n' + '\t' * tabs + '};' + + + @visitor.when(nodes.AssignNode) + def visit(self, node, tabs = 0): + return '\t' * tabs + f'{node.id} <- {self.visit(node.expr)}' + + + @visitor.when(nodes.CallNode) + def visit(self, node, tabs = 0): + obj = '' if node.obj is None else f'{self.visit(node.obj)}' if node.type else f'{self.visit(node.obj)}.' + args = ', '.join(self.visit(arg) for arg in node.args) + typex = '' if node.type is None else f'@ {node.type}' + return '\t' * tabs + f'{obj}{typex}{node.id} ({args})' + + + @visitor.when(nodes.IfThenElseNode) + def visit(self, node, tabs = 0): + ifx = self.visit(node.if_expr) + then = self.visit(node.then_expr, tabs + 1) + elsex = self.visit(node.else_expr, tabs + 1) + + return '\t' * tabs + f'if {ifx}\n' + '\t' * tabs + f'then\n{then}\n' + '\t' * tabs + f'else\n{elsex}\n' + '\t' * tabs + 'fi' + + + @visitor.when(nodes.WhileNode) + def visit(self, node, tabs = 0): + ans = f'while {self.visit(node.conditional_expr)} loop' + body = self.visit(node.loop_expr, tabs + 1) + + return '\t' * tabs + f'{ans}\n{body}\n' + '\t' * tabs + 'pool' + + + @visitor.when(nodes.BlockNode) + def visit(self, node, tabs = 0): + expr_list = ';\n'.join(self.visit(expr, tabs + 1) for expr in node.expr_list) + return '\t' * tabs + f'{{\n{expr_list};\n' + '\t' * tabs + '}' + + + @visitor.when(nodes.LetNode) + def visit(self, node, tabs = 0): + identifiers = [] + for idx, typex, id_expr in node.identifiers: + if id_expr: + identifiers.append(f'{idx}: {typex} <- {self.visit(id_expr)}') + else: + identifiers.append(f'{idx}: {typex}') + + identifiers = (',\n' + '\t' * (tabs + 1)).join(identifiers) + return '\t' * tabs + f'let {identifiers} in\n{self.visit(node.in_expr, tabs + 1)}' + + + @visitor.when(nodes.CaseNode) + def visit(self, node, tabs = 0): + predicate = self.visit(node.predicate) + branches = '\n'.join(f'\t' * (tabs + 1) + f'{idx}: {typex} =>\n{self.visit(expr, tabs + 2)};' for idx, typex, expr in node.branches) + + return '\t' * tabs + f'case {predicate} of \n{branches}\n' + '\t' * tabs + 'esac' + + @visitor.when(nodes.NotNode) + def visit(self, node, tabs = 0): + return '\t' * tabs + f'not {self.visit(node.expr)}' + + + @visitor.when(nodes.ConstantNumNode) + def visit(self, node, tabs = 0): + return '\t' * tabs + f'{node.lex}' + + @visitor.when(nodes.ConstantBoolNode) + def visit(self, node, tabs = 0): + return '\t' * tabs + f'{node.lex}' + + @visitor.when(nodes.ConstantStringNode) + def visit(self, node, tabs = 0): + return '\t' * tabs + f'{node.lex}' + + @visitor.when(nodes.VariableNode) + def visit(self, node, tabs = 0): + return '\t' * tabs + f'{node.lex}' + + + @visitor.when(nodes.InstantiateNode) + def visit(self, node, tabs = 0): + return '\t' * tabs + f'(new {node.lex})' + + @visitor.when(nodes.IsVoidNode) + def visit(self, node, tabs = 0): + return '\t' * tabs + f'isvoid {self.visit(node.lex)}' + + @visitor.when(nodes.ComplementNode) + def visit(self, node, tabs = 0): + return '\t' * tabs + f'~ {self.visit(node.lex)}' + + + @visitor.when(nodes.PlusNode) + def visit(self, node, tabs = 0): + return '\t' * tabs + f'{self.visit(node.left)} + {self.visit(node.right)}' + + @visitor.when(nodes.MinusNode) + def visit(self, node, tabs = 0): + return '\t' * tabs + f'{self.visit(node.left)} - {self.visit(node.right)}' + + @visitor.when(nodes.StarNode) + def visit(self, node, tabs = 0): + return '\t' * tabs + f'{self.visit(node.left)} * {self.visit(node.right)}' + + @visitor.when(nodes.DivNode) + def visit(self, node, tabs = 0): + return '\t' * tabs + f'{self.visit(node.left)} / {self.visit(node.right)}' + + @visitor.when(nodes.LessThanNode) + def visit(self, node, tabs = 0): + return '\t' * tabs + f'{self.visit(node.left)} < {self.visit(node.right)}' + + @visitor.when(nodes.LessEqualNode) + def visit(self, node, tabs = 0): + return '\t' * tabs + f'{self.visit(node.left)} <= {self.visit(node.right)}' + + @visitor.when(nodes.EqualNode) + def visit(self, node, tabs = 0): + return '\t' * tabs + f'{self.visit(node.left)} = {self.visit(node.right)}' \ No newline at end of file diff --git a/src/utils/semantic_check/type_builder.py b/src/utils/semantic_check/type_builder.py index f6af1804e..556c12060 100644 --- a/src/utils/semantic_check/type_builder.py +++ b/src/utils/semantic_check/type_builder.py @@ -2,7 +2,7 @@ from utils.ast.AST_Nodes import ast_nodes as nodes from cmp.semantic import SemanticError, ErrorType -NOT_INHERIT_FROM_BASICS_TYPES = '(%s, %s) - TypeError: Type %s cannot inherit from basic type %s' +NOT_INHERIT_FROM_BASICS_TYPES = '(%s, %s) - SemanticError: Class %s cannot inherit class %s. ' class TypeBuilder: @@ -28,8 +28,8 @@ def visit(self,node): if node.parent is not None: - if node.parent in ['Int', 'String', 'SELF_TYPE', 'Bool']: - self.errors.append(NOT_INHERIT_FROM_BASICS_TYPES % (node.line, node.column, node.id, node.parent)) + if node.parent in ['Int', 'String', 'SELF_TYPE', 'Bool', 'Object']: + self.errors.append(NOT_INHERIT_FROM_BASICS_TYPES % (node.line, node.parent_column, node.id, node.parent)) else: try: diff --git a/src/utils/semantic_check/type_checker.py b/src/utils/semantic_check/type_checker.py index b63740c0a..b910b92cc 100644 --- a/src/utils/semantic_check/type_checker.py +++ b/src/utils/semantic_check/type_checker.py @@ -15,6 +15,7 @@ INCOMPATIBLE_TYPES_ATTR = '(%s, %s) - TypeError: Inferred type %s of initialization of attribute %s does not conform to declared type %s.' INCOMPATIBLE_TYPES_ARG = '(%s, %s) - TypeError: Argument of \'%s\' has type %s instead of %s.' INCOMPATIBLE_TYPES_METH = '(%s, %s) - TypeError: Inferred return type %s of method %s does not conform to declared return type %s.' +INCOMPATIBLE_TYPES_IF = '(%s, %s) - TypeError: Predicate of \'%s\' does not have type %s.' INCOMPATIBLE_TYPES = '(%s, %s) - TypeError: Cannot convert %s into %s.' WRONG_SIGNATURE = '(%s, %s) - TypeError: Method %s already defined in %s with a different signature.' LOCAL_ALREADY_DEFINED = '(%s, %s) - TypeError: Variable %s is already defined in method %s.' @@ -23,6 +24,9 @@ INHERIT_ERROR = '(%s, %s) - TypeError: Class %s cannot inherit from class %s because they form a cycle.' METHOD_PARAMETERS = '(%s, %s) - TypeError: Method %s defined in %s receive %d parameters' +DUPLICATE_BRANCH = '(%s, %s) - SemanticError: Duplicate branch %s in case statement.' +UNDEFINED_TYPE_BRANCH = '(%s, %s) - TypeError: Class %s of case branch is undefined.' + class TypeChecker: @@ -77,7 +81,7 @@ def visit(self, node, scope): self.errors.append(INHERIT_ERROR % (node.line, node.column, self.current_type.name, self.current_type.parent.name)) self.current_type.parent = ErrorType() break - + for attr in current_parent.attributes: scope.define_variable(attr.name, attr.type) @@ -225,7 +229,7 @@ def visit(self, node, scope): if_type = self.visit(node.if_expr, scope.create_child()) if not if_type.conforms_to(self.context.get_type('Bool')): - self.errors.append(INCOMPATIBLE_TYPES % (node.line, node.column, if_type.name, 'Bool')) + self.errors.append(INCOMPATIBLE_TYPES_IF % (node.line, node.column,'if','Bool')) then_type = self.visit(node.then_expr, scope.create_child()) else_type = self.visit(node.else_expr, scope.create_child()) @@ -284,9 +288,13 @@ def visit(self, node, scope): self.visit(node.predicate, scope) case_type = None - for idx, typex, expr in node.branches: + for i,branch in enumerate(node.branches): + (idx, typex, expr) = branch + (line,column) = node.branchesPos[i] + if typex in [b[1] for b in node.branches[:i]]: + self.errors.append(DUPLICATE_BRANCH % (line, column, typex)) if typex == 'SELF_TYPE': - self.errors.append(SELF_TYPE_IN_CASE_BRANCH % (node.line, node.column)) + self.errors.append(SELF_TYPE_IN_CASE_BRANCH % (line, column)) id_type = ErrorType() else: @@ -294,7 +302,7 @@ def visit(self, node, scope): id_type = self.context.get_type(typex) except SemanticError as se: id_type = ErrorType() - self.errors.append(se.text) + self.errors.append(UNDEFINED_TYPE_BRANCH % (line, column, typex)) inner_scope = scope.create_child() inner_scope.define_variable(idx, id_type) diff --git a/src/utils/semantic_check/type_collector.py b/src/utils/semantic_check/type_collector.py index 1a5b4f828..dc160530f 100644 --- a/src/utils/semantic_check/type_collector.py +++ b/src/utils/semantic_check/type_collector.py @@ -2,6 +2,9 @@ from utils.ast.AST_Nodes import ast_nodes as nodes from cmp.semantic import SemanticError +NOT_REDEFINE_BASIC_TYPES = '(%s, %s) - SemanticError: Redefinition of basic class %s.' +NOT_REDEFINE_CLASSES = '(%s, %s) - SemanticError: Classes may not be redefined' + class TypeCollector(object): def __init__(self, context, errors): self.context = context @@ -50,7 +53,10 @@ def visit(self, node): @visitor.when(nodes.ClassDeclarationNode) def visit(self,node): try: + if node.id in ["Object", "Int", "String", "Bool", "IO"]: + self.errors.append(NOT_REDEFINE_BASIC_TYPES % (node.line, node.column, node.id)) + node.id = 'error_type' self.context.create_type(node.id) except SemanticError as se: - self.errors.append(se.text) + self.errors.append(NOT_REDEFINE_CLASSES % (node.classt_line, node.classt_column)) return \ No newline at end of file diff --git a/src/utils/semantic_check/type_inference.py b/src/utils/semantic_check/type_inference.py new file mode 100644 index 000000000..cf23de1d5 --- /dev/null +++ b/src/utils/semantic_check/type_inference.py @@ -0,0 +1,376 @@ +import cmp.visitor as visitor +from utils.ast.AST_Nodes import ast_nodes as nodes +from cmp.semantic import SemanticError, ErrorType, Scope, VariableInfo + +INFERENCE_ATTR_ERROR = 'Cannot infer type for attribute "%s" in class "%s".' +INFERENCE_METH_ERROR = 'Cannot infer return type for method "%s" in class "%s".' +INFERENCE_PARAMETER_ERROR = 'Cannot infer type for parameter "%s" of method "%s" in class "%s".' +INFERENCE_VARIABLE_ERROR = 'Cannot infer type for variable "%s" of method "%s" in class "%s".' + +class TypeInference: + def __init__(self, context, errors = []): + self.context = context + self.current_type = None + self.current_method = None + self.errors = errors + self.update = True + + + @visitor.on('node') + def visit(self, node, scope): + pass + + + @visitor.when(nodes.ProgramNode) + def visit(self, node, scope=None): + for i,dec in enumerate(node.declarations): + self.visit(dec, scope.children[i]) + + return scope + + + @visitor.when(nodes.ClassDeclarationNode) + def visit(self, node, scope): + self.current_type = self.context.get_type(node.id) + + attrs = [feat for feat in node.features if isinstance(feat, nodes.AttrDeclarationNode)] + i = 0 + for attr in attrs: + if attr.expr is not None: + attr.index = i + i += 1 + self.visit(attr, scope) + + meths = [feat for feat in node.features if isinstance(feat, nodes.MethDeclarationNode)] + for meth in meths: + self.visit(meth, scope.children[i]) + i+=1 + + for attr in attrs: + var = scope.find_variable(attr.id) + if var.type.name == 'AUTO_TYPE': + var.update_type() + if var.type.name == 'AUTO_TYPE': + self.errors.append(INFERENCE_ATTR_ERROR % (attr.id, self.current_type.name)) + else: + self.update = True + self.current_type.get_attribute(attr.id).type = var.type + attr.type = var.type.name + + return + + + @visitor.when(nodes.AttrDeclarationNode) + def visit(self, node, scope): + + if node.expr is not None: + attr = self.current_type.get_attribute(node.id) + var = scope.find_variable(node.id) + + type_expr = self.visit(node.expr, scope.children[node.index], attr.type) + + # se infiere el tipo a partir de su expresion de inicializacion + if type_expr.name != 'AUTO_TYPE': + var.expected_types.append(type_expr) + return + + @visitor.when(nodes.MethDeclarationNode) + def visit(self, node, scope): + self.current_method = self.current_type.get_method(node.id) + + return_type = self.current_method.return_type + + # el tipo del body se espera que sea el tipo de return type + body_type = self.visit(node.body, scope, self.current_type if return_type.name == 'SELF_TYPE' else return_type if return_type.name != 'AUTO_TYPE' else None) + + for i, (name, typex) in enumerate(node.params): + var = scope.find_variable(name) + var.expected_types = var.expected_types + self.current_method.expected_param_types[name] if name in self.current_method.expected_param_types else var.expected_types + + if var.type.name == 'AUTO_TYPE': + var.update_type() + if var.type.name == 'AUTO_TYPE': + self.errors.append(INFERENCE_PARAMETER_ERROR % (self.current_method.param_names[i], self.current_method.name, self.current_type.name)) + else: + self.update = True + self.current_method.param_types[i] = var.type + node.params[i][1] = var.type.name + + var = VariableInfo(self.current_method.name, return_type) + + # se infiere el tipo de retorno a partir del tipo del cuerpo del metodo + if body_type.name != 'AUTO_TYPE': + var.expected_types.append(body_type) + + var.expected_types = var.expected_types + [self.current_method.expected_return_type] if self.current_method.expected_return_type else var.expected_types + + if var.type.name == 'AUTO_TYPE': + var.update_type() + if var.type.name == 'AUTO_TYPE': + self.errors.append(INFERENCE_METH_ERROR % (self.current_method.name, self.current_type.name)) + else: + self.update = True + self.current_method.return_type = var.type + node.type = var.type.name + + self.current_method.expected_param_types = {} + self.current_method.expected_return_type = None + return + + + @visitor.when(nodes.AssignNode) + def visit(self, node, scope, expected_type = None): + var = scope.find_variable(node.id) if scope.is_defined(node.id) else None + + # el tipo de la expresion se inifere a partir del tipo esperado de la asignacion + type_expr = self.visit(node.expr, scope.children[0], var.type if var and var.type.name != 'AUTO_TYPE' else expected_type) + + # se infiere el tipo de la variable a partir de la expresion de asignacion + if type_expr.name != 'AUTO_TYPE': + var.expected_types.append(type_expr) + + return type_expr + + + @visitor.when(nodes.CallNode) + def visit(self, node, scope, expected_type = None): + typex = None + if node.type is not None: + try: + typex = self.context.get_type(node.type) + except SemanticError: + typex = ErrorType() + else: + if typex.name == 'SELF_TYPE' or typex.name == 'AUTO_TYPE': + typex = ErrorType() + + if node.obj is None: + type_obj = self.current_type + else: + type_obj = self.visit(node.obj, scope, typex) + + type_obj = type_obj if not typex else typex + + try: + meth = type_obj.get_method(node.id) + except SemanticError: + for arg in node.args: + self.visit(node.args, scope) + return ErrorType() + + for i, arg in enumerate(node.args): + type_arg = self.visit(arg, scope, meth.param_types[i] if i < len(meth.param_types) and meth.param_types[i].name != 'AUTO_TYPE' else None) + + # el tipo esperado de los parametros se infiere a partir del tipo de los argumentos + if i < len(meth.param_types) and type_arg.name != 'AUTO_TYPE': + try: + meth.expected_param_types[meth.param_names[i]].append(type_arg) + except KeyError: + meth.expected_param_types[meth.param_names[i]] = [type_arg] + + # el tipo de retorno del metodo llamado se infiere a partir del tipo esperado del llamado + meth.expected_return_type = expected_type if expected_type and expected_type.name != 'AUTO_TYPE' else meth.expected_return_type + + return meth.return_type if meth.return_type.name != 'SELF_TYPE' else type_obj + + + @visitor.when(nodes.IfThenElseNode) + def visit(self, node, scope, expected_type = None): + # se espera que el tipo de la expresion if sea Bool + if_type = self.visit(node.if_expr, scope.children[0], self.context.get_type('Bool')) + + then_type = self.visit(node.then_expr, scope.children[1]) + else_type = self.visit(node.else_expr, scope.children[2]) + + return then_type.join(else_type) + + + @visitor.when(nodes.WhileNode) + def visit(self, node, scope, expected_type = None): + + # la condicion del while debe ser de tipo Bool + self.visit(node.conditional_expr, scope, self.context.get_type('Bool')) + + self.visit(node.loop_expr, scope.children[0]) + + return self.context.get_type('Object') + + + @visitor.when(nodes.BlockNode) + def visit(self, node, scope, expected_type = None): + type_expr = ErrorType() + for i, expr in enumerate(node.expr_list): + # el tipo de la expresion se inifiere a partir de expected_type + type_expr = self.visit(expr, scope.children[i]) if i != len(node.expr_list) - 1 else self.visit(expr, scope.children[i], expected_type) + + return type_expr + + + @visitor.when(nodes.LetNode) + def visit(self, node, scope, expected_type = None): + # se inifiere l tipo a partir de expected_type + body_type = self.visit(node.in_expr, scope.children[-1], expected_type) + + child_scope_index = 0 + for i, (idx, typex, id_expr) in enumerate(node.identifiers): + if id_expr: + var = scope.find_variable(idx) + id_expr_type = self.visit(id_expr, scope.children[child_scope_index], var.type if var.type.name != 'AUTO_TYPE' else None) + child_scope_index += 1 + + # se inifere el tipo de un identificador a partir de su expresion de inicializacion + if id_expr_type.name != 'AUTO_TYPE': + var.expected_types.append(id_expr_type) + + + for i, (idx, typex, id_expr) in enumerate(node.identifiers): + var = scope.find_variable(idx) + if var.type.name == 'AUTO_TYPE': + var.update_type() + if var.type.name == 'AUTO_TYPE': + self.errors.append(INFERENCE_VARIABLE_ERROR % (var.name, self.current_method.name, self.current_type.name)) + else: + self.update = True + node.identifiers[i] = (idx, var.type.name, id_expr) + + + return body_type + + + @visitor.when(nodes.CaseNode) + def visit(self, node, scope, expected_type = None): + case_type = None + + for i, (idx, typex, expr) in enumerate(node.branches): + type_expr = self.visit(expr, scope.children[i]) + + case_type = case_type.join(type_expr) if case_type else type_expr + + return case_type + + + @visitor.when(nodes.NotNode) + def visit(self, node, scope, expected_type = None): + # se el tipo de la expresion de not se infiere que sea Bool + self.visit(node.expr, scope, self.context.get_type('Bool')) + + return self.context.get_type('Bool') + + + @visitor.when(nodes.ConstantNumNode) + def visit(self, node, scope, expected_type = None): + return self.context.get_type('Int') + + + @visitor.when(nodes.ConstantBoolNode) + def visit(self, node, scope, expected_type = None): + return self.context.get_type('Bool') + + + @visitor.when(nodes.ConstantStringNode) + def visit(self, node, scope, expected_type = None): + return self.context.get_type('String') + + + @visitor.when(nodes.VariableNode) + def visit(self, node, scope, expected_type = None): + var = scope.find_variable(node.lex) + + if var is not None: + # el tipo esperado de var es expected_type + if expected_type and expected_type != 'AUTO_TYPE': + var.expected_types.append(expected_type) + return var.type + + return ErrorType() + + + @visitor.when(nodes.InstantiateNode) + def visit(self, node, scope, expected_type = None): + if node.lex in self.context.types: + return self.context.get_type(node.lex) + + return ErrorType() + + + @visitor.when(nodes.IsVoidNode) + def visit(self, node, scope, expected_type = None): + self.visit(node.lex, scope) + + return self.context.get_type('Bool') + + + @visitor.when(nodes.ComplementNode) + def visit(self, node, scope, expected_type = None): + # el tipo de la expression se espera que sea Int + self.visit(node.lex, scope, self.context.get_type('Int')) + + return self.context.get_type('Int') + + + @visitor.when(nodes.PlusNode) + def visit(self, node, scope, expected_type = None): + # el tipo de la expresiones se espera que sea Int + self.visit(node.left, scope, self.context.get_type('Int')) + self.visit(node.right, scope, self.context.get_type('Int')) + + return self.context.get_type('Int') + + + @visitor.when(nodes.MinusNode) + def visit(self, node, scope, expected_type = None): + # el tipo de la expresiones se espera que sea Int + self.visit(node.left, scope, self.context.get_type('Int')) + self.visit(node.right, scope, self.context.get_type('Int')) + + return self.context.get_type('Int') + + + @visitor.when(nodes.StarNode) + def visit(self, node, scope, expected_type = None): + # el tipo de la expresiones se espera que sea Int + self.visit(node.left, scope, self.context.get_type('Int')) + self.visit(node.right, scope, self.context.get_type('Int')) + + return self.context.get_type('Int') + + + @visitor.when(nodes.DivNode) + def visit(self, node, scope, expected_type = None): + # el tipo de la expresiones se espera que sea Int + self.visit(node.left, scope, self.context.get_type('Int')) + self.visit(node.right, scope, self.context.get_type('Int')) + + return self.context.get_type('Int') + + + @visitor.when(nodes.LessThanNode) + def visit(self, node, scope, expected_type = None): + # el tipo de la expresiones se espera que sea Int + self.visit(node.left, scope, self.context.get_type('Int')) + self.visit(node.right, scope, self.context.get_type('Int')) + + return self.context.get_type('Bool') + + + @visitor.when(nodes.LessEqualNode) + def visit(self, node, scope, expected_type = None): + # el tipo de la expresiones se espera que sea Int + self.visit(node.left, scope, self.context.get_type('Int')) + self.visit(node.right, scope, self.context.get_type('Int')) + + return self.context.get_type('Bool') + + + + @visitor.when(nodes.EqualNode) + def visit(self, node, scope, expected_type = None): + type_left = self.visit(node.left, scope) + # se infiere el tipo a la derecha del igual a partir del tipo izquierdo + type_right = self.visit(node.right, scope, type_left if type_left.name != 'AUTO_TYPE' else None) + + if type_left.name == 'AUTO_TYPE': + # se inifiere el tipo a la izquierda del igual a partir de su tipo derecho + self.visit(node.left, scope, type_right if type_right.name != 'AUTO_TYPE' else None) + + return self.context.get_type('Bool') \ No newline at end of file From 44538fb7772ecc3fb2b8e2135a53964acbca0f71 Mon Sep 17 00:00:00 2001 From: Ale Date: Tue, 15 Feb 2022 13:30:20 -0800 Subject: [PATCH 24/83] update main --- src/main.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/main.py b/src/main.py index 7b8464413..6f77af4ee 100644 --- a/src/main.py +++ b/src/main.py @@ -7,9 +7,7 @@ from cmp.semantic import Context from utils.semantic_check.type_collector import TypeCollector from utils.semantic_check.type_builder import TypeBuilder -from utils.semantic_check.type_checker import TypeChecker - -a = 'arithmetic1.cl' +from utils.semantic_check.type_checker import TypeChecker def main(args): @@ -38,7 +36,7 @@ def main(args): if parser.error: print(parser.error) - exit(1) + raise Exception() # ast ast = evaluate_reverse_parse(G, derivation, operations, lexer.fixed_tokens(tokens)) @@ -58,14 +56,14 @@ def main(args): if semantic_errors: for error in semantic_errors: print(error) - exit(1) + raise Exception() -# if __name__ == "__main__": +if __name__ == "__main__": -# parser = argparse.ArgumentParser(description='description') -# parser.add_argument('-f', '--file', type=str, default='', help='file to read') + parser = argparse.ArgumentParser(description='description') + parser.add_argument('-f', '--file', type=str, default='', help='file to read') -# args = parser.parse_args() -# main(args) + args = parser.parse_args() + main(args) -main('dispatch1.cl') \ No newline at end of file +#main('dispatch1.cl') \ No newline at end of file From 2ff9e9211566e2262b960c33198737acf38cc746 Mon Sep 17 00:00:00 2001 From: Ale Date: Tue, 15 Feb 2022 13:51:36 -0800 Subject: [PATCH 25/83] instructions to run code --- src/coolc.sh | 9 +++++---- src/main.py | 33 +++++++++++++-------------------- 2 files changed, 18 insertions(+), 24 deletions(-) diff --git a/src/coolc.sh b/src/coolc.sh index 5d3764e5f..5a4697ff8 100755 --- a/src/coolc.sh +++ b/src/coolc.sh @@ -4,9 +4,10 @@ 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" # TODO: Recuerde cambiar estas +echo "Copyright (c) 2021: Alejandro Campos, Darian Dominguez" # TODO: líneas a los valores correctos + +FILE="main.py" # Llamar al compilador -echo "Compiling $INPUT_FILE into $OUTPUT_FILE" -python main.py -f $INPUT_FILE \ No newline at end of file +python ${FILE} $INPUT_FILE $OUTPUT_FILE diff --git a/src/main.py b/src/main.py index 6f77af4ee..f3dbe3c78 100644 --- a/src/main.py +++ b/src/main.py @@ -1,5 +1,7 @@ -import argparse +import argparse import os +import sys +from pathlib import Path from utils.COOL_Grammar import build_COOL_Grammar from utils.COOL_Lexer import COOL_Lexer from utils.parser.COOL_parser import COOL_Parser @@ -9,15 +11,16 @@ from utils.semantic_check.type_builder import TypeBuilder from utils.semantic_check.type_checker import TypeChecker -def main(args): +if __name__ == "__main__": + add = "lexer/comment1.cl" + + path: str = f"{Path.cwd()}/tests/{add}" if os.path.exists( + f"{Path.cwd()}/tests/{add}") else f"{Path.cwd()}/../tests/{add}" + + _in = sys.argv[1] if len(sys.argv) > 1 else path - try: - #with open(args.file, 'r') as file: - with open(os.getcwd() + '/tester/semantic/' + args, 'r') as file: - code = file.read() - except: - print(f"(0,0) - CompilerError: file {args.file} not found") - exit(1) + with open(_in) as file: + code = file.read() G = build_COOL_Grammar() @@ -56,14 +59,4 @@ def main(args): if semantic_errors: for error in semantic_errors: print(error) - raise Exception() - -if __name__ == "__main__": - - parser = argparse.ArgumentParser(description='description') - parser.add_argument('-f', '--file', type=str, default='', help='file to read') - - args = parser.parse_args() - main(args) - -#main('dispatch1.cl') \ No newline at end of file + raise Exception() \ No newline at end of file From 30572b8c3175def428ee5dea9d7210ba548b6cc6 Mon Sep 17 00:00:00 2001 From: Ale Date: Tue, 15 Feb 2022 13:55:45 -0800 Subject: [PATCH 26/83] updating code --- src/main.py | 1 - src/utils/COOL_Lexer.py | 1 - src/utils/semantic_check/type_inference.py | 376 --------------------- 3 files changed, 378 deletions(-) delete mode 100644 src/utils/semantic_check/type_inference.py diff --git a/src/main.py b/src/main.py index f3dbe3c78..ecf6ee5c4 100644 --- a/src/main.py +++ b/src/main.py @@ -1,4 +1,3 @@ -import argparse import os import sys from pathlib import Path diff --git a/src/utils/COOL_Lexer.py b/src/utils/COOL_Lexer.py index dc241493d..22aead8af 100644 --- a/src/utils/COOL_Lexer.py +++ b/src/utils/COOL_Lexer.py @@ -1,5 +1,4 @@ import re -import sys ''' Recibe como parametros el lexema, tipo, linea y columna donde se encuentra diff --git a/src/utils/semantic_check/type_inference.py b/src/utils/semantic_check/type_inference.py deleted file mode 100644 index cf23de1d5..000000000 --- a/src/utils/semantic_check/type_inference.py +++ /dev/null @@ -1,376 +0,0 @@ -import cmp.visitor as visitor -from utils.ast.AST_Nodes import ast_nodes as nodes -from cmp.semantic import SemanticError, ErrorType, Scope, VariableInfo - -INFERENCE_ATTR_ERROR = 'Cannot infer type for attribute "%s" in class "%s".' -INFERENCE_METH_ERROR = 'Cannot infer return type for method "%s" in class "%s".' -INFERENCE_PARAMETER_ERROR = 'Cannot infer type for parameter "%s" of method "%s" in class "%s".' -INFERENCE_VARIABLE_ERROR = 'Cannot infer type for variable "%s" of method "%s" in class "%s".' - -class TypeInference: - def __init__(self, context, errors = []): - self.context = context - self.current_type = None - self.current_method = None - self.errors = errors - self.update = True - - - @visitor.on('node') - def visit(self, node, scope): - pass - - - @visitor.when(nodes.ProgramNode) - def visit(self, node, scope=None): - for i,dec in enumerate(node.declarations): - self.visit(dec, scope.children[i]) - - return scope - - - @visitor.when(nodes.ClassDeclarationNode) - def visit(self, node, scope): - self.current_type = self.context.get_type(node.id) - - attrs = [feat for feat in node.features if isinstance(feat, nodes.AttrDeclarationNode)] - i = 0 - for attr in attrs: - if attr.expr is not None: - attr.index = i - i += 1 - self.visit(attr, scope) - - meths = [feat for feat in node.features if isinstance(feat, nodes.MethDeclarationNode)] - for meth in meths: - self.visit(meth, scope.children[i]) - i+=1 - - for attr in attrs: - var = scope.find_variable(attr.id) - if var.type.name == 'AUTO_TYPE': - var.update_type() - if var.type.name == 'AUTO_TYPE': - self.errors.append(INFERENCE_ATTR_ERROR % (attr.id, self.current_type.name)) - else: - self.update = True - self.current_type.get_attribute(attr.id).type = var.type - attr.type = var.type.name - - return - - - @visitor.when(nodes.AttrDeclarationNode) - def visit(self, node, scope): - - if node.expr is not None: - attr = self.current_type.get_attribute(node.id) - var = scope.find_variable(node.id) - - type_expr = self.visit(node.expr, scope.children[node.index], attr.type) - - # se infiere el tipo a partir de su expresion de inicializacion - if type_expr.name != 'AUTO_TYPE': - var.expected_types.append(type_expr) - return - - @visitor.when(nodes.MethDeclarationNode) - def visit(self, node, scope): - self.current_method = self.current_type.get_method(node.id) - - return_type = self.current_method.return_type - - # el tipo del body se espera que sea el tipo de return type - body_type = self.visit(node.body, scope, self.current_type if return_type.name == 'SELF_TYPE' else return_type if return_type.name != 'AUTO_TYPE' else None) - - for i, (name, typex) in enumerate(node.params): - var = scope.find_variable(name) - var.expected_types = var.expected_types + self.current_method.expected_param_types[name] if name in self.current_method.expected_param_types else var.expected_types - - if var.type.name == 'AUTO_TYPE': - var.update_type() - if var.type.name == 'AUTO_TYPE': - self.errors.append(INFERENCE_PARAMETER_ERROR % (self.current_method.param_names[i], self.current_method.name, self.current_type.name)) - else: - self.update = True - self.current_method.param_types[i] = var.type - node.params[i][1] = var.type.name - - var = VariableInfo(self.current_method.name, return_type) - - # se infiere el tipo de retorno a partir del tipo del cuerpo del metodo - if body_type.name != 'AUTO_TYPE': - var.expected_types.append(body_type) - - var.expected_types = var.expected_types + [self.current_method.expected_return_type] if self.current_method.expected_return_type else var.expected_types - - if var.type.name == 'AUTO_TYPE': - var.update_type() - if var.type.name == 'AUTO_TYPE': - self.errors.append(INFERENCE_METH_ERROR % (self.current_method.name, self.current_type.name)) - else: - self.update = True - self.current_method.return_type = var.type - node.type = var.type.name - - self.current_method.expected_param_types = {} - self.current_method.expected_return_type = None - return - - - @visitor.when(nodes.AssignNode) - def visit(self, node, scope, expected_type = None): - var = scope.find_variable(node.id) if scope.is_defined(node.id) else None - - # el tipo de la expresion se inifere a partir del tipo esperado de la asignacion - type_expr = self.visit(node.expr, scope.children[0], var.type if var and var.type.name != 'AUTO_TYPE' else expected_type) - - # se infiere el tipo de la variable a partir de la expresion de asignacion - if type_expr.name != 'AUTO_TYPE': - var.expected_types.append(type_expr) - - return type_expr - - - @visitor.when(nodes.CallNode) - def visit(self, node, scope, expected_type = None): - typex = None - if node.type is not None: - try: - typex = self.context.get_type(node.type) - except SemanticError: - typex = ErrorType() - else: - if typex.name == 'SELF_TYPE' or typex.name == 'AUTO_TYPE': - typex = ErrorType() - - if node.obj is None: - type_obj = self.current_type - else: - type_obj = self.visit(node.obj, scope, typex) - - type_obj = type_obj if not typex else typex - - try: - meth = type_obj.get_method(node.id) - except SemanticError: - for arg in node.args: - self.visit(node.args, scope) - return ErrorType() - - for i, arg in enumerate(node.args): - type_arg = self.visit(arg, scope, meth.param_types[i] if i < len(meth.param_types) and meth.param_types[i].name != 'AUTO_TYPE' else None) - - # el tipo esperado de los parametros se infiere a partir del tipo de los argumentos - if i < len(meth.param_types) and type_arg.name != 'AUTO_TYPE': - try: - meth.expected_param_types[meth.param_names[i]].append(type_arg) - except KeyError: - meth.expected_param_types[meth.param_names[i]] = [type_arg] - - # el tipo de retorno del metodo llamado se infiere a partir del tipo esperado del llamado - meth.expected_return_type = expected_type if expected_type and expected_type.name != 'AUTO_TYPE' else meth.expected_return_type - - return meth.return_type if meth.return_type.name != 'SELF_TYPE' else type_obj - - - @visitor.when(nodes.IfThenElseNode) - def visit(self, node, scope, expected_type = None): - # se espera que el tipo de la expresion if sea Bool - if_type = self.visit(node.if_expr, scope.children[0], self.context.get_type('Bool')) - - then_type = self.visit(node.then_expr, scope.children[1]) - else_type = self.visit(node.else_expr, scope.children[2]) - - return then_type.join(else_type) - - - @visitor.when(nodes.WhileNode) - def visit(self, node, scope, expected_type = None): - - # la condicion del while debe ser de tipo Bool - self.visit(node.conditional_expr, scope, self.context.get_type('Bool')) - - self.visit(node.loop_expr, scope.children[0]) - - return self.context.get_type('Object') - - - @visitor.when(nodes.BlockNode) - def visit(self, node, scope, expected_type = None): - type_expr = ErrorType() - for i, expr in enumerate(node.expr_list): - # el tipo de la expresion se inifiere a partir de expected_type - type_expr = self.visit(expr, scope.children[i]) if i != len(node.expr_list) - 1 else self.visit(expr, scope.children[i], expected_type) - - return type_expr - - - @visitor.when(nodes.LetNode) - def visit(self, node, scope, expected_type = None): - # se inifiere l tipo a partir de expected_type - body_type = self.visit(node.in_expr, scope.children[-1], expected_type) - - child_scope_index = 0 - for i, (idx, typex, id_expr) in enumerate(node.identifiers): - if id_expr: - var = scope.find_variable(idx) - id_expr_type = self.visit(id_expr, scope.children[child_scope_index], var.type if var.type.name != 'AUTO_TYPE' else None) - child_scope_index += 1 - - # se inifere el tipo de un identificador a partir de su expresion de inicializacion - if id_expr_type.name != 'AUTO_TYPE': - var.expected_types.append(id_expr_type) - - - for i, (idx, typex, id_expr) in enumerate(node.identifiers): - var = scope.find_variable(idx) - if var.type.name == 'AUTO_TYPE': - var.update_type() - if var.type.name == 'AUTO_TYPE': - self.errors.append(INFERENCE_VARIABLE_ERROR % (var.name, self.current_method.name, self.current_type.name)) - else: - self.update = True - node.identifiers[i] = (idx, var.type.name, id_expr) - - - return body_type - - - @visitor.when(nodes.CaseNode) - def visit(self, node, scope, expected_type = None): - case_type = None - - for i, (idx, typex, expr) in enumerate(node.branches): - type_expr = self.visit(expr, scope.children[i]) - - case_type = case_type.join(type_expr) if case_type else type_expr - - return case_type - - - @visitor.when(nodes.NotNode) - def visit(self, node, scope, expected_type = None): - # se el tipo de la expresion de not se infiere que sea Bool - self.visit(node.expr, scope, self.context.get_type('Bool')) - - return self.context.get_type('Bool') - - - @visitor.when(nodes.ConstantNumNode) - def visit(self, node, scope, expected_type = None): - return self.context.get_type('Int') - - - @visitor.when(nodes.ConstantBoolNode) - def visit(self, node, scope, expected_type = None): - return self.context.get_type('Bool') - - - @visitor.when(nodes.ConstantStringNode) - def visit(self, node, scope, expected_type = None): - return self.context.get_type('String') - - - @visitor.when(nodes.VariableNode) - def visit(self, node, scope, expected_type = None): - var = scope.find_variable(node.lex) - - if var is not None: - # el tipo esperado de var es expected_type - if expected_type and expected_type != 'AUTO_TYPE': - var.expected_types.append(expected_type) - return var.type - - return ErrorType() - - - @visitor.when(nodes.InstantiateNode) - def visit(self, node, scope, expected_type = None): - if node.lex in self.context.types: - return self.context.get_type(node.lex) - - return ErrorType() - - - @visitor.when(nodes.IsVoidNode) - def visit(self, node, scope, expected_type = None): - self.visit(node.lex, scope) - - return self.context.get_type('Bool') - - - @visitor.when(nodes.ComplementNode) - def visit(self, node, scope, expected_type = None): - # el tipo de la expression se espera que sea Int - self.visit(node.lex, scope, self.context.get_type('Int')) - - return self.context.get_type('Int') - - - @visitor.when(nodes.PlusNode) - def visit(self, node, scope, expected_type = None): - # el tipo de la expresiones se espera que sea Int - self.visit(node.left, scope, self.context.get_type('Int')) - self.visit(node.right, scope, self.context.get_type('Int')) - - return self.context.get_type('Int') - - - @visitor.when(nodes.MinusNode) - def visit(self, node, scope, expected_type = None): - # el tipo de la expresiones se espera que sea Int - self.visit(node.left, scope, self.context.get_type('Int')) - self.visit(node.right, scope, self.context.get_type('Int')) - - return self.context.get_type('Int') - - - @visitor.when(nodes.StarNode) - def visit(self, node, scope, expected_type = None): - # el tipo de la expresiones se espera que sea Int - self.visit(node.left, scope, self.context.get_type('Int')) - self.visit(node.right, scope, self.context.get_type('Int')) - - return self.context.get_type('Int') - - - @visitor.when(nodes.DivNode) - def visit(self, node, scope, expected_type = None): - # el tipo de la expresiones se espera que sea Int - self.visit(node.left, scope, self.context.get_type('Int')) - self.visit(node.right, scope, self.context.get_type('Int')) - - return self.context.get_type('Int') - - - @visitor.when(nodes.LessThanNode) - def visit(self, node, scope, expected_type = None): - # el tipo de la expresiones se espera que sea Int - self.visit(node.left, scope, self.context.get_type('Int')) - self.visit(node.right, scope, self.context.get_type('Int')) - - return self.context.get_type('Bool') - - - @visitor.when(nodes.LessEqualNode) - def visit(self, node, scope, expected_type = None): - # el tipo de la expresiones se espera que sea Int - self.visit(node.left, scope, self.context.get_type('Int')) - self.visit(node.right, scope, self.context.get_type('Int')) - - return self.context.get_type('Bool') - - - - @visitor.when(nodes.EqualNode) - def visit(self, node, scope, expected_type = None): - type_left = self.visit(node.left, scope) - # se infiere el tipo a la derecha del igual a partir del tipo izquierdo - type_right = self.visit(node.right, scope, type_left if type_left.name != 'AUTO_TYPE' else None) - - if type_left.name == 'AUTO_TYPE': - # se inifiere el tipo a la izquierda del igual a partir de su tipo derecho - self.visit(node.left, scope, type_right if type_right.name != 'AUTO_TYPE' else None) - - return self.context.get_type('Bool') \ No newline at end of file From 63922dd6fc0fd239d78fac242d02456ebc1de173 Mon Sep 17 00:00:00 2001 From: Alejandro Campos Matanzas <74170015+Alexx-4@users.noreply.github.com> Date: Tue, 15 Feb 2022 10:57:20 -0800 Subject: [PATCH 27/83] Update requirements.txt --- requirements.txt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/requirements.txt b/requirements.txt index da2d20840..9eb0cad1a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,2 @@ pytest -<<<<<<< HEAD pytest-ordering -======= -pytest-ordering -ply~=3.11 ->>>>>>> deac2a5cd44acaf60cc5f106ff68b289e987ff8c From 3c6dc705511baa5421ef7511b6aa799339383b29 Mon Sep 17 00:00:00 2001 From: Ale Date: Tue, 15 Feb 2022 14:06:00 -0800 Subject: [PATCH 28/83] update lexer --- src/main.py | 2 +- src/utils/COOL_Lexer.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.py b/src/main.py index ecf6ee5c4..8fa911acd 100644 --- a/src/main.py +++ b/src/main.py @@ -11,7 +11,7 @@ from utils.semantic_check.type_checker import TypeChecker if __name__ == "__main__": - add = "lexer/comment1.cl" + add = "lexer/string2.cl" path: str = f"{Path.cwd()}/tests/{add}" if os.path.exists( f"{Path.cwd()}/tests/{add}") else f"{Path.cwd()}/../tests/{add}" diff --git a/src/utils/COOL_Lexer.py b/src/utils/COOL_Lexer.py index 22aead8af..1aebf87b0 100644 --- a/src/utils/COOL_Lexer.py +++ b/src/utils/COOL_Lexer.py @@ -129,7 +129,7 @@ def tokenize(self,text): break else: - self.errors.append(f'({self.line}, {self.column + 1}) - LexicographicError: EOF in string constant') + self.errors.append(f'({self.line}, {self.column}) - LexicographicError: EOF in string constant') From 71ebe1ddfa5fa9214f1ab55c9921d51f9d22eaa2 Mon Sep 17 00:00:00 2001 From: Ale Date: Tue, 15 Feb 2022 14:44:14 -0800 Subject: [PATCH 29/83] modifing lexer --- src/main.py | 2 +- src/utils/COOL_Lexer.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main.py b/src/main.py index 8fa911acd..2d0b7ec94 100644 --- a/src/main.py +++ b/src/main.py @@ -11,7 +11,7 @@ from utils.semantic_check.type_checker import TypeChecker if __name__ == "__main__": - add = "lexer/string2.cl" + add = "parser/dispatch8.cl" path: str = f"{Path.cwd()}/tests/{add}" if os.path.exists( f"{Path.cwd()}/tests/{add}") else f"{Path.cwd()}/../tests/{add}" diff --git a/src/utils/COOL_Lexer.py b/src/utils/COOL_Lexer.py index 1aebf87b0..7da7753a7 100644 --- a/src/utils/COOL_Lexer.py +++ b/src/utils/COOL_Lexer.py @@ -156,7 +156,7 @@ def fixed_tokens(self, tokens): ''' -Esta clase guardara las propiedades sintacticas de COOL +Esta clase guarda las propiedades sintacticas de COOL ''' class COOL_Lexer(Lexer): def __init__(self): @@ -164,7 +164,7 @@ def __init__(self): 'id' : r'[a-z][a-zA-Z0-9_]*' , 'type' : r'[A-Z][a-zA-Z0-9_]*' , 'string' : r'\"' , - 'int' : r'\d' , + 'int' : r'\d+' , 'comment' : r'(\(\*)|--.*' , 'newline' : r'\n' , 'whitespace': r' +' , From f5c351e1c734266458b615bef0a0c52cfc662a2e Mon Sep 17 00:00:00 2001 From: Ale Date: Tue, 15 Feb 2022 21:48:43 -0800 Subject: [PATCH 30/83] fixing grammar-parser --- src/main.py | 4 +- src/utils/COOL_Grammar.py | 9 +- src/utils/COOL_Lexer.py | 2 +- src/utils/parser/COOL_parser.py | 2054 ++++++++++++++++--------------- src/utils/parser/parser.py | 2 - 5 files changed, 1050 insertions(+), 1021 deletions(-) diff --git a/src/main.py b/src/main.py index 2d0b7ec94..afbd22b00 100644 --- a/src/main.py +++ b/src/main.py @@ -11,7 +11,7 @@ from utils.semantic_check.type_checker import TypeChecker if __name__ == "__main__": - add = "parser/dispatch8.cl" + add = "parser/operation3.cl" path: str = f"{Path.cwd()}/tests/{add}" if os.path.exists( f"{Path.cwd()}/tests/{add}") else f"{Path.cwd()}/../tests/{add}" @@ -21,6 +21,7 @@ with open(_in) as file: code = file.read() + G = build_COOL_Grammar() # lexer @@ -34,6 +35,7 @@ # parser parser = COOL_Parser(G) + derivation, operations = parser(tokens) if parser.error: diff --git a/src/utils/COOL_Grammar.py b/src/utils/COOL_Grammar.py index 2fe488dcb..3ce91bc26 100644 --- a/src/utils/COOL_Grammar.py +++ b/src/utils/COOL_Grammar.py @@ -11,7 +11,7 @@ def build_COOL_Grammar(): feature_list, def_attr, def_meth, arg_list = G.NonTerminals(' ') expr, expr_list, id_list, case_list, comp = G.NonTerminals(' ') expr, arith, term, factor, atom, dispatch = G.NonTerminals(' ') - not_empty = G.NonTerminal('') + boolean = G.NonTerminal('') #terminales classx, let, inx = G.Terminals('class let in') @@ -49,7 +49,7 @@ def build_COOL_Grammar(): expr %= idx + arrow + expr, lambda h,s: node.AssignNode(s[1],s[3],s[2]) expr %= ifx + expr + then + expr + elsex + expr + fi, lambda h,s: node.IfThenElseNode(s[2],s[4],s[6],s[1]) expr %= whilex + expr + loop + expr + pool, lambda h,s: node.WhileNode(s[2],s[4],s[1]) - expr %= notx + expr, lambda h,s: node.NotNode(s[2],s[1]) + expr %= ocur + expr_list + ccur, lambda h,s: node.BlockNode(s[2],s[1]) @@ -68,7 +68,10 @@ def build_COOL_Grammar(): case_list %= idx + colon + typex + darrow + expr + semi, lambda h,s: [(s[1],s[3],s[5])] case_list %= idx + colon + typex + darrow + expr + semi + case_list, lambda h,s: [(s[1],s[3],s[5])] + s[7] - expr %= comp, lambda h,s: s[1] + expr %= boolean, lambda h,s: s[1] + + boolean %= comp, lambda h,s: s[1] + boolean %= notx + comp, lambda h,s: node.NotNode(s[2], s[1]) comp %= comp + less + arith, lambda h,s: node.LessThanNode(s[1],s[3],s[2]) comp %= comp + lesse + arith, lambda h,s: node.LessEqualNode(s[1],s[3],s[2]) diff --git a/src/utils/COOL_Lexer.py b/src/utils/COOL_Lexer.py index 7da7753a7..7f7f4e860 100644 --- a/src/utils/COOL_Lexer.py +++ b/src/utils/COOL_Lexer.py @@ -139,7 +139,7 @@ def tokenize(self,text): text = text[match.end():] if lexeme[:2] != '(*' and lexeme[0] != '"' else text - yield '$', self.eof, self.line, 1 + yield '$', self.eof, 0, 0 def _build_regex(sef,table): return re.compile('|'.join([f'(?P<{name}>{regex})' if name != regex else f'({name})' for name,regex in table.items()])) diff --git a/src/utils/parser/COOL_parser.py b/src/utils/parser/COOL_parser.py index 7966d556b..c764f13da 100644 --- a/src/utils/parser/COOL_parser.py +++ b/src/utils/parser/COOL_parser.py @@ -24,1161 +24,1178 @@ def __init__(self, G): (0, 'class') : ('SHIFT', 1), (1, 'type') : ('SHIFT', 2), (2, '{') : ('SHIFT', 3), - (2, 'inherits') : ('SHIFT', 131), + (2, 'inherits') : ('SHIFT', 132), (3, 'id') : ('SHIFT', 4), (3, '}') : ('REDUCE', 7), (4, ':') : ('SHIFT', 5), - (4, '(') : ('SHIFT', 109), + (4, '(') : ('SHIFT', 110), (5, 'type') : ('SHIFT', 6), (6, ';') : ('REDUCE', 8), (6, '<-') : ('SHIFT', 7), + (7, 'isvoid') : ('SHIFT', 27), + (7, '{') : ('SHIFT', 14), + (7, '(') : ('SHIFT', 13), + (7, 'let') : ('SHIFT', 8), (7, 'if') : ('SHIFT', 24), - (7, 'not') : ('SHIFT', 26), + (7, 'case') : ('SHIFT', 25), (7, 'id') : ('SHIFT', 18), (7, 'false') : ('SHIFT', 29), (7, 'int') : ('SHIFT', 21), (7, 'string') : ('SHIFT', 30), - (7, '(') : ('SHIFT', 13), - (7, 'true') : ('SHIFT', 28), - (7, 'let') : ('SHIFT', 8), - (7, 'isvoid') : ('SHIFT', 27), + (7, 'while') : ('SHIFT', 20), (7, '~') : ('SHIFT', 15), - (7, 'case') : ('SHIFT', 25), - (7, '{') : ('SHIFT', 14), (7, 'new') : ('SHIFT', 22), - (7, 'while') : ('SHIFT', 20), + (7, 'true') : ('SHIFT', 28), + (7, 'not') : ('SHIFT', 26), (8, 'id') : ('SHIFT', 9), (9, ':') : ('SHIFT', 10), (10, 'type') : ('SHIFT', 11), + (11, 'in') : ('REDUCE', 22), (11, '<-') : ('SHIFT', 12), - (11, 'in') : ('REDUCE', 23), - (11, ',') : ('SHIFT', 103), - (12, 'case') : ('SHIFT', 25), - (12, '{') : ('SHIFT', 14), - (12, '~') : ('SHIFT', 15), - (12, 'int') : ('SHIFT', 21), - (12, 'while') : ('SHIFT', 20), - (12, 'id') : ('SHIFT', 18), + (11, ',') : ('SHIFT', 104), + (12, 'isvoid') : ('SHIFT', 27), (12, '(') : ('SHIFT', 13), - (12, 'true') : ('SHIFT', 28), - (12, 'if') : ('SHIFT', 24), (12, 'not') : ('SHIFT', 26), (12, 'false') : ('SHIFT', 29), - (12, 'isvoid') : ('SHIFT', 27), + (12, 'id') : ('SHIFT', 18), + (12, 'int') : ('SHIFT', 21), + (12, '{') : ('SHIFT', 14), (12, 'string') : ('SHIFT', 30), - (12, 'new') : ('SHIFT', 22), + (12, 'if') : ('SHIFT', 24), (12, 'let') : ('SHIFT', 8), + (12, 'case') : ('SHIFT', 25), + (12, '~') : ('SHIFT', 15), + (12, 'new') : ('SHIFT', 22), + (12, 'true') : ('SHIFT', 28), + (12, 'while') : ('SHIFT', 20), + (13, 'while') : ('SHIFT', 20), + (13, '~') : ('SHIFT', 15), + (13, 'new') : ('SHIFT', 22), (13, 'true') : ('SHIFT', 28), - (13, 'id') : ('SHIFT', 18), - (13, 'false') : ('SHIFT', 29), - (13, 'let') : ('SHIFT', 8), - (13, 'int') : ('SHIFT', 21), - (13, 'string') : ('SHIFT', 30), + (13, 'not') : ('SHIFT', 26), + (13, 'isvoid') : ('SHIFT', 27), (13, '(') : ('SHIFT', 13), - (13, 'case') : ('SHIFT', 25), (13, '{') : ('SHIFT', 14), - (13, 'while') : ('SHIFT', 20), - (13, 'isvoid') : ('SHIFT', 27), - (13, '~') : ('SHIFT', 15), + (13, 'let') : ('SHIFT', 8), (13, 'if') : ('SHIFT', 24), - (13, 'not') : ('SHIFT', 26), - (13, 'new') : ('SHIFT', 22), + (13, 'id') : ('SHIFT', 18), + (13, 'case') : ('SHIFT', 25), + (13, 'false') : ('SHIFT', 29), + (13, 'string') : ('SHIFT', 30), + (13, 'int') : ('SHIFT', 21), + (14, 'isvoid') : ('SHIFT', 27), + (14, '{') : ('SHIFT', 14), + (14, '(') : ('SHIFT', 13), + (14, 'let') : ('SHIFT', 8), (14, 'if') : ('SHIFT', 24), - (14, 'not') : ('SHIFT', 26), - (14, 'false') : ('SHIFT', 29), + (14, 'case') : ('SHIFT', 25), (14, 'id') : ('SHIFT', 18), + (14, 'false') : ('SHIFT', 29), (14, 'int') : ('SHIFT', 21), (14, 'string') : ('SHIFT', 30), - (14, '(') : ('SHIFT', 13), - (14, 'true') : ('SHIFT', 28), - (14, 'let') : ('SHIFT', 8), - (14, 'isvoid') : ('SHIFT', 27), + (14, 'while') : ('SHIFT', 20), (14, '~') : ('SHIFT', 15), - (14, 'case') : ('SHIFT', 25), - (14, '{') : ('SHIFT', 14), (14, 'new') : ('SHIFT', 22), - (14, 'while') : ('SHIFT', 20), - (15, 'id') : ('SHIFT', 16), + (14, 'true') : ('SHIFT', 28), + (14, 'not') : ('SHIFT', 26), (15, 'false') : ('SHIFT', 29), - (15, 'string') : ('SHIFT', 30), - (15, 'true') : ('SHIFT', 28), + (15, 'id') : ('SHIFT', 16), + (15, 'new') : ('SHIFT', 22), (15, 'int') : ('SHIFT', 21), + (15, 'string') : ('SHIFT', 30), (15, 'isvoid') : ('SHIFT', 27), + (15, 'true') : ('SHIFT', 28), (15, '~') : ('SHIFT', 15), (15, '(') : ('SHIFT', 13), - (15, 'new') : ('SHIFT', 22), - (16, 'then') : ('REDUCE', 48), - (16, 'else') : ('REDUCE', 48), - (16, 'fi') : ('REDUCE', 48), - (16, 'of') : ('REDUCE', 48), - (16, 'in') : ('REDUCE', 48), - (16, ';') : ('REDUCE', 48), - (16, ',') : ('REDUCE', 48), - (16, '.') : ('REDUCE', 48), - (16, ')') : ('REDUCE', 48), - (16, '}') : ('REDUCE', 48), - (16, '=') : ('REDUCE', 48), - (16, '+') : ('REDUCE', 48), - (16, '-') : ('REDUCE', 48), - (16, '*') : ('REDUCE', 48), - (16, '/') : ('REDUCE', 48), - (16, '<') : ('REDUCE', 48), - (16, '<=') : ('REDUCE', 48), - (16, '@') : ('REDUCE', 48), - (16, 'loop') : ('REDUCE', 48), - (16, 'pool') : ('REDUCE', 48), + (16, 'fi') : ('REDUCE', 49), + (16, '=') : ('REDUCE', 49), + (16, '+') : ('REDUCE', 49), + (16, '-') : ('REDUCE', 49), + (16, 'of') : ('REDUCE', 49), + (16, '*') : ('REDUCE', 49), + (16, '/') : ('REDUCE', 49), + (16, '<') : ('REDUCE', 49), + (16, '<=') : ('REDUCE', 49), + (16, '@') : ('REDUCE', 49), + (16, 'in') : ('REDUCE', 49), + (16, ';') : ('REDUCE', 49), + (16, 'loop') : ('REDUCE', 49), + (16, 'pool') : ('REDUCE', 49), + (16, ',') : ('REDUCE', 49), + (16, '.') : ('REDUCE', 49), + (16, ')') : ('REDUCE', 49), + (16, 'then') : ('REDUCE', 49), + (16, 'else') : ('REDUCE', 49), + (16, '}') : ('REDUCE', 49), (16, '(') : ('SHIFT', 17), - (17, 'while') : ('SHIFT', 20), + (17, ')') : ('REDUCE', 58), + (17, '~') : ('SHIFT', 15), (17, 'id') : ('SHIFT', 18), (17, 'new') : ('SHIFT', 22), - (17, '~') : ('SHIFT', 15), - (17, 'case') : ('SHIFT', 25), - (17, 'if') : ('SHIFT', 24), - (17, 'not') : ('SHIFT', 26), + (17, '{') : ('SHIFT', 14), (17, 'true') : ('SHIFT', 28), - (17, 'false') : ('SHIFT', 29), - (17, 'int') : ('SHIFT', 21), + (17, 'let') : ('SHIFT', 8), + (17, 'if') : ('SHIFT', 24), + (17, 'case') : ('SHIFT', 25), (17, 'string') : ('SHIFT', 30), (17, 'isvoid') : ('SHIFT', 27), + (17, 'while') : ('SHIFT', 20), (17, '(') : ('SHIFT', 13), - (17, ')') : ('REDUCE', 57), - (17, 'let') : ('SHIFT', 8), - (17, '{') : ('SHIFT', 14), - (18, '(') : ('SHIFT', 17), - (18, 'then') : ('REDUCE', 48), - (18, 'else') : ('REDUCE', 48), - (18, 'fi') : ('REDUCE', 48), - (18, 'of') : ('REDUCE', 48), - (18, 'in') : ('REDUCE', 48), - (18, ';') : ('REDUCE', 48), - (18, ',') : ('REDUCE', 48), - (18, '.') : ('REDUCE', 48), - (18, ')') : ('REDUCE', 48), - (18, '}') : ('REDUCE', 48), - (18, '=') : ('REDUCE', 48), - (18, '+') : ('REDUCE', 48), - (18, '-') : ('REDUCE', 48), - (18, '*') : ('REDUCE', 48), - (18, '/') : ('REDUCE', 48), - (18, '<') : ('REDUCE', 48), - (18, '<=') : ('REDUCE', 48), - (18, '@') : ('REDUCE', 48), - (18, 'loop') : ('REDUCE', 48), - (18, 'pool') : ('REDUCE', 48), + (17, 'false') : ('SHIFT', 29), + (17, 'int') : ('SHIFT', 21), + (17, 'not') : ('SHIFT', 26), (18, '<-') : ('SHIFT', 19), - (19, 'id') : ('SHIFT', 18), + (18, 'fi') : ('REDUCE', 49), + (18, '=') : ('REDUCE', 49), + (18, '+') : ('REDUCE', 49), + (18, '-') : ('REDUCE', 49), + (18, 'of') : ('REDUCE', 49), + (18, '*') : ('REDUCE', 49), + (18, '/') : ('REDUCE', 49), + (18, '<') : ('REDUCE', 49), + (18, '<=') : ('REDUCE', 49), + (18, '@') : ('REDUCE', 49), + (18, 'in') : ('REDUCE', 49), + (18, ';') : ('REDUCE', 49), + (18, 'loop') : ('REDUCE', 49), + (18, 'pool') : ('REDUCE', 49), + (18, ',') : ('REDUCE', 49), + (18, '.') : ('REDUCE', 49), + (18, ')') : ('REDUCE', 49), + (18, 'then') : ('REDUCE', 49), + (18, 'else') : ('REDUCE', 49), + (18, '}') : ('REDUCE', 49), + (18, '(') : ('SHIFT', 17), (19, 'false') : ('SHIFT', 29), - (19, 'let') : ('SHIFT', 8), + (19, '{') : ('SHIFT', 14), + (19, 'id') : ('SHIFT', 18), (19, 'string') : ('SHIFT', 30), + (19, 'int') : ('SHIFT', 21), (19, 'isvoid') : ('SHIFT', 27), + (19, 'let') : ('SHIFT', 8), + (19, 'if') : ('SHIFT', 24), (19, 'case') : ('SHIFT', 25), - (19, '~') : ('SHIFT', 15), - (19, '{') : ('SHIFT', 14), (19, 'new') : ('SHIFT', 22), + (19, 'true') : ('SHIFT', 28), (19, 'while') : ('SHIFT', 20), - (19, 'if') : ('SHIFT', 24), - (19, 'not') : ('SHIFT', 26), - (19, 'int') : ('SHIFT', 21), + (19, '~') : ('SHIFT', 15), (19, '(') : ('SHIFT', 13), - (19, 'true') : ('SHIFT', 28), - (20, 'id') : ('SHIFT', 18), - (20, 'true') : ('SHIFT', 28), - (20, 'false') : ('SHIFT', 29), + (19, 'not') : ('SHIFT', 26), + (20, 'isvoid') : ('SHIFT', 27), (20, 'if') : ('SHIFT', 24), - (20, 'not') : ('SHIFT', 26), (20, 'let') : ('SHIFT', 8), + (20, 'case') : ('SHIFT', 25), + (20, 'id') : ('SHIFT', 18), + (20, 'false') : ('SHIFT', 29), (20, 'string') : ('SHIFT', 30), + (20, 'int') : ('SHIFT', 21), + (20, 'while') : ('SHIFT', 20), (20, 'new') : ('SHIFT', 22), - (20, '{') : ('SHIFT', 14), - (20, 'isvoid') : ('SHIFT', 27), + (20, 'true') : ('SHIFT', 28), (20, '~') : ('SHIFT', 15), - (20, 'case') : ('SHIFT', 25), - (20, 'int') : ('SHIFT', 21), + (20, 'not') : ('SHIFT', 26), (20, '(') : ('SHIFT', 13), - (20, 'while') : ('SHIFT', 20), - (21, 'then') : ('REDUCE', 47), - (21, 'else') : ('REDUCE', 47), - (21, 'fi') : ('REDUCE', 47), - (21, 'of') : ('REDUCE', 47), - (21, 'in') : ('REDUCE', 47), - (21, ';') : ('REDUCE', 47), - (21, ',') : ('REDUCE', 47), - (21, '.') : ('REDUCE', 47), - (21, ')') : ('REDUCE', 47), - (21, '}') : ('REDUCE', 47), - (21, '=') : ('REDUCE', 47), - (21, '+') : ('REDUCE', 47), - (21, '-') : ('REDUCE', 47), - (21, '*') : ('REDUCE', 47), - (21, '/') : ('REDUCE', 47), - (21, '<') : ('REDUCE', 47), - (21, '<=') : ('REDUCE', 47), - (21, '@') : ('REDUCE', 47), - (21, 'loop') : ('REDUCE', 47), - (21, 'pool') : ('REDUCE', 47), + (20, '{') : ('SHIFT', 14), + (21, 'fi') : ('REDUCE', 48), + (21, '=') : ('REDUCE', 48), + (21, '+') : ('REDUCE', 48), + (21, '-') : ('REDUCE', 48), + (21, 'of') : ('REDUCE', 48), + (21, '*') : ('REDUCE', 48), + (21, '/') : ('REDUCE', 48), + (21, '<') : ('REDUCE', 48), + (21, '<=') : ('REDUCE', 48), + (21, '@') : ('REDUCE', 48), + (21, 'in') : ('REDUCE', 48), + (21, ';') : ('REDUCE', 48), + (21, 'loop') : ('REDUCE', 48), + (21, 'pool') : ('REDUCE', 48), + (21, ',') : ('REDUCE', 48), + (21, '.') : ('REDUCE', 48), + (21, ')') : ('REDUCE', 48), + (21, 'then') : ('REDUCE', 48), + (21, 'else') : ('REDUCE', 48), + (21, '}') : ('REDUCE', 48), (22, 'type') : ('SHIFT', 23), - (23, 'then') : ('REDUCE', 49), - (23, 'else') : ('REDUCE', 49), - (23, 'fi') : ('REDUCE', 49), - (23, 'of') : ('REDUCE', 49), - (23, 'in') : ('REDUCE', 49), - (23, ';') : ('REDUCE', 49), - (23, ',') : ('REDUCE', 49), - (23, '.') : ('REDUCE', 49), - (23, ')') : ('REDUCE', 49), - (23, '}') : ('REDUCE', 49), - (23, '=') : ('REDUCE', 49), - (23, '+') : ('REDUCE', 49), - (23, '-') : ('REDUCE', 49), - (23, '*') : ('REDUCE', 49), - (23, '/') : ('REDUCE', 49), - (23, '<') : ('REDUCE', 49), - (23, '<=') : ('REDUCE', 49), - (23, '@') : ('REDUCE', 49), - (23, 'loop') : ('REDUCE', 49), - (23, 'pool') : ('REDUCE', 49), + (23, 'fi') : ('REDUCE', 50), + (23, '=') : ('REDUCE', 50), + (23, '+') : ('REDUCE', 50), + (23, '-') : ('REDUCE', 50), + (23, 'of') : ('REDUCE', 50), + (23, '*') : ('REDUCE', 50), + (23, '/') : ('REDUCE', 50), + (23, '<') : ('REDUCE', 50), + (23, '<=') : ('REDUCE', 50), + (23, '@') : ('REDUCE', 50), + (23, 'in') : ('REDUCE', 50), + (23, ';') : ('REDUCE', 50), + (23, 'loop') : ('REDUCE', 50), + (23, 'pool') : ('REDUCE', 50), + (23, ',') : ('REDUCE', 50), + (23, '.') : ('REDUCE', 50), + (23, ')') : ('REDUCE', 50), + (23, 'then') : ('REDUCE', 50), + (23, 'else') : ('REDUCE', 50), + (23, '}') : ('REDUCE', 50), + (24, 'isvoid') : ('SHIFT', 27), + (24, '(') : ('SHIFT', 13), (24, 'not') : ('SHIFT', 26), - (24, 'true') : ('SHIFT', 28), + (24, '{') : ('SHIFT', 14), + (24, 'false') : ('SHIFT', 29), + (24, 'id') : ('SHIFT', 18), + (24, 'int') : ('SHIFT', 21), (24, 'string') : ('SHIFT', 30), + (24, 'if') : ('SHIFT', 24), (24, 'let') : ('SHIFT', 8), - (24, 'id') : ('SHIFT', 18), + (24, 'case') : ('SHIFT', 25), (24, 'new') : ('SHIFT', 22), - (24, 'isvoid') : ('SHIFT', 27), + (24, 'true') : ('SHIFT', 28), (24, '~') : ('SHIFT', 15), - (24, 'case') : ('SHIFT', 25), - (24, '{') : ('SHIFT', 14), (24, 'while') : ('SHIFT', 20), - (24, 'false') : ('SHIFT', 29), - (24, 'int') : ('SHIFT', 21), - (24, '(') : ('SHIFT', 13), - (24, 'if') : ('SHIFT', 24), - (25, 'while') : ('SHIFT', 20), + (25, 'not') : ('SHIFT', 26), (25, 'true') : ('SHIFT', 28), - (25, 'false') : ('SHIFT', 29), - (25, 'id') : ('SHIFT', 18), - (25, 'int') : ('SHIFT', 21), - (25, 'let') : ('SHIFT', 8), - (25, 'string') : ('SHIFT', 30), - (25, 'isvoid') : ('SHIFT', 27), - (25, '~') : ('SHIFT', 15), - (25, 'new') : ('SHIFT', 22), (25, '{') : ('SHIFT', 14), - (25, 'case') : ('SHIFT', 25), + (25, '~') : ('SHIFT', 15), + (25, 'let') : ('SHIFT', 8), (25, 'if') : ('SHIFT', 24), - (25, 'not') : ('SHIFT', 26), + (25, 'case') : ('SHIFT', 25), + (25, 'id') : ('SHIFT', 18), (25, '(') : ('SHIFT', 13), - (26, 'id') : ('SHIFT', 18), + (25, 'new') : ('SHIFT', 22), + (25, 'while') : ('SHIFT', 20), + (25, 'isvoid') : ('SHIFT', 27), + (25, 'false') : ('SHIFT', 29), + (25, 'int') : ('SHIFT', 21), + (25, 'string') : ('SHIFT', 30), (26, 'false') : ('SHIFT', 29), - (26, 'let') : ('SHIFT', 8), + (26, 'id') : ('SHIFT', 16), + (26, 'int') : ('SHIFT', 21), (26, 'string') : ('SHIFT', 30), (26, 'isvoid') : ('SHIFT', 27), (26, '~') : ('SHIFT', 15), - (26, 'case') : ('SHIFT', 25), - (26, '{') : ('SHIFT', 14), - (26, 'new') : ('SHIFT', 22), - (26, 'while') : ('SHIFT', 20), - (26, 'if') : ('SHIFT', 24), - (26, 'not') : ('SHIFT', 26), - (26, 'int') : ('SHIFT', 21), (26, '(') : ('SHIFT', 13), + (26, 'new') : ('SHIFT', 22), (26, 'true') : ('SHIFT', 28), - (27, 'id') : ('SHIFT', 16), (27, 'false') : ('SHIFT', 29), - (27, 'string') : ('SHIFT', 30), - (27, 'true') : ('SHIFT', 28), + (27, 'id') : ('SHIFT', 16), + (27, 'new') : ('SHIFT', 22), (27, 'int') : ('SHIFT', 21), + (27, 'string') : ('SHIFT', 30), (27, 'isvoid') : ('SHIFT', 27), + (27, 'true') : ('SHIFT', 28), (27, '~') : ('SHIFT', 15), (27, '(') : ('SHIFT', 13), - (27, 'new') : ('SHIFT', 22), - (28, 'then') : ('REDUCE', 44), - (28, 'else') : ('REDUCE', 44), - (28, 'fi') : ('REDUCE', 44), - (28, 'of') : ('REDUCE', 44), - (28, 'in') : ('REDUCE', 44), - (28, ';') : ('REDUCE', 44), - (28, ',') : ('REDUCE', 44), - (28, '.') : ('REDUCE', 44), - (28, ')') : ('REDUCE', 44), - (28, '}') : ('REDUCE', 44), - (28, '=') : ('REDUCE', 44), - (28, '+') : ('REDUCE', 44), - (28, '-') : ('REDUCE', 44), - (28, '*') : ('REDUCE', 44), - (28, '/') : ('REDUCE', 44), - (28, '<') : ('REDUCE', 44), - (28, '<=') : ('REDUCE', 44), - (28, '@') : ('REDUCE', 44), - (28, 'loop') : ('REDUCE', 44), - (28, 'pool') : ('REDUCE', 44), - (29, 'then') : ('REDUCE', 45), - (29, 'else') : ('REDUCE', 45), - (29, 'fi') : ('REDUCE', 45), - (29, 'of') : ('REDUCE', 45), - (29, 'in') : ('REDUCE', 45), - (29, ';') : ('REDUCE', 45), - (29, ',') : ('REDUCE', 45), - (29, '.') : ('REDUCE', 45), - (29, ')') : ('REDUCE', 45), - (29, '}') : ('REDUCE', 45), - (29, '=') : ('REDUCE', 45), - (29, '+') : ('REDUCE', 45), - (29, '-') : ('REDUCE', 45), - (29, '*') : ('REDUCE', 45), - (29, '/') : ('REDUCE', 45), - (29, '<') : ('REDUCE', 45), - (29, '<=') : ('REDUCE', 45), - (29, '@') : ('REDUCE', 45), - (29, 'loop') : ('REDUCE', 45), - (29, 'pool') : ('REDUCE', 45), - (30, 'then') : ('REDUCE', 46), - (30, 'else') : ('REDUCE', 46), - (30, 'fi') : ('REDUCE', 46), - (30, 'of') : ('REDUCE', 46), - (30, 'in') : ('REDUCE', 46), - (30, ';') : ('REDUCE', 46), - (30, ',') : ('REDUCE', 46), - (30, '.') : ('REDUCE', 46), - (30, ')') : ('REDUCE', 46), - (30, '}') : ('REDUCE', 46), - (30, '=') : ('REDUCE', 46), - (30, '+') : ('REDUCE', 46), - (30, '-') : ('REDUCE', 46), - (30, '*') : ('REDUCE', 46), - (30, '/') : ('REDUCE', 46), - (30, '<') : ('REDUCE', 46), - (30, '<=') : ('REDUCE', 46), - (30, '@') : ('REDUCE', 46), - (30, 'loop') : ('REDUCE', 46), - (30, 'pool') : ('REDUCE', 46), - (31, '<') : ('REDUCE', 41), - (31, '<=') : ('REDUCE', 41), - (31, ')') : ('REDUCE', 41), - (31, 'then') : ('REDUCE', 41), - (31, '}') : ('REDUCE', 41), - (31, 'else') : ('REDUCE', 41), - (31, 'fi') : ('REDUCE', 41), - (31, '=') : ('REDUCE', 41), - (31, 'in') : ('REDUCE', 41), - (31, ';') : ('REDUCE', 41), - (31, '+') : ('REDUCE', 41), - (31, '-') : ('REDUCE', 41), - (31, 'loop') : ('REDUCE', 41), - (31, 'of') : ('REDUCE', 41), - (31, '*') : ('REDUCE', 41), - (31, 'pool') : ('REDUCE', 41), - (31, ',') : ('REDUCE', 41), - (31, '/') : ('REDUCE', 41), - (32, '@') : ('SHIFT', 60), - (32, '<') : ('REDUCE', 43), - (32, '<=') : ('REDUCE', 43), - (32, ')') : ('REDUCE', 43), - (32, 'then') : ('REDUCE', 43), - (32, '}') : ('REDUCE', 43), - (32, 'else') : ('REDUCE', 43), - (32, 'fi') : ('REDUCE', 43), - (32, '=') : ('REDUCE', 43), - (32, 'in') : ('REDUCE', 43), - (32, ';') : ('REDUCE', 43), - (32, '+') : ('REDUCE', 43), - (32, '-') : ('REDUCE', 43), - (32, 'loop') : ('REDUCE', 43), - (32, 'of') : ('REDUCE', 43), - (32, '*') : ('REDUCE', 43), - (32, 'pool') : ('REDUCE', 43), - (32, ',') : ('REDUCE', 43), - (32, '/') : ('REDUCE', 43), + (28, 'fi') : ('REDUCE', 45), + (28, '=') : ('REDUCE', 45), + (28, '+') : ('REDUCE', 45), + (28, '-') : ('REDUCE', 45), + (28, 'of') : ('REDUCE', 45), + (28, '*') : ('REDUCE', 45), + (28, '/') : ('REDUCE', 45), + (28, '<') : ('REDUCE', 45), + (28, '<=') : ('REDUCE', 45), + (28, '@') : ('REDUCE', 45), + (28, 'in') : ('REDUCE', 45), + (28, ';') : ('REDUCE', 45), + (28, 'loop') : ('REDUCE', 45), + (28, 'pool') : ('REDUCE', 45), + (28, ',') : ('REDUCE', 45), + (28, '.') : ('REDUCE', 45), + (28, ')') : ('REDUCE', 45), + (28, 'then') : ('REDUCE', 45), + (28, 'else') : ('REDUCE', 45), + (28, '}') : ('REDUCE', 45), + (29, 'fi') : ('REDUCE', 46), + (29, '=') : ('REDUCE', 46), + (29, '+') : ('REDUCE', 46), + (29, '-') : ('REDUCE', 46), + (29, 'of') : ('REDUCE', 46), + (29, '*') : ('REDUCE', 46), + (29, '/') : ('REDUCE', 46), + (29, '<') : ('REDUCE', 46), + (29, '<=') : ('REDUCE', 46), + (29, '@') : ('REDUCE', 46), + (29, 'in') : ('REDUCE', 46), + (29, ';') : ('REDUCE', 46), + (29, 'loop') : ('REDUCE', 46), + (29, 'pool') : ('REDUCE', 46), + (29, ',') : ('REDUCE', 46), + (29, '.') : ('REDUCE', 46), + (29, ')') : ('REDUCE', 46), + (29, 'then') : ('REDUCE', 46), + (29, 'else') : ('REDUCE', 46), + (29, '}') : ('REDUCE', 46), + (30, 'fi') : ('REDUCE', 47), + (30, '=') : ('REDUCE', 47), + (30, '+') : ('REDUCE', 47), + (30, '-') : ('REDUCE', 47), + (30, 'of') : ('REDUCE', 47), + (30, '*') : ('REDUCE', 47), + (30, '/') : ('REDUCE', 47), + (30, '<') : ('REDUCE', 47), + (30, '<=') : ('REDUCE', 47), + (30, '@') : ('REDUCE', 47), + (30, 'in') : ('REDUCE', 47), + (30, ';') : ('REDUCE', 47), + (30, 'loop') : ('REDUCE', 47), + (30, 'pool') : ('REDUCE', 47), + (30, ',') : ('REDUCE', 47), + (30, '.') : ('REDUCE', 47), + (30, ')') : ('REDUCE', 47), + (30, 'then') : ('REDUCE', 47), + (30, 'else') : ('REDUCE', 47), + (30, '}') : ('REDUCE', 47), + (31, '/') : ('REDUCE', 42), + (31, '}') : ('REDUCE', 42), + (31, 'fi') : ('REDUCE', 42), + (31, 'in') : ('REDUCE', 42), + (31, '<') : ('REDUCE', 42), + (31, '=') : ('REDUCE', 42), + (31, ';') : ('REDUCE', 42), + (31, '<=') : ('REDUCE', 42), + (31, '+') : ('REDUCE', 42), + (31, 'else') : ('REDUCE', 42), + (31, ')') : ('REDUCE', 42), + (31, '-') : ('REDUCE', 42), + (31, 'then') : ('REDUCE', 42), + (31, 'of') : ('REDUCE', 42), + (31, 'loop') : ('REDUCE', 42), + (31, '*') : ('REDUCE', 42), + (31, 'pool') : ('REDUCE', 42), + (31, ',') : ('REDUCE', 42), + (32, '@') : ('SHIFT', 61), (32, '.') : ('SHIFT', 33), + (32, '/') : ('REDUCE', 44), + (32, '}') : ('REDUCE', 44), + (32, 'fi') : ('REDUCE', 44), + (32, 'in') : ('REDUCE', 44), + (32, '<') : ('REDUCE', 44), + (32, '=') : ('REDUCE', 44), + (32, ';') : ('REDUCE', 44), + (32, '<=') : ('REDUCE', 44), + (32, '+') : ('REDUCE', 44), + (32, 'else') : ('REDUCE', 44), + (32, ')') : ('REDUCE', 44), + (32, '-') : ('REDUCE', 44), + (32, 'then') : ('REDUCE', 44), + (32, 'of') : ('REDUCE', 44), + (32, 'loop') : ('REDUCE', 44), + (32, '*') : ('REDUCE', 44), + (32, 'pool') : ('REDUCE', 44), + (32, ',') : ('REDUCE', 44), (33, 'id') : ('SHIFT', 34), (34, '(') : ('SHIFT', 35), - (35, 'while') : ('SHIFT', 20), + (35, ')') : ('REDUCE', 58), + (35, '~') : ('SHIFT', 15), (35, 'id') : ('SHIFT', 18), (35, 'new') : ('SHIFT', 22), - (35, '~') : ('SHIFT', 15), - (35, 'case') : ('SHIFT', 25), - (35, 'if') : ('SHIFT', 24), - (35, 'not') : ('SHIFT', 26), + (35, '{') : ('SHIFT', 14), (35, 'true') : ('SHIFT', 28), - (35, 'false') : ('SHIFT', 29), - (35, 'int') : ('SHIFT', 21), + (35, 'let') : ('SHIFT', 8), + (35, 'if') : ('SHIFT', 24), + (35, 'case') : ('SHIFT', 25), (35, 'string') : ('SHIFT', 30), (35, 'isvoid') : ('SHIFT', 27), + (35, 'while') : ('SHIFT', 20), (35, '(') : ('SHIFT', 13), - (35, ')') : ('REDUCE', 57), - (35, 'let') : ('SHIFT', 8), - (35, '{') : ('SHIFT', 14), + (35, 'false') : ('SHIFT', 29), + (35, 'int') : ('SHIFT', 21), + (35, 'not') : ('SHIFT', 26), (36, ')') : ('SHIFT', 37), - (37, 'then') : ('REDUCE', 52), - (37, 'else') : ('REDUCE', 52), - (37, 'fi') : ('REDUCE', 52), - (37, 'of') : ('REDUCE', 52), - (37, 'in') : ('REDUCE', 52), - (37, ';') : ('REDUCE', 52), - (37, ',') : ('REDUCE', 52), - (37, '.') : ('REDUCE', 52), - (37, ')') : ('REDUCE', 52), - (37, '}') : ('REDUCE', 52), - (37, '=') : ('REDUCE', 52), - (37, '+') : ('REDUCE', 52), - (37, '-') : ('REDUCE', 52), - (37, '*') : ('REDUCE', 52), - (37, '/') : ('REDUCE', 52), - (37, '<') : ('REDUCE', 52), - (37, '<=') : ('REDUCE', 52), - (37, '@') : ('REDUCE', 52), - (37, 'loop') : ('REDUCE', 52), - (37, 'pool') : ('REDUCE', 52), - (38, '<=') : ('SHIFT', 54), - (38, '<') : ('SHIFT', 52), - (38, ')') : ('REDUCE', 30), - (38, 'then') : ('REDUCE', 30), - (38, '}') : ('REDUCE', 30), - (38, 'else') : ('REDUCE', 30), + (37, 'fi') : ('REDUCE', 53), + (37, '=') : ('REDUCE', 53), + (37, '+') : ('REDUCE', 53), + (37, '-') : ('REDUCE', 53), + (37, 'of') : ('REDUCE', 53), + (37, '*') : ('REDUCE', 53), + (37, '/') : ('REDUCE', 53), + (37, '<') : ('REDUCE', 53), + (37, '<=') : ('REDUCE', 53), + (37, '@') : ('REDUCE', 53), + (37, 'in') : ('REDUCE', 53), + (37, ';') : ('REDUCE', 53), + (37, 'loop') : ('REDUCE', 53), + (37, 'pool') : ('REDUCE', 53), + (37, ',') : ('REDUCE', 53), + (37, '.') : ('REDUCE', 53), + (37, ')') : ('REDUCE', 53), + (37, 'then') : ('REDUCE', 53), + (37, 'else') : ('REDUCE', 53), + (37, '}') : ('REDUCE', 53), + (38, 'pool') : ('REDUCE', 30), (38, 'fi') : ('REDUCE', 30), (38, 'in') : ('REDUCE', 30), (38, ';') : ('REDUCE', 30), - (38, 'loop') : ('REDUCE', 30), + (38, ')') : ('REDUCE', 30), + (38, 'then') : ('REDUCE', 30), (38, 'of') : ('REDUCE', 30), - (38, 'pool') : ('REDUCE', 30), + (38, 'loop') : ('REDUCE', 30), + (38, 'else') : ('REDUCE', 30), + (38, '}') : ('REDUCE', 30), (38, ',') : ('REDUCE', 30), + (38, '<=') : ('SHIFT', 54), + (38, '<') : ('SHIFT', 52), (38, '=') : ('SHIFT', 39), (39, 'false') : ('SHIFT', 29), (39, 'id') : ('SHIFT', 16), (39, 'string') : ('SHIFT', 30), + (39, 'int') : ('SHIFT', 21), (39, 'isvoid') : ('SHIFT', 27), (39, '~') : ('SHIFT', 15), - (39, 'int') : ('SHIFT', 21), (39, '(') : ('SHIFT', 13), (39, 'new') : ('SHIFT', 22), (39, 'true') : ('SHIFT', 28), - (40, '+') : ('SHIFT', 41), - (40, '<') : ('REDUCE', 33), - (40, '<=') : ('REDUCE', 33), - (40, ')') : ('REDUCE', 33), - (40, 'then') : ('REDUCE', 33), - (40, '}') : ('REDUCE', 33), - (40, 'else') : ('REDUCE', 33), - (40, 'fi') : ('REDUCE', 33), - (40, '=') : ('REDUCE', 33), - (40, 'in') : ('REDUCE', 33), - (40, ';') : ('REDUCE', 33), - (40, 'loop') : ('REDUCE', 33), - (40, 'of') : ('REDUCE', 33), - (40, 'pool') : ('REDUCE', 33), - (40, ',') : ('REDUCE', 33), + (40, '}') : ('REDUCE', 34), + (40, 'fi') : ('REDUCE', 34), + (40, 'in') : ('REDUCE', 34), + (40, '<') : ('REDUCE', 34), + (40, '=') : ('REDUCE', 34), + (40, ';') : ('REDUCE', 34), + (40, '<=') : ('REDUCE', 34), + (40, ')') : ('REDUCE', 34), + (40, 'then') : ('REDUCE', 34), + (40, 'loop') : ('REDUCE', 34), + (40, 'of') : ('REDUCE', 34), + (40, 'else') : ('REDUCE', 34), + (40, 'pool') : ('REDUCE', 34), + (40, ',') : ('REDUCE', 34), (40, '-') : ('SHIFT', 49), - (41, 'id') : ('SHIFT', 16), + (40, '+') : ('SHIFT', 41), (41, 'false') : ('SHIFT', 29), - (41, 'string') : ('SHIFT', 30), + (41, 'id') : ('SHIFT', 16), (41, 'int') : ('SHIFT', 21), - (41, '~') : ('SHIFT', 15), + (41, 'string') : ('SHIFT', 30), (41, 'isvoid') : ('SHIFT', 27), + (41, '~') : ('SHIFT', 15), (41, '(') : ('SHIFT', 13), (41, 'new') : ('SHIFT', 22), (41, 'true') : ('SHIFT', 28), - (42, '<') : ('REDUCE', 35), - (42, '<=') : ('REDUCE', 35), - (42, ')') : ('REDUCE', 35), - (42, 'then') : ('REDUCE', 35), - (42, '}') : ('REDUCE', 35), - (42, 'else') : ('REDUCE', 35), - (42, 'fi') : ('REDUCE', 35), - (42, '=') : ('REDUCE', 35), - (42, 'in') : ('REDUCE', 35), - (42, ';') : ('REDUCE', 35), - (42, '+') : ('REDUCE', 35), - (42, '-') : ('REDUCE', 35), - (42, 'loop') : ('REDUCE', 35), - (42, 'of') : ('REDUCE', 35), - (42, 'pool') : ('REDUCE', 35), - (42, ',') : ('REDUCE', 35), (42, '/') : ('SHIFT', 46), (42, '*') : ('SHIFT', 43), + (42, '}') : ('REDUCE', 36), + (42, 'fi') : ('REDUCE', 36), + (42, 'in') : ('REDUCE', 36), + (42, '<') : ('REDUCE', 36), + (42, '=') : ('REDUCE', 36), + (42, ';') : ('REDUCE', 36), + (42, '<=') : ('REDUCE', 36), + (42, '+') : ('REDUCE', 36), + (42, ')') : ('REDUCE', 36), + (42, '-') : ('REDUCE', 36), + (42, 'then') : ('REDUCE', 36), + (42, 'of') : ('REDUCE', 36), + (42, 'loop') : ('REDUCE', 36), + (42, 'else') : ('REDUCE', 36), + (42, 'pool') : ('REDUCE', 36), + (42, ',') : ('REDUCE', 36), (43, 'false') : ('SHIFT', 29), (43, 'id') : ('SHIFT', 16), + (43, 'new') : ('SHIFT', 22), (43, 'string') : ('SHIFT', 30), - (43, 'true') : ('SHIFT', 28), (43, 'int') : ('SHIFT', 21), + (43, 'true') : ('SHIFT', 28), (43, 'isvoid') : ('SHIFT', 27), (43, '~') : ('SHIFT', 15), (43, '(') : ('SHIFT', 13), - (43, 'new') : ('SHIFT', 22), - (44, '<') : ('REDUCE', 38), - (44, '<=') : ('REDUCE', 38), - (44, ')') : ('REDUCE', 38), - (44, 'then') : ('REDUCE', 38), - (44, '}') : ('REDUCE', 38), - (44, 'else') : ('REDUCE', 38), - (44, 'fi') : ('REDUCE', 38), - (44, '=') : ('REDUCE', 38), - (44, 'in') : ('REDUCE', 38), - (44, ';') : ('REDUCE', 38), - (44, '+') : ('REDUCE', 38), - (44, '-') : ('REDUCE', 38), - (44, 'loop') : ('REDUCE', 38), - (44, 'of') : ('REDUCE', 38), - (44, '*') : ('REDUCE', 38), - (44, 'pool') : ('REDUCE', 38), - (44, ',') : ('REDUCE', 38), - (44, '/') : ('REDUCE', 38), - (45, 'then') : ('REDUCE', 51), - (45, 'else') : ('REDUCE', 51), - (45, 'fi') : ('REDUCE', 51), - (45, 'of') : ('REDUCE', 51), - (45, 'in') : ('REDUCE', 51), - (45, ';') : ('REDUCE', 51), - (45, ',') : ('REDUCE', 51), - (45, '.') : ('REDUCE', 51), - (45, ')') : ('REDUCE', 51), - (45, '}') : ('REDUCE', 51), - (45, '=') : ('REDUCE', 51), - (45, '+') : ('REDUCE', 51), - (45, '-') : ('REDUCE', 51), - (45, '*') : ('REDUCE', 51), - (45, '/') : ('REDUCE', 51), - (45, '<') : ('REDUCE', 51), - (45, '<=') : ('REDUCE', 51), - (45, '@') : ('REDUCE', 51), - (45, 'loop') : ('REDUCE', 51), - (45, 'pool') : ('REDUCE', 51), + (44, '/') : ('REDUCE', 39), + (44, '}') : ('REDUCE', 39), + (44, 'fi') : ('REDUCE', 39), + (44, 'in') : ('REDUCE', 39), + (44, '<') : ('REDUCE', 39), + (44, '=') : ('REDUCE', 39), + (44, ';') : ('REDUCE', 39), + (44, '<=') : ('REDUCE', 39), + (44, '+') : ('REDUCE', 39), + (44, 'else') : ('REDUCE', 39), + (44, ')') : ('REDUCE', 39), + (44, '-') : ('REDUCE', 39), + (44, 'then') : ('REDUCE', 39), + (44, 'of') : ('REDUCE', 39), + (44, 'loop') : ('REDUCE', 39), + (44, '*') : ('REDUCE', 39), + (44, 'pool') : ('REDUCE', 39), + (44, ',') : ('REDUCE', 39), + (45, 'fi') : ('REDUCE', 52), + (45, '=') : ('REDUCE', 52), + (45, '+') : ('REDUCE', 52), + (45, '-') : ('REDUCE', 52), + (45, 'of') : ('REDUCE', 52), + (45, '*') : ('REDUCE', 52), + (45, '/') : ('REDUCE', 52), + (45, '<') : ('REDUCE', 52), + (45, '<=') : ('REDUCE', 52), + (45, '@') : ('REDUCE', 52), + (45, 'in') : ('REDUCE', 52), + (45, ';') : ('REDUCE', 52), + (45, 'loop') : ('REDUCE', 52), + (45, 'pool') : ('REDUCE', 52), + (45, ',') : ('REDUCE', 52), + (45, '.') : ('REDUCE', 52), + (45, ')') : ('REDUCE', 52), + (45, 'then') : ('REDUCE', 52), + (45, 'else') : ('REDUCE', 52), + (45, '}') : ('REDUCE', 52), (46, 'false') : ('SHIFT', 29), (46, 'id') : ('SHIFT', 16), + (46, 'new') : ('SHIFT', 22), (46, 'string') : ('SHIFT', 30), - (46, 'true') : ('SHIFT', 28), (46, 'int') : ('SHIFT', 21), + (46, 'true') : ('SHIFT', 28), (46, 'isvoid') : ('SHIFT', 27), (46, '~') : ('SHIFT', 15), (46, '(') : ('SHIFT', 13), - (46, 'new') : ('SHIFT', 22), - (47, '<') : ('REDUCE', 39), - (47, '<=') : ('REDUCE', 39), - (47, ')') : ('REDUCE', 39), - (47, 'then') : ('REDUCE', 39), - (47, '}') : ('REDUCE', 39), - (47, 'else') : ('REDUCE', 39), - (47, 'fi') : ('REDUCE', 39), - (47, '=') : ('REDUCE', 39), - (47, 'in') : ('REDUCE', 39), - (47, ';') : ('REDUCE', 39), - (47, '+') : ('REDUCE', 39), - (47, '-') : ('REDUCE', 39), - (47, 'loop') : ('REDUCE', 39), - (47, 'of') : ('REDUCE', 39), - (47, '*') : ('REDUCE', 39), - (47, 'pool') : ('REDUCE', 39), - (47, ',') : ('REDUCE', 39), - (47, '/') : ('REDUCE', 39), - (48, '<') : ('REDUCE', 40), - (48, '<=') : ('REDUCE', 40), - (48, ')') : ('REDUCE', 40), - (48, 'then') : ('REDUCE', 40), - (48, '}') : ('REDUCE', 40), - (48, 'else') : ('REDUCE', 40), - (48, 'fi') : ('REDUCE', 40), - (48, '=') : ('REDUCE', 40), - (48, 'in') : ('REDUCE', 40), - (48, ';') : ('REDUCE', 40), - (48, '+') : ('REDUCE', 40), - (48, '-') : ('REDUCE', 40), - (48, 'loop') : ('REDUCE', 40), - (48, 'of') : ('REDUCE', 40), - (48, '*') : ('REDUCE', 40), - (48, 'pool') : ('REDUCE', 40), - (48, ',') : ('REDUCE', 40), - (48, '/') : ('REDUCE', 40), - (49, 'id') : ('SHIFT', 16), + (47, '/') : ('REDUCE', 40), + (47, '}') : ('REDUCE', 40), + (47, 'fi') : ('REDUCE', 40), + (47, 'in') : ('REDUCE', 40), + (47, '<') : ('REDUCE', 40), + (47, '=') : ('REDUCE', 40), + (47, ';') : ('REDUCE', 40), + (47, '<=') : ('REDUCE', 40), + (47, '+') : ('REDUCE', 40), + (47, 'else') : ('REDUCE', 40), + (47, ')') : ('REDUCE', 40), + (47, '-') : ('REDUCE', 40), + (47, 'then') : ('REDUCE', 40), + (47, 'of') : ('REDUCE', 40), + (47, 'loop') : ('REDUCE', 40), + (47, '*') : ('REDUCE', 40), + (47, 'pool') : ('REDUCE', 40), + (47, ',') : ('REDUCE', 40), + (48, '/') : ('REDUCE', 41), + (48, '}') : ('REDUCE', 41), + (48, 'fi') : ('REDUCE', 41), + (48, 'in') : ('REDUCE', 41), + (48, '<') : ('REDUCE', 41), + (48, '=') : ('REDUCE', 41), + (48, ';') : ('REDUCE', 41), + (48, '<=') : ('REDUCE', 41), + (48, '+') : ('REDUCE', 41), + (48, 'else') : ('REDUCE', 41), + (48, ')') : ('REDUCE', 41), + (48, '-') : ('REDUCE', 41), + (48, 'then') : ('REDUCE', 41), + (48, 'of') : ('REDUCE', 41), + (48, 'loop') : ('REDUCE', 41), + (48, '*') : ('REDUCE', 41), + (48, 'pool') : ('REDUCE', 41), + (48, ',') : ('REDUCE', 41), (49, 'false') : ('SHIFT', 29), - (49, 'string') : ('SHIFT', 30), + (49, 'id') : ('SHIFT', 16), (49, 'int') : ('SHIFT', 21), - (49, '~') : ('SHIFT', 15), + (49, 'string') : ('SHIFT', 30), (49, 'isvoid') : ('SHIFT', 27), + (49, '~') : ('SHIFT', 15), (49, '(') : ('SHIFT', 13), (49, 'new') : ('SHIFT', 22), (49, 'true') : ('SHIFT', 28), (50, '/') : ('SHIFT', 46), - (50, '<') : ('REDUCE', 36), - (50, '<=') : ('REDUCE', 36), - (50, ')') : ('REDUCE', 36), - (50, 'then') : ('REDUCE', 36), - (50, '}') : ('REDUCE', 36), - (50, 'else') : ('REDUCE', 36), - (50, 'fi') : ('REDUCE', 36), - (50, '=') : ('REDUCE', 36), - (50, 'in') : ('REDUCE', 36), - (50, ';') : ('REDUCE', 36), - (50, '+') : ('REDUCE', 36), - (50, '-') : ('REDUCE', 36), - (50, 'loop') : ('REDUCE', 36), - (50, 'of') : ('REDUCE', 36), - (50, 'pool') : ('REDUCE', 36), - (50, ',') : ('REDUCE', 36), + (50, '}') : ('REDUCE', 37), + (50, 'fi') : ('REDUCE', 37), + (50, 'in') : ('REDUCE', 37), + (50, '<') : ('REDUCE', 37), + (50, '=') : ('REDUCE', 37), + (50, ';') : ('REDUCE', 37), + (50, '<=') : ('REDUCE', 37), + (50, '+') : ('REDUCE', 37), + (50, ')') : ('REDUCE', 37), + (50, '-') : ('REDUCE', 37), + (50, 'then') : ('REDUCE', 37), + (50, 'of') : ('REDUCE', 37), + (50, 'loop') : ('REDUCE', 37), + (50, 'else') : ('REDUCE', 37), + (50, 'pool') : ('REDUCE', 37), + (50, ',') : ('REDUCE', 37), (50, '*') : ('SHIFT', 43), - (51, '<') : ('REDUCE', 37), - (51, '<=') : ('REDUCE', 37), - (51, ')') : ('REDUCE', 37), - (51, 'then') : ('REDUCE', 37), - (51, '}') : ('REDUCE', 37), - (51, 'else') : ('REDUCE', 37), - (51, 'fi') : ('REDUCE', 37), - (51, '=') : ('REDUCE', 37), - (51, 'in') : ('REDUCE', 37), - (51, ';') : ('REDUCE', 37), - (51, '+') : ('REDUCE', 37), - (51, '-') : ('REDUCE', 37), - (51, 'loop') : ('REDUCE', 37), - (51, 'of') : ('REDUCE', 37), - (51, 'pool') : ('REDUCE', 37), - (51, ',') : ('REDUCE', 37), (51, '/') : ('SHIFT', 46), (51, '*') : ('SHIFT', 43), + (51, '}') : ('REDUCE', 38), + (51, 'fi') : ('REDUCE', 38), + (51, 'in') : ('REDUCE', 38), + (51, '<') : ('REDUCE', 38), + (51, '=') : ('REDUCE', 38), + (51, ';') : ('REDUCE', 38), + (51, '<=') : ('REDUCE', 38), + (51, '+') : ('REDUCE', 38), + (51, ')') : ('REDUCE', 38), + (51, '-') : ('REDUCE', 38), + (51, 'then') : ('REDUCE', 38), + (51, 'of') : ('REDUCE', 38), + (51, 'loop') : ('REDUCE', 38), + (51, 'else') : ('REDUCE', 38), + (51, 'pool') : ('REDUCE', 38), + (51, ',') : ('REDUCE', 38), (52, 'false') : ('SHIFT', 29), (52, 'id') : ('SHIFT', 16), (52, 'string') : ('SHIFT', 30), + (52, 'int') : ('SHIFT', 21), (52, 'isvoid') : ('SHIFT', 27), (52, '~') : ('SHIFT', 15), - (52, 'int') : ('SHIFT', 21), (52, '(') : ('SHIFT', 13), (52, 'new') : ('SHIFT', 22), (52, 'true') : ('SHIFT', 28), - (53, '<') : ('REDUCE', 31), - (53, '<=') : ('REDUCE', 31), - (53, ')') : ('REDUCE', 31), - (53, 'then') : ('REDUCE', 31), - (53, '}') : ('REDUCE', 31), - (53, 'else') : ('REDUCE', 31), - (53, 'fi') : ('REDUCE', 31), - (53, '=') : ('REDUCE', 31), - (53, 'in') : ('REDUCE', 31), - (53, ';') : ('REDUCE', 31), - (53, 'loop') : ('REDUCE', 31), - (53, 'of') : ('REDUCE', 31), - (53, 'pool') : ('REDUCE', 31), - (53, ',') : ('REDUCE', 31), - (53, '+') : ('SHIFT', 41), + (53, '}') : ('REDUCE', 32), + (53, 'fi') : ('REDUCE', 32), + (53, 'in') : ('REDUCE', 32), + (53, '<') : ('REDUCE', 32), + (53, '=') : ('REDUCE', 32), + (53, ';') : ('REDUCE', 32), + (53, '<=') : ('REDUCE', 32), + (53, ')') : ('REDUCE', 32), + (53, 'then') : ('REDUCE', 32), + (53, 'loop') : ('REDUCE', 32), + (53, 'of') : ('REDUCE', 32), + (53, 'else') : ('REDUCE', 32), + (53, 'pool') : ('REDUCE', 32), + (53, ',') : ('REDUCE', 32), (53, '-') : ('SHIFT', 49), + (53, '+') : ('SHIFT', 41), (54, 'false') : ('SHIFT', 29), (54, 'id') : ('SHIFT', 16), (54, 'string') : ('SHIFT', 30), + (54, 'int') : ('SHIFT', 21), (54, 'isvoid') : ('SHIFT', 27), (54, '~') : ('SHIFT', 15), - (54, 'int') : ('SHIFT', 21), (54, '(') : ('SHIFT', 13), (54, 'new') : ('SHIFT', 22), (54, 'true') : ('SHIFT', 28), (55, '-') : ('SHIFT', 49), + (55, '}') : ('REDUCE', 33), + (55, 'fi') : ('REDUCE', 33), + (55, 'in') : ('REDUCE', 33), + (55, '<') : ('REDUCE', 33), + (55, '=') : ('REDUCE', 33), + (55, ';') : ('REDUCE', 33), + (55, '<=') : ('REDUCE', 33), + (55, ')') : ('REDUCE', 33), + (55, 'then') : ('REDUCE', 33), + (55, 'loop') : ('REDUCE', 33), + (55, 'of') : ('REDUCE', 33), + (55, 'else') : ('REDUCE', 33), + (55, 'pool') : ('REDUCE', 33), + (55, ',') : ('REDUCE', 33), (55, '+') : ('SHIFT', 41), - (55, '<') : ('REDUCE', 32), - (55, '<=') : ('REDUCE', 32), - (55, ')') : ('REDUCE', 32), - (55, 'then') : ('REDUCE', 32), - (55, '}') : ('REDUCE', 32), - (55, 'else') : ('REDUCE', 32), - (55, 'fi') : ('REDUCE', 32), - (55, '=') : ('REDUCE', 32), - (55, 'in') : ('REDUCE', 32), - (55, ';') : ('REDUCE', 32), - (55, 'loop') : ('REDUCE', 32), - (55, 'of') : ('REDUCE', 32), - (55, 'pool') : ('REDUCE', 32), - (55, ',') : ('REDUCE', 32), (56, ',') : ('SHIFT', 57), - (56, ')') : ('REDUCE', 55), - (57, 'while') : ('SHIFT', 20), + (56, ')') : ('REDUCE', 56), + (57, ')') : ('REDUCE', 58), + (57, 'int') : ('SHIFT', 21), (57, 'id') : ('SHIFT', 18), (57, 'new') : ('SHIFT', 22), - (57, '~') : ('SHIFT', 15), - (57, 'case') : ('SHIFT', 25), + (57, '{') : ('SHIFT', 14), + (57, 'true') : ('SHIFT', 28), + (57, 'let') : ('SHIFT', 8), (57, 'if') : ('SHIFT', 24), + (57, 'case') : ('SHIFT', 25), (57, 'not') : ('SHIFT', 26), - (57, 'true') : ('SHIFT', 28), - (57, 'false') : ('SHIFT', 29), - (57, 'int') : ('SHIFT', 21), - (57, 'string') : ('SHIFT', 30), (57, 'isvoid') : ('SHIFT', 27), + (57, 'while') : ('SHIFT', 20), (57, '(') : ('SHIFT', 13), - (57, ')') : ('REDUCE', 57), - (57, 'let') : ('SHIFT', 8), - (57, '{') : ('SHIFT', 14), - (58, ')') : ('REDUCE', 56), - (59, '<') : ('REDUCE', 34), - (59, '<=') : ('REDUCE', 34), - (59, ')') : ('REDUCE', 34), - (59, 'then') : ('REDUCE', 34), - (59, '}') : ('REDUCE', 34), - (59, 'else') : ('REDUCE', 34), - (59, 'fi') : ('REDUCE', 34), - (59, '=') : ('REDUCE', 34), - (59, 'in') : ('REDUCE', 34), - (59, ';') : ('REDUCE', 34), - (59, 'loop') : ('REDUCE', 34), - (59, 'of') : ('REDUCE', 34), - (59, 'pool') : ('REDUCE', 34), - (59, ',') : ('REDUCE', 34), - (59, '+') : ('SHIFT', 41), + (57, 'false') : ('SHIFT', 29), + (57, 'string') : ('SHIFT', 30), + (57, '~') : ('SHIFT', 15), + (58, ')') : ('REDUCE', 57), + (59, '}') : ('REDUCE', 35), + (59, 'fi') : ('REDUCE', 35), + (59, 'in') : ('REDUCE', 35), + (59, '<') : ('REDUCE', 35), + (59, '=') : ('REDUCE', 35), + (59, ';') : ('REDUCE', 35), + (59, '<=') : ('REDUCE', 35), + (59, ')') : ('REDUCE', 35), + (59, 'then') : ('REDUCE', 35), + (59, 'loop') : ('REDUCE', 35), + (59, 'of') : ('REDUCE', 35), + (59, 'else') : ('REDUCE', 35), + (59, 'pool') : ('REDUCE', 35), + (59, ',') : ('REDUCE', 35), (59, '-') : ('SHIFT', 49), - (60, 'type') : ('SHIFT', 61), - (61, '.') : ('SHIFT', 62), - (62, 'id') : ('SHIFT', 63), - (63, '(') : ('SHIFT', 64), - (64, 'while') : ('SHIFT', 20), - (64, 'id') : ('SHIFT', 18), - (64, 'new') : ('SHIFT', 22), - (64, '~') : ('SHIFT', 15), - (64, 'case') : ('SHIFT', 25), - (64, 'if') : ('SHIFT', 24), - (64, 'not') : ('SHIFT', 26), - (64, 'true') : ('SHIFT', 28), - (64, 'false') : ('SHIFT', 29), - (64, 'int') : ('SHIFT', 21), - (64, 'string') : ('SHIFT', 30), - (64, 'isvoid') : ('SHIFT', 27), - (64, '(') : ('SHIFT', 13), - (64, ')') : ('REDUCE', 57), - (64, 'let') : ('SHIFT', 8), - (64, '{') : ('SHIFT', 14), - (65, ')') : ('SHIFT', 66), - (66, 'then') : ('REDUCE', 54), - (66, 'else') : ('REDUCE', 54), - (66, 'fi') : ('REDUCE', 54), - (66, 'of') : ('REDUCE', 54), - (66, 'in') : ('REDUCE', 54), - (66, ';') : ('REDUCE', 54), - (66, ',') : ('REDUCE', 54), - (66, '.') : ('REDUCE', 54), - (66, ')') : ('REDUCE', 54), - (66, '}') : ('REDUCE', 54), - (66, '=') : ('REDUCE', 54), - (66, '+') : ('REDUCE', 54), - (66, '-') : ('REDUCE', 54), - (66, '*') : ('REDUCE', 54), - (66, '/') : ('REDUCE', 54), - (66, '<') : ('REDUCE', 54), - (66, '<=') : ('REDUCE', 54), - (66, '@') : ('REDUCE', 54), - (66, 'loop') : ('REDUCE', 54), - (66, 'pool') : ('REDUCE', 54), - (67, ')') : ('REDUCE', 18), - (67, 'then') : ('REDUCE', 18), - (67, '}') : ('REDUCE', 18), - (67, 'else') : ('REDUCE', 18), - (67, 'fi') : ('REDUCE', 18), - (67, 'in') : ('REDUCE', 18), - (67, ';') : ('REDUCE', 18), - (67, 'loop') : ('REDUCE', 18), - (67, 'of') : ('REDUCE', 18), - (67, 'pool') : ('REDUCE', 18), - (67, ',') : ('REDUCE', 18), - (68, 'of') : ('SHIFT', 69), - (69, 'id') : ('SHIFT', 70), - (70, ':') : ('SHIFT', 71), - (71, 'type') : ('SHIFT', 72), - (72, '=>') : ('SHIFT', 73), - (73, 'if') : ('SHIFT', 24), - (73, 'not') : ('SHIFT', 26), - (73, 'id') : ('SHIFT', 18), - (73, 'false') : ('SHIFT', 29), - (73, 'int') : ('SHIFT', 21), - (73, 'string') : ('SHIFT', 30), - (73, '(') : ('SHIFT', 13), - (73, 'true') : ('SHIFT', 28), - (73, 'let') : ('SHIFT', 8), - (73, 'isvoid') : ('SHIFT', 27), - (73, '~') : ('SHIFT', 15), - (73, 'case') : ('SHIFT', 25), - (73, '{') : ('SHIFT', 14), - (73, 'new') : ('SHIFT', 22), - (73, 'while') : ('SHIFT', 20), - (74, ';') : ('SHIFT', 75), - (75, 'id') : ('SHIFT', 70), - (75, 'esac') : ('REDUCE', 28), - (76, 'esac') : ('REDUCE', 29), - (77, 'esac') : ('SHIFT', 78), - (78, ')') : ('REDUCE', 27), - (78, 'then') : ('REDUCE', 27), - (78, '}') : ('REDUCE', 27), - (78, 'else') : ('REDUCE', 27), - (78, 'fi') : ('REDUCE', 27), - (78, 'in') : ('REDUCE', 27), - (78, ';') : ('REDUCE', 27), - (78, 'loop') : ('REDUCE', 27), - (78, 'of') : ('REDUCE', 27), - (78, 'pool') : ('REDUCE', 27), - (78, ',') : ('REDUCE', 27), - (79, 'then') : ('SHIFT', 80), - (80, 'id') : ('SHIFT', 18), - (80, 'let') : ('SHIFT', 8), - (80, 'false') : ('SHIFT', 29), - (80, 'int') : ('SHIFT', 21), - (80, 'isvoid') : ('SHIFT', 27), - (80, '~') : ('SHIFT', 15), - (80, 'string') : ('SHIFT', 30), - (80, '(') : ('SHIFT', 13), - (80, 'case') : ('SHIFT', 25), - (80, 'new') : ('SHIFT', 22), - (80, 'while') : ('SHIFT', 20), - (80, 'if') : ('SHIFT', 24), - (80, 'not') : ('SHIFT', 26), - (80, '{') : ('SHIFT', 14), - (80, 'true') : ('SHIFT', 28), - (81, 'else') : ('SHIFT', 82), - (82, 'case') : ('SHIFT', 25), - (82, 'not') : ('SHIFT', 26), - (82, 'int') : ('SHIFT', 21), - (82, '(') : ('SHIFT', 13), - (82, 'while') : ('SHIFT', 20), - (82, 'id') : ('SHIFT', 18), - (82, 'true') : ('SHIFT', 28), - (82, 'if') : ('SHIFT', 24), - (82, 'false') : ('SHIFT', 29), - (82, 'let') : ('SHIFT', 8), - (82, 'string') : ('SHIFT', 30), - (82, 'isvoid') : ('SHIFT', 27), - (82, '~') : ('SHIFT', 15), - (82, 'new') : ('SHIFT', 22), - (82, '{') : ('SHIFT', 14), - (83, 'fi') : ('SHIFT', 84), - (84, ')') : ('REDUCE', 16), - (84, 'then') : ('REDUCE', 16), - (84, '}') : ('REDUCE', 16), - (84, 'else') : ('REDUCE', 16), - (84, 'fi') : ('REDUCE', 16), - (84, 'in') : ('REDUCE', 16), - (84, ';') : ('REDUCE', 16), - (84, 'loop') : ('REDUCE', 16), - (84, 'of') : ('REDUCE', 16), - (84, 'pool') : ('REDUCE', 16), - (84, ',') : ('REDUCE', 16), - (85, 'loop') : ('SHIFT', 86), - (86, 'let') : ('SHIFT', 8), - (86, 'new') : ('SHIFT', 22), - (86, 'id') : ('SHIFT', 18), - (86, 'isvoid') : ('SHIFT', 27), - (86, '~') : ('SHIFT', 15), - (86, 'case') : ('SHIFT', 25), - (86, '{') : ('SHIFT', 14), - (86, 'true') : ('SHIFT', 28), - (86, 'while') : ('SHIFT', 20), - (86, 'false') : ('SHIFT', 29), - (86, 'int') : ('SHIFT', 21), - (86, 'string') : ('SHIFT', 30), - (86, '(') : ('SHIFT', 13), - (86, 'if') : ('SHIFT', 24), - (86, 'not') : ('SHIFT', 26), - (87, 'pool') : ('SHIFT', 88), - (88, ')') : ('REDUCE', 17), - (88, 'then') : ('REDUCE', 17), - (88, '}') : ('REDUCE', 17), - (88, 'else') : ('REDUCE', 17), - (88, 'fi') : ('REDUCE', 17), - (88, 'in') : ('REDUCE', 17), - (88, ';') : ('REDUCE', 17), - (88, 'loop') : ('REDUCE', 17), - (88, 'of') : ('REDUCE', 17), - (88, 'pool') : ('REDUCE', 17), - (88, ',') : ('REDUCE', 17), - (89, ')') : ('REDUCE', 15), - (89, 'then') : ('REDUCE', 15), - (89, '}') : ('REDUCE', 15), - (89, 'else') : ('REDUCE', 15), - (89, 'fi') : ('REDUCE', 15), - (89, 'in') : ('REDUCE', 15), - (89, ';') : ('REDUCE', 15), - (89, 'loop') : ('REDUCE', 15), - (89, 'of') : ('REDUCE', 15), - (89, 'pool') : ('REDUCE', 15), - (89, ',') : ('REDUCE', 15), - (90, ')') : ('SHIFT', 91), - (91, 'then') : ('REDUCE', 53), - (91, 'else') : ('REDUCE', 53), - (91, 'fi') : ('REDUCE', 53), - (91, 'of') : ('REDUCE', 53), - (91, 'in') : ('REDUCE', 53), - (91, ';') : ('REDUCE', 53), - (91, ',') : ('REDUCE', 53), - (91, '.') : ('REDUCE', 53), - (91, ')') : ('REDUCE', 53), - (91, '}') : ('REDUCE', 53), - (91, '=') : ('REDUCE', 53), - (91, '+') : ('REDUCE', 53), - (91, '-') : ('REDUCE', 53), - (91, '*') : ('REDUCE', 53), - (91, '/') : ('REDUCE', 53), - (91, '<') : ('REDUCE', 53), - (91, '<=') : ('REDUCE', 53), - (91, '@') : ('REDUCE', 53), - (91, 'loop') : ('REDUCE', 53), - (91, 'pool') : ('REDUCE', 53), - (92, '<') : ('REDUCE', 42), - (92, '<=') : ('REDUCE', 42), - (92, ')') : ('REDUCE', 42), - (92, 'then') : ('REDUCE', 42), - (92, '}') : ('REDUCE', 42), - (92, 'else') : ('REDUCE', 42), - (92, 'fi') : ('REDUCE', 42), - (92, '=') : ('REDUCE', 42), - (92, 'in') : ('REDUCE', 42), - (92, ';') : ('REDUCE', 42), - (92, '+') : ('REDUCE', 42), - (92, '-') : ('REDUCE', 42), - (92, 'loop') : ('REDUCE', 42), - (92, 'of') : ('REDUCE', 42), - (92, '*') : ('REDUCE', 42), - (92, 'pool') : ('REDUCE', 42), - (92, ',') : ('REDUCE', 42), - (92, '/') : ('REDUCE', 42), - (93, '}') : ('SHIFT', 94), - (94, ')') : ('REDUCE', 19), - (94, 'then') : ('REDUCE', 19), - (94, '}') : ('REDUCE', 19), - (94, 'else') : ('REDUCE', 19), - (94, 'fi') : ('REDUCE', 19), - (94, 'in') : ('REDUCE', 19), - (94, ';') : ('REDUCE', 19), - (94, 'loop') : ('REDUCE', 19), - (94, 'of') : ('REDUCE', 19), - (94, 'pool') : ('REDUCE', 19), - (94, ',') : ('REDUCE', 19), - (95, ';') : ('SHIFT', 96), - (96, 'if') : ('SHIFT', 24), - (96, 'not') : ('SHIFT', 26), - (96, 'id') : ('SHIFT', 18), - (96, 'false') : ('SHIFT', 29), - (96, 'int') : ('SHIFT', 21), - (96, 'string') : ('SHIFT', 30), - (96, '(') : ('SHIFT', 13), - (96, '}') : ('REDUCE', 20), - (96, 'true') : ('SHIFT', 28), - (96, 'let') : ('SHIFT', 8), - (96, 'isvoid') : ('SHIFT', 27), - (96, '~') : ('SHIFT', 15), - (96, 'case') : ('SHIFT', 25), - (96, '{') : ('SHIFT', 14), - (96, 'new') : ('SHIFT', 22), - (96, 'while') : ('SHIFT', 20), - (97, '}') : ('REDUCE', 21), - (98, ')') : ('SHIFT', 99), - (99, 'then') : ('REDUCE', 50), - (99, 'else') : ('REDUCE', 50), - (99, 'fi') : ('REDUCE', 50), - (99, 'of') : ('REDUCE', 50), - (99, 'in') : ('REDUCE', 50), - (99, ';') : ('REDUCE', 50), - (99, ',') : ('REDUCE', 50), - (99, '.') : ('REDUCE', 50), - (99, ')') : ('REDUCE', 50), - (99, '}') : ('REDUCE', 50), - (99, '=') : ('REDUCE', 50), - (99, '+') : ('REDUCE', 50), - (99, '-') : ('REDUCE', 50), - (99, '*') : ('REDUCE', 50), - (99, '/') : ('REDUCE', 50), - (99, '<') : ('REDUCE', 50), - (99, '<=') : ('REDUCE', 50), - (99, '@') : ('REDUCE', 50), - (99, 'loop') : ('REDUCE', 50), - (99, 'pool') : ('REDUCE', 50), - (100, 'in') : ('REDUCE', 24), - (100, ',') : ('SHIFT', 101), - (101, 'id') : ('SHIFT', 9), - (102, 'in') : ('REDUCE', 26), - (103, 'id') : ('SHIFT', 9), - (104, 'in') : ('REDUCE', 25), - (105, 'in') : ('SHIFT', 106), - (106, 'id') : ('SHIFT', 18), - (106, 'false') : ('SHIFT', 29), - (106, 'let') : ('SHIFT', 8), - (106, 'string') : ('SHIFT', 30), - (106, 'isvoid') : ('SHIFT', 27), - (106, 'case') : ('SHIFT', 25), - (106, '~') : ('SHIFT', 15), - (106, '{') : ('SHIFT', 14), - (106, 'new') : ('SHIFT', 22), - (106, 'while') : ('SHIFT', 20), - (106, 'if') : ('SHIFT', 24), - (106, 'not') : ('SHIFT', 26), - (106, 'int') : ('SHIFT', 21), - (106, '(') : ('SHIFT', 13), - (106, 'true') : ('SHIFT', 28), - (107, ')') : ('REDUCE', 22), - (107, 'then') : ('REDUCE', 22), - (107, '}') : ('REDUCE', 22), - (107, 'else') : ('REDUCE', 22), - (107, 'fi') : ('REDUCE', 22), - (107, 'in') : ('REDUCE', 22), - (107, ';') : ('REDUCE', 22), - (107, 'loop') : ('REDUCE', 22), - (107, 'of') : ('REDUCE', 22), - (107, 'pool') : ('REDUCE', 22), - (107, ',') : ('REDUCE', 22), - (108, ';') : ('REDUCE', 9), - (109, ')') : ('REDUCE', 13), - (109, 'id') : ('SHIFT', 110), - (110, ':') : ('SHIFT', 111), - (111, 'type') : ('SHIFT', 112), - (112, ',') : ('REDUCE', 14), - (112, ')') : ('REDUCE', 14), - (113, ')') : ('SHIFT', 114), - (114, ':') : ('SHIFT', 115), - (115, 'type') : ('SHIFT', 116), - (116, '{') : ('SHIFT', 117), - (117, 'string') : ('SHIFT', 30), - (117, '(') : ('SHIFT', 13), - (117, 'isvoid') : ('SHIFT', 27), - (117, '~') : ('SHIFT', 15), - (117, 'let') : ('SHIFT', 8), - (117, 'true') : ('SHIFT', 28), - (117, 'case') : ('SHIFT', 25), - (117, '{') : ('SHIFT', 14), - (117, 'while') : ('SHIFT', 20), - (117, 'id') : ('SHIFT', 18), - (117, 'new') : ('SHIFT', 22), - (117, 'if') : ('SHIFT', 24), - (117, 'not') : ('SHIFT', 26), - (117, 'false') : ('SHIFT', 29), - (117, 'int') : ('SHIFT', 21), - (118, '}') : ('SHIFT', 119), - (119, ';') : ('REDUCE', 10), - (120, ',') : ('SHIFT', 121), - (120, ')') : ('REDUCE', 11), - (121, ')') : ('REDUCE', 13), - (121, 'id') : ('SHIFT', 110), - (122, ')') : ('REDUCE', 12), - (123, '}') : ('SHIFT', 124), - (124, ';') : ('REDUCE', 3), - (125, ';') : ('SHIFT', 126), - (126, 'id') : ('SHIFT', 4), - (126, '}') : ('REDUCE', 7), - (127, '}') : ('REDUCE', 5), - (128, ';') : ('SHIFT', 129), - (129, 'id') : ('SHIFT', 4), - (129, '}') : ('REDUCE', 7), - (130, '}') : ('REDUCE', 6), - (131, 'type') : ('SHIFT', 132), - (132, '{') : ('SHIFT', 133), - (133, 'id') : ('SHIFT', 4), - (133, '}') : ('REDUCE', 7), - (134, '}') : ('SHIFT', 135), - (135, ';') : ('REDUCE', 4), - (136, '$') : ('REDUCE', 0), - (137, ';') : ('SHIFT', 138), - (138, 'class') : ('SHIFT', 1), - (138, '$') : ('REDUCE', 1), - (139, '$') : ('REDUCE', 2), - (140, '$') : ('OK', None) + (59, '+') : ('SHIFT', 41), + (60, 'pool') : ('REDUCE', 29), + (60, 'fi') : ('REDUCE', 29), + (60, 'in') : ('REDUCE', 29), + (60, ';') : ('REDUCE', 29), + (60, ')') : ('REDUCE', 29), + (60, 'then') : ('REDUCE', 29), + (60, 'of') : ('REDUCE', 29), + (60, 'loop') : ('REDUCE', 29), + (60, 'else') : ('REDUCE', 29), + (60, '}') : ('REDUCE', 29), + (60, ',') : ('REDUCE', 29), + (61, 'type') : ('SHIFT', 62), + (62, '.') : ('SHIFT', 63), + (63, 'id') : ('SHIFT', 64), + (64, '(') : ('SHIFT', 65), + (65, ')') : ('REDUCE', 58), + (65, '~') : ('SHIFT', 15), + (65, 'id') : ('SHIFT', 18), + (65, 'new') : ('SHIFT', 22), + (65, '{') : ('SHIFT', 14), + (65, 'true') : ('SHIFT', 28), + (65, 'let') : ('SHIFT', 8), + (65, 'if') : ('SHIFT', 24), + (65, 'case') : ('SHIFT', 25), + (65, 'string') : ('SHIFT', 30), + (65, 'isvoid') : ('SHIFT', 27), + (65, 'while') : ('SHIFT', 20), + (65, '(') : ('SHIFT', 13), + (65, 'false') : ('SHIFT', 29), + (65, 'int') : ('SHIFT', 21), + (65, 'not') : ('SHIFT', 26), + (66, ')') : ('SHIFT', 67), + (67, 'fi') : ('REDUCE', 55), + (67, '=') : ('REDUCE', 55), + (67, '+') : ('REDUCE', 55), + (67, '-') : ('REDUCE', 55), + (67, 'of') : ('REDUCE', 55), + (67, '*') : ('REDUCE', 55), + (67, '/') : ('REDUCE', 55), + (67, '<') : ('REDUCE', 55), + (67, '<=') : ('REDUCE', 55), + (67, '@') : ('REDUCE', 55), + (67, 'in') : ('REDUCE', 55), + (67, ';') : ('REDUCE', 55), + (67, 'loop') : ('REDUCE', 55), + (67, 'pool') : ('REDUCE', 55), + (67, ',') : ('REDUCE', 55), + (67, '.') : ('REDUCE', 55), + (67, ')') : ('REDUCE', 55), + (67, 'then') : ('REDUCE', 55), + (67, 'else') : ('REDUCE', 55), + (67, '}') : ('REDUCE', 55), + (68, '<=') : ('SHIFT', 54), + (68, '<') : ('SHIFT', 52), + (68, '=') : ('SHIFT', 39), + (68, '}') : ('REDUCE', 31), + (68, 'fi') : ('REDUCE', 31), + (68, 'in') : ('REDUCE', 31), + (68, ';') : ('REDUCE', 31), + (68, ')') : ('REDUCE', 31), + (68, 'then') : ('REDUCE', 31), + (68, 'of') : ('REDUCE', 31), + (68, 'loop') : ('REDUCE', 31), + (68, 'else') : ('REDUCE', 31), + (68, 'pool') : ('REDUCE', 31), + (68, ',') : ('REDUCE', 31), + (69, 'of') : ('SHIFT', 70), + (70, 'id') : ('SHIFT', 71), + (71, ':') : ('SHIFT', 72), + (72, 'type') : ('SHIFT', 73), + (73, '=>') : ('SHIFT', 74), + (74, 'isvoid') : ('SHIFT', 27), + (74, '{') : ('SHIFT', 14), + (74, '(') : ('SHIFT', 13), + (74, 'let') : ('SHIFT', 8), + (74, 'if') : ('SHIFT', 24), + (74, 'case') : ('SHIFT', 25), + (74, 'id') : ('SHIFT', 18), + (74, 'false') : ('SHIFT', 29), + (74, 'int') : ('SHIFT', 21), + (74, 'string') : ('SHIFT', 30), + (74, 'while') : ('SHIFT', 20), + (74, '~') : ('SHIFT', 15), + (74, 'new') : ('SHIFT', 22), + (74, 'true') : ('SHIFT', 28), + (74, 'not') : ('SHIFT', 26), + (75, ';') : ('SHIFT', 76), + (76, 'id') : ('SHIFT', 71), + (76, 'esac') : ('REDUCE', 27), + (77, 'esac') : ('REDUCE', 28), + (78, 'esac') : ('SHIFT', 79), + (79, '}') : ('REDUCE', 26), + (79, 'fi') : ('REDUCE', 26), + (79, 'in') : ('REDUCE', 26), + (79, ';') : ('REDUCE', 26), + (79, ')') : ('REDUCE', 26), + (79, 'then') : ('REDUCE', 26), + (79, 'loop') : ('REDUCE', 26), + (79, 'of') : ('REDUCE', 26), + (79, 'else') : ('REDUCE', 26), + (79, 'pool') : ('REDUCE', 26), + (79, ',') : ('REDUCE', 26), + (80, 'then') : ('SHIFT', 81), + (81, 'not') : ('SHIFT', 26), + (81, 'new') : ('SHIFT', 22), + (81, 'true') : ('SHIFT', 28), + (81, '{') : ('SHIFT', 14), + (81, 'id') : ('SHIFT', 18), + (81, 'let') : ('SHIFT', 8), + (81, 'case') : ('SHIFT', 25), + (81, 'if') : ('SHIFT', 24), + (81, '~') : ('SHIFT', 15), + (81, '(') : ('SHIFT', 13), + (81, 'while') : ('SHIFT', 20), + (81, 'false') : ('SHIFT', 29), + (81, 'isvoid') : ('SHIFT', 27), + (81, 'string') : ('SHIFT', 30), + (81, 'int') : ('SHIFT', 21), + (82, 'else') : ('SHIFT', 83), + (83, '(') : ('SHIFT', 13), + (83, 'isvoid') : ('SHIFT', 27), + (83, 'not') : ('SHIFT', 26), + (83, 'id') : ('SHIFT', 18), + (83, 'false') : ('SHIFT', 29), + (83, 'string') : ('SHIFT', 30), + (83, 'int') : ('SHIFT', 21), + (83, '{') : ('SHIFT', 14), + (83, 'let') : ('SHIFT', 8), + (83, 'case') : ('SHIFT', 25), + (83, 'if') : ('SHIFT', 24), + (83, 'new') : ('SHIFT', 22), + (83, 'true') : ('SHIFT', 28), + (83, '~') : ('SHIFT', 15), + (83, 'while') : ('SHIFT', 20), + (84, 'fi') : ('SHIFT', 85), + (85, '}') : ('REDUCE', 16), + (85, 'fi') : ('REDUCE', 16), + (85, 'in') : ('REDUCE', 16), + (85, ';') : ('REDUCE', 16), + (85, ')') : ('REDUCE', 16), + (85, 'then') : ('REDUCE', 16), + (85, 'loop') : ('REDUCE', 16), + (85, 'of') : ('REDUCE', 16), + (85, 'else') : ('REDUCE', 16), + (85, 'pool') : ('REDUCE', 16), + (85, ',') : ('REDUCE', 16), + (86, 'loop') : ('SHIFT', 87), + (87, 'true') : ('SHIFT', 28), + (87, 'not') : ('SHIFT', 26), + (87, '{') : ('SHIFT', 14), + (87, 'isvoid') : ('SHIFT', 27), + (87, '(') : ('SHIFT', 13), + (87, 'let') : ('SHIFT', 8), + (87, 'if') : ('SHIFT', 24), + (87, 'case') : ('SHIFT', 25), + (87, 'id') : ('SHIFT', 18), + (87, 'false') : ('SHIFT', 29), + (87, 'int') : ('SHIFT', 21), + (87, 'string') : ('SHIFT', 30), + (87, 'while') : ('SHIFT', 20), + (87, '~') : ('SHIFT', 15), + (87, 'new') : ('SHIFT', 22), + (88, 'pool') : ('SHIFT', 89), + (89, '}') : ('REDUCE', 17), + (89, 'fi') : ('REDUCE', 17), + (89, 'in') : ('REDUCE', 17), + (89, ';') : ('REDUCE', 17), + (89, ')') : ('REDUCE', 17), + (89, 'then') : ('REDUCE', 17), + (89, 'of') : ('REDUCE', 17), + (89, 'loop') : ('REDUCE', 17), + (89, 'else') : ('REDUCE', 17), + (89, 'pool') : ('REDUCE', 17), + (89, ',') : ('REDUCE', 17), + (90, '}') : ('REDUCE', 15), + (90, 'fi') : ('REDUCE', 15), + (90, 'in') : ('REDUCE', 15), + (90, ';') : ('REDUCE', 15), + (90, ')') : ('REDUCE', 15), + (90, 'then') : ('REDUCE', 15), + (90, 'loop') : ('REDUCE', 15), + (90, 'of') : ('REDUCE', 15), + (90, 'else') : ('REDUCE', 15), + (90, 'pool') : ('REDUCE', 15), + (90, ',') : ('REDUCE', 15), + (91, ')') : ('SHIFT', 92), + (92, 'fi') : ('REDUCE', 54), + (92, '=') : ('REDUCE', 54), + (92, '+') : ('REDUCE', 54), + (92, '-') : ('REDUCE', 54), + (92, 'of') : ('REDUCE', 54), + (92, '*') : ('REDUCE', 54), + (92, '/') : ('REDUCE', 54), + (92, '<') : ('REDUCE', 54), + (92, '<=') : ('REDUCE', 54), + (92, '@') : ('REDUCE', 54), + (92, 'in') : ('REDUCE', 54), + (92, ';') : ('REDUCE', 54), + (92, 'loop') : ('REDUCE', 54), + (92, 'pool') : ('REDUCE', 54), + (92, ',') : ('REDUCE', 54), + (92, '.') : ('REDUCE', 54), + (92, ')') : ('REDUCE', 54), + (92, 'then') : ('REDUCE', 54), + (92, 'else') : ('REDUCE', 54), + (92, '}') : ('REDUCE', 54), + (93, '/') : ('REDUCE', 43), + (93, '}') : ('REDUCE', 43), + (93, 'fi') : ('REDUCE', 43), + (93, 'in') : ('REDUCE', 43), + (93, '<') : ('REDUCE', 43), + (93, '=') : ('REDUCE', 43), + (93, ';') : ('REDUCE', 43), + (93, '<=') : ('REDUCE', 43), + (93, '+') : ('REDUCE', 43), + (93, 'else') : ('REDUCE', 43), + (93, ')') : ('REDUCE', 43), + (93, '-') : ('REDUCE', 43), + (93, 'then') : ('REDUCE', 43), + (93, 'of') : ('REDUCE', 43), + (93, 'loop') : ('REDUCE', 43), + (93, '*') : ('REDUCE', 43), + (93, 'pool') : ('REDUCE', 43), + (93, ',') : ('REDUCE', 43), + (94, '}') : ('SHIFT', 95), + (95, '}') : ('REDUCE', 18), + (95, 'fi') : ('REDUCE', 18), + (95, 'in') : ('REDUCE', 18), + (95, ';') : ('REDUCE', 18), + (95, ')') : ('REDUCE', 18), + (95, 'then') : ('REDUCE', 18), + (95, 'of') : ('REDUCE', 18), + (95, 'loop') : ('REDUCE', 18), + (95, 'else') : ('REDUCE', 18), + (95, 'pool') : ('REDUCE', 18), + (95, ',') : ('REDUCE', 18), + (96, ';') : ('SHIFT', 97), + (97, 'isvoid') : ('SHIFT', 27), + (97, '{') : ('SHIFT', 14), + (97, '(') : ('SHIFT', 13), + (97, 'let') : ('SHIFT', 8), + (97, 'if') : ('SHIFT', 24), + (97, 'case') : ('SHIFT', 25), + (97, 'id') : ('SHIFT', 18), + (97, 'false') : ('SHIFT', 29), + (97, 'int') : ('SHIFT', 21), + (97, 'string') : ('SHIFT', 30), + (97, 'while') : ('SHIFT', 20), + (97, '}') : ('REDUCE', 19), + (97, '~') : ('SHIFT', 15), + (97, 'new') : ('SHIFT', 22), + (97, 'true') : ('SHIFT', 28), + (97, 'not') : ('SHIFT', 26), + (98, '}') : ('REDUCE', 20), + (99, ')') : ('SHIFT', 100), + (100, 'fi') : ('REDUCE', 51), + (100, '=') : ('REDUCE', 51), + (100, '+') : ('REDUCE', 51), + (100, '-') : ('REDUCE', 51), + (100, 'of') : ('REDUCE', 51), + (100, '*') : ('REDUCE', 51), + (100, '/') : ('REDUCE', 51), + (100, '<') : ('REDUCE', 51), + (100, '<=') : ('REDUCE', 51), + (100, '@') : ('REDUCE', 51), + (100, 'in') : ('REDUCE', 51), + (100, ';') : ('REDUCE', 51), + (100, 'loop') : ('REDUCE', 51), + (100, 'pool') : ('REDUCE', 51), + (100, ',') : ('REDUCE', 51), + (100, '.') : ('REDUCE', 51), + (100, ')') : ('REDUCE', 51), + (100, 'then') : ('REDUCE', 51), + (100, 'else') : ('REDUCE', 51), + (100, '}') : ('REDUCE', 51), + (101, 'in') : ('REDUCE', 23), + (101, ',') : ('SHIFT', 102), + (102, 'id') : ('SHIFT', 9), + (103, 'in') : ('REDUCE', 25), + (104, 'id') : ('SHIFT', 9), + (105, 'in') : ('REDUCE', 24), + (106, 'in') : ('SHIFT', 107), + (107, 'false') : ('SHIFT', 29), + (107, '{') : ('SHIFT', 14), + (107, 'id') : ('SHIFT', 18), + (107, 'string') : ('SHIFT', 30), + (107, 'int') : ('SHIFT', 21), + (107, 'isvoid') : ('SHIFT', 27), + (107, 'let') : ('SHIFT', 8), + (107, 'if') : ('SHIFT', 24), + (107, 'case') : ('SHIFT', 25), + (107, 'new') : ('SHIFT', 22), + (107, 'true') : ('SHIFT', 28), + (107, 'while') : ('SHIFT', 20), + (107, '~') : ('SHIFT', 15), + (107, '(') : ('SHIFT', 13), + (107, 'not') : ('SHIFT', 26), + (108, '}') : ('REDUCE', 21), + (108, 'fi') : ('REDUCE', 21), + (108, 'in') : ('REDUCE', 21), + (108, ';') : ('REDUCE', 21), + (108, ')') : ('REDUCE', 21), + (108, 'then') : ('REDUCE', 21), + (108, 'of') : ('REDUCE', 21), + (108, 'loop') : ('REDUCE', 21), + (108, 'else') : ('REDUCE', 21), + (108, 'pool') : ('REDUCE', 21), + (108, ',') : ('REDUCE', 21), + (109, ';') : ('REDUCE', 9), + (110, 'id') : ('SHIFT', 111), + (110, ')') : ('REDUCE', 13), + (111, ':') : ('SHIFT', 112), + (112, 'type') : ('SHIFT', 113), + (113, ')') : ('REDUCE', 14), + (113, ',') : ('REDUCE', 14), + (114, ')') : ('SHIFT', 115), + (115, ':') : ('SHIFT', 116), + (116, 'type') : ('SHIFT', 117), + (117, '{') : ('SHIFT', 118), + (118, 'isvoid') : ('SHIFT', 27), + (118, 'id') : ('SHIFT', 18), + (118, 'let') : ('SHIFT', 8), + (118, 'new') : ('SHIFT', 22), + (118, 'true') : ('SHIFT', 28), + (118, 'while') : ('SHIFT', 20), + (118, '~') : ('SHIFT', 15), + (118, '(') : ('SHIFT', 13), + (118, 'not') : ('SHIFT', 26), + (118, 'int') : ('SHIFT', 21), + (118, '{') : ('SHIFT', 14), + (118, 'false') : ('SHIFT', 29), + (118, 'if') : ('SHIFT', 24), + (118, 'string') : ('SHIFT', 30), + (118, 'case') : ('SHIFT', 25), + (119, '}') : ('SHIFT', 120), + (120, ';') : ('REDUCE', 10), + (121, ')') : ('REDUCE', 11), + (121, ',') : ('SHIFT', 122), + (122, 'id') : ('SHIFT', 111), + (122, ')') : ('REDUCE', 13), + (123, ')') : ('REDUCE', 12), + (124, '}') : ('SHIFT', 125), + (125, ';') : ('REDUCE', 3), + (126, ';') : ('SHIFT', 127), + (127, 'id') : ('SHIFT', 4), + (127, '}') : ('REDUCE', 7), + (128, '}') : ('REDUCE', 5), + (129, ';') : ('SHIFT', 130), + (130, 'id') : ('SHIFT', 4), + (130, '}') : ('REDUCE', 7), + (131, '}') : ('REDUCE', 6), + (132, 'type') : ('SHIFT', 133), + (133, '{') : ('SHIFT', 134), + (134, '}') : ('REDUCE', 7), + (134, 'id') : ('SHIFT', 4), + (135, '}') : ('SHIFT', 136), + (136, ';') : ('REDUCE', 4), + (137, '$') : ('REDUCE', 0), + (141, '$') : ('OK', None), + (138, ';') : ('SHIFT', 139), + (139, '$') : ('REDUCE', 1), + (139, 'class') : ('SHIFT', 1), + (140, '$') : ('REDUCE', 2) } self.goto = { - (0, '') : 137, - (0, ''): 140, - (0, '') : 136, - (3, '') : 123, - (3, '') : 125, - (3, '') : 128, - (7, '') : 59, + (0, '') : 137, + (0, ''): 141, + (0, '') : 138, + (3, '') : 124, + (3, '') : 126, + (3, '') : 129, (7, '') : 38, - (7, '') : 48, - (7, '') : 51, (7, '') : 32, + (7, '') : 51, + (7, '') : 48, + (7, '') : 59, + (7, '') : 109, (7, '') : 45, - (7, '') : 108, - (8, '') : 105, - (12, '') : 51, - (12, '') : 48, + (7, '') : 60, + (8, '') : 106, (12, '') : 38, - (12, '') : 100, + (12, '') : 51, (12, '') : 32, - (12, '') : 45, + (12, '') : 48, (12, '') : 59, - (13, '') : 51, + (12, '') : 60, + (12, '') : 101, + (12, '') : 45, + (13, '') : 99, (13, '') : 38, - (13, '') : 59, + (13, '') : 51, + (13, '') : 60, (13, '') : 32, - (13, '') : 45, - (13, '') : 98, + (13, '') : 59, (13, '') : 48, - (14, '') : 95, - (14, '') : 32, - (14, '') : 59, + (13, '') : 45, (14, '') : 38, - (14, '') : 48, + (14, '') : 32, (14, '') : 51, + (14, '') : 48, + (14, '') : 59, (14, '') : 45, - (14, '') : 93, - (15, '') : 45, - (15, '') : 92, + (14, '') : 96, + (14, '') : 94, + (14, '') : 60, (15, '') : 32, - (17, '') : 38, - (17, '') : 48, + (15, '') : 93, + (15, '') : 45, (17, '') : 51, - (17, '') : 59, + (17, '') : 60, (17, '') : 32, - (17, '') : 90, - (17, '') : 45, + (17, '') : 91, + (17, '') : 59, + (17, '') : 38, (17, '') : 56, + (17, '') : 48, + (17, '') : 45, (19, '') : 38, (19, '') : 51, - (19, '') : 32, + (19, '') : 90, (19, '') : 59, + (19, '') : 32, (19, '') : 48, - (19, '') : 89, + (19, '') : 60, (19, '') : 45, - (20, '') : 59, - (20, '') : 38, (20, '') : 32, (20, '') : 51, - (20, '') : 48, - (20, '') : 85, + (20, '') : 38, (20, '') : 45, + (20, '') : 48, + (20, '') : 59, + (20, '') : 86, + (20, '') : 60, (24, '') : 38, - (24, '') : 32, (24, '') : 51, - (24, '') : 59, - (24, '') : 48, - (24, '') : 79, + (24, '') : 32, + (24, '') : 60, (24, '') : 45, + (24, '') : 48, + (24, '') : 59, + (24, '') : 80, + (25, '') : 32, (25, '') : 59, - (25, '') : 51, + (25, '') : 60, (25, '') : 38, - (25, '') : 32, - (25, '') : 48, + (25, '') : 51, (25, '') : 45, - (25, '') : 68, - (26, '') : 38, + (25, '') : 69, + (25, '') : 48, + (26, '') : 68, (26, '') : 51, - (26, '') : 32, - (26, '') : 67, (26, '') : 59, + (26, '') : 32, (26, '') : 48, (26, '') : 45, + (27, '') : 32, (27, '') : 31, (27, '') : 45, - (27, '') : 32, - (35, '') : 38, (35, '') : 36, - (35, '') : 48, (35, '') : 51, - (35, '') : 59, + (35, '') : 60, (35, '') : 32, - (35, '') : 45, + (35, '') : 59, + (35, '') : 38, (35, '') : 56, - (39, '') : 40, + (35, '') : 48, + (35, '') : 45, (39, '') : 51, (39, '') : 32, (39, '') : 48, + (39, '') : 40, (39, '') : 45, (41, '') : 42, (41, '') : 32, (41, '') : 48, (41, '') : 45, - (43, '') : 45, (43, '') : 32, (43, '') : 44, - (46, '') : 45, + (43, '') : 45, (46, '') : 32, (46, '') : 47, + (46, '') : 45, (49, '') : 50, (49, '') : 32, (49, '') : 48, @@ -1193,91 +1210,100 @@ def __init__(self, G): (54, '') : 32, (54, '') : 48, (54, '') : 45, - (57, '') : 38, - (57, '') : 48, (57, '') : 51, - (57, '') : 59, + (57, '') : 60, (57, '') : 32, + (57, '') : 59, + (57, '') : 38, + (57, '') : 56, + (57, '') : 48, (57, '') : 58, (57, '') : 45, - (57, '') : 56, - (64, '') : 38, - (64, '') : 48, - (64, '') : 51, - (64, '') : 59, - (64, '') : 32, - (64, '') : 45, - (64, '') : 56, - (64, '') : 65, - (69, '') : 77, - (73, '') : 59, - (73, '') : 38, - (73, '') : 48, - (73, '') : 51, - (73, '') : 32, - (73, '') : 74, - (73, '') : 45, - (75, '') : 76, - (80, '') : 48, - (80, '') : 51, - (80, '') : 59, - (80, '') : 32, - (80, '') : 38, - (80, '') : 45, - (80, '') : 81, - (82, '') : 32, - (82, '') : 38, - (82, '') : 59, - (82, '') : 51, - (82, '') : 45, - (82, '') : 48, - (82, '') : 83, - (86, '') : 59, - (86, '') : 48, - (86, '') : 51, - (86, '') : 38, - (86, '') : 32, - (86, '') : 45, - (86, '') : 87, - (96, '') : 95, - (96, '') : 59, - (96, '') : 38, - (96, '') : 48, - (96, '') : 51, - (96, '') : 32, - (96, '') : 45, - (96, '') : 97, - (101, '') : 102, - (103, '') : 104, - (106, '') : 38, - (106, '') : 51, - (106, '') : 32, - (106, '') : 59, - (106, '') : 48, - (106, '') : 45, - (106, '') : 107, - (109, '') : 113, - (109, '') : 120, - (117, '') : 51, - (117, '') : 59, - (117, '') : 45, - (117, '') : 32, - (117, '') : 118, - (117, '') : 38, - (117, '') : 48, - (121, '') : 120, - (121, '') : 122, - (126, '') : 127, - (126, '') : 125, - (126, '') : 128, - (129, '') : 130, - (129, '') : 125, - (129, '') : 128, - (133, '') : 134, - (133, '') : 125, - (133, '') : 128, - (138, '') : 137, - (138, '') : 139 + (65, '') : 51, + (65, '') : 60, + (65, '') : 32, + (65, '') : 59, + (65, '') : 38, + (65, '') : 66, + (65, '') : 56, + (65, '') : 48, + (65, '') : 45, + (70, '') : 78, + (74, '') : 38, + (74, '') : 75, + (74, '') : 32, + (74, '') : 51, + (74, '') : 48, + (74, '') : 59, + (74, '') : 45, + (74, '') : 60, + (76, '') : 77, + (81, '') : 51, + (81, '') : 32, + (81, '') : 48, + (81, '') : 59, + (81, '') : 60, + (81, '') : 38, + (81, '') : 82, + (81, '') : 45, + (83, '') : 59, + (83, '') : 32, + (83, '') : 38, + (83, '') : 51, + (83, '') : 45, + (83, '') : 60, + (83, '') : 48, + (83, '') : 84, + (87, '') : 88, + (87, '') : 38, + (87, '') : 59, + (87, '') : 60, + (87, '') : 32, + (87, '') : 51, + (87, '') : 48, + (87, '') : 45, + (97, '') : 38, + (97, '') : 32, + (97, '') : 51, + (97, '') : 48, + (97, '') : 59, + (97, '') : 45, + (97, '') : 96, + (97, '') : 98, + (97, '') : 60, + (102, '') : 103, + (104, '') : 105, + (107, '') : 38, + (107, '') : 51, + (107, '') : 59, + (107, '') : 32, + (107, '') : 48, + (107, '') : 108, + (107, '') : 60, + (107, '') : 45, + (110, '') : 121, + (110, '') : 114, + (118, '') : 59, + (118, '') : 32, + (118, '') : 51, + (118, '') : 48, + (118, '') : 38, + (118, '') : 119, + (118, '') : 60, + (118, '') : 45, + (122, '') : 121, + (122, '') : 123, + (127, '') : 126, + (127, '') : 128, + (127, '') : 129, + (130, '') : 126, + (130, '') : 131, + (130, '') : 129, + (134, '') : 126, + (134, '') : 129, + (134, '') : 135, + (139, '') : 138, + (139, '') : 140 } diff --git a/src/utils/parser/parser.py b/src/utils/parser/parser.py index c94fbc8cc..40c08c4d2 100644 --- a/src/utils/parser/parser.py +++ b/src/utils/parser/parser.py @@ -1,7 +1,5 @@ from cmp.utils import ContainerSet -from cmp.pycompiler import Sentence from itertools import islice -from collections import deque class Parser: def __init__(self,G): From 32ca3c01c38ce57477ffdc9f4d1d6f0aaad7e9e4 Mon Sep 17 00:00:00 2001 From: Ale Date: Tue, 15 Feb 2022 22:26:40 -0800 Subject: [PATCH 31/83] updating --- src/main.py | 8 ++++++-- src/utils/COOL_Grammar.py | 10 ++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main.py b/src/main.py index afbd22b00..739e3dc5f 100644 --- a/src/main.py +++ b/src/main.py @@ -10,8 +10,10 @@ from utils.semantic_check.type_builder import TypeBuilder from utils.semantic_check.type_checker import TypeChecker +from utils.parser.LALR_1 import LALR1_Parser + if __name__ == "__main__": - add = "parser/operation3.cl" + add = "parser/mixed1.cl" path: str = f"{Path.cwd()}/tests/{add}" if os.path.exists( f"{Path.cwd()}/tests/{add}") else f"{Path.cwd()}/../tests/{add}" @@ -34,7 +36,9 @@ raise Exception() # parser - parser = COOL_Parser(G) + #parser = COOL_Parser(G) + + parser = LALR1_Parser(G) derivation, operations = parser(tokens) diff --git a/src/utils/COOL_Grammar.py b/src/utils/COOL_Grammar.py index 3ce91bc26..0d8667ae8 100644 --- a/src/utils/COOL_Grammar.py +++ b/src/utils/COOL_Grammar.py @@ -11,7 +11,7 @@ def build_COOL_Grammar(): feature_list, def_attr, def_meth, arg_list = G.NonTerminals(' ') expr, expr_list, id_list, case_list, comp = G.NonTerminals(' ') expr, arith, term, factor, atom, dispatch = G.NonTerminals(' ') - boolean = G.NonTerminal('') + not_empty = G.NonTerminal('') #terminales classx, let, inx = G.Terminals('class let in') @@ -47,7 +47,6 @@ def build_COOL_Grammar(): param %= idx + colon + typex, lambda h,s: [s[1],s[3]] expr %= idx + arrow + expr, lambda h,s: node.AssignNode(s[1],s[3],s[2]) - expr %= ifx + expr + then + expr + elsex + expr + fi, lambda h,s: node.IfThenElseNode(s[2],s[4],s[6],s[1]) expr %= whilex + expr + loop + expr + pool, lambda h,s: node.WhileNode(s[2],s[4],s[1]) @@ -68,10 +67,7 @@ def build_COOL_Grammar(): case_list %= idx + colon + typex + darrow + expr + semi, lambda h,s: [(s[1],s[3],s[5])] case_list %= idx + colon + typex + darrow + expr + semi + case_list, lambda h,s: [(s[1],s[3],s[5])] + s[7] - expr %= boolean, lambda h,s: s[1] - - boolean %= comp, lambda h,s: s[1] - boolean %= notx + comp, lambda h,s: node.NotNode(s[2], s[1]) + expr %= comp, lambda h,s: s[1] comp %= comp + less + arith, lambda h,s: node.LessThanNode(s[1],s[3],s[2]) comp %= comp + lesse + arith, lambda h,s: node.LessEqualNode(s[1],s[3],s[2]) @@ -88,6 +84,7 @@ def build_COOL_Grammar(): factor %= isvoid + factor, lambda h,s: node.IsVoidNode(s[2]) factor %= tilde + factor, lambda h,s: node.ComplementNode(s[2], s[1]) + factor %= notx + atom, lambda h,s: node.NotNode(s[2],s[1]) factor %= atom, lambda h,s: s[1] atom %= true, lambda h,s: node.ConstantBoolNode(s[1]) @@ -96,6 +93,7 @@ def build_COOL_Grammar(): atom %= num, lambda h,s: node.ConstantNumNode(s[1]) atom %= idx, lambda h,s: node.VariableNode(s[1]) atom %= new + typex, lambda h,s: node.InstantiateNode(s[2],s[1]) + atom %= ifx + expr + then + expr + elsex + expr + fi, lambda h,s: node.IfThenElseNode(s[2],s[4],s[6],s[1]) atom %= opar + expr + cpar, lambda h,s: s[2] atom %= dispatch, lambda h,s: s[1] From 230b01ca13341207d258dfdd33b488d18abc51f0 Mon Sep 17 00:00:00 2001 From: Ale Date: Tue, 15 Feb 2022 22:59:57 -0800 Subject: [PATCH 32/83] lexer-parser ready --- src/main.py | 6 +- src/utils/COOL_Grammar.py | 4 +- src/utils/parser/COOL_parser.py | 2394 ++++++++++++++++--------------- 3 files changed, 1203 insertions(+), 1201 deletions(-) diff --git a/src/main.py b/src/main.py index 739e3dc5f..c0d03122b 100644 --- a/src/main.py +++ b/src/main.py @@ -13,7 +13,7 @@ from utils.parser.LALR_1 import LALR1_Parser if __name__ == "__main__": - add = "parser/mixed1.cl" + add = "parser/dispatch2.cl" path: str = f"{Path.cwd()}/tests/{add}" if os.path.exists( f"{Path.cwd()}/tests/{add}") else f"{Path.cwd()}/../tests/{add}" @@ -36,9 +36,7 @@ raise Exception() # parser - #parser = COOL_Parser(G) - - parser = LALR1_Parser(G) + parser = COOL_Parser(G) derivation, operations = parser(tokens) diff --git a/src/utils/COOL_Grammar.py b/src/utils/COOL_Grammar.py index 0d8667ae8..93d3b7f18 100644 --- a/src/utils/COOL_Grammar.py +++ b/src/utils/COOL_Grammar.py @@ -41,7 +41,7 @@ def build_COOL_Grammar(): def_meth %= idx + opar + param_list + cpar + colon + typex + ocur + expr + ccur, lambda h,s: node.MethDeclarationNode(s[1],s[3],s[6],s[8],s[7]) param_list %= param, lambda h,s: [s[1]] - param_list %= param + comma + param_list, lambda h,s: [s[1]] + s[3] + param_list %= param_list + comma + param, lambda h,s: [s[1]] + s[3] param_list %= G.Epsilon, lambda h,s: [] param %= idx + colon + typex, lambda h,s: [s[1],s[3]] @@ -102,7 +102,7 @@ def build_COOL_Grammar(): dispatch %= atom + at + typex + dot + idx + opar + arg_list + cpar, lambda h,s: node.CallNode(s[5],s[7],s[1],s[3]) arg_list %= expr, lambda h,s: [s[1]] - arg_list %= expr + comma + arg_list, lambda h,s: [s[1]] + s[3] + arg_list %= arg_list + comma + expr, lambda h,s: [s[1]] + s[3] arg_list %= G.Epsilon, lambda h,s: [] return G \ No newline at end of file diff --git a/src/utils/parser/COOL_parser.py b/src/utils/parser/COOL_parser.py index c764f13da..418810cb8 100644 --- a/src/utils/parser/COOL_parser.py +++ b/src/utils/parser/COOL_parser.py @@ -23,1287 +23,1291 @@ def __init__(self, G): self.action = { (0, 'class') : ('SHIFT', 1), (1, 'type') : ('SHIFT', 2), + (2, 'inherits') : ('SHIFT', 131), (2, '{') : ('SHIFT', 3), - (2, 'inherits') : ('SHIFT', 132), (3, 'id') : ('SHIFT', 4), (3, '}') : ('REDUCE', 7), + (4, '(') : ('SHIFT', 109), (4, ':') : ('SHIFT', 5), - (4, '(') : ('SHIFT', 110), (5, 'type') : ('SHIFT', 6), - (6, ';') : ('REDUCE', 8), (6, '<-') : ('SHIFT', 7), - (7, 'isvoid') : ('SHIFT', 27), - (7, '{') : ('SHIFT', 14), + (6, ';') : ('REDUCE', 8), + (7, 'true') : ('SHIFT', 27), + (7, 'not') : ('SHIFT', 26), + (7, 'case') : ('SHIFT', 25), (7, '(') : ('SHIFT', 13), (7, 'let') : ('SHIFT', 8), - (7, 'if') : ('SHIFT', 24), - (7, 'case') : ('SHIFT', 25), - (7, 'id') : ('SHIFT', 18), - (7, 'false') : ('SHIFT', 29), - (7, 'int') : ('SHIFT', 21), - (7, 'string') : ('SHIFT', 30), + (7, 'string') : ('SHIFT', 29), (7, 'while') : ('SHIFT', 20), + (7, 'false') : ('SHIFT', 28), + (7, 'isvoid') : ('SHIFT', 34), + (7, 'id') : ('SHIFT', 18), + (7, 'if') : ('SHIFT', 24), + (7, '{') : ('SHIFT', 14), (7, '~') : ('SHIFT', 15), (7, 'new') : ('SHIFT', 22), - (7, 'true') : ('SHIFT', 28), - (7, 'not') : ('SHIFT', 26), + (7, 'int') : ('SHIFT', 21), (8, 'id') : ('SHIFT', 9), (9, ':') : ('SHIFT', 10), (10, 'type') : ('SHIFT', 11), - (11, 'in') : ('REDUCE', 22), + (11, ',') : ('SHIFT', 103), (11, '<-') : ('SHIFT', 12), - (11, ',') : ('SHIFT', 104), - (12, 'isvoid') : ('SHIFT', 27), - (12, '(') : ('SHIFT', 13), - (12, 'not') : ('SHIFT', 26), - (12, 'false') : ('SHIFT', 29), + (11, 'in') : ('REDUCE', 21), (12, 'id') : ('SHIFT', 18), (12, 'int') : ('SHIFT', 21), + (12, 'not') : ('SHIFT', 26), + (12, 'true') : ('SHIFT', 27), + (12, '(') : ('SHIFT', 13), (12, '{') : ('SHIFT', 14), - (12, 'string') : ('SHIFT', 30), - (12, 'if') : ('SHIFT', 24), - (12, 'let') : ('SHIFT', 8), + (12, 'string') : ('SHIFT', 29), (12, 'case') : ('SHIFT', 25), + (12, 'false') : ('SHIFT', 28), + (12, 'let') : ('SHIFT', 8), + (12, 'while') : ('SHIFT', 20), + (12, 'isvoid') : ('SHIFT', 34), (12, '~') : ('SHIFT', 15), + (12, 'if') : ('SHIFT', 24), (12, 'new') : ('SHIFT', 22), - (12, 'true') : ('SHIFT', 28), - (12, 'while') : ('SHIFT', 20), - (13, 'while') : ('SHIFT', 20), + (13, 'id') : ('SHIFT', 18), + (13, 'case') : ('SHIFT', 25), + (13, 'if') : ('SHIFT', 24), + (13, 'let') : ('SHIFT', 8), (13, '~') : ('SHIFT', 15), + (13, 'while') : ('SHIFT', 20), (13, 'new') : ('SHIFT', 22), - (13, 'true') : ('SHIFT', 28), (13, 'not') : ('SHIFT', 26), - (13, 'isvoid') : ('SHIFT', 27), + (13, 'int') : ('SHIFT', 21), + (13, 'true') : ('SHIFT', 27), (13, '(') : ('SHIFT', 13), + (13, 'string') : ('SHIFT', 29), + (13, 'false') : ('SHIFT', 28), (13, '{') : ('SHIFT', 14), - (13, 'let') : ('SHIFT', 8), - (13, 'if') : ('SHIFT', 24), - (13, 'id') : ('SHIFT', 18), - (13, 'case') : ('SHIFT', 25), - (13, 'false') : ('SHIFT', 29), - (13, 'string') : ('SHIFT', 30), - (13, 'int') : ('SHIFT', 21), - (14, 'isvoid') : ('SHIFT', 27), - (14, '{') : ('SHIFT', 14), + (13, 'isvoid') : ('SHIFT', 34), + (14, 'true') : ('SHIFT', 27), + (14, 'not') : ('SHIFT', 26), + (14, 'case') : ('SHIFT', 25), (14, '(') : ('SHIFT', 13), (14, 'let') : ('SHIFT', 8), - (14, 'if') : ('SHIFT', 24), - (14, 'case') : ('SHIFT', 25), + (14, 'while') : ('SHIFT', 20), + (14, 'string') : ('SHIFT', 29), + (14, 'false') : ('SHIFT', 28), + (14, 'isvoid') : ('SHIFT', 34), (14, 'id') : ('SHIFT', 18), - (14, 'false') : ('SHIFT', 29), + (14, 'if') : ('SHIFT', 24), (14, 'int') : ('SHIFT', 21), - (14, 'string') : ('SHIFT', 30), - (14, 'while') : ('SHIFT', 20), + (14, '{') : ('SHIFT', 14), (14, '~') : ('SHIFT', 15), (14, 'new') : ('SHIFT', 22), - (14, 'true') : ('SHIFT', 28), - (14, 'not') : ('SHIFT', 26), - (15, 'false') : ('SHIFT', 29), (15, 'id') : ('SHIFT', 16), + (15, 'string') : ('SHIFT', 29), + (15, 'if') : ('SHIFT', 24), + (15, '~') : ('SHIFT', 15), + (15, 'false') : ('SHIFT', 28), (15, 'new') : ('SHIFT', 22), (15, 'int') : ('SHIFT', 21), - (15, 'string') : ('SHIFT', 30), - (15, 'isvoid') : ('SHIFT', 27), - (15, 'true') : ('SHIFT', 28), - (15, '~') : ('SHIFT', 15), + (15, 'not') : ('SHIFT', 26), + (15, 'isvoid') : ('SHIFT', 34), + (15, 'true') : ('SHIFT', 27), (15, '(') : ('SHIFT', 13), - (16, 'fi') : ('REDUCE', 49), - (16, '=') : ('REDUCE', 49), - (16, '+') : ('REDUCE', 49), - (16, '-') : ('REDUCE', 49), - (16, 'of') : ('REDUCE', 49), - (16, '*') : ('REDUCE', 49), - (16, '/') : ('REDUCE', 49), - (16, '<') : ('REDUCE', 49), - (16, '<=') : ('REDUCE', 49), - (16, '@') : ('REDUCE', 49), - (16, 'in') : ('REDUCE', 49), - (16, ';') : ('REDUCE', 49), - (16, 'loop') : ('REDUCE', 49), - (16, 'pool') : ('REDUCE', 49), - (16, ',') : ('REDUCE', 49), - (16, '.') : ('REDUCE', 49), - (16, ')') : ('REDUCE', 49), - (16, 'then') : ('REDUCE', 49), - (16, 'else') : ('REDUCE', 49), - (16, '}') : ('REDUCE', 49), + (16, '/') : ('REDUCE', 47), + (16, '<') : ('REDUCE', 47), + (16, '<=') : ('REDUCE', 47), + (16, '@') : ('REDUCE', 47), + (16, 'in') : ('REDUCE', 47), + (16, ';') : ('REDUCE', 47), + (16, 'loop') : ('REDUCE', 47), + (16, 'pool') : ('REDUCE', 47), + (16, ',') : ('REDUCE', 47), + (16, '.') : ('REDUCE', 47), + (16, ')') : ('REDUCE', 47), + (16, 'then') : ('REDUCE', 47), + (16, 'else') : ('REDUCE', 47), + (16, '}') : ('REDUCE', 47), + (16, 'fi') : ('REDUCE', 47), + (16, '=') : ('REDUCE', 47), + (16, '+') : ('REDUCE', 47), + (16, 'of') : ('REDUCE', 47), + (16, '-') : ('REDUCE', 47), + (16, '*') : ('REDUCE', 47), (16, '(') : ('SHIFT', 17), - (17, ')') : ('REDUCE', 58), - (17, '~') : ('SHIFT', 15), - (17, 'id') : ('SHIFT', 18), - (17, 'new') : ('SHIFT', 22), - (17, '{') : ('SHIFT', 14), - (17, 'true') : ('SHIFT', 28), - (17, 'let') : ('SHIFT', 8), (17, 'if') : ('SHIFT', 24), + (17, '{') : ('SHIFT', 14), + (17, 'new') : ('SHIFT', 22), + (17, 'int') : ('SHIFT', 21), + (17, 'isvoid') : ('SHIFT', 34), + (17, 'true') : ('SHIFT', 27), (17, 'case') : ('SHIFT', 25), - (17, 'string') : ('SHIFT', 30), - (17, 'isvoid') : ('SHIFT', 27), - (17, 'while') : ('SHIFT', 20), (17, '(') : ('SHIFT', 13), - (17, 'false') : ('SHIFT', 29), - (17, 'int') : ('SHIFT', 21), + (17, 'string') : ('SHIFT', 29), + (17, 'let') : ('SHIFT', 8), + (17, 'while') : ('SHIFT', 20), + (17, ',') : ('REDUCE', 57), + (17, ')') : ('REDUCE', 57), + (17, '~') : ('SHIFT', 15), + (17, 'false') : ('SHIFT', 28), (17, 'not') : ('SHIFT', 26), + (17, 'id') : ('SHIFT', 18), (18, '<-') : ('SHIFT', 19), - (18, 'fi') : ('REDUCE', 49), - (18, '=') : ('REDUCE', 49), - (18, '+') : ('REDUCE', 49), - (18, '-') : ('REDUCE', 49), - (18, 'of') : ('REDUCE', 49), - (18, '*') : ('REDUCE', 49), - (18, '/') : ('REDUCE', 49), - (18, '<') : ('REDUCE', 49), - (18, '<=') : ('REDUCE', 49), - (18, '@') : ('REDUCE', 49), - (18, 'in') : ('REDUCE', 49), - (18, ';') : ('REDUCE', 49), - (18, 'loop') : ('REDUCE', 49), - (18, 'pool') : ('REDUCE', 49), - (18, ',') : ('REDUCE', 49), - (18, '.') : ('REDUCE', 49), - (18, ')') : ('REDUCE', 49), - (18, 'then') : ('REDUCE', 49), - (18, 'else') : ('REDUCE', 49), - (18, '}') : ('REDUCE', 49), + (18, '/') : ('REDUCE', 47), + (18, '<') : ('REDUCE', 47), + (18, '<=') : ('REDUCE', 47), + (18, '@') : ('REDUCE', 47), + (18, 'in') : ('REDUCE', 47), + (18, ';') : ('REDUCE', 47), + (18, 'loop') : ('REDUCE', 47), + (18, 'pool') : ('REDUCE', 47), + (18, ',') : ('REDUCE', 47), + (18, '.') : ('REDUCE', 47), + (18, ')') : ('REDUCE', 47), + (18, 'then') : ('REDUCE', 47), + (18, 'else') : ('REDUCE', 47), + (18, '}') : ('REDUCE', 47), + (18, 'fi') : ('REDUCE', 47), + (18, '=') : ('REDUCE', 47), + (18, '+') : ('REDUCE', 47), + (18, 'of') : ('REDUCE', 47), + (18, '-') : ('REDUCE', 47), + (18, '*') : ('REDUCE', 47), (18, '(') : ('SHIFT', 17), - (19, 'false') : ('SHIFT', 29), - (19, '{') : ('SHIFT', 14), + (19, 'string') : ('SHIFT', 29), + (19, 'false') : ('SHIFT', 28), (19, 'id') : ('SHIFT', 18), - (19, 'string') : ('SHIFT', 30), - (19, 'int') : ('SHIFT', 21), - (19, 'isvoid') : ('SHIFT', 27), - (19, 'let') : ('SHIFT', 8), + (19, 'isvoid') : ('SHIFT', 34), + (19, '{') : ('SHIFT', 14), (19, 'if') : ('SHIFT', 24), + (19, '~') : ('SHIFT', 15), (19, 'case') : ('SHIFT', 25), (19, 'new') : ('SHIFT', 22), - (19, 'true') : ('SHIFT', 28), + (19, 'let') : ('SHIFT', 8), + (19, 'int') : ('SHIFT', 21), (19, 'while') : ('SHIFT', 20), - (19, '~') : ('SHIFT', 15), - (19, '(') : ('SHIFT', 13), (19, 'not') : ('SHIFT', 26), - (20, 'isvoid') : ('SHIFT', 27), - (20, 'if') : ('SHIFT', 24), - (20, 'let') : ('SHIFT', 8), - (20, 'case') : ('SHIFT', 25), + (19, 'true') : ('SHIFT', 27), + (19, '(') : ('SHIFT', 13), (20, 'id') : ('SHIFT', 18), - (20, 'false') : ('SHIFT', 29), - (20, 'string') : ('SHIFT', 30), + (20, 'new') : ('SHIFT', 22), + (20, '{') : ('SHIFT', 14), (20, 'int') : ('SHIFT', 21), + (20, 'true') : ('SHIFT', 27), + (20, '(') : ('SHIFT', 13), + (20, 'string') : ('SHIFT', 29), + (20, 'if') : ('SHIFT', 24), + (20, 'case') : ('SHIFT', 25), + (20, 'let') : ('SHIFT', 8), + (20, 'isvoid') : ('SHIFT', 34), (20, 'while') : ('SHIFT', 20), - (20, 'new') : ('SHIFT', 22), - (20, 'true') : ('SHIFT', 28), + (20, 'false') : ('SHIFT', 28), (20, '~') : ('SHIFT', 15), (20, 'not') : ('SHIFT', 26), - (20, '(') : ('SHIFT', 13), - (20, '{') : ('SHIFT', 14), - (21, 'fi') : ('REDUCE', 48), - (21, '=') : ('REDUCE', 48), - (21, '+') : ('REDUCE', 48), - (21, '-') : ('REDUCE', 48), - (21, 'of') : ('REDUCE', 48), - (21, '*') : ('REDUCE', 48), - (21, '/') : ('REDUCE', 48), - (21, '<') : ('REDUCE', 48), - (21, '<=') : ('REDUCE', 48), - (21, '@') : ('REDUCE', 48), - (21, 'in') : ('REDUCE', 48), - (21, ';') : ('REDUCE', 48), - (21, 'loop') : ('REDUCE', 48), - (21, 'pool') : ('REDUCE', 48), - (21, ',') : ('REDUCE', 48), - (21, '.') : ('REDUCE', 48), - (21, ')') : ('REDUCE', 48), - (21, 'then') : ('REDUCE', 48), - (21, 'else') : ('REDUCE', 48), - (21, '}') : ('REDUCE', 48), + (21, '/') : ('REDUCE', 46), + (21, '<') : ('REDUCE', 46), + (21, '<=') : ('REDUCE', 46), + (21, '@') : ('REDUCE', 46), + (21, 'in') : ('REDUCE', 46), + (21, ';') : ('REDUCE', 46), + (21, 'loop') : ('REDUCE', 46), + (21, 'pool') : ('REDUCE', 46), + (21, ',') : ('REDUCE', 46), + (21, '.') : ('REDUCE', 46), + (21, ')') : ('REDUCE', 46), + (21, 'then') : ('REDUCE', 46), + (21, 'else') : ('REDUCE', 46), + (21, '}') : ('REDUCE', 46), + (21, 'fi') : ('REDUCE', 46), + (21, '=') : ('REDUCE', 46), + (21, '+') : ('REDUCE', 46), + (21, 'of') : ('REDUCE', 46), + (21, '-') : ('REDUCE', 46), + (21, '*') : ('REDUCE', 46), (22, 'type') : ('SHIFT', 23), - (23, 'fi') : ('REDUCE', 50), - (23, '=') : ('REDUCE', 50), - (23, '+') : ('REDUCE', 50), - (23, '-') : ('REDUCE', 50), - (23, 'of') : ('REDUCE', 50), - (23, '*') : ('REDUCE', 50), - (23, '/') : ('REDUCE', 50), - (23, '<') : ('REDUCE', 50), - (23, '<=') : ('REDUCE', 50), - (23, '@') : ('REDUCE', 50), - (23, 'in') : ('REDUCE', 50), - (23, ';') : ('REDUCE', 50), - (23, 'loop') : ('REDUCE', 50), - (23, 'pool') : ('REDUCE', 50), - (23, ',') : ('REDUCE', 50), - (23, '.') : ('REDUCE', 50), - (23, ')') : ('REDUCE', 50), - (23, 'then') : ('REDUCE', 50), - (23, 'else') : ('REDUCE', 50), - (23, '}') : ('REDUCE', 50), - (24, 'isvoid') : ('SHIFT', 27), + (23, '/') : ('REDUCE', 48), + (23, '<') : ('REDUCE', 48), + (23, '<=') : ('REDUCE', 48), + (23, '@') : ('REDUCE', 48), + (23, 'in') : ('REDUCE', 48), + (23, ';') : ('REDUCE', 48), + (23, 'loop') : ('REDUCE', 48), + (23, 'pool') : ('REDUCE', 48), + (23, ',') : ('REDUCE', 48), + (23, '.') : ('REDUCE', 48), + (23, ')') : ('REDUCE', 48), + (23, 'then') : ('REDUCE', 48), + (23, 'else') : ('REDUCE', 48), + (23, '}') : ('REDUCE', 48), + (23, 'fi') : ('REDUCE', 48), + (23, '=') : ('REDUCE', 48), + (23, '+') : ('REDUCE', 48), + (23, 'of') : ('REDUCE', 48), + (23, '-') : ('REDUCE', 48), + (23, '*') : ('REDUCE', 48), (24, '(') : ('SHIFT', 13), - (24, 'not') : ('SHIFT', 26), - (24, '{') : ('SHIFT', 14), - (24, 'false') : ('SHIFT', 29), (24, 'id') : ('SHIFT', 18), - (24, 'int') : ('SHIFT', 21), - (24, 'string') : ('SHIFT', 30), - (24, 'if') : ('SHIFT', 24), - (24, 'let') : ('SHIFT', 8), - (24, 'case') : ('SHIFT', 25), - (24, 'new') : ('SHIFT', 22), - (24, 'true') : ('SHIFT', 28), + (24, 'string') : ('SHIFT', 29), (24, '~') : ('SHIFT', 15), + (24, '{') : ('SHIFT', 14), + (24, 'not') : ('SHIFT', 26), + (24, 'false') : ('SHIFT', 28), + (24, 'case') : ('SHIFT', 25), + (24, 'let') : ('SHIFT', 8), (24, 'while') : ('SHIFT', 20), - (25, 'not') : ('SHIFT', 26), - (25, 'true') : ('SHIFT', 28), - (25, '{') : ('SHIFT', 14), - (25, '~') : ('SHIFT', 15), + (24, 'if') : ('SHIFT', 24), + (24, 'isvoid') : ('SHIFT', 34), + (24, 'new') : ('SHIFT', 22), + (24, 'int') : ('SHIFT', 21), + (24, 'true') : ('SHIFT', 27), + (25, 'isvoid') : ('SHIFT', 34), + (25, 'id') : ('SHIFT', 18), + (25, 'case') : ('SHIFT', 25), (25, 'let') : ('SHIFT', 8), (25, 'if') : ('SHIFT', 24), - (25, 'case') : ('SHIFT', 25), - (25, 'id') : ('SHIFT', 18), - (25, '(') : ('SHIFT', 13), - (25, 'new') : ('SHIFT', 22), (25, 'while') : ('SHIFT', 20), - (25, 'isvoid') : ('SHIFT', 27), - (25, 'false') : ('SHIFT', 29), + (25, '~') : ('SHIFT', 15), + (25, 'new') : ('SHIFT', 22), (25, 'int') : ('SHIFT', 21), - (25, 'string') : ('SHIFT', 30), - (26, 'false') : ('SHIFT', 29), + (25, 'not') : ('SHIFT', 26), + (25, 'true') : ('SHIFT', 27), + (25, '(') : ('SHIFT', 13), + (25, 'string') : ('SHIFT', 29), + (25, 'false') : ('SHIFT', 28), + (25, '{') : ('SHIFT', 14), (26, 'id') : ('SHIFT', 16), + (26, 'false') : ('SHIFT', 28), + (26, 'string') : ('SHIFT', 29), + (26, 'new') : ('SHIFT', 22), (26, 'int') : ('SHIFT', 21), - (26, 'string') : ('SHIFT', 30), - (26, 'isvoid') : ('SHIFT', 27), - (26, '~') : ('SHIFT', 15), + (26, 'if') : ('SHIFT', 24), + (26, 'true') : ('SHIFT', 27), (26, '(') : ('SHIFT', 13), - (26, 'new') : ('SHIFT', 22), - (26, 'true') : ('SHIFT', 28), - (27, 'false') : ('SHIFT', 29), - (27, 'id') : ('SHIFT', 16), - (27, 'new') : ('SHIFT', 22), - (27, 'int') : ('SHIFT', 21), - (27, 'string') : ('SHIFT', 30), - (27, 'isvoid') : ('SHIFT', 27), - (27, 'true') : ('SHIFT', 28), - (27, '~') : ('SHIFT', 15), - (27, '(') : ('SHIFT', 13), - (28, 'fi') : ('REDUCE', 45), - (28, '=') : ('REDUCE', 45), - (28, '+') : ('REDUCE', 45), - (28, '-') : ('REDUCE', 45), - (28, 'of') : ('REDUCE', 45), - (28, '*') : ('REDUCE', 45), - (28, '/') : ('REDUCE', 45), - (28, '<') : ('REDUCE', 45), - (28, '<=') : ('REDUCE', 45), - (28, '@') : ('REDUCE', 45), - (28, 'in') : ('REDUCE', 45), - (28, ';') : ('REDUCE', 45), - (28, 'loop') : ('REDUCE', 45), - (28, 'pool') : ('REDUCE', 45), - (28, ',') : ('REDUCE', 45), - (28, '.') : ('REDUCE', 45), - (28, ')') : ('REDUCE', 45), - (28, 'then') : ('REDUCE', 45), - (28, 'else') : ('REDUCE', 45), - (28, '}') : ('REDUCE', 45), - (29, 'fi') : ('REDUCE', 46), - (29, '=') : ('REDUCE', 46), - (29, '+') : ('REDUCE', 46), - (29, '-') : ('REDUCE', 46), - (29, 'of') : ('REDUCE', 46), - (29, '*') : ('REDUCE', 46), - (29, '/') : ('REDUCE', 46), - (29, '<') : ('REDUCE', 46), - (29, '<=') : ('REDUCE', 46), - (29, '@') : ('REDUCE', 46), - (29, 'in') : ('REDUCE', 46), - (29, ';') : ('REDUCE', 46), - (29, 'loop') : ('REDUCE', 46), - (29, 'pool') : ('REDUCE', 46), - (29, ',') : ('REDUCE', 46), - (29, '.') : ('REDUCE', 46), - (29, ')') : ('REDUCE', 46), - (29, 'then') : ('REDUCE', 46), - (29, 'else') : ('REDUCE', 46), - (29, '}') : ('REDUCE', 46), - (30, 'fi') : ('REDUCE', 47), - (30, '=') : ('REDUCE', 47), - (30, '+') : ('REDUCE', 47), - (30, '-') : ('REDUCE', 47), - (30, 'of') : ('REDUCE', 47), - (30, '*') : ('REDUCE', 47), - (30, '/') : ('REDUCE', 47), - (30, '<') : ('REDUCE', 47), - (30, '<=') : ('REDUCE', 47), - (30, '@') : ('REDUCE', 47), - (30, 'in') : ('REDUCE', 47), - (30, ';') : ('REDUCE', 47), - (30, 'loop') : ('REDUCE', 47), - (30, 'pool') : ('REDUCE', 47), - (30, ',') : ('REDUCE', 47), - (30, '.') : ('REDUCE', 47), - (30, ')') : ('REDUCE', 47), - (30, 'then') : ('REDUCE', 47), - (30, 'else') : ('REDUCE', 47), - (30, '}') : ('REDUCE', 47), - (31, '/') : ('REDUCE', 42), - (31, '}') : ('REDUCE', 42), - (31, 'fi') : ('REDUCE', 42), - (31, 'in') : ('REDUCE', 42), - (31, '<') : ('REDUCE', 42), - (31, '=') : ('REDUCE', 42), - (31, ';') : ('REDUCE', 42), - (31, '<=') : ('REDUCE', 42), - (31, '+') : ('REDUCE', 42), - (31, 'else') : ('REDUCE', 42), - (31, ')') : ('REDUCE', 42), - (31, '-') : ('REDUCE', 42), - (31, 'then') : ('REDUCE', 42), - (31, 'of') : ('REDUCE', 42), - (31, 'loop') : ('REDUCE', 42), - (31, '*') : ('REDUCE', 42), - (31, 'pool') : ('REDUCE', 42), - (31, ',') : ('REDUCE', 42), - (32, '@') : ('SHIFT', 61), - (32, '.') : ('SHIFT', 33), - (32, '/') : ('REDUCE', 44), - (32, '}') : ('REDUCE', 44), - (32, 'fi') : ('REDUCE', 44), - (32, 'in') : ('REDUCE', 44), - (32, '<') : ('REDUCE', 44), - (32, '=') : ('REDUCE', 44), - (32, ';') : ('REDUCE', 44), - (32, '<=') : ('REDUCE', 44), - (32, '+') : ('REDUCE', 44), - (32, 'else') : ('REDUCE', 44), - (32, ')') : ('REDUCE', 44), - (32, '-') : ('REDUCE', 44), - (32, 'then') : ('REDUCE', 44), - (32, 'of') : ('REDUCE', 44), - (32, 'loop') : ('REDUCE', 44), - (32, '*') : ('REDUCE', 44), - (32, 'pool') : ('REDUCE', 44), - (32, ',') : ('REDUCE', 44), - (33, 'id') : ('SHIFT', 34), - (34, '(') : ('SHIFT', 35), - (35, ')') : ('REDUCE', 58), - (35, '~') : ('SHIFT', 15), - (35, 'id') : ('SHIFT', 18), - (35, 'new') : ('SHIFT', 22), - (35, '{') : ('SHIFT', 14), - (35, 'true') : ('SHIFT', 28), - (35, 'let') : ('SHIFT', 8), - (35, 'if') : ('SHIFT', 24), - (35, 'case') : ('SHIFT', 25), - (35, 'string') : ('SHIFT', 30), - (35, 'isvoid') : ('SHIFT', 27), - (35, 'while') : ('SHIFT', 20), - (35, '(') : ('SHIFT', 13), - (35, 'false') : ('SHIFT', 29), - (35, 'int') : ('SHIFT', 21), - (35, 'not') : ('SHIFT', 26), - (36, ')') : ('SHIFT', 37), - (37, 'fi') : ('REDUCE', 53), - (37, '=') : ('REDUCE', 53), - (37, '+') : ('REDUCE', 53), - (37, '-') : ('REDUCE', 53), - (37, 'of') : ('REDUCE', 53), - (37, '*') : ('REDUCE', 53), - (37, '/') : ('REDUCE', 53), - (37, '<') : ('REDUCE', 53), - (37, '<=') : ('REDUCE', 53), - (37, '@') : ('REDUCE', 53), - (37, 'in') : ('REDUCE', 53), - (37, ';') : ('REDUCE', 53), - (37, 'loop') : ('REDUCE', 53), - (37, 'pool') : ('REDUCE', 53), - (37, ',') : ('REDUCE', 53), - (37, '.') : ('REDUCE', 53), - (37, ')') : ('REDUCE', 53), - (37, 'then') : ('REDUCE', 53), - (37, 'else') : ('REDUCE', 53), - (37, '}') : ('REDUCE', 53), - (38, 'pool') : ('REDUCE', 30), - (38, 'fi') : ('REDUCE', 30), - (38, 'in') : ('REDUCE', 30), - (38, ';') : ('REDUCE', 30), - (38, ')') : ('REDUCE', 30), - (38, 'then') : ('REDUCE', 30), - (38, 'of') : ('REDUCE', 30), - (38, 'loop') : ('REDUCE', 30), - (38, 'else') : ('REDUCE', 30), - (38, '}') : ('REDUCE', 30), - (38, ',') : ('REDUCE', 30), - (38, '<=') : ('SHIFT', 54), - (38, '<') : ('SHIFT', 52), - (38, '=') : ('SHIFT', 39), - (39, 'false') : ('SHIFT', 29), - (39, 'id') : ('SHIFT', 16), - (39, 'string') : ('SHIFT', 30), - (39, 'int') : ('SHIFT', 21), - (39, 'isvoid') : ('SHIFT', 27), - (39, '~') : ('SHIFT', 15), - (39, '(') : ('SHIFT', 13), - (39, 'new') : ('SHIFT', 22), - (39, 'true') : ('SHIFT', 28), - (40, '}') : ('REDUCE', 34), - (40, 'fi') : ('REDUCE', 34), - (40, 'in') : ('REDUCE', 34), - (40, '<') : ('REDUCE', 34), - (40, '=') : ('REDUCE', 34), - (40, ';') : ('REDUCE', 34), - (40, '<=') : ('REDUCE', 34), - (40, ')') : ('REDUCE', 34), - (40, 'then') : ('REDUCE', 34), - (40, 'loop') : ('REDUCE', 34), - (40, 'of') : ('REDUCE', 34), - (40, 'else') : ('REDUCE', 34), - (40, 'pool') : ('REDUCE', 34), - (40, ',') : ('REDUCE', 34), - (40, '-') : ('SHIFT', 49), - (40, '+') : ('SHIFT', 41), - (41, 'false') : ('SHIFT', 29), - (41, 'id') : ('SHIFT', 16), + (27, '/') : ('REDUCE', 43), + (27, '<') : ('REDUCE', 43), + (27, '<=') : ('REDUCE', 43), + (27, '@') : ('REDUCE', 43), + (27, 'in') : ('REDUCE', 43), + (27, ';') : ('REDUCE', 43), + (27, 'loop') : ('REDUCE', 43), + (27, 'pool') : ('REDUCE', 43), + (27, ',') : ('REDUCE', 43), + (27, '.') : ('REDUCE', 43), + (27, ')') : ('REDUCE', 43), + (27, 'then') : ('REDUCE', 43), + (27, 'else') : ('REDUCE', 43), + (27, '}') : ('REDUCE', 43), + (27, 'fi') : ('REDUCE', 43), + (27, '=') : ('REDUCE', 43), + (27, '+') : ('REDUCE', 43), + (27, 'of') : ('REDUCE', 43), + (27, '-') : ('REDUCE', 43), + (27, '*') : ('REDUCE', 43), + (28, '/') : ('REDUCE', 44), + (28, '<') : ('REDUCE', 44), + (28, '<=') : ('REDUCE', 44), + (28, '@') : ('REDUCE', 44), + (28, 'in') : ('REDUCE', 44), + (28, ';') : ('REDUCE', 44), + (28, 'loop') : ('REDUCE', 44), + (28, 'pool') : ('REDUCE', 44), + (28, ',') : ('REDUCE', 44), + (28, '.') : ('REDUCE', 44), + (28, ')') : ('REDUCE', 44), + (28, 'then') : ('REDUCE', 44), + (28, 'else') : ('REDUCE', 44), + (28, '}') : ('REDUCE', 44), + (28, 'fi') : ('REDUCE', 44), + (28, '=') : ('REDUCE', 44), + (28, '+') : ('REDUCE', 44), + (28, 'of') : ('REDUCE', 44), + (28, '-') : ('REDUCE', 44), + (28, '*') : ('REDUCE', 44), + (29, '/') : ('REDUCE', 45), + (29, '<') : ('REDUCE', 45), + (29, '<=') : ('REDUCE', 45), + (29, '@') : ('REDUCE', 45), + (29, 'in') : ('REDUCE', 45), + (29, ';') : ('REDUCE', 45), + (29, 'loop') : ('REDUCE', 45), + (29, 'pool') : ('REDUCE', 45), + (29, ',') : ('REDUCE', 45), + (29, '.') : ('REDUCE', 45), + (29, ')') : ('REDUCE', 45), + (29, 'then') : ('REDUCE', 45), + (29, 'else') : ('REDUCE', 45), + (29, '}') : ('REDUCE', 45), + (29, 'fi') : ('REDUCE', 45), + (29, '=') : ('REDUCE', 45), + (29, '+') : ('REDUCE', 45), + (29, 'of') : ('REDUCE', 45), + (29, '-') : ('REDUCE', 45), + (29, '*') : ('REDUCE', 45), + (30, ',') : ('REDUCE', 41), + (30, '/') : ('REDUCE', 41), + (30, 'fi') : ('REDUCE', 41), + (30, 'pool') : ('REDUCE', 41), + (30, '<') : ('REDUCE', 41), + (30, 'in') : ('REDUCE', 41), + (30, '=') : ('REDUCE', 41), + (30, '<=') : ('REDUCE', 41), + (30, ';') : ('REDUCE', 41), + (30, '+') : ('REDUCE', 41), + (30, '*') : ('REDUCE', 41), + (30, ')') : ('REDUCE', 41), + (30, 'of') : ('REDUCE', 41), + (30, 'then') : ('REDUCE', 41), + (30, '-') : ('REDUCE', 41), + (30, 'loop') : ('REDUCE', 41), + (30, 'else') : ('REDUCE', 41), + (30, '}') : ('REDUCE', 41), + (30, '.') : ('SHIFT', 31), + (30, '@') : ('SHIFT', 37), + (31, 'id') : ('SHIFT', 32), + (32, '(') : ('SHIFT', 33), + (33, 'if') : ('SHIFT', 24), + (33, '{') : ('SHIFT', 14), + (33, 'new') : ('SHIFT', 22), + (33, 'int') : ('SHIFT', 21), + (33, 'isvoid') : ('SHIFT', 34), + (33, 'true') : ('SHIFT', 27), + (33, 'case') : ('SHIFT', 25), + (33, '(') : ('SHIFT', 13), + (33, 'string') : ('SHIFT', 29), + (33, 'let') : ('SHIFT', 8), + (33, 'while') : ('SHIFT', 20), + (33, ',') : ('REDUCE', 57), + (33, ')') : ('REDUCE', 57), + (33, '~') : ('SHIFT', 15), + (33, 'false') : ('SHIFT', 28), + (33, 'not') : ('SHIFT', 26), + (33, 'id') : ('SHIFT', 18), + (34, 'id') : ('SHIFT', 16), + (34, 'string') : ('SHIFT', 29), + (34, 'if') : ('SHIFT', 24), + (34, '~') : ('SHIFT', 15), + (34, 'false') : ('SHIFT', 28), + (34, 'new') : ('SHIFT', 22), + (34, 'int') : ('SHIFT', 21), + (34, 'not') : ('SHIFT', 26), + (34, 'isvoid') : ('SHIFT', 34), + (34, 'true') : ('SHIFT', 27), + (34, '(') : ('SHIFT', 13), + (35, ',') : ('REDUCE', 39), + (35, '/') : ('REDUCE', 39), + (35, 'fi') : ('REDUCE', 39), + (35, 'pool') : ('REDUCE', 39), + (35, '<') : ('REDUCE', 39), + (35, 'in') : ('REDUCE', 39), + (35, '=') : ('REDUCE', 39), + (35, '<=') : ('REDUCE', 39), + (35, ';') : ('REDUCE', 39), + (35, '+') : ('REDUCE', 39), + (35, '*') : ('REDUCE', 39), + (35, ')') : ('REDUCE', 39), + (35, 'of') : ('REDUCE', 39), + (35, 'then') : ('REDUCE', 39), + (35, '-') : ('REDUCE', 39), + (35, 'loop') : ('REDUCE', 39), + (35, 'else') : ('REDUCE', 39), + (35, '}') : ('REDUCE', 39), + (36, ',') : ('REDUCE', 42), + (36, '/') : ('REDUCE', 42), + (36, 'fi') : ('REDUCE', 42), + (36, 'pool') : ('REDUCE', 42), + (36, '<') : ('REDUCE', 42), + (36, 'in') : ('REDUCE', 42), + (36, '=') : ('REDUCE', 42), + (36, '<=') : ('REDUCE', 42), + (36, ';') : ('REDUCE', 42), + (36, '+') : ('REDUCE', 42), + (36, '*') : ('REDUCE', 42), + (36, ')') : ('REDUCE', 42), + (36, 'of') : ('REDUCE', 42), + (36, 'then') : ('REDUCE', 42), + (36, '-') : ('REDUCE', 42), + (36, 'loop') : ('REDUCE', 42), + (36, 'else') : ('REDUCE', 42), + (36, '}') : ('REDUCE', 42), + (36, '.') : ('SHIFT', 31), + (36, '@') : ('SHIFT', 37), + (37, 'type') : ('SHIFT', 38), + (38, '.') : ('SHIFT', 39), + (39, 'id') : ('SHIFT', 40), + (40, '(') : ('SHIFT', 41), + (41, 'if') : ('SHIFT', 24), + (41, '{') : ('SHIFT', 14), + (41, 'new') : ('SHIFT', 22), (41, 'int') : ('SHIFT', 21), - (41, 'string') : ('SHIFT', 30), - (41, 'isvoid') : ('SHIFT', 27), - (41, '~') : ('SHIFT', 15), + (41, 'isvoid') : ('SHIFT', 34), + (41, 'true') : ('SHIFT', 27), + (41, 'case') : ('SHIFT', 25), (41, '(') : ('SHIFT', 13), - (41, 'new') : ('SHIFT', 22), - (41, 'true') : ('SHIFT', 28), - (42, '/') : ('SHIFT', 46), - (42, '*') : ('SHIFT', 43), - (42, '}') : ('REDUCE', 36), - (42, 'fi') : ('REDUCE', 36), - (42, 'in') : ('REDUCE', 36), - (42, '<') : ('REDUCE', 36), - (42, '=') : ('REDUCE', 36), - (42, ';') : ('REDUCE', 36), - (42, '<=') : ('REDUCE', 36), - (42, '+') : ('REDUCE', 36), - (42, ')') : ('REDUCE', 36), - (42, '-') : ('REDUCE', 36), - (42, 'then') : ('REDUCE', 36), - (42, 'of') : ('REDUCE', 36), - (42, 'loop') : ('REDUCE', 36), - (42, 'else') : ('REDUCE', 36), - (42, 'pool') : ('REDUCE', 36), - (42, ',') : ('REDUCE', 36), - (43, 'false') : ('SHIFT', 29), - (43, 'id') : ('SHIFT', 16), + (41, 'string') : ('SHIFT', 29), + (41, 'let') : ('SHIFT', 8), + (41, 'while') : ('SHIFT', 20), + (41, ',') : ('REDUCE', 57), + (41, ')') : ('REDUCE', 57), + (41, '~') : ('SHIFT', 15), + (41, 'false') : ('SHIFT', 28), + (41, 'not') : ('SHIFT', 26), + (41, 'id') : ('SHIFT', 18), + (42, ',') : ('SHIFT', 43), + (42, ')') : ('SHIFT', 64), + (43, 'if') : ('SHIFT', 24), + (43, '{') : ('SHIFT', 14), (43, 'new') : ('SHIFT', 22), - (43, 'string') : ('SHIFT', 30), (43, 'int') : ('SHIFT', 21), - (43, 'true') : ('SHIFT', 28), - (43, 'isvoid') : ('SHIFT', 27), - (43, '~') : ('SHIFT', 15), + (43, 'isvoid') : ('SHIFT', 34), + (43, 'true') : ('SHIFT', 27), + (43, 'case') : ('SHIFT', 25), (43, '(') : ('SHIFT', 13), - (44, '/') : ('REDUCE', 39), - (44, '}') : ('REDUCE', 39), - (44, 'fi') : ('REDUCE', 39), - (44, 'in') : ('REDUCE', 39), - (44, '<') : ('REDUCE', 39), - (44, '=') : ('REDUCE', 39), - (44, ';') : ('REDUCE', 39), - (44, '<=') : ('REDUCE', 39), - (44, '+') : ('REDUCE', 39), - (44, 'else') : ('REDUCE', 39), - (44, ')') : ('REDUCE', 39), - (44, '-') : ('REDUCE', 39), - (44, 'then') : ('REDUCE', 39), - (44, 'of') : ('REDUCE', 39), - (44, 'loop') : ('REDUCE', 39), - (44, '*') : ('REDUCE', 39), - (44, 'pool') : ('REDUCE', 39), - (44, ',') : ('REDUCE', 39), - (45, 'fi') : ('REDUCE', 52), - (45, '=') : ('REDUCE', 52), - (45, '+') : ('REDUCE', 52), - (45, '-') : ('REDUCE', 52), - (45, 'of') : ('REDUCE', 52), - (45, '*') : ('REDUCE', 52), - (45, '/') : ('REDUCE', 52), - (45, '<') : ('REDUCE', 52), - (45, '<=') : ('REDUCE', 52), - (45, '@') : ('REDUCE', 52), - (45, 'in') : ('REDUCE', 52), - (45, ';') : ('REDUCE', 52), - (45, 'loop') : ('REDUCE', 52), - (45, 'pool') : ('REDUCE', 52), - (45, ',') : ('REDUCE', 52), - (45, '.') : ('REDUCE', 52), - (45, ')') : ('REDUCE', 52), - (45, 'then') : ('REDUCE', 52), - (45, 'else') : ('REDUCE', 52), - (45, '}') : ('REDUCE', 52), - (46, 'false') : ('SHIFT', 29), - (46, 'id') : ('SHIFT', 16), - (46, 'new') : ('SHIFT', 22), - (46, 'string') : ('SHIFT', 30), - (46, 'int') : ('SHIFT', 21), - (46, 'true') : ('SHIFT', 28), - (46, 'isvoid') : ('SHIFT', 27), - (46, '~') : ('SHIFT', 15), - (46, '(') : ('SHIFT', 13), - (47, '/') : ('REDUCE', 40), - (47, '}') : ('REDUCE', 40), - (47, 'fi') : ('REDUCE', 40), - (47, 'in') : ('REDUCE', 40), - (47, '<') : ('REDUCE', 40), - (47, '=') : ('REDUCE', 40), - (47, ';') : ('REDUCE', 40), - (47, '<=') : ('REDUCE', 40), - (47, '+') : ('REDUCE', 40), - (47, 'else') : ('REDUCE', 40), - (47, ')') : ('REDUCE', 40), - (47, '-') : ('REDUCE', 40), - (47, 'then') : ('REDUCE', 40), - (47, 'of') : ('REDUCE', 40), - (47, 'loop') : ('REDUCE', 40), - (47, '*') : ('REDUCE', 40), - (47, 'pool') : ('REDUCE', 40), - (47, ',') : ('REDUCE', 40), - (48, '/') : ('REDUCE', 41), - (48, '}') : ('REDUCE', 41), - (48, 'fi') : ('REDUCE', 41), - (48, 'in') : ('REDUCE', 41), - (48, '<') : ('REDUCE', 41), - (48, '=') : ('REDUCE', 41), - (48, ';') : ('REDUCE', 41), - (48, '<=') : ('REDUCE', 41), - (48, '+') : ('REDUCE', 41), - (48, 'else') : ('REDUCE', 41), - (48, ')') : ('REDUCE', 41), - (48, '-') : ('REDUCE', 41), - (48, 'then') : ('REDUCE', 41), - (48, 'of') : ('REDUCE', 41), - (48, 'loop') : ('REDUCE', 41), - (48, '*') : ('REDUCE', 41), - (48, 'pool') : ('REDUCE', 41), - (48, ',') : ('REDUCE', 41), - (49, 'false') : ('SHIFT', 29), + (43, 'string') : ('SHIFT', 29), + (43, 'let') : ('SHIFT', 8), + (43, 'while') : ('SHIFT', 20), + (43, '~') : ('SHIFT', 15), + (43, 'false') : ('SHIFT', 28), + (43, 'not') : ('SHIFT', 26), + (43, 'id') : ('SHIFT', 18), + (44, '<') : ('SHIFT', 58), + (44, '<=') : ('SHIFT', 60), + (44, ',') : ('REDUCE', 28), + (44, 'fi') : ('REDUCE', 28), + (44, 'in') : ('REDUCE', 28), + (44, ';') : ('REDUCE', 28), + (44, ')') : ('REDUCE', 28), + (44, 'of') : ('REDUCE', 28), + (44, 'then') : ('REDUCE', 28), + (44, 'loop') : ('REDUCE', 28), + (44, '}') : ('REDUCE', 28), + (44, 'else') : ('REDUCE', 28), + (44, 'pool') : ('REDUCE', 28), + (44, '=') : ('SHIFT', 45), + (45, 'id') : ('SHIFT', 16), + (45, 'string') : ('SHIFT', 29), + (45, 'if') : ('SHIFT', 24), + (45, '~') : ('SHIFT', 15), + (45, 'false') : ('SHIFT', 28), + (45, 'new') : ('SHIFT', 22), + (45, 'int') : ('SHIFT', 21), + (45, 'not') : ('SHIFT', 26), + (45, 'isvoid') : ('SHIFT', 34), + (45, 'true') : ('SHIFT', 27), + (45, '(') : ('SHIFT', 13), + (46, '-') : ('SHIFT', 55), + (46, '+') : ('SHIFT', 47), + (46, ',') : ('REDUCE', 31), + (46, 'fi') : ('REDUCE', 31), + (46, 'pool') : ('REDUCE', 31), + (46, '<') : ('REDUCE', 31), + (46, 'in') : ('REDUCE', 31), + (46, '=') : ('REDUCE', 31), + (46, '<=') : ('REDUCE', 31), + (46, ';') : ('REDUCE', 31), + (46, ')') : ('REDUCE', 31), + (46, 'of') : ('REDUCE', 31), + (46, 'then') : ('REDUCE', 31), + (46, 'loop') : ('REDUCE', 31), + (46, 'else') : ('REDUCE', 31), + (46, '}') : ('REDUCE', 31), + (47, 'id') : ('SHIFT', 16), + (47, 'string') : ('SHIFT', 29), + (47, 'if') : ('SHIFT', 24), + (47, '~') : ('SHIFT', 15), + (47, 'false') : ('SHIFT', 28), + (47, 'new') : ('SHIFT', 22), + (47, 'int') : ('SHIFT', 21), + (47, 'not') : ('SHIFT', 26), + (47, 'isvoid') : ('SHIFT', 34), + (47, 'true') : ('SHIFT', 27), + (47, '(') : ('SHIFT', 13), + (48, '/') : ('SHIFT', 52), + (48, ',') : ('REDUCE', 33), + (48, 'fi') : ('REDUCE', 33), + (48, 'pool') : ('REDUCE', 33), + (48, '<') : ('REDUCE', 33), + (48, 'in') : ('REDUCE', 33), + (48, '=') : ('REDUCE', 33), + (48, '<=') : ('REDUCE', 33), + (48, ';') : ('REDUCE', 33), + (48, '+') : ('REDUCE', 33), + (48, ')') : ('REDUCE', 33), + (48, 'of') : ('REDUCE', 33), + (48, 'then') : ('REDUCE', 33), + (48, '-') : ('REDUCE', 33), + (48, 'loop') : ('REDUCE', 33), + (48, 'else') : ('REDUCE', 33), + (48, '}') : ('REDUCE', 33), + (48, '*') : ('SHIFT', 49), (49, 'id') : ('SHIFT', 16), - (49, 'int') : ('SHIFT', 21), - (49, 'string') : ('SHIFT', 30), - (49, 'isvoid') : ('SHIFT', 27), + (49, 'string') : ('SHIFT', 29), + (49, 'if') : ('SHIFT', 24), (49, '~') : ('SHIFT', 15), - (49, '(') : ('SHIFT', 13), + (49, 'false') : ('SHIFT', 28), (49, 'new') : ('SHIFT', 22), - (49, 'true') : ('SHIFT', 28), - (50, '/') : ('SHIFT', 46), - (50, '}') : ('REDUCE', 37), - (50, 'fi') : ('REDUCE', 37), - (50, 'in') : ('REDUCE', 37), - (50, '<') : ('REDUCE', 37), - (50, '=') : ('REDUCE', 37), - (50, ';') : ('REDUCE', 37), - (50, '<=') : ('REDUCE', 37), - (50, '+') : ('REDUCE', 37), - (50, ')') : ('REDUCE', 37), - (50, '-') : ('REDUCE', 37), - (50, 'then') : ('REDUCE', 37), - (50, 'of') : ('REDUCE', 37), - (50, 'loop') : ('REDUCE', 37), - (50, 'else') : ('REDUCE', 37), - (50, 'pool') : ('REDUCE', 37), - (50, ',') : ('REDUCE', 37), - (50, '*') : ('SHIFT', 43), - (51, '/') : ('SHIFT', 46), - (51, '*') : ('SHIFT', 43), - (51, '}') : ('REDUCE', 38), - (51, 'fi') : ('REDUCE', 38), - (51, 'in') : ('REDUCE', 38), - (51, '<') : ('REDUCE', 38), - (51, '=') : ('REDUCE', 38), - (51, ';') : ('REDUCE', 38), - (51, '<=') : ('REDUCE', 38), - (51, '+') : ('REDUCE', 38), - (51, ')') : ('REDUCE', 38), - (51, '-') : ('REDUCE', 38), - (51, 'then') : ('REDUCE', 38), - (51, 'of') : ('REDUCE', 38), - (51, 'loop') : ('REDUCE', 38), - (51, 'else') : ('REDUCE', 38), - (51, 'pool') : ('REDUCE', 38), - (51, ',') : ('REDUCE', 38), - (52, 'false') : ('SHIFT', 29), + (49, 'int') : ('SHIFT', 21), + (49, 'not') : ('SHIFT', 26), + (49, 'isvoid') : ('SHIFT', 34), + (49, 'true') : ('SHIFT', 27), + (49, '(') : ('SHIFT', 13), + (50, ',') : ('REDUCE', 36), + (50, '/') : ('REDUCE', 36), + (50, 'fi') : ('REDUCE', 36), + (50, 'pool') : ('REDUCE', 36), + (50, '<') : ('REDUCE', 36), + (50, 'in') : ('REDUCE', 36), + (50, '=') : ('REDUCE', 36), + (50, '<=') : ('REDUCE', 36), + (50, ';') : ('REDUCE', 36), + (50, '+') : ('REDUCE', 36), + (50, '*') : ('REDUCE', 36), + (50, ')') : ('REDUCE', 36), + (50, 'of') : ('REDUCE', 36), + (50, 'then') : ('REDUCE', 36), + (50, '-') : ('REDUCE', 36), + (50, 'loop') : ('REDUCE', 36), + (50, 'else') : ('REDUCE', 36), + (50, '}') : ('REDUCE', 36), + (51, '/') : ('REDUCE', 51), + (51, '<') : ('REDUCE', 51), + (51, '<=') : ('REDUCE', 51), + (51, '@') : ('REDUCE', 51), + (51, 'in') : ('REDUCE', 51), + (51, ';') : ('REDUCE', 51), + (51, 'loop') : ('REDUCE', 51), + (51, 'pool') : ('REDUCE', 51), + (51, ',') : ('REDUCE', 51), + (51, '.') : ('REDUCE', 51), + (51, ')') : ('REDUCE', 51), + (51, 'then') : ('REDUCE', 51), + (51, 'else') : ('REDUCE', 51), + (51, '}') : ('REDUCE', 51), + (51, 'fi') : ('REDUCE', 51), + (51, '=') : ('REDUCE', 51), + (51, '+') : ('REDUCE', 51), + (51, 'of') : ('REDUCE', 51), + (51, '-') : ('REDUCE', 51), + (51, '*') : ('REDUCE', 51), (52, 'id') : ('SHIFT', 16), - (52, 'string') : ('SHIFT', 30), - (52, 'int') : ('SHIFT', 21), - (52, 'isvoid') : ('SHIFT', 27), + (52, 'string') : ('SHIFT', 29), + (52, 'if') : ('SHIFT', 24), (52, '~') : ('SHIFT', 15), - (52, '(') : ('SHIFT', 13), + (52, 'false') : ('SHIFT', 28), (52, 'new') : ('SHIFT', 22), - (52, 'true') : ('SHIFT', 28), - (53, '}') : ('REDUCE', 32), - (53, 'fi') : ('REDUCE', 32), - (53, 'in') : ('REDUCE', 32), - (53, '<') : ('REDUCE', 32), - (53, '=') : ('REDUCE', 32), - (53, ';') : ('REDUCE', 32), - (53, '<=') : ('REDUCE', 32), - (53, ')') : ('REDUCE', 32), - (53, 'then') : ('REDUCE', 32), - (53, 'loop') : ('REDUCE', 32), - (53, 'of') : ('REDUCE', 32), - (53, 'else') : ('REDUCE', 32), - (53, 'pool') : ('REDUCE', 32), - (53, ',') : ('REDUCE', 32), - (53, '-') : ('SHIFT', 49), - (53, '+') : ('SHIFT', 41), - (54, 'false') : ('SHIFT', 29), - (54, 'id') : ('SHIFT', 16), - (54, 'string') : ('SHIFT', 30), - (54, 'int') : ('SHIFT', 21), - (54, 'isvoid') : ('SHIFT', 27), - (54, '~') : ('SHIFT', 15), - (54, '(') : ('SHIFT', 13), - (54, 'new') : ('SHIFT', 22), - (54, 'true') : ('SHIFT', 28), - (55, '-') : ('SHIFT', 49), - (55, '}') : ('REDUCE', 33), - (55, 'fi') : ('REDUCE', 33), - (55, 'in') : ('REDUCE', 33), - (55, '<') : ('REDUCE', 33), - (55, '=') : ('REDUCE', 33), - (55, ';') : ('REDUCE', 33), - (55, '<=') : ('REDUCE', 33), - (55, ')') : ('REDUCE', 33), - (55, 'then') : ('REDUCE', 33), - (55, 'loop') : ('REDUCE', 33), - (55, 'of') : ('REDUCE', 33), - (55, 'else') : ('REDUCE', 33), - (55, 'pool') : ('REDUCE', 33), - (55, ',') : ('REDUCE', 33), - (55, '+') : ('SHIFT', 41), - (56, ',') : ('SHIFT', 57), - (56, ')') : ('REDUCE', 56), - (57, ')') : ('REDUCE', 58), - (57, 'int') : ('SHIFT', 21), - (57, 'id') : ('SHIFT', 18), - (57, 'new') : ('SHIFT', 22), - (57, '{') : ('SHIFT', 14), - (57, 'true') : ('SHIFT', 28), - (57, 'let') : ('SHIFT', 8), - (57, 'if') : ('SHIFT', 24), - (57, 'case') : ('SHIFT', 25), - (57, 'not') : ('SHIFT', 26), - (57, 'isvoid') : ('SHIFT', 27), - (57, 'while') : ('SHIFT', 20), - (57, '(') : ('SHIFT', 13), - (57, 'false') : ('SHIFT', 29), - (57, 'string') : ('SHIFT', 30), - (57, '~') : ('SHIFT', 15), - (58, ')') : ('REDUCE', 57), - (59, '}') : ('REDUCE', 35), - (59, 'fi') : ('REDUCE', 35), - (59, 'in') : ('REDUCE', 35), - (59, '<') : ('REDUCE', 35), - (59, '=') : ('REDUCE', 35), - (59, ';') : ('REDUCE', 35), - (59, '<=') : ('REDUCE', 35), - (59, ')') : ('REDUCE', 35), - (59, 'then') : ('REDUCE', 35), - (59, 'loop') : ('REDUCE', 35), - (59, 'of') : ('REDUCE', 35), - (59, 'else') : ('REDUCE', 35), - (59, 'pool') : ('REDUCE', 35), - (59, ',') : ('REDUCE', 35), - (59, '-') : ('SHIFT', 49), - (59, '+') : ('SHIFT', 41), - (60, 'pool') : ('REDUCE', 29), - (60, 'fi') : ('REDUCE', 29), - (60, 'in') : ('REDUCE', 29), - (60, ';') : ('REDUCE', 29), - (60, ')') : ('REDUCE', 29), - (60, 'then') : ('REDUCE', 29), - (60, 'of') : ('REDUCE', 29), - (60, 'loop') : ('REDUCE', 29), - (60, 'else') : ('REDUCE', 29), - (60, '}') : ('REDUCE', 29), - (60, ',') : ('REDUCE', 29), - (61, 'type') : ('SHIFT', 62), - (62, '.') : ('SHIFT', 63), - (63, 'id') : ('SHIFT', 64), - (64, '(') : ('SHIFT', 65), - (65, ')') : ('REDUCE', 58), - (65, '~') : ('SHIFT', 15), - (65, 'id') : ('SHIFT', 18), - (65, 'new') : ('SHIFT', 22), - (65, '{') : ('SHIFT', 14), - (65, 'true') : ('SHIFT', 28), - (65, 'let') : ('SHIFT', 8), - (65, 'if') : ('SHIFT', 24), - (65, 'case') : ('SHIFT', 25), - (65, 'string') : ('SHIFT', 30), - (65, 'isvoid') : ('SHIFT', 27), - (65, 'while') : ('SHIFT', 20), - (65, '(') : ('SHIFT', 13), - (65, 'false') : ('SHIFT', 29), - (65, 'int') : ('SHIFT', 21), - (65, 'not') : ('SHIFT', 26), + (52, 'int') : ('SHIFT', 21), + (52, 'not') : ('SHIFT', 26), + (52, 'isvoid') : ('SHIFT', 34), + (52, 'true') : ('SHIFT', 27), + (52, '(') : ('SHIFT', 13), + (53, ',') : ('REDUCE', 37), + (53, '/') : ('REDUCE', 37), + (53, 'fi') : ('REDUCE', 37), + (53, 'pool') : ('REDUCE', 37), + (53, '<') : ('REDUCE', 37), + (53, 'in') : ('REDUCE', 37), + (53, '=') : ('REDUCE', 37), + (53, '<=') : ('REDUCE', 37), + (53, ';') : ('REDUCE', 37), + (53, '+') : ('REDUCE', 37), + (53, '*') : ('REDUCE', 37), + (53, ')') : ('REDUCE', 37), + (53, 'of') : ('REDUCE', 37), + (53, 'then') : ('REDUCE', 37), + (53, '-') : ('REDUCE', 37), + (53, 'loop') : ('REDUCE', 37), + (53, 'else') : ('REDUCE', 37), + (53, '}') : ('REDUCE', 37), + (54, ',') : ('REDUCE', 38), + (54, '/') : ('REDUCE', 38), + (54, 'fi') : ('REDUCE', 38), + (54, 'pool') : ('REDUCE', 38), + (54, '<') : ('REDUCE', 38), + (54, 'in') : ('REDUCE', 38), + (54, '=') : ('REDUCE', 38), + (54, '<=') : ('REDUCE', 38), + (54, ';') : ('REDUCE', 38), + (54, '+') : ('REDUCE', 38), + (54, '*') : ('REDUCE', 38), + (54, ')') : ('REDUCE', 38), + (54, 'of') : ('REDUCE', 38), + (54, 'then') : ('REDUCE', 38), + (54, '-') : ('REDUCE', 38), + (54, 'loop') : ('REDUCE', 38), + (54, 'else') : ('REDUCE', 38), + (54, '}') : ('REDUCE', 38), + (55, 'id') : ('SHIFT', 16), + (55, 'string') : ('SHIFT', 29), + (55, 'if') : ('SHIFT', 24), + (55, '~') : ('SHIFT', 15), + (55, 'false') : ('SHIFT', 28), + (55, 'new') : ('SHIFT', 22), + (55, 'int') : ('SHIFT', 21), + (55, 'not') : ('SHIFT', 26), + (55, 'isvoid') : ('SHIFT', 34), + (55, 'true') : ('SHIFT', 27), + (55, '(') : ('SHIFT', 13), + (56, '/') : ('SHIFT', 52), + (56, ',') : ('REDUCE', 34), + (56, 'fi') : ('REDUCE', 34), + (56, 'pool') : ('REDUCE', 34), + (56, '<') : ('REDUCE', 34), + (56, 'in') : ('REDUCE', 34), + (56, '=') : ('REDUCE', 34), + (56, '<=') : ('REDUCE', 34), + (56, ';') : ('REDUCE', 34), + (56, '+') : ('REDUCE', 34), + (56, ')') : ('REDUCE', 34), + (56, 'of') : ('REDUCE', 34), + (56, 'then') : ('REDUCE', 34), + (56, '-') : ('REDUCE', 34), + (56, 'loop') : ('REDUCE', 34), + (56, 'else') : ('REDUCE', 34), + (56, '}') : ('REDUCE', 34), + (56, '*') : ('SHIFT', 49), + (57, '*') : ('SHIFT', 49), + (57, ',') : ('REDUCE', 35), + (57, 'fi') : ('REDUCE', 35), + (57, 'pool') : ('REDUCE', 35), + (57, '<') : ('REDUCE', 35), + (57, 'in') : ('REDUCE', 35), + (57, '=') : ('REDUCE', 35), + (57, '<=') : ('REDUCE', 35), + (57, ';') : ('REDUCE', 35), + (57, '+') : ('REDUCE', 35), + (57, ')') : ('REDUCE', 35), + (57, 'of') : ('REDUCE', 35), + (57, 'then') : ('REDUCE', 35), + (57, '-') : ('REDUCE', 35), + (57, 'loop') : ('REDUCE', 35), + (57, 'else') : ('REDUCE', 35), + (57, '}') : ('REDUCE', 35), + (57, '/') : ('SHIFT', 52), + (58, 'id') : ('SHIFT', 16), + (58, '(') : ('SHIFT', 13), + (58, 'string') : ('SHIFT', 29), + (58, 'if') : ('SHIFT', 24), + (58, '~') : ('SHIFT', 15), + (58, 'false') : ('SHIFT', 28), + (58, 'new') : ('SHIFT', 22), + (58, 'int') : ('SHIFT', 21), + (58, 'not') : ('SHIFT', 26), + (58, 'isvoid') : ('SHIFT', 34), + (58, 'true') : ('SHIFT', 27), + (59, '-') : ('SHIFT', 55), + (59, '+') : ('SHIFT', 47), + (59, ',') : ('REDUCE', 29), + (59, 'fi') : ('REDUCE', 29), + (59, 'pool') : ('REDUCE', 29), + (59, '<') : ('REDUCE', 29), + (59, 'in') : ('REDUCE', 29), + (59, '=') : ('REDUCE', 29), + (59, '<=') : ('REDUCE', 29), + (59, ';') : ('REDUCE', 29), + (59, ')') : ('REDUCE', 29), + (59, 'of') : ('REDUCE', 29), + (59, 'then') : ('REDUCE', 29), + (59, 'loop') : ('REDUCE', 29), + (59, 'else') : ('REDUCE', 29), + (59, '}') : ('REDUCE', 29), + (60, 'id') : ('SHIFT', 16), + (60, 'string') : ('SHIFT', 29), + (60, 'if') : ('SHIFT', 24), + (60, '~') : ('SHIFT', 15), + (60, 'false') : ('SHIFT', 28), + (60, 'new') : ('SHIFT', 22), + (60, 'int') : ('SHIFT', 21), + (60, 'not') : ('SHIFT', 26), + (60, 'isvoid') : ('SHIFT', 34), + (60, 'true') : ('SHIFT', 27), + (60, '(') : ('SHIFT', 13), + (61, '-') : ('SHIFT', 55), + (61, '+') : ('SHIFT', 47), + (61, ',') : ('REDUCE', 30), + (61, 'fi') : ('REDUCE', 30), + (61, 'pool') : ('REDUCE', 30), + (61, '<') : ('REDUCE', 30), + (61, 'in') : ('REDUCE', 30), + (61, '=') : ('REDUCE', 30), + (61, '<=') : ('REDUCE', 30), + (61, ';') : ('REDUCE', 30), + (61, ')') : ('REDUCE', 30), + (61, 'of') : ('REDUCE', 30), + (61, 'then') : ('REDUCE', 30), + (61, 'loop') : ('REDUCE', 30), + (61, 'else') : ('REDUCE', 30), + (61, '}') : ('REDUCE', 30), + (62, ',') : ('REDUCE', 56), + (62, ')') : ('REDUCE', 56), + (63, '-') : ('SHIFT', 55), + (63, '+') : ('SHIFT', 47), + (63, ',') : ('REDUCE', 32), + (63, 'fi') : ('REDUCE', 32), + (63, 'in') : ('REDUCE', 32), + (63, '<') : ('REDUCE', 32), + (63, '=') : ('REDUCE', 32), + (63, '<=') : ('REDUCE', 32), + (63, ';') : ('REDUCE', 32), + (63, ')') : ('REDUCE', 32), + (63, 'of') : ('REDUCE', 32), + (63, 'then') : ('REDUCE', 32), + (63, 'loop') : ('REDUCE', 32), + (63, '}') : ('REDUCE', 32), + (63, 'else') : ('REDUCE', 32), + (63, 'pool') : ('REDUCE', 32), + (64, '/') : ('REDUCE', 54), + (64, '<') : ('REDUCE', 54), + (64, '<=') : ('REDUCE', 54), + (64, '@') : ('REDUCE', 54), + (64, 'in') : ('REDUCE', 54), + (64, ';') : ('REDUCE', 54), + (64, 'loop') : ('REDUCE', 54), + (64, 'pool') : ('REDUCE', 54), + (64, ',') : ('REDUCE', 54), + (64, '.') : ('REDUCE', 54), + (64, ')') : ('REDUCE', 54), + (64, 'then') : ('REDUCE', 54), + (64, 'else') : ('REDUCE', 54), + (64, '}') : ('REDUCE', 54), + (64, 'fi') : ('REDUCE', 54), + (64, '=') : ('REDUCE', 54), + (64, '+') : ('REDUCE', 54), + (64, 'of') : ('REDUCE', 54), + (64, '-') : ('REDUCE', 54), + (64, '*') : ('REDUCE', 54), + (65, ',') : ('REDUCE', 55), + (65, ')') : ('REDUCE', 55), + (66, ',') : ('SHIFT', 43), (66, ')') : ('SHIFT', 67), - (67, 'fi') : ('REDUCE', 55), - (67, '=') : ('REDUCE', 55), - (67, '+') : ('REDUCE', 55), - (67, '-') : ('REDUCE', 55), - (67, 'of') : ('REDUCE', 55), - (67, '*') : ('REDUCE', 55), - (67, '/') : ('REDUCE', 55), - (67, '<') : ('REDUCE', 55), - (67, '<=') : ('REDUCE', 55), - (67, '@') : ('REDUCE', 55), - (67, 'in') : ('REDUCE', 55), - (67, ';') : ('REDUCE', 55), - (67, 'loop') : ('REDUCE', 55), - (67, 'pool') : ('REDUCE', 55), - (67, ',') : ('REDUCE', 55), - (67, '.') : ('REDUCE', 55), - (67, ')') : ('REDUCE', 55), - (67, 'then') : ('REDUCE', 55), - (67, 'else') : ('REDUCE', 55), - (67, '}') : ('REDUCE', 55), - (68, '<=') : ('SHIFT', 54), - (68, '<') : ('SHIFT', 52), - (68, '=') : ('SHIFT', 39), - (68, '}') : ('REDUCE', 31), - (68, 'fi') : ('REDUCE', 31), - (68, 'in') : ('REDUCE', 31), - (68, ';') : ('REDUCE', 31), - (68, ')') : ('REDUCE', 31), - (68, 'then') : ('REDUCE', 31), - (68, 'of') : ('REDUCE', 31), - (68, 'loop') : ('REDUCE', 31), - (68, 'else') : ('REDUCE', 31), - (68, 'pool') : ('REDUCE', 31), - (68, ',') : ('REDUCE', 31), - (69, 'of') : ('SHIFT', 70), - (70, 'id') : ('SHIFT', 71), - (71, ':') : ('SHIFT', 72), - (72, 'type') : ('SHIFT', 73), - (73, '=>') : ('SHIFT', 74), - (74, 'isvoid') : ('SHIFT', 27), - (74, '{') : ('SHIFT', 14), - (74, '(') : ('SHIFT', 13), - (74, 'let') : ('SHIFT', 8), - (74, 'if') : ('SHIFT', 24), - (74, 'case') : ('SHIFT', 25), - (74, 'id') : ('SHIFT', 18), - (74, 'false') : ('SHIFT', 29), - (74, 'int') : ('SHIFT', 21), - (74, 'string') : ('SHIFT', 30), - (74, 'while') : ('SHIFT', 20), - (74, '~') : ('SHIFT', 15), - (74, 'new') : ('SHIFT', 22), - (74, 'true') : ('SHIFT', 28), - (74, 'not') : ('SHIFT', 26), - (75, ';') : ('SHIFT', 76), - (76, 'id') : ('SHIFT', 71), + (67, '/') : ('REDUCE', 52), + (67, '<') : ('REDUCE', 52), + (67, '<=') : ('REDUCE', 52), + (67, '@') : ('REDUCE', 52), + (67, 'in') : ('REDUCE', 52), + (67, ';') : ('REDUCE', 52), + (67, 'loop') : ('REDUCE', 52), + (67, 'pool') : ('REDUCE', 52), + (67, ',') : ('REDUCE', 52), + (67, '.') : ('REDUCE', 52), + (67, ')') : ('REDUCE', 52), + (67, 'then') : ('REDUCE', 52), + (67, 'else') : ('REDUCE', 52), + (67, '}') : ('REDUCE', 52), + (67, 'fi') : ('REDUCE', 52), + (67, '=') : ('REDUCE', 52), + (67, '+') : ('REDUCE', 52), + (67, 'of') : ('REDUCE', 52), + (67, '-') : ('REDUCE', 52), + (67, '*') : ('REDUCE', 52), + (68, 'of') : ('SHIFT', 69), + (69, 'id') : ('SHIFT', 70), + (70, ':') : ('SHIFT', 71), + (71, 'type') : ('SHIFT', 72), + (72, '=>') : ('SHIFT', 73), + (73, 'true') : ('SHIFT', 27), + (73, 'not') : ('SHIFT', 26), + (73, 'case') : ('SHIFT', 25), + (73, '(') : ('SHIFT', 13), + (73, 'let') : ('SHIFT', 8), + (73, 'string') : ('SHIFT', 29), + (73, 'while') : ('SHIFT', 20), + (73, 'false') : ('SHIFT', 28), + (73, 'isvoid') : ('SHIFT', 34), + (73, 'id') : ('SHIFT', 18), + (73, 'if') : ('SHIFT', 24), + (73, '{') : ('SHIFT', 14), + (73, '~') : ('SHIFT', 15), + (73, 'new') : ('SHIFT', 22), + (73, 'int') : ('SHIFT', 21), + (74, ';') : ('SHIFT', 75), + (75, 'id') : ('SHIFT', 70), + (75, 'esac') : ('REDUCE', 26), (76, 'esac') : ('REDUCE', 27), - (77, 'esac') : ('REDUCE', 28), - (78, 'esac') : ('SHIFT', 79), - (79, '}') : ('REDUCE', 26), - (79, 'fi') : ('REDUCE', 26), - (79, 'in') : ('REDUCE', 26), - (79, ';') : ('REDUCE', 26), - (79, ')') : ('REDUCE', 26), - (79, 'then') : ('REDUCE', 26), - (79, 'loop') : ('REDUCE', 26), - (79, 'of') : ('REDUCE', 26), - (79, 'else') : ('REDUCE', 26), - (79, 'pool') : ('REDUCE', 26), - (79, ',') : ('REDUCE', 26), - (80, 'then') : ('SHIFT', 81), - (81, 'not') : ('SHIFT', 26), - (81, 'new') : ('SHIFT', 22), - (81, 'true') : ('SHIFT', 28), - (81, '{') : ('SHIFT', 14), - (81, 'id') : ('SHIFT', 18), - (81, 'let') : ('SHIFT', 8), - (81, 'case') : ('SHIFT', 25), - (81, 'if') : ('SHIFT', 24), - (81, '~') : ('SHIFT', 15), - (81, '(') : ('SHIFT', 13), - (81, 'while') : ('SHIFT', 20), - (81, 'false') : ('SHIFT', 29), - (81, 'isvoid') : ('SHIFT', 27), - (81, 'string') : ('SHIFT', 30), - (81, 'int') : ('SHIFT', 21), - (82, 'else') : ('SHIFT', 83), - (83, '(') : ('SHIFT', 13), - (83, 'isvoid') : ('SHIFT', 27), - (83, 'not') : ('SHIFT', 26), - (83, 'id') : ('SHIFT', 18), - (83, 'false') : ('SHIFT', 29), - (83, 'string') : ('SHIFT', 30), - (83, 'int') : ('SHIFT', 21), - (83, '{') : ('SHIFT', 14), - (83, 'let') : ('SHIFT', 8), - (83, 'case') : ('SHIFT', 25), - (83, 'if') : ('SHIFT', 24), - (83, 'new') : ('SHIFT', 22), - (83, 'true') : ('SHIFT', 28), - (83, '~') : ('SHIFT', 15), - (83, 'while') : ('SHIFT', 20), - (84, 'fi') : ('SHIFT', 85), - (85, '}') : ('REDUCE', 16), - (85, 'fi') : ('REDUCE', 16), - (85, 'in') : ('REDUCE', 16), - (85, ';') : ('REDUCE', 16), - (85, ')') : ('REDUCE', 16), - (85, 'then') : ('REDUCE', 16), - (85, 'loop') : ('REDUCE', 16), - (85, 'of') : ('REDUCE', 16), - (85, 'else') : ('REDUCE', 16), - (85, 'pool') : ('REDUCE', 16), - (85, ',') : ('REDUCE', 16), - (86, 'loop') : ('SHIFT', 87), - (87, 'true') : ('SHIFT', 28), - (87, 'not') : ('SHIFT', 26), - (87, '{') : ('SHIFT', 14), - (87, 'isvoid') : ('SHIFT', 27), - (87, '(') : ('SHIFT', 13), - (87, 'let') : ('SHIFT', 8), - (87, 'if') : ('SHIFT', 24), - (87, 'case') : ('SHIFT', 25), - (87, 'id') : ('SHIFT', 18), - (87, 'false') : ('SHIFT', 29), - (87, 'int') : ('SHIFT', 21), - (87, 'string') : ('SHIFT', 30), - (87, 'while') : ('SHIFT', 20), - (87, '~') : ('SHIFT', 15), - (87, 'new') : ('SHIFT', 22), - (88, 'pool') : ('SHIFT', 89), - (89, '}') : ('REDUCE', 17), - (89, 'fi') : ('REDUCE', 17), - (89, 'in') : ('REDUCE', 17), - (89, ';') : ('REDUCE', 17), - (89, ')') : ('REDUCE', 17), - (89, 'then') : ('REDUCE', 17), - (89, 'of') : ('REDUCE', 17), - (89, 'loop') : ('REDUCE', 17), - (89, 'else') : ('REDUCE', 17), - (89, 'pool') : ('REDUCE', 17), - (89, ',') : ('REDUCE', 17), - (90, '}') : ('REDUCE', 15), - (90, 'fi') : ('REDUCE', 15), - (90, 'in') : ('REDUCE', 15), - (90, ';') : ('REDUCE', 15), - (90, ')') : ('REDUCE', 15), - (90, 'then') : ('REDUCE', 15), - (90, 'loop') : ('REDUCE', 15), - (90, 'of') : ('REDUCE', 15), - (90, 'else') : ('REDUCE', 15), - (90, 'pool') : ('REDUCE', 15), - (90, ',') : ('REDUCE', 15), - (91, ')') : ('SHIFT', 92), - (92, 'fi') : ('REDUCE', 54), - (92, '=') : ('REDUCE', 54), - (92, '+') : ('REDUCE', 54), - (92, '-') : ('REDUCE', 54), - (92, 'of') : ('REDUCE', 54), - (92, '*') : ('REDUCE', 54), - (92, '/') : ('REDUCE', 54), - (92, '<') : ('REDUCE', 54), - (92, '<=') : ('REDUCE', 54), - (92, '@') : ('REDUCE', 54), - (92, 'in') : ('REDUCE', 54), - (92, ';') : ('REDUCE', 54), - (92, 'loop') : ('REDUCE', 54), - (92, 'pool') : ('REDUCE', 54), - (92, ',') : ('REDUCE', 54), - (92, '.') : ('REDUCE', 54), - (92, ')') : ('REDUCE', 54), - (92, 'then') : ('REDUCE', 54), - (92, 'else') : ('REDUCE', 54), - (92, '}') : ('REDUCE', 54), - (93, '/') : ('REDUCE', 43), - (93, '}') : ('REDUCE', 43), - (93, 'fi') : ('REDUCE', 43), - (93, 'in') : ('REDUCE', 43), - (93, '<') : ('REDUCE', 43), - (93, '=') : ('REDUCE', 43), - (93, ';') : ('REDUCE', 43), - (93, '<=') : ('REDUCE', 43), - (93, '+') : ('REDUCE', 43), - (93, 'else') : ('REDUCE', 43), - (93, ')') : ('REDUCE', 43), - (93, '-') : ('REDUCE', 43), - (93, 'then') : ('REDUCE', 43), - (93, 'of') : ('REDUCE', 43), - (93, 'loop') : ('REDUCE', 43), - (93, '*') : ('REDUCE', 43), - (93, 'pool') : ('REDUCE', 43), - (93, ',') : ('REDUCE', 43), - (94, '}') : ('SHIFT', 95), - (95, '}') : ('REDUCE', 18), - (95, 'fi') : ('REDUCE', 18), - (95, 'in') : ('REDUCE', 18), - (95, ';') : ('REDUCE', 18), - (95, ')') : ('REDUCE', 18), - (95, 'then') : ('REDUCE', 18), - (95, 'of') : ('REDUCE', 18), - (95, 'loop') : ('REDUCE', 18), - (95, 'else') : ('REDUCE', 18), - (95, 'pool') : ('REDUCE', 18), - (95, ',') : ('REDUCE', 18), - (96, ';') : ('SHIFT', 97), - (97, 'isvoid') : ('SHIFT', 27), - (97, '{') : ('SHIFT', 14), - (97, '(') : ('SHIFT', 13), - (97, 'let') : ('SHIFT', 8), - (97, 'if') : ('SHIFT', 24), - (97, 'case') : ('SHIFT', 25), - (97, 'id') : ('SHIFT', 18), - (97, 'false') : ('SHIFT', 29), - (97, 'int') : ('SHIFT', 21), - (97, 'string') : ('SHIFT', 30), - (97, 'while') : ('SHIFT', 20), + (77, 'esac') : ('SHIFT', 78), + (78, ',') : ('REDUCE', 25), + (78, 'fi') : ('REDUCE', 25), + (78, 'pool') : ('REDUCE', 25), + (78, 'in') : ('REDUCE', 25), + (78, ';') : ('REDUCE', 25), + (78, ')') : ('REDUCE', 25), + (78, 'of') : ('REDUCE', 25), + (78, 'then') : ('REDUCE', 25), + (78, 'loop') : ('REDUCE', 25), + (78, 'else') : ('REDUCE', 25), + (78, '}') : ('REDUCE', 25), + (79, 'then') : ('SHIFT', 80), + (80, 'case') : ('SHIFT', 25), + (80, 'false') : ('SHIFT', 28), + (80, 'let') : ('SHIFT', 8), + (80, '~') : ('SHIFT', 15), + (80, 'while') : ('SHIFT', 20), + (80, 'id') : ('SHIFT', 18), + (80, 'not') : ('SHIFT', 26), + (80, 'if') : ('SHIFT', 24), + (80, 'new') : ('SHIFT', 22), + (80, 'int') : ('SHIFT', 21), + (80, 'true') : ('SHIFT', 27), + (80, '(') : ('SHIFT', 13), + (80, '{') : ('SHIFT', 14), + (80, 'string') : ('SHIFT', 29), + (80, 'isvoid') : ('SHIFT', 34), + (81, 'else') : ('SHIFT', 82), + (82, 'case') : ('SHIFT', 25), + (82, 'let') : ('SHIFT', 8), + (82, '~') : ('SHIFT', 15), + (82, 'while') : ('SHIFT', 20), + (82, 'false') : ('SHIFT', 28), + (82, 'not') : ('SHIFT', 26), + (82, 'id') : ('SHIFT', 18), + (82, 'if') : ('SHIFT', 24), + (82, 'new') : ('SHIFT', 22), + (82, 'int') : ('SHIFT', 21), + (82, '{') : ('SHIFT', 14), + (82, 'isvoid') : ('SHIFT', 34), + (82, 'true') : ('SHIFT', 27), + (82, '(') : ('SHIFT', 13), + (82, 'string') : ('SHIFT', 29), + (83, 'fi') : ('SHIFT', 84), + (84, '/') : ('REDUCE', 49), + (84, '<') : ('REDUCE', 49), + (84, '<=') : ('REDUCE', 49), + (84, '@') : ('REDUCE', 49), + (84, 'in') : ('REDUCE', 49), + (84, ';') : ('REDUCE', 49), + (84, 'loop') : ('REDUCE', 49), + (84, 'pool') : ('REDUCE', 49), + (84, ',') : ('REDUCE', 49), + (84, '.') : ('REDUCE', 49), + (84, ')') : ('REDUCE', 49), + (84, 'then') : ('REDUCE', 49), + (84, 'else') : ('REDUCE', 49), + (84, '}') : ('REDUCE', 49), + (84, 'fi') : ('REDUCE', 49), + (84, '=') : ('REDUCE', 49), + (84, '+') : ('REDUCE', 49), + (84, 'of') : ('REDUCE', 49), + (84, '-') : ('REDUCE', 49), + (84, '*') : ('REDUCE', 49), + (85, 'loop') : ('SHIFT', 86), + (86, 'id') : ('SHIFT', 18), + (86, 'case') : ('SHIFT', 25), + (86, 'let') : ('SHIFT', 8), + (86, 'if') : ('SHIFT', 24), + (86, 'while') : ('SHIFT', 20), + (86, 'new') : ('SHIFT', 22), + (86, 'isvoid') : ('SHIFT', 34), + (86, 'int') : ('SHIFT', 21), + (86, 'true') : ('SHIFT', 27), + (86, '(') : ('SHIFT', 13), + (86, 'string') : ('SHIFT', 29), + (86, '~') : ('SHIFT', 15), + (86, 'false') : ('SHIFT', 28), + (86, '{') : ('SHIFT', 14), + (86, 'not') : ('SHIFT', 26), + (87, 'pool') : ('SHIFT', 88), + (88, ',') : ('REDUCE', 16), + (88, 'fi') : ('REDUCE', 16), + (88, 'pool') : ('REDUCE', 16), + (88, 'in') : ('REDUCE', 16), + (88, ';') : ('REDUCE', 16), + (88, ')') : ('REDUCE', 16), + (88, 'of') : ('REDUCE', 16), + (88, 'then') : ('REDUCE', 16), + (88, 'loop') : ('REDUCE', 16), + (88, 'else') : ('REDUCE', 16), + (88, '}') : ('REDUCE', 16), + (89, ',') : ('REDUCE', 15), + (89, 'fi') : ('REDUCE', 15), + (89, 'pool') : ('REDUCE', 15), + (89, 'in') : ('REDUCE', 15), + (89, ';') : ('REDUCE', 15), + (89, ')') : ('REDUCE', 15), + (89, 'of') : ('REDUCE', 15), + (89, 'then') : ('REDUCE', 15), + (89, 'loop') : ('REDUCE', 15), + (89, 'else') : ('REDUCE', 15), + (89, '}') : ('REDUCE', 15), + (90, ')') : ('SHIFT', 91), + (90, ',') : ('SHIFT', 43), + (91, '/') : ('REDUCE', 53), + (91, '<') : ('REDUCE', 53), + (91, '<=') : ('REDUCE', 53), + (91, '@') : ('REDUCE', 53), + (91, 'in') : ('REDUCE', 53), + (91, ';') : ('REDUCE', 53), + (91, 'loop') : ('REDUCE', 53), + (91, 'pool') : ('REDUCE', 53), + (91, ',') : ('REDUCE', 53), + (91, '.') : ('REDUCE', 53), + (91, ')') : ('REDUCE', 53), + (91, 'then') : ('REDUCE', 53), + (91, 'else') : ('REDUCE', 53), + (91, '}') : ('REDUCE', 53), + (91, 'fi') : ('REDUCE', 53), + (91, '=') : ('REDUCE', 53), + (91, '+') : ('REDUCE', 53), + (91, 'of') : ('REDUCE', 53), + (91, '-') : ('REDUCE', 53), + (91, '*') : ('REDUCE', 53), + (92, ',') : ('REDUCE', 40), + (92, '/') : ('REDUCE', 40), + (92, 'fi') : ('REDUCE', 40), + (92, 'pool') : ('REDUCE', 40), + (92, '<') : ('REDUCE', 40), + (92, 'in') : ('REDUCE', 40), + (92, '=') : ('REDUCE', 40), + (92, '<=') : ('REDUCE', 40), + (92, ';') : ('REDUCE', 40), + (92, '+') : ('REDUCE', 40), + (92, '*') : ('REDUCE', 40), + (92, ')') : ('REDUCE', 40), + (92, 'of') : ('REDUCE', 40), + (92, 'then') : ('REDUCE', 40), + (92, '-') : ('REDUCE', 40), + (92, 'loop') : ('REDUCE', 40), + (92, 'else') : ('REDUCE', 40), + (92, '}') : ('REDUCE', 40), + (93, '}') : ('SHIFT', 94), + (94, ',') : ('REDUCE', 17), + (94, 'fi') : ('REDUCE', 17), + (94, 'pool') : ('REDUCE', 17), + (94, 'in') : ('REDUCE', 17), + (94, ';') : ('REDUCE', 17), + (94, ')') : ('REDUCE', 17), + (94, 'of') : ('REDUCE', 17), + (94, 'then') : ('REDUCE', 17), + (94, 'loop') : ('REDUCE', 17), + (94, 'else') : ('REDUCE', 17), + (94, '}') : ('REDUCE', 17), + (95, ';') : ('SHIFT', 96), + (96, 'true') : ('SHIFT', 27), + (96, 'not') : ('SHIFT', 26), + (96, 'case') : ('SHIFT', 25), + (96, '(') : ('SHIFT', 13), + (96, 'let') : ('SHIFT', 8), + (96, 'string') : ('SHIFT', 29), + (96, 'while') : ('SHIFT', 20), + (96, '}') : ('REDUCE', 18), + (96, 'false') : ('SHIFT', 28), + (96, 'isvoid') : ('SHIFT', 34), + (96, 'id') : ('SHIFT', 18), + (96, 'if') : ('SHIFT', 24), + (96, '{') : ('SHIFT', 14), + (96, '~') : ('SHIFT', 15), + (96, 'new') : ('SHIFT', 22), + (96, 'int') : ('SHIFT', 21), (97, '}') : ('REDUCE', 19), - (97, '~') : ('SHIFT', 15), - (97, 'new') : ('SHIFT', 22), - (97, 'true') : ('SHIFT', 28), - (97, 'not') : ('SHIFT', 26), - (98, '}') : ('REDUCE', 20), - (99, ')') : ('SHIFT', 100), - (100, 'fi') : ('REDUCE', 51), - (100, '=') : ('REDUCE', 51), - (100, '+') : ('REDUCE', 51), - (100, '-') : ('REDUCE', 51), - (100, 'of') : ('REDUCE', 51), - (100, '*') : ('REDUCE', 51), - (100, '/') : ('REDUCE', 51), - (100, '<') : ('REDUCE', 51), - (100, '<=') : ('REDUCE', 51), - (100, '@') : ('REDUCE', 51), - (100, 'in') : ('REDUCE', 51), - (100, ';') : ('REDUCE', 51), - (100, 'loop') : ('REDUCE', 51), - (100, 'pool') : ('REDUCE', 51), - (100, ',') : ('REDUCE', 51), - (100, '.') : ('REDUCE', 51), - (100, ')') : ('REDUCE', 51), - (100, 'then') : ('REDUCE', 51), - (100, 'else') : ('REDUCE', 51), - (100, '}') : ('REDUCE', 51), - (101, 'in') : ('REDUCE', 23), - (101, ',') : ('SHIFT', 102), - (102, 'id') : ('SHIFT', 9), - (103, 'in') : ('REDUCE', 25), - (104, 'id') : ('SHIFT', 9), - (105, 'in') : ('REDUCE', 24), - (106, 'in') : ('SHIFT', 107), - (107, 'false') : ('SHIFT', 29), - (107, '{') : ('SHIFT', 14), - (107, 'id') : ('SHIFT', 18), - (107, 'string') : ('SHIFT', 30), - (107, 'int') : ('SHIFT', 21), - (107, 'isvoid') : ('SHIFT', 27), - (107, 'let') : ('SHIFT', 8), - (107, 'if') : ('SHIFT', 24), - (107, 'case') : ('SHIFT', 25), - (107, 'new') : ('SHIFT', 22), - (107, 'true') : ('SHIFT', 28), - (107, 'while') : ('SHIFT', 20), - (107, '~') : ('SHIFT', 15), - (107, '(') : ('SHIFT', 13), - (107, 'not') : ('SHIFT', 26), - (108, '}') : ('REDUCE', 21), - (108, 'fi') : ('REDUCE', 21), - (108, 'in') : ('REDUCE', 21), - (108, ';') : ('REDUCE', 21), - (108, ')') : ('REDUCE', 21), - (108, 'then') : ('REDUCE', 21), - (108, 'of') : ('REDUCE', 21), - (108, 'loop') : ('REDUCE', 21), - (108, 'else') : ('REDUCE', 21), - (108, 'pool') : ('REDUCE', 21), - (108, ',') : ('REDUCE', 21), - (109, ';') : ('REDUCE', 9), - (110, 'id') : ('SHIFT', 111), - (110, ')') : ('REDUCE', 13), - (111, ':') : ('SHIFT', 112), - (112, 'type') : ('SHIFT', 113), - (113, ')') : ('REDUCE', 14), - (113, ',') : ('REDUCE', 14), - (114, ')') : ('SHIFT', 115), - (115, ':') : ('SHIFT', 116), - (116, 'type') : ('SHIFT', 117), - (117, '{') : ('SHIFT', 118), - (118, 'isvoid') : ('SHIFT', 27), - (118, 'id') : ('SHIFT', 18), - (118, 'let') : ('SHIFT', 8), - (118, 'new') : ('SHIFT', 22), - (118, 'true') : ('SHIFT', 28), - (118, 'while') : ('SHIFT', 20), - (118, '~') : ('SHIFT', 15), - (118, '(') : ('SHIFT', 13), - (118, 'not') : ('SHIFT', 26), - (118, 'int') : ('SHIFT', 21), - (118, '{') : ('SHIFT', 14), - (118, 'false') : ('SHIFT', 29), - (118, 'if') : ('SHIFT', 24), - (118, 'string') : ('SHIFT', 30), - (118, 'case') : ('SHIFT', 25), - (119, '}') : ('SHIFT', 120), - (120, ';') : ('REDUCE', 10), - (121, ')') : ('REDUCE', 11), - (121, ',') : ('SHIFT', 122), - (122, 'id') : ('SHIFT', 111), - (122, ')') : ('REDUCE', 13), - (123, ')') : ('REDUCE', 12), - (124, '}') : ('SHIFT', 125), - (125, ';') : ('REDUCE', 3), - (126, ';') : ('SHIFT', 127), - (127, 'id') : ('SHIFT', 4), - (127, '}') : ('REDUCE', 7), - (128, '}') : ('REDUCE', 5), - (129, ';') : ('SHIFT', 130), - (130, 'id') : ('SHIFT', 4), - (130, '}') : ('REDUCE', 7), - (131, '}') : ('REDUCE', 6), - (132, 'type') : ('SHIFT', 133), - (133, '{') : ('SHIFT', 134), - (134, '}') : ('REDUCE', 7), - (134, 'id') : ('SHIFT', 4), - (135, '}') : ('SHIFT', 136), - (136, ';') : ('REDUCE', 4), - (137, '$') : ('REDUCE', 0), - (141, '$') : ('OK', None), - (138, ';') : ('SHIFT', 139), - (139, '$') : ('REDUCE', 1), - (139, 'class') : ('SHIFT', 1), - (140, '$') : ('REDUCE', 2) + (98, ')') : ('SHIFT', 99), + (99, '/') : ('REDUCE', 50), + (99, '<') : ('REDUCE', 50), + (99, '<=') : ('REDUCE', 50), + (99, '@') : ('REDUCE', 50), + (99, 'in') : ('REDUCE', 50), + (99, ';') : ('REDUCE', 50), + (99, 'loop') : ('REDUCE', 50), + (99, 'pool') : ('REDUCE', 50), + (99, ',') : ('REDUCE', 50), + (99, '.') : ('REDUCE', 50), + (99, ')') : ('REDUCE', 50), + (99, 'then') : ('REDUCE', 50), + (99, 'else') : ('REDUCE', 50), + (99, '}') : ('REDUCE', 50), + (99, 'fi') : ('REDUCE', 50), + (99, '=') : ('REDUCE', 50), + (99, '+') : ('REDUCE', 50), + (99, 'of') : ('REDUCE', 50), + (99, '-') : ('REDUCE', 50), + (99, '*') : ('REDUCE', 50), + (100, 'in') : ('REDUCE', 22), + (100, ',') : ('SHIFT', 101), + (101, 'id') : ('SHIFT', 9), + (102, 'in') : ('REDUCE', 24), + (103, 'id') : ('SHIFT', 9), + (104, 'in') : ('REDUCE', 23), + (105, 'in') : ('SHIFT', 106), + (106, 'string') : ('SHIFT', 29), + (106, 'false') : ('SHIFT', 28), + (106, 'id') : ('SHIFT', 18), + (106, 'isvoid') : ('SHIFT', 34), + (106, '{') : ('SHIFT', 14), + (106, 'if') : ('SHIFT', 24), + (106, '~') : ('SHIFT', 15), + (106, 'case') : ('SHIFT', 25), + (106, 'new') : ('SHIFT', 22), + (106, 'let') : ('SHIFT', 8), + (106, 'int') : ('SHIFT', 21), + (106, 'while') : ('SHIFT', 20), + (106, 'not') : ('SHIFT', 26), + (106, 'true') : ('SHIFT', 27), + (106, '(') : ('SHIFT', 13), + (107, ',') : ('REDUCE', 20), + (107, 'fi') : ('REDUCE', 20), + (107, 'pool') : ('REDUCE', 20), + (107, 'in') : ('REDUCE', 20), + (107, ';') : ('REDUCE', 20), + (107, ')') : ('REDUCE', 20), + (107, 'of') : ('REDUCE', 20), + (107, 'then') : ('REDUCE', 20), + (107, 'loop') : ('REDUCE', 20), + (107, 'else') : ('REDUCE', 20), + (107, '}') : ('REDUCE', 20), + (108, ';') : ('REDUCE', 9), + (109, 'id') : ('SHIFT', 110), + (109, ',') : ('REDUCE', 13), + (109, ')') : ('REDUCE', 13), + (110, ':') : ('SHIFT', 111), + (111, 'type') : ('SHIFT', 112), + (112, ',') : ('REDUCE', 14), + (112, ')') : ('REDUCE', 14), + (113, ',') : ('SHIFT', 114), + (113, ')') : ('SHIFT', 116), + (114, 'id') : ('SHIFT', 110), + (115, ',') : ('REDUCE', 12), + (115, ')') : ('REDUCE', 12), + (116, ':') : ('SHIFT', 117), + (117, 'type') : ('SHIFT', 118), + (118, '{') : ('SHIFT', 119), + (119, 'not') : ('SHIFT', 26), + (119, 'case') : ('SHIFT', 25), + (119, 'let') : ('SHIFT', 8), + (119, 'new') : ('SHIFT', 22), + (119, 'int') : ('SHIFT', 21), + (119, 'while') : ('SHIFT', 20), + (119, 'true') : ('SHIFT', 27), + (119, '(') : ('SHIFT', 13), + (119, 'string') : ('SHIFT', 29), + (119, 'isvoid') : ('SHIFT', 34), + (119, 'false') : ('SHIFT', 28), + (119, 'id') : ('SHIFT', 18), + (119, '{') : ('SHIFT', 14), + (119, '~') : ('SHIFT', 15), + (119, 'if') : ('SHIFT', 24), + (120, '}') : ('SHIFT', 121), + (121, ';') : ('REDUCE', 10), + (122, ',') : ('REDUCE', 11), + (122, ')') : ('REDUCE', 11), + (123, '}') : ('SHIFT', 124), + (124, ';') : ('REDUCE', 3), + (125, ';') : ('SHIFT', 126), + (126, 'id') : ('SHIFT', 4), + (126, '}') : ('REDUCE', 7), + (127, '}') : ('REDUCE', 5), + (128, ';') : ('SHIFT', 129), + (129, 'id') : ('SHIFT', 4), + (129, '}') : ('REDUCE', 7), + (130, '}') : ('REDUCE', 6), + (131, 'type') : ('SHIFT', 132), + (132, '{') : ('SHIFT', 133), + (133, 'id') : ('SHIFT', 4), + (133, '}') : ('REDUCE', 7), + (134, '}') : ('SHIFT', 135), + (135, ';') : ('REDUCE', 4), + (136, '$') : ('REDUCE', 0), + (140, '$') : ('OK', None), + (137, ';') : ('SHIFT', 138), + (138, '$') : ('REDUCE', 1), + (138, 'class') : ('SHIFT', 1), + (139, '$') : ('REDUCE', 2) } self.goto = { - (0, '') : 137, - (0, ''): 141, - (0, '') : 138, - (3, '') : 124, - (3, '') : 126, - (3, '') : 129, - (7, '') : 38, - (7, '') : 32, - (7, '') : 51, - (7, '') : 48, - (7, '') : 59, - (7, '') : 109, - (7, '') : 45, - (7, '') : 60, - (8, '') : 106, - (12, '') : 38, - (12, '') : 51, - (12, '') : 32, - (12, '') : 48, - (12, '') : 59, - (12, '') : 60, - (12, '') : 101, - (12, '') : 45, - (13, '') : 99, - (13, '') : 38, - (13, '') : 51, - (13, '') : 60, - (13, '') : 32, - (13, '') : 59, - (13, '') : 48, - (13, '') : 45, - (14, '') : 38, - (14, '') : 32, - (14, '') : 51, - (14, '') : 48, - (14, '') : 59, - (14, '') : 45, - (14, '') : 96, - (14, '') : 94, - (14, '') : 60, - (15, '') : 32, - (15, '') : 93, - (15, '') : 45, - (17, '') : 51, - (17, '') : 60, - (17, '') : 32, - (17, '') : 91, - (17, '') : 59, - (17, '') : 38, - (17, '') : 56, - (17, '') : 48, - (17, '') : 45, - (19, '') : 38, - (19, '') : 51, - (19, '') : 90, - (19, '') : 59, - (19, '') : 32, - (19, '') : 48, - (19, '') : 60, - (19, '') : 45, - (20, '') : 32, - (20, '') : 51, - (20, '') : 38, - (20, '') : 45, - (20, '') : 48, - (20, '') : 59, - (20, '') : 86, - (20, '') : 60, - (24, '') : 38, - (24, '') : 51, - (24, '') : 32, - (24, '') : 60, - (24, '') : 45, - (24, '') : 48, - (24, '') : 59, - (24, '') : 80, - (25, '') : 32, - (25, '') : 59, - (25, '') : 60, - (25, '') : 38, - (25, '') : 51, - (25, '') : 45, - (25, '') : 69, - (25, '') : 48, - (26, '') : 68, - (26, '') : 51, - (26, '') : 59, - (26, '') : 32, - (26, '') : 48, - (26, '') : 45, - (27, '') : 32, - (27, '') : 31, - (27, '') : 45, - (35, '') : 36, - (35, '') : 51, - (35, '') : 60, - (35, '') : 32, - (35, '') : 59, - (35, '') : 38, - (35, '') : 56, - (35, '') : 48, - (35, '') : 45, - (39, '') : 51, - (39, '') : 32, - (39, '') : 48, - (39, '') : 40, - (39, '') : 45, - (41, '') : 42, - (41, '') : 32, - (41, '') : 48, - (41, '') : 45, - (43, '') : 32, - (43, '') : 44, - (43, '') : 45, - (46, '') : 32, - (46, '') : 47, - (46, '') : 45, - (49, '') : 50, - (49, '') : 32, - (49, '') : 48, - (49, '') : 45, - (52, '') : 53, - (52, '') : 51, - (52, '') : 32, - (52, '') : 48, - (52, '') : 45, - (54, '') : 55, - (54, '') : 51, - (54, '') : 32, - (54, '') : 48, - (54, '') : 45, - (57, '') : 51, - (57, '') : 60, - (57, '') : 32, - (57, '') : 59, - (57, '') : 38, - (57, '') : 56, - (57, '') : 48, - (57, '') : 58, - (57, '') : 45, - (65, '') : 51, - (65, '') : 60, - (65, '') : 32, - (65, '') : 59, - (65, '') : 38, - (65, '') : 66, - (65, '') : 56, - (65, '') : 48, - (65, '') : 45, - (70, '') : 78, - (74, '') : 38, - (74, '') : 75, - (74, '') : 32, - (74, '') : 51, - (74, '') : 48, - (74, '') : 59, - (74, '') : 45, - (74, '') : 60, - (76, '') : 77, - (81, '') : 51, - (81, '') : 32, - (81, '') : 48, - (81, '') : 59, - (81, '') : 60, - (81, '') : 38, - (81, '') : 82, - (81, '') : 45, - (83, '') : 59, - (83, '') : 32, - (83, '') : 38, - (83, '') : 51, - (83, '') : 45, - (83, '') : 60, - (83, '') : 48, - (83, '') : 84, - (87, '') : 88, - (87, '') : 38, - (87, '') : 59, - (87, '') : 60, - (87, '') : 32, - (87, '') : 51, - (87, '') : 48, - (87, '') : 45, - (97, '') : 38, - (97, '') : 32, - (97, '') : 51, - (97, '') : 48, - (97, '') : 59, - (97, '') : 45, - (97, '') : 96, - (97, '') : 98, - (97, '') : 60, - (102, '') : 103, - (104, '') : 105, - (107, '') : 38, - (107, '') : 51, - (107, '') : 59, - (107, '') : 32, - (107, '') : 48, - (107, '') : 108, - (107, '') : 60, - (107, '') : 45, - (110, '') : 121, - (110, '') : 114, - (118, '') : 59, - (118, '') : 32, - (118, '') : 51, - (118, '') : 48, - (118, '') : 38, - (118, '') : 119, - (118, '') : 60, - (118, '') : 45, - (122, '') : 121, - (122, '') : 123, - (127, '') : 126, - (127, '') : 128, - (127, '') : 129, - (130, '') : 126, - (130, '') : 131, - (130, '') : 129, - (134, '') : 126, - (134, '') : 129, - (134, '') : 135, - (139, '') : 138, - (139, '') : 140 + (0, '') : 136, + (0, '') : 140, + (0, '') : 137, + (3, '') : 125, + (3, '') : 123, + (3, '') : 128, + (7, '') : 36, + (7, '') : 54, + (7, '') : 63, + (7, '') : 44, + (7, '') : 51, + (7, '') : 57, + (7, '') : 108, + (8, '') : 105, + (12, '') : 63, + (12, '') : 54, + (12, '') : 36, + (12, '') : 44, + (12, '') : 57, + (12, '') : 51, + (12, '') : 100, + (13, '') : 57, + (13, '') : 36, + (13, '') : 51, + (13, '') : 63, + (13, '') : 44, + (13, '') : 54, + (13, '') : 98, + (14, '') : 36, + (14, '') : 93, + (14, '') : 54, + (14, '') : 95, + (14, '') : 63, + (14, '') : 44, + (14, '') : 51, + (14, '') : 57, + (15, '') : 36, + (15, '') : 51, + (15, '') : 92, + (17, '') : 57, + (17, '') : 44, + (17, '') : 65, + (17, '') : 36, + (17, '') : 90, + (17, '') : 63, + (17, '') : 54, + (17, '') : 51, + (19, '') : 44, + (19, '') : 63, + (19, '') : 36, + (19, '') : 57, + (19, '') : 51, + (19, '') : 89, + (19, '') : 54, + (20, '') : 44, + (20, '') : 63, + (20, '') : 36, + (20, '') : 57, + (20, '') : 85, + (20, '') : 51, + (20, '') : 54, + (24, '') : 57, + (24, '') : 44, + (24, '') : 79, + (24, '') : 54, + (24, '') : 36, + (24, '') : 51, + (24, '') : 63, + (25, '') : 63, + (25, '') : 36, + (25, '') : 51, + (25, '') : 57, + (25, '') : 68, + (25, '') : 44, + (25, '') : 54, + (26, '') : 30, + (26, '') : 51, + (33, '') : 57, + (33, '') : 44, + (33, '') : 65, + (33, '') : 36, + (33, '') : 66, + (33, '') : 63, + (33, '') : 54, + (33, '') : 51, + (34, '') : 36, + (34, '') : 51, + (34, '') : 35, + (41, '') : 57, + (41, '') : 44, + (41, '') : 65, + (41, '') : 36, + (41, '') : 42, + (41, '') : 63, + (41, '') : 54, + (41, '') : 51, + (43, '') : 57, + (43, '') : 44, + (43, '') : 36, + (43, '') : 62, + (43, '') : 63, + (43, '') : 54, + (43, '') : 51, + (45, '') : 36, + (45, '') : 51, + (45, '') : 46, + (45, '') : 57, + (45, '') : 54, + (47, '') : 36, + (47, '') : 51, + (47, '') : 48, + (47, '') : 54, + (49, '') : 36, + (49, '') : 51, + (49, '') : 50, + (52, '') : 36, + (52, '') : 51, + (52, '') : 53, + (55, '') : 36, + (55, '') : 51, + (55, '') : 56, + (55, '') : 54, + (58, '') : 36, + (58, '') : 51, + (58, '') : 57, + (58, '') : 59, + (58, '') : 54, + (60, '') : 36, + (60, '') : 51, + (60, '') : 57, + (60, '') : 61, + (60, '') : 54, + (69, '') : 77, + (73, '') : 36, + (73, '') : 54, + (73, '') : 74, + (73, '') : 63, + (73, '') : 44, + (73, '') : 51, + (73, '') : 57, + (75, '') : 76, + (80, '') : 63, + (80, '') : 57, + (80, '') : 44, + (80, '') : 81, + (80, '') : 36, + (80, '') : 51, + (80, '') : 54, + (82, '') : 63, + (82, '') : 57, + (82, '') : 44, + (82, '') : 54, + (82, '') : 51, + (82, '') : 83, + (82, '') : 36, + (86, '') : 36, + (86, '') : 51, + (86, '') : 63, + (86, '') : 44, + (86, '') : 57, + (86, '') : 87, + (86, '') : 54, + (96, '') : 36, + (96, '') : 54, + (96, '') : 95, + (96, '') : 63, + (96, '') : 44, + (96, '') : 97, + (96, '') : 51, + (96, '') : 57, + (101, '') : 102, + (103, '') : 104, + (106, '') : 44, + (106, '') : 63, + (106, '') : 36, + (106, '') : 57, + (106, '') : 51, + (106, '') : 107, + (106, '') : 54, + (109, '') : 113, + (109, '') : 122, + (114, '') : 115, + (119, '') : 54, + (119, '') : 63, + (119, '') : 36, + (119, '') : 44, + (119, '') : 57, + (119, '') : 51, + (119, '') : 120, + (126, '') : 125, + (126, '') : 127, + (126, '') : 128, + (129, '') : 125, + (129, '') : 128, + (129, '') : 130, + (133, '') : 134, + (133, '') : 125, + (133, '') : 128, + (138, '') : 139, + (138, '') : 137 } From b60c5e102b069203811ee88e3b00aefd9a4a77c8 Mon Sep 17 00:00:00 2001 From: Ale Date: Tue, 15 Feb 2022 23:29:31 -0800 Subject: [PATCH 33/83] parser ok --- src/main.py | 2 +- src/utils/COOL_Grammar.py | 15 +- src/utils/parser/COOL_parser.py | 2086 +++++++++++++++---------------- 3 files changed, 1052 insertions(+), 1051 deletions(-) diff --git a/src/main.py b/src/main.py index c0d03122b..4983b1b1e 100644 --- a/src/main.py +++ b/src/main.py @@ -13,7 +13,7 @@ from utils.parser.LALR_1 import LALR1_Parser if __name__ == "__main__": - add = "parser/dispatch2.cl" + add = "parser/dispatch8.cl" path: str = f"{Path.cwd()}/tests/{add}" if os.path.exists( f"{Path.cwd()}/tests/{add}") else f"{Path.cwd()}/../tests/{add}" diff --git a/src/utils/COOL_Grammar.py b/src/utils/COOL_Grammar.py index 93d3b7f18..25fe8b993 100644 --- a/src/utils/COOL_Grammar.py +++ b/src/utils/COOL_Grammar.py @@ -11,7 +11,7 @@ def build_COOL_Grammar(): feature_list, def_attr, def_meth, arg_list = G.NonTerminals(' ') expr, expr_list, id_list, case_list, comp = G.NonTerminals(' ') expr, arith, term, factor, atom, dispatch = G.NonTerminals(' ') - not_empty = G.NonTerminal('') + nonEmpty_argList, nonEmpty_paramList = G.NonTerminals(' ') #terminales classx, let, inx = G.Terminals('class let in') @@ -40,15 +40,16 @@ def build_COOL_Grammar(): def_meth %= idx + opar + param_list + cpar + colon + typex + ocur + expr + ccur, lambda h,s: node.MethDeclarationNode(s[1],s[3],s[6],s[8],s[7]) - param_list %= param, lambda h,s: [s[1]] - param_list %= param_list + comma + param, lambda h,s: [s[1]] + s[3] param_list %= G.Epsilon, lambda h,s: [] + param_list %= nonEmpty_paramList, lambda h,s: s[1] + + nonEmpty_paramList %= param, lambda h,s: [s[1]] + nonEmpty_paramList %= param + comma + nonEmpty_paramList, lambda h,s: [s[1]] + s[3] param %= idx + colon + typex, lambda h,s: [s[1],s[3]] expr %= idx + arrow + expr, lambda h,s: node.AssignNode(s[1],s[3],s[2]) expr %= whilex + expr + loop + expr + pool, lambda h,s: node.WhileNode(s[2],s[4],s[1]) - expr %= ocur + expr_list + ccur, lambda h,s: node.BlockNode(s[2],s[1]) @@ -101,8 +102,10 @@ def build_COOL_Grammar(): dispatch %= idx + opar + arg_list + cpar, lambda h,s: node.CallNode(s[1],s[3]) dispatch %= atom + at + typex + dot + idx + opar + arg_list + cpar, lambda h,s: node.CallNode(s[5],s[7],s[1],s[3]) - arg_list %= expr, lambda h,s: [s[1]] - arg_list %= arg_list + comma + expr, lambda h,s: [s[1]] + s[3] arg_list %= G.Epsilon, lambda h,s: [] + arg_list %= nonEmpty_argList, lambda h,s: s[1] + + nonEmpty_argList %= expr, lambda h,s: [s[1]] + nonEmpty_argList %= expr + comma + nonEmpty_argList, lambda h,s: [s[1]] + s[3] return G \ No newline at end of file diff --git a/src/utils/parser/COOL_parser.py b/src/utils/parser/COOL_parser.py index 418810cb8..edaa3ba96 100644 --- a/src/utils/parser/COOL_parser.py +++ b/src/utils/parser/COOL_parser.py @@ -23,1291 +23,1289 @@ def __init__(self, G): self.action = { (0, 'class') : ('SHIFT', 1), (1, 'type') : ('SHIFT', 2), - (2, 'inherits') : ('SHIFT', 131), (2, '{') : ('SHIFT', 3), + (2, 'inherits') : ('SHIFT', 133), (3, 'id') : ('SHIFT', 4), (3, '}') : ('REDUCE', 7), - (4, '(') : ('SHIFT', 109), + (4, '(') : ('SHIFT', 110), (4, ':') : ('SHIFT', 5), (5, 'type') : ('SHIFT', 6), (6, '<-') : ('SHIFT', 7), (6, ';') : ('REDUCE', 8), + (7, 'id') : ('SHIFT', 18), (7, 'true') : ('SHIFT', 27), - (7, 'not') : ('SHIFT', 26), - (7, 'case') : ('SHIFT', 25), + (7, 'new') : ('SHIFT', 22), + (7, 'if') : ('SHIFT', 24), (7, '(') : ('SHIFT', 13), (7, 'let') : ('SHIFT', 8), + (7, '~') : ('SHIFT', 15), + (7, 'int') : ('SHIFT', 21), (7, 'string') : ('SHIFT', 29), + (7, 'not') : ('SHIFT', 26), (7, 'while') : ('SHIFT', 20), - (7, 'false') : ('SHIFT', 28), (7, 'isvoid') : ('SHIFT', 34), - (7, 'id') : ('SHIFT', 18), - (7, 'if') : ('SHIFT', 24), + (7, 'case') : ('SHIFT', 25), + (7, 'false') : ('SHIFT', 28), (7, '{') : ('SHIFT', 14), - (7, '~') : ('SHIFT', 15), - (7, 'new') : ('SHIFT', 22), - (7, 'int') : ('SHIFT', 21), (8, 'id') : ('SHIFT', 9), (9, ':') : ('SHIFT', 10), (10, 'type') : ('SHIFT', 11), - (11, ',') : ('SHIFT', 103), + (11, ',') : ('SHIFT', 104), (11, '<-') : ('SHIFT', 12), - (11, 'in') : ('REDUCE', 21), - (12, 'id') : ('SHIFT', 18), - (12, 'int') : ('SHIFT', 21), + (11, 'in') : ('REDUCE', 22), + (12, 'false') : ('SHIFT', 28), (12, 'not') : ('SHIFT', 26), + (12, 'while') : ('SHIFT', 20), + (12, 'id') : ('SHIFT', 18), + (12, 'isvoid') : ('SHIFT', 34), + (12, 'case') : ('SHIFT', 25), (12, 'true') : ('SHIFT', 27), + (12, 'new') : ('SHIFT', 22), + (12, 'if') : ('SHIFT', 24), (12, '(') : ('SHIFT', 13), (12, '{') : ('SHIFT', 14), + (12, 'int') : ('SHIFT', 21), (12, 'string') : ('SHIFT', 29), - (12, 'case') : ('SHIFT', 25), - (12, 'false') : ('SHIFT', 28), (12, 'let') : ('SHIFT', 8), - (12, 'while') : ('SHIFT', 20), - (12, 'isvoid') : ('SHIFT', 34), (12, '~') : ('SHIFT', 15), - (12, 'if') : ('SHIFT', 24), - (12, 'new') : ('SHIFT', 22), (13, 'id') : ('SHIFT', 18), - (13, 'case') : ('SHIFT', 25), - (13, 'if') : ('SHIFT', 24), (13, 'let') : ('SHIFT', 8), + (13, 'false') : ('SHIFT', 28), (13, '~') : ('SHIFT', 15), - (13, 'while') : ('SHIFT', 20), + (13, 'true') : ('SHIFT', 27), + (13, 'if') : ('SHIFT', 24), + (13, '(') : ('SHIFT', 13), (13, 'new') : ('SHIFT', 22), (13, 'not') : ('SHIFT', 26), + (13, 'while') : ('SHIFT', 20), + (13, 'case') : ('SHIFT', 25), + (13, 'isvoid') : ('SHIFT', 34), (13, 'int') : ('SHIFT', 21), - (13, 'true') : ('SHIFT', 27), - (13, '(') : ('SHIFT', 13), (13, 'string') : ('SHIFT', 29), - (13, 'false') : ('SHIFT', 28), (13, '{') : ('SHIFT', 14), - (13, 'isvoid') : ('SHIFT', 34), + (14, 'id') : ('SHIFT', 18), (14, 'true') : ('SHIFT', 27), - (14, 'not') : ('SHIFT', 26), - (14, 'case') : ('SHIFT', 25), + (14, 'new') : ('SHIFT', 22), + (14, 'if') : ('SHIFT', 24), (14, '(') : ('SHIFT', 13), (14, 'let') : ('SHIFT', 8), - (14, 'while') : ('SHIFT', 20), + (14, '~') : ('SHIFT', 15), + (14, 'int') : ('SHIFT', 21), (14, 'string') : ('SHIFT', 29), - (14, 'false') : ('SHIFT', 28), + (14, 'not') : ('SHIFT', 26), + (14, 'while') : ('SHIFT', 20), (14, 'isvoid') : ('SHIFT', 34), - (14, 'id') : ('SHIFT', 18), - (14, 'if') : ('SHIFT', 24), - (14, 'int') : ('SHIFT', 21), + (14, 'case') : ('SHIFT', 25), + (14, 'false') : ('SHIFT', 28), (14, '{') : ('SHIFT', 14), - (14, '~') : ('SHIFT', 15), - (14, 'new') : ('SHIFT', 22), + (15, 'true') : ('SHIFT', 27), (15, 'id') : ('SHIFT', 16), - (15, 'string') : ('SHIFT', 29), (15, 'if') : ('SHIFT', 24), + (15, '(') : ('SHIFT', 13), (15, '~') : ('SHIFT', 15), - (15, 'false') : ('SHIFT', 28), (15, 'new') : ('SHIFT', 22), + (15, 'false') : ('SHIFT', 28), (15, 'int') : ('SHIFT', 21), + (15, 'string') : ('SHIFT', 29), (15, 'not') : ('SHIFT', 26), (15, 'isvoid') : ('SHIFT', 34), - (15, 'true') : ('SHIFT', 27), - (15, '(') : ('SHIFT', 13), - (16, '/') : ('REDUCE', 47), - (16, '<') : ('REDUCE', 47), - (16, '<=') : ('REDUCE', 47), - (16, '@') : ('REDUCE', 47), - (16, 'in') : ('REDUCE', 47), - (16, ';') : ('REDUCE', 47), - (16, 'loop') : ('REDUCE', 47), - (16, 'pool') : ('REDUCE', 47), - (16, ',') : ('REDUCE', 47), - (16, '.') : ('REDUCE', 47), - (16, ')') : ('REDUCE', 47), - (16, 'then') : ('REDUCE', 47), - (16, 'else') : ('REDUCE', 47), - (16, '}') : ('REDUCE', 47), - (16, 'fi') : ('REDUCE', 47), - (16, '=') : ('REDUCE', 47), - (16, '+') : ('REDUCE', 47), - (16, 'of') : ('REDUCE', 47), - (16, '-') : ('REDUCE', 47), - (16, '*') : ('REDUCE', 47), (16, '(') : ('SHIFT', 17), - (17, 'if') : ('SHIFT', 24), - (17, '{') : ('SHIFT', 14), - (17, 'new') : ('SHIFT', 22), - (17, 'int') : ('SHIFT', 21), - (17, 'isvoid') : ('SHIFT', 34), - (17, 'true') : ('SHIFT', 27), - (17, 'case') : ('SHIFT', 25), - (17, '(') : ('SHIFT', 13), - (17, 'string') : ('SHIFT', 29), + (16, '-') : ('REDUCE', 48), + (16, 'of') : ('REDUCE', 48), + (16, '*') : ('REDUCE', 48), + (16, '/') : ('REDUCE', 48), + (16, '<') : ('REDUCE', 48), + (16, '<=') : ('REDUCE', 48), + (16, '@') : ('REDUCE', 48), + (16, 'in') : ('REDUCE', 48), + (16, ';') : ('REDUCE', 48), + (16, 'loop') : ('REDUCE', 48), + (16, 'pool') : ('REDUCE', 48), + (16, ',') : ('REDUCE', 48), + (16, '.') : ('REDUCE', 48), + (16, ')') : ('REDUCE', 48), + (16, 'then') : ('REDUCE', 48), + (16, 'else') : ('REDUCE', 48), + (16, '}') : ('REDUCE', 48), + (16, 'fi') : ('REDUCE', 48), + (16, '=') : ('REDUCE', 48), + (16, '+') : ('REDUCE', 48), (17, 'let') : ('SHIFT', 8), - (17, 'while') : ('SHIFT', 20), - (17, ',') : ('REDUCE', 57), - (17, ')') : ('REDUCE', 57), + (17, 'int') : ('SHIFT', 21), (17, '~') : ('SHIFT', 15), - (17, 'false') : ('SHIFT', 28), + (17, 'string') : ('SHIFT', 29), + (17, 'new') : ('SHIFT', 22), + (17, ')') : ('REDUCE', 56), (17, 'not') : ('SHIFT', 26), (17, 'id') : ('SHIFT', 18), + (17, 'isvoid') : ('SHIFT', 34), + (17, 'while') : ('SHIFT', 20), + (17, 'false') : ('SHIFT', 28), + (17, 'case') : ('SHIFT', 25), + (17, '{') : ('SHIFT', 14), + (17, 'true') : ('SHIFT', 27), + (17, 'if') : ('SHIFT', 24), + (17, '(') : ('SHIFT', 13), (18, '<-') : ('SHIFT', 19), - (18, '/') : ('REDUCE', 47), - (18, '<') : ('REDUCE', 47), - (18, '<=') : ('REDUCE', 47), - (18, '@') : ('REDUCE', 47), - (18, 'in') : ('REDUCE', 47), - (18, ';') : ('REDUCE', 47), - (18, 'loop') : ('REDUCE', 47), - (18, 'pool') : ('REDUCE', 47), - (18, ',') : ('REDUCE', 47), - (18, '.') : ('REDUCE', 47), - (18, ')') : ('REDUCE', 47), - (18, 'then') : ('REDUCE', 47), - (18, 'else') : ('REDUCE', 47), - (18, '}') : ('REDUCE', 47), - (18, 'fi') : ('REDUCE', 47), - (18, '=') : ('REDUCE', 47), - (18, '+') : ('REDUCE', 47), - (18, 'of') : ('REDUCE', 47), - (18, '-') : ('REDUCE', 47), - (18, '*') : ('REDUCE', 47), (18, '(') : ('SHIFT', 17), - (19, 'string') : ('SHIFT', 29), - (19, 'false') : ('SHIFT', 28), - (19, 'id') : ('SHIFT', 18), - (19, 'isvoid') : ('SHIFT', 34), - (19, '{') : ('SHIFT', 14), + (18, '-') : ('REDUCE', 48), + (18, 'of') : ('REDUCE', 48), + (18, '*') : ('REDUCE', 48), + (18, '/') : ('REDUCE', 48), + (18, '<') : ('REDUCE', 48), + (18, '<=') : ('REDUCE', 48), + (18, '@') : ('REDUCE', 48), + (18, 'in') : ('REDUCE', 48), + (18, ';') : ('REDUCE', 48), + (18, 'loop') : ('REDUCE', 48), + (18, 'pool') : ('REDUCE', 48), + (18, ',') : ('REDUCE', 48), + (18, '.') : ('REDUCE', 48), + (18, ')') : ('REDUCE', 48), + (18, 'then') : ('REDUCE', 48), + (18, 'else') : ('REDUCE', 48), + (18, '}') : ('REDUCE', 48), + (18, 'fi') : ('REDUCE', 48), + (18, '=') : ('REDUCE', 48), + (18, '+') : ('REDUCE', 48), + (19, 'true') : ('SHIFT', 27), (19, 'if') : ('SHIFT', 24), + (19, 'id') : ('SHIFT', 18), + (19, '(') : ('SHIFT', 13), (19, '~') : ('SHIFT', 15), - (19, 'case') : ('SHIFT', 25), (19, 'new') : ('SHIFT', 22), (19, 'let') : ('SHIFT', 8), (19, 'int') : ('SHIFT', 21), - (19, 'while') : ('SHIFT', 20), + (19, 'string') : ('SHIFT', 29), (19, 'not') : ('SHIFT', 26), - (19, 'true') : ('SHIFT', 27), - (19, '(') : ('SHIFT', 13), + (19, 'isvoid') : ('SHIFT', 34), + (19, 'while') : ('SHIFT', 20), + (19, 'case') : ('SHIFT', 25), + (19, 'false') : ('SHIFT', 28), + (19, '{') : ('SHIFT', 14), + (20, 'isvoid') : ('SHIFT', 34), (20, 'id') : ('SHIFT', 18), - (20, 'new') : ('SHIFT', 22), (20, '{') : ('SHIFT', 14), - (20, 'int') : ('SHIFT', 21), (20, 'true') : ('SHIFT', 27), + (20, 'if') : ('SHIFT', 24), + (20, 'new') : ('SHIFT', 22), (20, '(') : ('SHIFT', 13), + (20, 'int') : ('SHIFT', 21), (20, 'string') : ('SHIFT', 29), - (20, 'if') : ('SHIFT', 24), - (20, 'case') : ('SHIFT', 25), (20, 'let') : ('SHIFT', 8), - (20, 'isvoid') : ('SHIFT', 34), + (20, '~') : ('SHIFT', 15), (20, 'while') : ('SHIFT', 20), (20, 'false') : ('SHIFT', 28), - (20, '~') : ('SHIFT', 15), (20, 'not') : ('SHIFT', 26), - (21, '/') : ('REDUCE', 46), - (21, '<') : ('REDUCE', 46), - (21, '<=') : ('REDUCE', 46), - (21, '@') : ('REDUCE', 46), - (21, 'in') : ('REDUCE', 46), - (21, ';') : ('REDUCE', 46), - (21, 'loop') : ('REDUCE', 46), - (21, 'pool') : ('REDUCE', 46), - (21, ',') : ('REDUCE', 46), - (21, '.') : ('REDUCE', 46), - (21, ')') : ('REDUCE', 46), - (21, 'then') : ('REDUCE', 46), - (21, 'else') : ('REDUCE', 46), - (21, '}') : ('REDUCE', 46), - (21, 'fi') : ('REDUCE', 46), - (21, '=') : ('REDUCE', 46), - (21, '+') : ('REDUCE', 46), - (21, 'of') : ('REDUCE', 46), - (21, '-') : ('REDUCE', 46), - (21, '*') : ('REDUCE', 46), + (20, 'case') : ('SHIFT', 25), + (21, '-') : ('REDUCE', 47), + (21, 'of') : ('REDUCE', 47), + (21, '*') : ('REDUCE', 47), + (21, '/') : ('REDUCE', 47), + (21, '<') : ('REDUCE', 47), + (21, '<=') : ('REDUCE', 47), + (21, '@') : ('REDUCE', 47), + (21, 'in') : ('REDUCE', 47), + (21, ';') : ('REDUCE', 47), + (21, 'loop') : ('REDUCE', 47), + (21, 'pool') : ('REDUCE', 47), + (21, ',') : ('REDUCE', 47), + (21, '.') : ('REDUCE', 47), + (21, ')') : ('REDUCE', 47), + (21, 'then') : ('REDUCE', 47), + (21, 'else') : ('REDUCE', 47), + (21, '}') : ('REDUCE', 47), + (21, 'fi') : ('REDUCE', 47), + (21, '=') : ('REDUCE', 47), + (21, '+') : ('REDUCE', 47), (22, 'type') : ('SHIFT', 23), - (23, '/') : ('REDUCE', 48), - (23, '<') : ('REDUCE', 48), - (23, '<=') : ('REDUCE', 48), - (23, '@') : ('REDUCE', 48), - (23, 'in') : ('REDUCE', 48), - (23, ';') : ('REDUCE', 48), - (23, 'loop') : ('REDUCE', 48), - (23, 'pool') : ('REDUCE', 48), - (23, ',') : ('REDUCE', 48), - (23, '.') : ('REDUCE', 48), - (23, ')') : ('REDUCE', 48), - (23, 'then') : ('REDUCE', 48), - (23, 'else') : ('REDUCE', 48), - (23, '}') : ('REDUCE', 48), - (23, 'fi') : ('REDUCE', 48), - (23, '=') : ('REDUCE', 48), - (23, '+') : ('REDUCE', 48), - (23, 'of') : ('REDUCE', 48), - (23, '-') : ('REDUCE', 48), - (23, '*') : ('REDUCE', 48), - (24, '(') : ('SHIFT', 13), - (24, 'id') : ('SHIFT', 18), + (23, '-') : ('REDUCE', 49), + (23, 'of') : ('REDUCE', 49), + (23, '*') : ('REDUCE', 49), + (23, '/') : ('REDUCE', 49), + (23, '<') : ('REDUCE', 49), + (23, '<=') : ('REDUCE', 49), + (23, '@') : ('REDUCE', 49), + (23, 'in') : ('REDUCE', 49), + (23, ';') : ('REDUCE', 49), + (23, 'loop') : ('REDUCE', 49), + (23, 'pool') : ('REDUCE', 49), + (23, ',') : ('REDUCE', 49), + (23, '.') : ('REDUCE', 49), + (23, ')') : ('REDUCE', 49), + (23, 'then') : ('REDUCE', 49), + (23, 'else') : ('REDUCE', 49), + (23, '}') : ('REDUCE', 49), + (23, 'fi') : ('REDUCE', 49), + (23, '=') : ('REDUCE', 49), + (23, '+') : ('REDUCE', 49), + (24, 'int') : ('SHIFT', 21), + (24, 'not') : ('SHIFT', 26), (24, 'string') : ('SHIFT', 29), - (24, '~') : ('SHIFT', 15), + (24, 'isvoid') : ('SHIFT', 34), + (24, 'while') : ('SHIFT', 20), + (24, 'id') : ('SHIFT', 18), + (24, 'case') : ('SHIFT', 25), (24, '{') : ('SHIFT', 14), - (24, 'not') : ('SHIFT', 26), (24, 'false') : ('SHIFT', 28), - (24, 'case') : ('SHIFT', 25), (24, 'let') : ('SHIFT', 8), - (24, 'while') : ('SHIFT', 20), (24, 'if') : ('SHIFT', 24), - (24, 'isvoid') : ('SHIFT', 34), - (24, 'new') : ('SHIFT', 22), - (24, 'int') : ('SHIFT', 21), + (24, '~') : ('SHIFT', 15), (24, 'true') : ('SHIFT', 27), - (25, 'isvoid') : ('SHIFT', 34), - (25, 'id') : ('SHIFT', 18), - (25, 'case') : ('SHIFT', 25), + (24, 'new') : ('SHIFT', 22), + (24, '(') : ('SHIFT', 13), (25, 'let') : ('SHIFT', 8), - (25, 'if') : ('SHIFT', 24), - (25, 'while') : ('SHIFT', 20), + (25, 'id') : ('SHIFT', 18), (25, '~') : ('SHIFT', 15), - (25, 'new') : ('SHIFT', 22), - (25, 'int') : ('SHIFT', 21), + (25, 'while') : ('SHIFT', 20), + (25, 'false') : ('SHIFT', 28), + (25, 'case') : ('SHIFT', 25), (25, 'not') : ('SHIFT', 26), (25, 'true') : ('SHIFT', 27), + (25, '{') : ('SHIFT', 14), + (25, 'new') : ('SHIFT', 22), + (25, 'if') : ('SHIFT', 24), (25, '(') : ('SHIFT', 13), + (25, 'isvoid') : ('SHIFT', 34), + (25, 'int') : ('SHIFT', 21), (25, 'string') : ('SHIFT', 29), - (25, 'false') : ('SHIFT', 28), - (25, '{') : ('SHIFT', 14), + (26, 'true') : ('SHIFT', 27), + (26, 'int') : ('SHIFT', 21), (26, 'id') : ('SHIFT', 16), - (26, 'false') : ('SHIFT', 28), (26, 'string') : ('SHIFT', 29), - (26, 'new') : ('SHIFT', 22), - (26, 'int') : ('SHIFT', 21), (26, 'if') : ('SHIFT', 24), - (26, 'true') : ('SHIFT', 27), (26, '(') : ('SHIFT', 13), - (27, '/') : ('REDUCE', 43), - (27, '<') : ('REDUCE', 43), - (27, '<=') : ('REDUCE', 43), - (27, '@') : ('REDUCE', 43), - (27, 'in') : ('REDUCE', 43), - (27, ';') : ('REDUCE', 43), - (27, 'loop') : ('REDUCE', 43), - (27, 'pool') : ('REDUCE', 43), - (27, ',') : ('REDUCE', 43), - (27, '.') : ('REDUCE', 43), - (27, ')') : ('REDUCE', 43), - (27, 'then') : ('REDUCE', 43), - (27, 'else') : ('REDUCE', 43), - (27, '}') : ('REDUCE', 43), - (27, 'fi') : ('REDUCE', 43), - (27, '=') : ('REDUCE', 43), - (27, '+') : ('REDUCE', 43), - (27, 'of') : ('REDUCE', 43), - (27, '-') : ('REDUCE', 43), - (27, '*') : ('REDUCE', 43), - (28, '/') : ('REDUCE', 44), - (28, '<') : ('REDUCE', 44), - (28, '<=') : ('REDUCE', 44), - (28, '@') : ('REDUCE', 44), - (28, 'in') : ('REDUCE', 44), - (28, ';') : ('REDUCE', 44), - (28, 'loop') : ('REDUCE', 44), - (28, 'pool') : ('REDUCE', 44), - (28, ',') : ('REDUCE', 44), - (28, '.') : ('REDUCE', 44), - (28, ')') : ('REDUCE', 44), - (28, 'then') : ('REDUCE', 44), - (28, 'else') : ('REDUCE', 44), - (28, '}') : ('REDUCE', 44), - (28, 'fi') : ('REDUCE', 44), - (28, '=') : ('REDUCE', 44), - (28, '+') : ('REDUCE', 44), - (28, 'of') : ('REDUCE', 44), - (28, '-') : ('REDUCE', 44), - (28, '*') : ('REDUCE', 44), - (29, '/') : ('REDUCE', 45), - (29, '<') : ('REDUCE', 45), - (29, '<=') : ('REDUCE', 45), - (29, '@') : ('REDUCE', 45), - (29, 'in') : ('REDUCE', 45), - (29, ';') : ('REDUCE', 45), - (29, 'loop') : ('REDUCE', 45), - (29, 'pool') : ('REDUCE', 45), - (29, ',') : ('REDUCE', 45), - (29, '.') : ('REDUCE', 45), - (29, ')') : ('REDUCE', 45), - (29, 'then') : ('REDUCE', 45), - (29, 'else') : ('REDUCE', 45), - (29, '}') : ('REDUCE', 45), - (29, 'fi') : ('REDUCE', 45), - (29, '=') : ('REDUCE', 45), - (29, '+') : ('REDUCE', 45), - (29, 'of') : ('REDUCE', 45), - (29, '-') : ('REDUCE', 45), - (29, '*') : ('REDUCE', 45), - (30, ',') : ('REDUCE', 41), - (30, '/') : ('REDUCE', 41), - (30, 'fi') : ('REDUCE', 41), - (30, 'pool') : ('REDUCE', 41), - (30, '<') : ('REDUCE', 41), - (30, 'in') : ('REDUCE', 41), - (30, '=') : ('REDUCE', 41), - (30, '<=') : ('REDUCE', 41), - (30, ';') : ('REDUCE', 41), - (30, '+') : ('REDUCE', 41), - (30, '*') : ('REDUCE', 41), - (30, ')') : ('REDUCE', 41), - (30, 'of') : ('REDUCE', 41), - (30, 'then') : ('REDUCE', 41), - (30, '-') : ('REDUCE', 41), - (30, 'loop') : ('REDUCE', 41), - (30, 'else') : ('REDUCE', 41), - (30, '}') : ('REDUCE', 41), - (30, '.') : ('SHIFT', 31), + (26, 'new') : ('SHIFT', 22), + (26, 'false') : ('SHIFT', 28), + (27, '-') : ('REDUCE', 44), + (27, 'of') : ('REDUCE', 44), + (27, '*') : ('REDUCE', 44), + (27, '/') : ('REDUCE', 44), + (27, '<') : ('REDUCE', 44), + (27, '<=') : ('REDUCE', 44), + (27, '@') : ('REDUCE', 44), + (27, 'in') : ('REDUCE', 44), + (27, ';') : ('REDUCE', 44), + (27, 'loop') : ('REDUCE', 44), + (27, 'pool') : ('REDUCE', 44), + (27, ',') : ('REDUCE', 44), + (27, '.') : ('REDUCE', 44), + (27, ')') : ('REDUCE', 44), + (27, 'then') : ('REDUCE', 44), + (27, 'else') : ('REDUCE', 44), + (27, '}') : ('REDUCE', 44), + (27, 'fi') : ('REDUCE', 44), + (27, '=') : ('REDUCE', 44), + (27, '+') : ('REDUCE', 44), + (28, '-') : ('REDUCE', 45), + (28, 'of') : ('REDUCE', 45), + (28, '*') : ('REDUCE', 45), + (28, '/') : ('REDUCE', 45), + (28, '<') : ('REDUCE', 45), + (28, '<=') : ('REDUCE', 45), + (28, '@') : ('REDUCE', 45), + (28, 'in') : ('REDUCE', 45), + (28, ';') : ('REDUCE', 45), + (28, 'loop') : ('REDUCE', 45), + (28, 'pool') : ('REDUCE', 45), + (28, ',') : ('REDUCE', 45), + (28, '.') : ('REDUCE', 45), + (28, ')') : ('REDUCE', 45), + (28, 'then') : ('REDUCE', 45), + (28, 'else') : ('REDUCE', 45), + (28, '}') : ('REDUCE', 45), + (28, 'fi') : ('REDUCE', 45), + (28, '=') : ('REDUCE', 45), + (28, '+') : ('REDUCE', 45), + (29, '-') : ('REDUCE', 46), + (29, 'of') : ('REDUCE', 46), + (29, '*') : ('REDUCE', 46), + (29, '/') : ('REDUCE', 46), + (29, '<') : ('REDUCE', 46), + (29, '<=') : ('REDUCE', 46), + (29, '@') : ('REDUCE', 46), + (29, 'in') : ('REDUCE', 46), + (29, ';') : ('REDUCE', 46), + (29, 'loop') : ('REDUCE', 46), + (29, 'pool') : ('REDUCE', 46), + (29, ',') : ('REDUCE', 46), + (29, '.') : ('REDUCE', 46), + (29, ')') : ('REDUCE', 46), + (29, 'then') : ('REDUCE', 46), + (29, 'else') : ('REDUCE', 46), + (29, '}') : ('REDUCE', 46), + (29, 'fi') : ('REDUCE', 46), + (29, '=') : ('REDUCE', 46), + (29, '+') : ('REDUCE', 46), (30, '@') : ('SHIFT', 37), + (30, '.') : ('SHIFT', 31), + (30, '-') : ('REDUCE', 42), + (30, 'then') : ('REDUCE', 42), + (30, 'loop') : ('REDUCE', 42), + (30, 'of') : ('REDUCE', 42), + (30, ';') : ('REDUCE', 42), + (30, '*') : ('REDUCE', 42), + (30, 'else') : ('REDUCE', 42), + (30, 'pool') : ('REDUCE', 42), + (30, '}') : ('REDUCE', 42), + (30, ',') : ('REDUCE', 42), + (30, '/') : ('REDUCE', 42), + (30, 'fi') : ('REDUCE', 42), + (30, '<') : ('REDUCE', 42), + (30, 'in') : ('REDUCE', 42), + (30, '=') : ('REDUCE', 42), + (30, '<=') : ('REDUCE', 42), + (30, '+') : ('REDUCE', 42), + (30, ')') : ('REDUCE', 42), (31, 'id') : ('SHIFT', 32), (32, '(') : ('SHIFT', 33), - (33, 'if') : ('SHIFT', 24), - (33, '{') : ('SHIFT', 14), - (33, 'new') : ('SHIFT', 22), - (33, 'int') : ('SHIFT', 21), - (33, 'isvoid') : ('SHIFT', 34), - (33, 'true') : ('SHIFT', 27), - (33, 'case') : ('SHIFT', 25), - (33, '(') : ('SHIFT', 13), - (33, 'string') : ('SHIFT', 29), (33, 'let') : ('SHIFT', 8), - (33, 'while') : ('SHIFT', 20), - (33, ',') : ('REDUCE', 57), - (33, ')') : ('REDUCE', 57), + (33, 'int') : ('SHIFT', 21), (33, '~') : ('SHIFT', 15), - (33, 'false') : ('SHIFT', 28), + (33, 'string') : ('SHIFT', 29), + (33, 'new') : ('SHIFT', 22), + (33, ')') : ('REDUCE', 56), (33, 'not') : ('SHIFT', 26), (33, 'id') : ('SHIFT', 18), + (33, 'isvoid') : ('SHIFT', 34), + (33, 'while') : ('SHIFT', 20), + (33, 'false') : ('SHIFT', 28), + (33, 'case') : ('SHIFT', 25), + (33, '{') : ('SHIFT', 14), + (33, 'true') : ('SHIFT', 27), + (33, 'if') : ('SHIFT', 24), + (33, '(') : ('SHIFT', 13), + (34, 'true') : ('SHIFT', 27), (34, 'id') : ('SHIFT', 16), - (34, 'string') : ('SHIFT', 29), (34, 'if') : ('SHIFT', 24), + (34, '(') : ('SHIFT', 13), (34, '~') : ('SHIFT', 15), - (34, 'false') : ('SHIFT', 28), (34, 'new') : ('SHIFT', 22), + (34, 'false') : ('SHIFT', 28), (34, 'int') : ('SHIFT', 21), + (34, 'string') : ('SHIFT', 29), (34, 'not') : ('SHIFT', 26), (34, 'isvoid') : ('SHIFT', 34), - (34, 'true') : ('SHIFT', 27), - (34, '(') : ('SHIFT', 13), - (35, ',') : ('REDUCE', 39), - (35, '/') : ('REDUCE', 39), - (35, 'fi') : ('REDUCE', 39), - (35, 'pool') : ('REDUCE', 39), - (35, '<') : ('REDUCE', 39), - (35, 'in') : ('REDUCE', 39), - (35, '=') : ('REDUCE', 39), - (35, '<=') : ('REDUCE', 39), - (35, ';') : ('REDUCE', 39), - (35, '+') : ('REDUCE', 39), - (35, '*') : ('REDUCE', 39), - (35, ')') : ('REDUCE', 39), - (35, 'of') : ('REDUCE', 39), - (35, 'then') : ('REDUCE', 39), - (35, '-') : ('REDUCE', 39), - (35, 'loop') : ('REDUCE', 39), - (35, 'else') : ('REDUCE', 39), - (35, '}') : ('REDUCE', 39), - (36, ',') : ('REDUCE', 42), - (36, '/') : ('REDUCE', 42), - (36, 'fi') : ('REDUCE', 42), - (36, 'pool') : ('REDUCE', 42), - (36, '<') : ('REDUCE', 42), - (36, 'in') : ('REDUCE', 42), - (36, '=') : ('REDUCE', 42), - (36, '<=') : ('REDUCE', 42), - (36, ';') : ('REDUCE', 42), - (36, '+') : ('REDUCE', 42), - (36, '*') : ('REDUCE', 42), - (36, ')') : ('REDUCE', 42), - (36, 'of') : ('REDUCE', 42), - (36, 'then') : ('REDUCE', 42), - (36, '-') : ('REDUCE', 42), - (36, 'loop') : ('REDUCE', 42), - (36, 'else') : ('REDUCE', 42), - (36, '}') : ('REDUCE', 42), - (36, '.') : ('SHIFT', 31), + (35, '-') : ('REDUCE', 40), + (35, 'then') : ('REDUCE', 40), + (35, 'loop') : ('REDUCE', 40), + (35, 'of') : ('REDUCE', 40), + (35, ';') : ('REDUCE', 40), + (35, '*') : ('REDUCE', 40), + (35, 'else') : ('REDUCE', 40), + (35, 'pool') : ('REDUCE', 40), + (35, '}') : ('REDUCE', 40), + (35, ',') : ('REDUCE', 40), + (35, '/') : ('REDUCE', 40), + (35, 'fi') : ('REDUCE', 40), + (35, '<') : ('REDUCE', 40), + (35, 'in') : ('REDUCE', 40), + (35, '=') : ('REDUCE', 40), + (35, '<=') : ('REDUCE', 40), + (35, '+') : ('REDUCE', 40), + (35, ')') : ('REDUCE', 40), (36, '@') : ('SHIFT', 37), + (36, '.') : ('SHIFT', 31), + (36, '-') : ('REDUCE', 43), + (36, 'then') : ('REDUCE', 43), + (36, 'loop') : ('REDUCE', 43), + (36, 'of') : ('REDUCE', 43), + (36, ';') : ('REDUCE', 43), + (36, '*') : ('REDUCE', 43), + (36, 'else') : ('REDUCE', 43), + (36, 'pool') : ('REDUCE', 43), + (36, '}') : ('REDUCE', 43), + (36, ',') : ('REDUCE', 43), + (36, '/') : ('REDUCE', 43), + (36, 'fi') : ('REDUCE', 43), + (36, '<') : ('REDUCE', 43), + (36, 'in') : ('REDUCE', 43), + (36, '=') : ('REDUCE', 43), + (36, '<=') : ('REDUCE', 43), + (36, '+') : ('REDUCE', 43), + (36, ')') : ('REDUCE', 43), (37, 'type') : ('SHIFT', 38), (38, '.') : ('SHIFT', 39), (39, 'id') : ('SHIFT', 40), (40, '(') : ('SHIFT', 41), - (41, 'if') : ('SHIFT', 24), - (41, '{') : ('SHIFT', 14), - (41, 'new') : ('SHIFT', 22), - (41, 'int') : ('SHIFT', 21), - (41, 'isvoid') : ('SHIFT', 34), - (41, 'true') : ('SHIFT', 27), - (41, 'case') : ('SHIFT', 25), - (41, '(') : ('SHIFT', 13), - (41, 'string') : ('SHIFT', 29), (41, 'let') : ('SHIFT', 8), - (41, 'while') : ('SHIFT', 20), - (41, ',') : ('REDUCE', 57), - (41, ')') : ('REDUCE', 57), + (41, 'int') : ('SHIFT', 21), (41, '~') : ('SHIFT', 15), - (41, 'false') : ('SHIFT', 28), + (41, 'string') : ('SHIFT', 29), + (41, 'new') : ('SHIFT', 22), + (41, ')') : ('REDUCE', 56), (41, 'not') : ('SHIFT', 26), (41, 'id') : ('SHIFT', 18), - (42, ',') : ('SHIFT', 43), - (42, ')') : ('SHIFT', 64), - (43, 'if') : ('SHIFT', 24), - (43, '{') : ('SHIFT', 14), - (43, 'new') : ('SHIFT', 22), - (43, 'int') : ('SHIFT', 21), - (43, 'isvoid') : ('SHIFT', 34), - (43, 'true') : ('SHIFT', 27), - (43, 'case') : ('SHIFT', 25), - (43, '(') : ('SHIFT', 13), - (43, 'string') : ('SHIFT', 29), - (43, 'let') : ('SHIFT', 8), - (43, 'while') : ('SHIFT', 20), - (43, '~') : ('SHIFT', 15), - (43, 'false') : ('SHIFT', 28), - (43, 'not') : ('SHIFT', 26), - (43, 'id') : ('SHIFT', 18), - (44, '<') : ('SHIFT', 58), + (41, 'isvoid') : ('SHIFT', 34), + (41, 'while') : ('SHIFT', 20), + (41, 'false') : ('SHIFT', 28), + (41, 'case') : ('SHIFT', 25), + (41, '{') : ('SHIFT', 14), + (41, 'true') : ('SHIFT', 27), + (41, 'if') : ('SHIFT', 24), + (41, '(') : ('SHIFT', 13), + (42, ')') : ('SHIFT', 43), + (43, '-') : ('REDUCE', 55), + (43, 'of') : ('REDUCE', 55), + (43, '*') : ('REDUCE', 55), + (43, '/') : ('REDUCE', 55), + (43, '<') : ('REDUCE', 55), + (43, '<=') : ('REDUCE', 55), + (43, '@') : ('REDUCE', 55), + (43, 'in') : ('REDUCE', 55), + (43, ';') : ('REDUCE', 55), + (43, 'loop') : ('REDUCE', 55), + (43, 'pool') : ('REDUCE', 55), + (43, ',') : ('REDUCE', 55), + (43, '.') : ('REDUCE', 55), + (43, ')') : ('REDUCE', 55), + (43, 'then') : ('REDUCE', 55), + (43, 'else') : ('REDUCE', 55), + (43, '}') : ('REDUCE', 55), + (43, 'fi') : ('REDUCE', 55), + (43, '=') : ('REDUCE', 55), + (43, '+') : ('REDUCE', 55), (44, '<=') : ('SHIFT', 60), - (44, ',') : ('REDUCE', 28), - (44, 'fi') : ('REDUCE', 28), - (44, 'in') : ('REDUCE', 28), - (44, ';') : ('REDUCE', 28), - (44, ')') : ('REDUCE', 28), - (44, 'of') : ('REDUCE', 28), - (44, 'then') : ('REDUCE', 28), - (44, 'loop') : ('REDUCE', 28), - (44, '}') : ('REDUCE', 28), - (44, 'else') : ('REDUCE', 28), - (44, 'pool') : ('REDUCE', 28), + (44, 'then') : ('REDUCE', 29), + (44, 'loop') : ('REDUCE', 29), + (44, 'of') : ('REDUCE', 29), + (44, 'else') : ('REDUCE', 29), + (44, 'pool') : ('REDUCE', 29), + (44, '}') : ('REDUCE', 29), + (44, ',') : ('REDUCE', 29), + (44, 'fi') : ('REDUCE', 29), + (44, 'in') : ('REDUCE', 29), + (44, ';') : ('REDUCE', 29), + (44, ')') : ('REDUCE', 29), + (44, '<') : ('SHIFT', 58), (44, '=') : ('SHIFT', 45), + (45, 'true') : ('SHIFT', 27), (45, 'id') : ('SHIFT', 16), - (45, 'string') : ('SHIFT', 29), (45, 'if') : ('SHIFT', 24), + (45, '(') : ('SHIFT', 13), (45, '~') : ('SHIFT', 15), - (45, 'false') : ('SHIFT', 28), (45, 'new') : ('SHIFT', 22), + (45, 'false') : ('SHIFT', 28), (45, 'int') : ('SHIFT', 21), + (45, 'string') : ('SHIFT', 29), (45, 'not') : ('SHIFT', 26), (45, 'isvoid') : ('SHIFT', 34), - (45, 'true') : ('SHIFT', 27), - (45, '(') : ('SHIFT', 13), (46, '-') : ('SHIFT', 55), (46, '+') : ('SHIFT', 47), - (46, ',') : ('REDUCE', 31), - (46, 'fi') : ('REDUCE', 31), - (46, 'pool') : ('REDUCE', 31), - (46, '<') : ('REDUCE', 31), - (46, 'in') : ('REDUCE', 31), - (46, '=') : ('REDUCE', 31), - (46, '<=') : ('REDUCE', 31), - (46, ';') : ('REDUCE', 31), - (46, ')') : ('REDUCE', 31), - (46, 'of') : ('REDUCE', 31), - (46, 'then') : ('REDUCE', 31), - (46, 'loop') : ('REDUCE', 31), - (46, 'else') : ('REDUCE', 31), - (46, '}') : ('REDUCE', 31), + (46, 'then') : ('REDUCE', 32), + (46, 'loop') : ('REDUCE', 32), + (46, 'of') : ('REDUCE', 32), + (46, ';') : ('REDUCE', 32), + (46, 'else') : ('REDUCE', 32), + (46, 'pool') : ('REDUCE', 32), + (46, '}') : ('REDUCE', 32), + (46, ',') : ('REDUCE', 32), + (46, 'fi') : ('REDUCE', 32), + (46, '<') : ('REDUCE', 32), + (46, 'in') : ('REDUCE', 32), + (46, '=') : ('REDUCE', 32), + (46, '<=') : ('REDUCE', 32), + (46, ')') : ('REDUCE', 32), + (47, 'true') : ('SHIFT', 27), (47, 'id') : ('SHIFT', 16), - (47, 'string') : ('SHIFT', 29), (47, 'if') : ('SHIFT', 24), + (47, '(') : ('SHIFT', 13), (47, '~') : ('SHIFT', 15), - (47, 'false') : ('SHIFT', 28), (47, 'new') : ('SHIFT', 22), + (47, 'false') : ('SHIFT', 28), (47, 'int') : ('SHIFT', 21), + (47, 'string') : ('SHIFT', 29), (47, 'not') : ('SHIFT', 26), (47, 'isvoid') : ('SHIFT', 34), - (47, 'true') : ('SHIFT', 27), - (47, '(') : ('SHIFT', 13), - (48, '/') : ('SHIFT', 52), - (48, ',') : ('REDUCE', 33), - (48, 'fi') : ('REDUCE', 33), - (48, 'pool') : ('REDUCE', 33), - (48, '<') : ('REDUCE', 33), - (48, 'in') : ('REDUCE', 33), - (48, '=') : ('REDUCE', 33), - (48, '<=') : ('REDUCE', 33), - (48, ';') : ('REDUCE', 33), - (48, '+') : ('REDUCE', 33), - (48, ')') : ('REDUCE', 33), - (48, 'of') : ('REDUCE', 33), - (48, 'then') : ('REDUCE', 33), - (48, '-') : ('REDUCE', 33), - (48, 'loop') : ('REDUCE', 33), - (48, 'else') : ('REDUCE', 33), - (48, '}') : ('REDUCE', 33), + (48, '-') : ('REDUCE', 34), + (48, 'then') : ('REDUCE', 34), + (48, 'loop') : ('REDUCE', 34), + (48, 'of') : ('REDUCE', 34), + (48, ';') : ('REDUCE', 34), + (48, 'else') : ('REDUCE', 34), + (48, 'pool') : ('REDUCE', 34), + (48, '}') : ('REDUCE', 34), + (48, ',') : ('REDUCE', 34), + (48, 'fi') : ('REDUCE', 34), + (48, '<') : ('REDUCE', 34), + (48, 'in') : ('REDUCE', 34), + (48, '=') : ('REDUCE', 34), + (48, '<=') : ('REDUCE', 34), + (48, '+') : ('REDUCE', 34), + (48, ')') : ('REDUCE', 34), (48, '*') : ('SHIFT', 49), + (48, '/') : ('SHIFT', 52), + (49, 'true') : ('SHIFT', 27), (49, 'id') : ('SHIFT', 16), - (49, 'string') : ('SHIFT', 29), (49, 'if') : ('SHIFT', 24), + (49, '(') : ('SHIFT', 13), (49, '~') : ('SHIFT', 15), - (49, 'false') : ('SHIFT', 28), (49, 'new') : ('SHIFT', 22), + (49, 'false') : ('SHIFT', 28), (49, 'int') : ('SHIFT', 21), + (49, 'string') : ('SHIFT', 29), (49, 'not') : ('SHIFT', 26), (49, 'isvoid') : ('SHIFT', 34), - (49, 'true') : ('SHIFT', 27), - (49, '(') : ('SHIFT', 13), - (50, ',') : ('REDUCE', 36), - (50, '/') : ('REDUCE', 36), - (50, 'fi') : ('REDUCE', 36), - (50, 'pool') : ('REDUCE', 36), - (50, '<') : ('REDUCE', 36), - (50, 'in') : ('REDUCE', 36), - (50, '=') : ('REDUCE', 36), - (50, '<=') : ('REDUCE', 36), - (50, ';') : ('REDUCE', 36), - (50, '+') : ('REDUCE', 36), - (50, '*') : ('REDUCE', 36), - (50, ')') : ('REDUCE', 36), - (50, 'of') : ('REDUCE', 36), - (50, 'then') : ('REDUCE', 36), - (50, '-') : ('REDUCE', 36), - (50, 'loop') : ('REDUCE', 36), - (50, 'else') : ('REDUCE', 36), - (50, '}') : ('REDUCE', 36), - (51, '/') : ('REDUCE', 51), - (51, '<') : ('REDUCE', 51), - (51, '<=') : ('REDUCE', 51), - (51, '@') : ('REDUCE', 51), - (51, 'in') : ('REDUCE', 51), - (51, ';') : ('REDUCE', 51), - (51, 'loop') : ('REDUCE', 51), - (51, 'pool') : ('REDUCE', 51), - (51, ',') : ('REDUCE', 51), - (51, '.') : ('REDUCE', 51), - (51, ')') : ('REDUCE', 51), - (51, 'then') : ('REDUCE', 51), - (51, 'else') : ('REDUCE', 51), - (51, '}') : ('REDUCE', 51), - (51, 'fi') : ('REDUCE', 51), - (51, '=') : ('REDUCE', 51), - (51, '+') : ('REDUCE', 51), - (51, 'of') : ('REDUCE', 51), - (51, '-') : ('REDUCE', 51), - (51, '*') : ('REDUCE', 51), + (50, '-') : ('REDUCE', 37), + (50, 'then') : ('REDUCE', 37), + (50, 'loop') : ('REDUCE', 37), + (50, 'of') : ('REDUCE', 37), + (50, ';') : ('REDUCE', 37), + (50, '*') : ('REDUCE', 37), + (50, 'else') : ('REDUCE', 37), + (50, 'pool') : ('REDUCE', 37), + (50, '}') : ('REDUCE', 37), + (50, ',') : ('REDUCE', 37), + (50, '/') : ('REDUCE', 37), + (50, 'fi') : ('REDUCE', 37), + (50, '<') : ('REDUCE', 37), + (50, 'in') : ('REDUCE', 37), + (50, '=') : ('REDUCE', 37), + (50, '<=') : ('REDUCE', 37), + (50, '+') : ('REDUCE', 37), + (50, ')') : ('REDUCE', 37), + (51, '-') : ('REDUCE', 52), + (51, 'of') : ('REDUCE', 52), + (51, '*') : ('REDUCE', 52), + (51, '/') : ('REDUCE', 52), + (51, '<') : ('REDUCE', 52), + (51, '<=') : ('REDUCE', 52), + (51, '@') : ('REDUCE', 52), + (51, 'in') : ('REDUCE', 52), + (51, ';') : ('REDUCE', 52), + (51, 'loop') : ('REDUCE', 52), + (51, 'pool') : ('REDUCE', 52), + (51, ',') : ('REDUCE', 52), + (51, '.') : ('REDUCE', 52), + (51, ')') : ('REDUCE', 52), + (51, 'then') : ('REDUCE', 52), + (51, 'else') : ('REDUCE', 52), + (51, '}') : ('REDUCE', 52), + (51, 'fi') : ('REDUCE', 52), + (51, '=') : ('REDUCE', 52), + (51, '+') : ('REDUCE', 52), + (52, 'true') : ('SHIFT', 27), (52, 'id') : ('SHIFT', 16), - (52, 'string') : ('SHIFT', 29), (52, 'if') : ('SHIFT', 24), + (52, '(') : ('SHIFT', 13), (52, '~') : ('SHIFT', 15), - (52, 'false') : ('SHIFT', 28), (52, 'new') : ('SHIFT', 22), + (52, 'false') : ('SHIFT', 28), (52, 'int') : ('SHIFT', 21), + (52, 'string') : ('SHIFT', 29), (52, 'not') : ('SHIFT', 26), (52, 'isvoid') : ('SHIFT', 34), - (52, 'true') : ('SHIFT', 27), - (52, '(') : ('SHIFT', 13), - (53, ',') : ('REDUCE', 37), - (53, '/') : ('REDUCE', 37), - (53, 'fi') : ('REDUCE', 37), - (53, 'pool') : ('REDUCE', 37), - (53, '<') : ('REDUCE', 37), - (53, 'in') : ('REDUCE', 37), - (53, '=') : ('REDUCE', 37), - (53, '<=') : ('REDUCE', 37), - (53, ';') : ('REDUCE', 37), - (53, '+') : ('REDUCE', 37), - (53, '*') : ('REDUCE', 37), - (53, ')') : ('REDUCE', 37), - (53, 'of') : ('REDUCE', 37), - (53, 'then') : ('REDUCE', 37), - (53, '-') : ('REDUCE', 37), - (53, 'loop') : ('REDUCE', 37), - (53, 'else') : ('REDUCE', 37), - (53, '}') : ('REDUCE', 37), - (54, ',') : ('REDUCE', 38), - (54, '/') : ('REDUCE', 38), - (54, 'fi') : ('REDUCE', 38), - (54, 'pool') : ('REDUCE', 38), - (54, '<') : ('REDUCE', 38), - (54, 'in') : ('REDUCE', 38), - (54, '=') : ('REDUCE', 38), - (54, '<=') : ('REDUCE', 38), - (54, ';') : ('REDUCE', 38), - (54, '+') : ('REDUCE', 38), - (54, '*') : ('REDUCE', 38), - (54, ')') : ('REDUCE', 38), - (54, 'of') : ('REDUCE', 38), - (54, 'then') : ('REDUCE', 38), - (54, '-') : ('REDUCE', 38), - (54, 'loop') : ('REDUCE', 38), - (54, 'else') : ('REDUCE', 38), - (54, '}') : ('REDUCE', 38), + (53, '-') : ('REDUCE', 38), + (53, 'then') : ('REDUCE', 38), + (53, 'loop') : ('REDUCE', 38), + (53, 'of') : ('REDUCE', 38), + (53, ';') : ('REDUCE', 38), + (53, '*') : ('REDUCE', 38), + (53, 'else') : ('REDUCE', 38), + (53, 'pool') : ('REDUCE', 38), + (53, '}') : ('REDUCE', 38), + (53, ',') : ('REDUCE', 38), + (53, '/') : ('REDUCE', 38), + (53, 'fi') : ('REDUCE', 38), + (53, '<') : ('REDUCE', 38), + (53, 'in') : ('REDUCE', 38), + (53, '=') : ('REDUCE', 38), + (53, '<=') : ('REDUCE', 38), + (53, '+') : ('REDUCE', 38), + (53, ')') : ('REDUCE', 38), + (54, '-') : ('REDUCE', 39), + (54, 'then') : ('REDUCE', 39), + (54, 'loop') : ('REDUCE', 39), + (54, 'of') : ('REDUCE', 39), + (54, ';') : ('REDUCE', 39), + (54, '*') : ('REDUCE', 39), + (54, 'else') : ('REDUCE', 39), + (54, 'pool') : ('REDUCE', 39), + (54, '}') : ('REDUCE', 39), + (54, ',') : ('REDUCE', 39), + (54, '/') : ('REDUCE', 39), + (54, 'fi') : ('REDUCE', 39), + (54, '<') : ('REDUCE', 39), + (54, 'in') : ('REDUCE', 39), + (54, '=') : ('REDUCE', 39), + (54, '<=') : ('REDUCE', 39), + (54, '+') : ('REDUCE', 39), + (54, ')') : ('REDUCE', 39), + (55, 'true') : ('SHIFT', 27), (55, 'id') : ('SHIFT', 16), - (55, 'string') : ('SHIFT', 29), (55, 'if') : ('SHIFT', 24), + (55, '(') : ('SHIFT', 13), (55, '~') : ('SHIFT', 15), - (55, 'false') : ('SHIFT', 28), (55, 'new') : ('SHIFT', 22), + (55, 'false') : ('SHIFT', 28), (55, 'int') : ('SHIFT', 21), + (55, 'string') : ('SHIFT', 29), (55, 'not') : ('SHIFT', 26), (55, 'isvoid') : ('SHIFT', 34), - (55, 'true') : ('SHIFT', 27), - (55, '(') : ('SHIFT', 13), - (56, '/') : ('SHIFT', 52), - (56, ',') : ('REDUCE', 34), - (56, 'fi') : ('REDUCE', 34), - (56, 'pool') : ('REDUCE', 34), - (56, '<') : ('REDUCE', 34), - (56, 'in') : ('REDUCE', 34), - (56, '=') : ('REDUCE', 34), - (56, '<=') : ('REDUCE', 34), - (56, ';') : ('REDUCE', 34), - (56, '+') : ('REDUCE', 34), - (56, ')') : ('REDUCE', 34), - (56, 'of') : ('REDUCE', 34), - (56, 'then') : ('REDUCE', 34), - (56, '-') : ('REDUCE', 34), - (56, 'loop') : ('REDUCE', 34), - (56, 'else') : ('REDUCE', 34), - (56, '}') : ('REDUCE', 34), + (56, '-') : ('REDUCE', 35), + (56, 'then') : ('REDUCE', 35), + (56, 'loop') : ('REDUCE', 35), + (56, 'of') : ('REDUCE', 35), + (56, ';') : ('REDUCE', 35), + (56, 'else') : ('REDUCE', 35), + (56, 'pool') : ('REDUCE', 35), + (56, '}') : ('REDUCE', 35), + (56, ',') : ('REDUCE', 35), + (56, 'fi') : ('REDUCE', 35), + (56, '<') : ('REDUCE', 35), + (56, 'in') : ('REDUCE', 35), + (56, '=') : ('REDUCE', 35), + (56, '<=') : ('REDUCE', 35), + (56, '+') : ('REDUCE', 35), + (56, ')') : ('REDUCE', 35), (56, '*') : ('SHIFT', 49), + (56, '/') : ('SHIFT', 52), (57, '*') : ('SHIFT', 49), - (57, ',') : ('REDUCE', 35), - (57, 'fi') : ('REDUCE', 35), - (57, 'pool') : ('REDUCE', 35), - (57, '<') : ('REDUCE', 35), - (57, 'in') : ('REDUCE', 35), - (57, '=') : ('REDUCE', 35), - (57, '<=') : ('REDUCE', 35), - (57, ';') : ('REDUCE', 35), - (57, '+') : ('REDUCE', 35), - (57, ')') : ('REDUCE', 35), - (57, 'of') : ('REDUCE', 35), - (57, 'then') : ('REDUCE', 35), - (57, '-') : ('REDUCE', 35), - (57, 'loop') : ('REDUCE', 35), - (57, 'else') : ('REDUCE', 35), - (57, '}') : ('REDUCE', 35), (57, '/') : ('SHIFT', 52), + (57, '-') : ('REDUCE', 36), + (57, 'then') : ('REDUCE', 36), + (57, 'loop') : ('REDUCE', 36), + (57, 'of') : ('REDUCE', 36), + (57, ';') : ('REDUCE', 36), + (57, 'else') : ('REDUCE', 36), + (57, 'pool') : ('REDUCE', 36), + (57, '}') : ('REDUCE', 36), + (57, ',') : ('REDUCE', 36), + (57, 'fi') : ('REDUCE', 36), + (57, '<') : ('REDUCE', 36), + (57, 'in') : ('REDUCE', 36), + (57, '=') : ('REDUCE', 36), + (57, '<=') : ('REDUCE', 36), + (57, '+') : ('REDUCE', 36), + (57, ')') : ('REDUCE', 36), + (58, 'true') : ('SHIFT', 27), (58, 'id') : ('SHIFT', 16), - (58, '(') : ('SHIFT', 13), - (58, 'string') : ('SHIFT', 29), (58, 'if') : ('SHIFT', 24), + (58, '(') : ('SHIFT', 13), (58, '~') : ('SHIFT', 15), - (58, 'false') : ('SHIFT', 28), (58, 'new') : ('SHIFT', 22), + (58, 'false') : ('SHIFT', 28), (58, 'int') : ('SHIFT', 21), + (58, 'string') : ('SHIFT', 29), (58, 'not') : ('SHIFT', 26), (58, 'isvoid') : ('SHIFT', 34), - (58, 'true') : ('SHIFT', 27), (59, '-') : ('SHIFT', 55), (59, '+') : ('SHIFT', 47), - (59, ',') : ('REDUCE', 29), - (59, 'fi') : ('REDUCE', 29), - (59, 'pool') : ('REDUCE', 29), - (59, '<') : ('REDUCE', 29), - (59, 'in') : ('REDUCE', 29), - (59, '=') : ('REDUCE', 29), - (59, '<=') : ('REDUCE', 29), - (59, ';') : ('REDUCE', 29), - (59, ')') : ('REDUCE', 29), - (59, 'of') : ('REDUCE', 29), - (59, 'then') : ('REDUCE', 29), - (59, 'loop') : ('REDUCE', 29), - (59, 'else') : ('REDUCE', 29), - (59, '}') : ('REDUCE', 29), + (59, 'then') : ('REDUCE', 30), + (59, 'loop') : ('REDUCE', 30), + (59, 'of') : ('REDUCE', 30), + (59, ';') : ('REDUCE', 30), + (59, 'else') : ('REDUCE', 30), + (59, 'pool') : ('REDUCE', 30), + (59, '}') : ('REDUCE', 30), + (59, ',') : ('REDUCE', 30), + (59, 'fi') : ('REDUCE', 30), + (59, '<') : ('REDUCE', 30), + (59, 'in') : ('REDUCE', 30), + (59, '=') : ('REDUCE', 30), + (59, '<=') : ('REDUCE', 30), + (59, ')') : ('REDUCE', 30), + (60, 'true') : ('SHIFT', 27), (60, 'id') : ('SHIFT', 16), - (60, 'string') : ('SHIFT', 29), (60, 'if') : ('SHIFT', 24), + (60, '(') : ('SHIFT', 13), (60, '~') : ('SHIFT', 15), - (60, 'false') : ('SHIFT', 28), (60, 'new') : ('SHIFT', 22), + (60, 'false') : ('SHIFT', 28), (60, 'int') : ('SHIFT', 21), + (60, 'string') : ('SHIFT', 29), (60, 'not') : ('SHIFT', 26), (60, 'isvoid') : ('SHIFT', 34), - (60, 'true') : ('SHIFT', 27), - (60, '(') : ('SHIFT', 13), (61, '-') : ('SHIFT', 55), (61, '+') : ('SHIFT', 47), - (61, ',') : ('REDUCE', 30), - (61, 'fi') : ('REDUCE', 30), - (61, 'pool') : ('REDUCE', 30), - (61, '<') : ('REDUCE', 30), - (61, 'in') : ('REDUCE', 30), - (61, '=') : ('REDUCE', 30), - (61, '<=') : ('REDUCE', 30), - (61, ';') : ('REDUCE', 30), - (61, ')') : ('REDUCE', 30), - (61, 'of') : ('REDUCE', 30), - (61, 'then') : ('REDUCE', 30), - (61, 'loop') : ('REDUCE', 30), - (61, 'else') : ('REDUCE', 30), - (61, '}') : ('REDUCE', 30), - (62, ',') : ('REDUCE', 56), - (62, ')') : ('REDUCE', 56), - (63, '-') : ('SHIFT', 55), - (63, '+') : ('SHIFT', 47), - (63, ',') : ('REDUCE', 32), - (63, 'fi') : ('REDUCE', 32), - (63, 'in') : ('REDUCE', 32), - (63, '<') : ('REDUCE', 32), - (63, '=') : ('REDUCE', 32), - (63, '<=') : ('REDUCE', 32), - (63, ';') : ('REDUCE', 32), - (63, ')') : ('REDUCE', 32), - (63, 'of') : ('REDUCE', 32), - (63, 'then') : ('REDUCE', 32), - (63, 'loop') : ('REDUCE', 32), - (63, '}') : ('REDUCE', 32), - (63, 'else') : ('REDUCE', 32), - (63, 'pool') : ('REDUCE', 32), - (64, '/') : ('REDUCE', 54), - (64, '<') : ('REDUCE', 54), - (64, '<=') : ('REDUCE', 54), - (64, '@') : ('REDUCE', 54), - (64, 'in') : ('REDUCE', 54), - (64, ';') : ('REDUCE', 54), - (64, 'loop') : ('REDUCE', 54), - (64, 'pool') : ('REDUCE', 54), - (64, ',') : ('REDUCE', 54), - (64, '.') : ('REDUCE', 54), - (64, ')') : ('REDUCE', 54), - (64, 'then') : ('REDUCE', 54), - (64, 'else') : ('REDUCE', 54), - (64, '}') : ('REDUCE', 54), - (64, 'fi') : ('REDUCE', 54), - (64, '=') : ('REDUCE', 54), - (64, '+') : ('REDUCE', 54), - (64, 'of') : ('REDUCE', 54), - (64, '-') : ('REDUCE', 54), - (64, '*') : ('REDUCE', 54), - (65, ',') : ('REDUCE', 55), - (65, ')') : ('REDUCE', 55), - (66, ',') : ('SHIFT', 43), - (66, ')') : ('SHIFT', 67), - (67, '/') : ('REDUCE', 52), - (67, '<') : ('REDUCE', 52), - (67, '<=') : ('REDUCE', 52), - (67, '@') : ('REDUCE', 52), - (67, 'in') : ('REDUCE', 52), - (67, ';') : ('REDUCE', 52), - (67, 'loop') : ('REDUCE', 52), - (67, 'pool') : ('REDUCE', 52), - (67, ',') : ('REDUCE', 52), - (67, '.') : ('REDUCE', 52), - (67, ')') : ('REDUCE', 52), - (67, 'then') : ('REDUCE', 52), - (67, 'else') : ('REDUCE', 52), - (67, '}') : ('REDUCE', 52), - (67, 'fi') : ('REDUCE', 52), - (67, '=') : ('REDUCE', 52), - (67, '+') : ('REDUCE', 52), - (67, 'of') : ('REDUCE', 52), - (67, '-') : ('REDUCE', 52), - (67, '*') : ('REDUCE', 52), - (68, 'of') : ('SHIFT', 69), - (69, 'id') : ('SHIFT', 70), - (70, ':') : ('SHIFT', 71), - (71, 'type') : ('SHIFT', 72), - (72, '=>') : ('SHIFT', 73), - (73, 'true') : ('SHIFT', 27), - (73, 'not') : ('SHIFT', 26), - (73, 'case') : ('SHIFT', 25), - (73, '(') : ('SHIFT', 13), - (73, 'let') : ('SHIFT', 8), - (73, 'string') : ('SHIFT', 29), - (73, 'while') : ('SHIFT', 20), - (73, 'false') : ('SHIFT', 28), - (73, 'isvoid') : ('SHIFT', 34), - (73, 'id') : ('SHIFT', 18), - (73, 'if') : ('SHIFT', 24), - (73, '{') : ('SHIFT', 14), - (73, '~') : ('SHIFT', 15), - (73, 'new') : ('SHIFT', 22), - (73, 'int') : ('SHIFT', 21), - (74, ';') : ('SHIFT', 75), - (75, 'id') : ('SHIFT', 70), - (75, 'esac') : ('REDUCE', 26), + (61, 'then') : ('REDUCE', 31), + (61, 'loop') : ('REDUCE', 31), + (61, 'of') : ('REDUCE', 31), + (61, ';') : ('REDUCE', 31), + (61, 'else') : ('REDUCE', 31), + (61, 'pool') : ('REDUCE', 31), + (61, '}') : ('REDUCE', 31), + (61, ',') : ('REDUCE', 31), + (61, 'fi') : ('REDUCE', 31), + (61, '<') : ('REDUCE', 31), + (61, 'in') : ('REDUCE', 31), + (61, '=') : ('REDUCE', 31), + (61, '<=') : ('REDUCE', 31), + (61, ')') : ('REDUCE', 31), + (62, ',') : ('SHIFT', 63), + (62, ')') : ('REDUCE', 58), + (63, 'let') : ('SHIFT', 8), + (63, 'int') : ('SHIFT', 21), + (63, '~') : ('SHIFT', 15), + (63, 'string') : ('SHIFT', 29), + (63, 'not') : ('SHIFT', 26), + (63, 'id') : ('SHIFT', 18), + (63, 'isvoid') : ('SHIFT', 34), + (63, 'while') : ('SHIFT', 20), + (63, 'false') : ('SHIFT', 28), + (63, 'case') : ('SHIFT', 25), + (63, 'if') : ('SHIFT', 24), + (63, '{') : ('SHIFT', 14), + (63, 'true') : ('SHIFT', 27), + (63, 'new') : ('SHIFT', 22), + (63, '(') : ('SHIFT', 13), + (64, 'then') : ('REDUCE', 33), + (64, 'loop') : ('REDUCE', 33), + (64, 'of') : ('REDUCE', 33), + (64, '<=') : ('REDUCE', 33), + (64, 'else') : ('REDUCE', 33), + (64, 'pool') : ('REDUCE', 33), + (64, '}') : ('REDUCE', 33), + (64, ',') : ('REDUCE', 33), + (64, 'fi') : ('REDUCE', 33), + (64, '<') : ('REDUCE', 33), + (64, 'in') : ('REDUCE', 33), + (64, '=') : ('REDUCE', 33), + (64, ';') : ('REDUCE', 33), + (64, ')') : ('REDUCE', 33), + (64, '-') : ('SHIFT', 55), + (64, '+') : ('SHIFT', 47), + (65, ')') : ('REDUCE', 59), + (66, ')') : ('REDUCE', 57), + (67, ')') : ('SHIFT', 68), + (68, '-') : ('REDUCE', 53), + (68, 'of') : ('REDUCE', 53), + (68, '*') : ('REDUCE', 53), + (68, '/') : ('REDUCE', 53), + (68, '<') : ('REDUCE', 53), + (68, '<=') : ('REDUCE', 53), + (68, '@') : ('REDUCE', 53), + (68, 'in') : ('REDUCE', 53), + (68, ';') : ('REDUCE', 53), + (68, 'loop') : ('REDUCE', 53), + (68, 'pool') : ('REDUCE', 53), + (68, ',') : ('REDUCE', 53), + (68, '.') : ('REDUCE', 53), + (68, ')') : ('REDUCE', 53), + (68, 'then') : ('REDUCE', 53), + (68, 'else') : ('REDUCE', 53), + (68, '}') : ('REDUCE', 53), + (68, 'fi') : ('REDUCE', 53), + (68, '=') : ('REDUCE', 53), + (68, '+') : ('REDUCE', 53), + (69, 'of') : ('SHIFT', 70), + (70, 'id') : ('SHIFT', 71), + (71, ':') : ('SHIFT', 72), + (72, 'type') : ('SHIFT', 73), + (73, '=>') : ('SHIFT', 74), + (74, 'id') : ('SHIFT', 18), + (74, 'true') : ('SHIFT', 27), + (74, 'new') : ('SHIFT', 22), + (74, 'if') : ('SHIFT', 24), + (74, '(') : ('SHIFT', 13), + (74, 'let') : ('SHIFT', 8), + (74, '~') : ('SHIFT', 15), + (74, 'int') : ('SHIFT', 21), + (74, 'string') : ('SHIFT', 29), + (74, 'not') : ('SHIFT', 26), + (74, 'while') : ('SHIFT', 20), + (74, 'isvoid') : ('SHIFT', 34), + (74, 'case') : ('SHIFT', 25), + (74, 'false') : ('SHIFT', 28), + (74, '{') : ('SHIFT', 14), + (75, ';') : ('SHIFT', 76), + (76, 'id') : ('SHIFT', 71), (76, 'esac') : ('REDUCE', 27), - (77, 'esac') : ('SHIFT', 78), - (78, ',') : ('REDUCE', 25), - (78, 'fi') : ('REDUCE', 25), - (78, 'pool') : ('REDUCE', 25), - (78, 'in') : ('REDUCE', 25), - (78, ';') : ('REDUCE', 25), - (78, ')') : ('REDUCE', 25), - (78, 'of') : ('REDUCE', 25), - (78, 'then') : ('REDUCE', 25), - (78, 'loop') : ('REDUCE', 25), - (78, 'else') : ('REDUCE', 25), - (78, '}') : ('REDUCE', 25), - (79, 'then') : ('SHIFT', 80), - (80, 'case') : ('SHIFT', 25), - (80, 'false') : ('SHIFT', 28), - (80, 'let') : ('SHIFT', 8), - (80, '~') : ('SHIFT', 15), - (80, 'while') : ('SHIFT', 20), - (80, 'id') : ('SHIFT', 18), - (80, 'not') : ('SHIFT', 26), - (80, 'if') : ('SHIFT', 24), - (80, 'new') : ('SHIFT', 22), - (80, 'int') : ('SHIFT', 21), - (80, 'true') : ('SHIFT', 27), - (80, '(') : ('SHIFT', 13), - (80, '{') : ('SHIFT', 14), - (80, 'string') : ('SHIFT', 29), - (80, 'isvoid') : ('SHIFT', 34), - (81, 'else') : ('SHIFT', 82), - (82, 'case') : ('SHIFT', 25), - (82, 'let') : ('SHIFT', 8), - (82, '~') : ('SHIFT', 15), - (82, 'while') : ('SHIFT', 20), - (82, 'false') : ('SHIFT', 28), - (82, 'not') : ('SHIFT', 26), - (82, 'id') : ('SHIFT', 18), - (82, 'if') : ('SHIFT', 24), - (82, 'new') : ('SHIFT', 22), - (82, 'int') : ('SHIFT', 21), - (82, '{') : ('SHIFT', 14), - (82, 'isvoid') : ('SHIFT', 34), - (82, 'true') : ('SHIFT', 27), - (82, '(') : ('SHIFT', 13), - (82, 'string') : ('SHIFT', 29), - (83, 'fi') : ('SHIFT', 84), - (84, '/') : ('REDUCE', 49), - (84, '<') : ('REDUCE', 49), - (84, '<=') : ('REDUCE', 49), - (84, '@') : ('REDUCE', 49), - (84, 'in') : ('REDUCE', 49), - (84, ';') : ('REDUCE', 49), - (84, 'loop') : ('REDUCE', 49), - (84, 'pool') : ('REDUCE', 49), - (84, ',') : ('REDUCE', 49), - (84, '.') : ('REDUCE', 49), - (84, ')') : ('REDUCE', 49), - (84, 'then') : ('REDUCE', 49), - (84, 'else') : ('REDUCE', 49), - (84, '}') : ('REDUCE', 49), - (84, 'fi') : ('REDUCE', 49), - (84, '=') : ('REDUCE', 49), - (84, '+') : ('REDUCE', 49), - (84, 'of') : ('REDUCE', 49), - (84, '-') : ('REDUCE', 49), - (84, '*') : ('REDUCE', 49), - (85, 'loop') : ('SHIFT', 86), - (86, 'id') : ('SHIFT', 18), - (86, 'case') : ('SHIFT', 25), - (86, 'let') : ('SHIFT', 8), - (86, 'if') : ('SHIFT', 24), - (86, 'while') : ('SHIFT', 20), - (86, 'new') : ('SHIFT', 22), - (86, 'isvoid') : ('SHIFT', 34), - (86, 'int') : ('SHIFT', 21), - (86, 'true') : ('SHIFT', 27), - (86, '(') : ('SHIFT', 13), - (86, 'string') : ('SHIFT', 29), - (86, '~') : ('SHIFT', 15), - (86, 'false') : ('SHIFT', 28), - (86, '{') : ('SHIFT', 14), - (86, 'not') : ('SHIFT', 26), - (87, 'pool') : ('SHIFT', 88), - (88, ',') : ('REDUCE', 16), - (88, 'fi') : ('REDUCE', 16), - (88, 'pool') : ('REDUCE', 16), - (88, 'in') : ('REDUCE', 16), - (88, ';') : ('REDUCE', 16), - (88, ')') : ('REDUCE', 16), - (88, 'of') : ('REDUCE', 16), - (88, 'then') : ('REDUCE', 16), - (88, 'loop') : ('REDUCE', 16), - (88, 'else') : ('REDUCE', 16), - (88, '}') : ('REDUCE', 16), - (89, ',') : ('REDUCE', 15), - (89, 'fi') : ('REDUCE', 15), - (89, 'pool') : ('REDUCE', 15), - (89, 'in') : ('REDUCE', 15), - (89, ';') : ('REDUCE', 15), - (89, ')') : ('REDUCE', 15), - (89, 'of') : ('REDUCE', 15), - (89, 'then') : ('REDUCE', 15), - (89, 'loop') : ('REDUCE', 15), - (89, 'else') : ('REDUCE', 15), - (89, '}') : ('REDUCE', 15), - (90, ')') : ('SHIFT', 91), - (90, ',') : ('SHIFT', 43), - (91, '/') : ('REDUCE', 53), - (91, '<') : ('REDUCE', 53), - (91, '<=') : ('REDUCE', 53), - (91, '@') : ('REDUCE', 53), - (91, 'in') : ('REDUCE', 53), - (91, ';') : ('REDUCE', 53), - (91, 'loop') : ('REDUCE', 53), - (91, 'pool') : ('REDUCE', 53), - (91, ',') : ('REDUCE', 53), - (91, '.') : ('REDUCE', 53), - (91, ')') : ('REDUCE', 53), - (91, 'then') : ('REDUCE', 53), - (91, 'else') : ('REDUCE', 53), - (91, '}') : ('REDUCE', 53), - (91, 'fi') : ('REDUCE', 53), - (91, '=') : ('REDUCE', 53), - (91, '+') : ('REDUCE', 53), - (91, 'of') : ('REDUCE', 53), - (91, '-') : ('REDUCE', 53), - (91, '*') : ('REDUCE', 53), - (92, ',') : ('REDUCE', 40), - (92, '/') : ('REDUCE', 40), - (92, 'fi') : ('REDUCE', 40), - (92, 'pool') : ('REDUCE', 40), - (92, '<') : ('REDUCE', 40), - (92, 'in') : ('REDUCE', 40), - (92, '=') : ('REDUCE', 40), - (92, '<=') : ('REDUCE', 40), - (92, ';') : ('REDUCE', 40), - (92, '+') : ('REDUCE', 40), - (92, '*') : ('REDUCE', 40), - (92, ')') : ('REDUCE', 40), - (92, 'of') : ('REDUCE', 40), - (92, 'then') : ('REDUCE', 40), - (92, '-') : ('REDUCE', 40), - (92, 'loop') : ('REDUCE', 40), - (92, 'else') : ('REDUCE', 40), - (92, '}') : ('REDUCE', 40), - (93, '}') : ('SHIFT', 94), - (94, ',') : ('REDUCE', 17), - (94, 'fi') : ('REDUCE', 17), - (94, 'pool') : ('REDUCE', 17), - (94, 'in') : ('REDUCE', 17), - (94, ';') : ('REDUCE', 17), - (94, ')') : ('REDUCE', 17), - (94, 'of') : ('REDUCE', 17), - (94, 'then') : ('REDUCE', 17), - (94, 'loop') : ('REDUCE', 17), - (94, 'else') : ('REDUCE', 17), - (94, '}') : ('REDUCE', 17), - (95, ';') : ('SHIFT', 96), - (96, 'true') : ('SHIFT', 27), - (96, 'not') : ('SHIFT', 26), - (96, 'case') : ('SHIFT', 25), - (96, '(') : ('SHIFT', 13), - (96, 'let') : ('SHIFT', 8), - (96, 'string') : ('SHIFT', 29), - (96, 'while') : ('SHIFT', 20), - (96, '}') : ('REDUCE', 18), - (96, 'false') : ('SHIFT', 28), - (96, 'isvoid') : ('SHIFT', 34), - (96, 'id') : ('SHIFT', 18), - (96, 'if') : ('SHIFT', 24), - (96, '{') : ('SHIFT', 14), - (96, '~') : ('SHIFT', 15), - (96, 'new') : ('SHIFT', 22), - (96, 'int') : ('SHIFT', 21), + (77, 'esac') : ('REDUCE', 28), + (78, 'esac') : ('SHIFT', 79), + (79, 'then') : ('REDUCE', 26), + (79, 'loop') : ('REDUCE', 26), + (79, 'of') : ('REDUCE', 26), + (79, 'else') : ('REDUCE', 26), + (79, 'pool') : ('REDUCE', 26), + (79, '}') : ('REDUCE', 26), + (79, ',') : ('REDUCE', 26), + (79, 'fi') : ('REDUCE', 26), + (79, 'in') : ('REDUCE', 26), + (79, ';') : ('REDUCE', 26), + (79, ')') : ('REDUCE', 26), + (80, 'then') : ('SHIFT', 81), + (81, 'id') : ('SHIFT', 18), + (81, 'false') : ('SHIFT', 28), + (81, 'while') : ('SHIFT', 20), + (81, 'case') : ('SHIFT', 25), + (81, '~') : ('SHIFT', 15), + (81, '{') : ('SHIFT', 14), + (81, 'true') : ('SHIFT', 27), + (81, 'if') : ('SHIFT', 24), + (81, '(') : ('SHIFT', 13), + (81, 'new') : ('SHIFT', 22), + (81, 'not') : ('SHIFT', 26), + (81, 'int') : ('SHIFT', 21), + (81, 'string') : ('SHIFT', 29), + (81, 'let') : ('SHIFT', 8), + (81, 'isvoid') : ('SHIFT', 34), + (82, 'else') : ('SHIFT', 83), + (83, 'while') : ('SHIFT', 20), + (83, 'id') : ('SHIFT', 18), + (83, 'case') : ('SHIFT', 25), + (83, '{') : ('SHIFT', 14), + (83, 'false') : ('SHIFT', 28), + (83, '~') : ('SHIFT', 15), + (83, 'true') : ('SHIFT', 27), + (83, 'let') : ('SHIFT', 8), + (83, 'new') : ('SHIFT', 22), + (83, 'if') : ('SHIFT', 24), + (83, '(') : ('SHIFT', 13), + (83, 'not') : ('SHIFT', 26), + (83, 'isvoid') : ('SHIFT', 34), + (83, 'int') : ('SHIFT', 21), + (83, 'string') : ('SHIFT', 29), + (84, 'fi') : ('SHIFT', 85), + (85, '-') : ('REDUCE', 50), + (85, 'of') : ('REDUCE', 50), + (85, '*') : ('REDUCE', 50), + (85, '/') : ('REDUCE', 50), + (85, '<') : ('REDUCE', 50), + (85, '<=') : ('REDUCE', 50), + (85, '@') : ('REDUCE', 50), + (85, 'in') : ('REDUCE', 50), + (85, ';') : ('REDUCE', 50), + (85, 'loop') : ('REDUCE', 50), + (85, 'pool') : ('REDUCE', 50), + (85, ',') : ('REDUCE', 50), + (85, '.') : ('REDUCE', 50), + (85, ')') : ('REDUCE', 50), + (85, 'then') : ('REDUCE', 50), + (85, 'else') : ('REDUCE', 50), + (85, '}') : ('REDUCE', 50), + (85, 'fi') : ('REDUCE', 50), + (85, '=') : ('REDUCE', 50), + (85, '+') : ('REDUCE', 50), + (86, 'loop') : ('SHIFT', 87), + (87, 'id') : ('SHIFT', 18), + (87, 'new') : ('SHIFT', 22), + (87, 'if') : ('SHIFT', 24), + (87, '(') : ('SHIFT', 13), + (87, 'let') : ('SHIFT', 8), + (87, 'int') : ('SHIFT', 21), + (87, 'string') : ('SHIFT', 29), + (87, '~') : ('SHIFT', 15), + (87, 'while') : ('SHIFT', 20), + (87, 'false') : ('SHIFT', 28), + (87, 'case') : ('SHIFT', 25), + (87, 'not') : ('SHIFT', 26), + (87, 'isvoid') : ('SHIFT', 34), + (87, '{') : ('SHIFT', 14), + (87, 'true') : ('SHIFT', 27), + (88, 'pool') : ('SHIFT', 89), + (89, 'then') : ('REDUCE', 17), + (89, 'loop') : ('REDUCE', 17), + (89, 'of') : ('REDUCE', 17), + (89, 'else') : ('REDUCE', 17), + (89, 'pool') : ('REDUCE', 17), + (89, '}') : ('REDUCE', 17), + (89, ',') : ('REDUCE', 17), + (89, 'fi') : ('REDUCE', 17), + (89, 'in') : ('REDUCE', 17), + (89, ';') : ('REDUCE', 17), + (89, ')') : ('REDUCE', 17), + (90, 'then') : ('REDUCE', 16), + (90, 'loop') : ('REDUCE', 16), + (90, 'of') : ('REDUCE', 16), + (90, 'else') : ('REDUCE', 16), + (90, 'pool') : ('REDUCE', 16), + (90, '}') : ('REDUCE', 16), + (90, ',') : ('REDUCE', 16), + (90, 'fi') : ('REDUCE', 16), + (90, 'in') : ('REDUCE', 16), + (90, ';') : ('REDUCE', 16), + (90, ')') : ('REDUCE', 16), + (91, ')') : ('SHIFT', 92), + (92, '-') : ('REDUCE', 54), + (92, 'of') : ('REDUCE', 54), + (92, '*') : ('REDUCE', 54), + (92, '/') : ('REDUCE', 54), + (92, '<') : ('REDUCE', 54), + (92, '<=') : ('REDUCE', 54), + (92, '@') : ('REDUCE', 54), + (92, 'in') : ('REDUCE', 54), + (92, ';') : ('REDUCE', 54), + (92, 'loop') : ('REDUCE', 54), + (92, 'pool') : ('REDUCE', 54), + (92, ',') : ('REDUCE', 54), + (92, '.') : ('REDUCE', 54), + (92, ')') : ('REDUCE', 54), + (92, 'then') : ('REDUCE', 54), + (92, 'else') : ('REDUCE', 54), + (92, '}') : ('REDUCE', 54), + (92, 'fi') : ('REDUCE', 54), + (92, '=') : ('REDUCE', 54), + (92, '+') : ('REDUCE', 54), + (93, '-') : ('REDUCE', 41), + (93, 'then') : ('REDUCE', 41), + (93, 'loop') : ('REDUCE', 41), + (93, 'of') : ('REDUCE', 41), + (93, ';') : ('REDUCE', 41), + (93, '*') : ('REDUCE', 41), + (93, 'else') : ('REDUCE', 41), + (93, 'pool') : ('REDUCE', 41), + (93, '}') : ('REDUCE', 41), + (93, ',') : ('REDUCE', 41), + (93, '/') : ('REDUCE', 41), + (93, 'fi') : ('REDUCE', 41), + (93, '<') : ('REDUCE', 41), + (93, 'in') : ('REDUCE', 41), + (93, '=') : ('REDUCE', 41), + (93, '<=') : ('REDUCE', 41), + (93, '+') : ('REDUCE', 41), + (93, ')') : ('REDUCE', 41), + (94, '}') : ('SHIFT', 95), + (95, 'then') : ('REDUCE', 18), + (95, 'loop') : ('REDUCE', 18), + (95, 'of') : ('REDUCE', 18), + (95, 'else') : ('REDUCE', 18), + (95, 'pool') : ('REDUCE', 18), + (95, '}') : ('REDUCE', 18), + (95, ',') : ('REDUCE', 18), + (95, 'fi') : ('REDUCE', 18), + (95, 'in') : ('REDUCE', 18), + (95, ';') : ('REDUCE', 18), + (95, ')') : ('REDUCE', 18), + (96, ';') : ('SHIFT', 97), + (97, 'id') : ('SHIFT', 18), + (97, 'true') : ('SHIFT', 27), + (97, 'new') : ('SHIFT', 22), + (97, 'if') : ('SHIFT', 24), (97, '}') : ('REDUCE', 19), - (98, ')') : ('SHIFT', 99), - (99, '/') : ('REDUCE', 50), - (99, '<') : ('REDUCE', 50), - (99, '<=') : ('REDUCE', 50), - (99, '@') : ('REDUCE', 50), - (99, 'in') : ('REDUCE', 50), - (99, ';') : ('REDUCE', 50), - (99, 'loop') : ('REDUCE', 50), - (99, 'pool') : ('REDUCE', 50), - (99, ',') : ('REDUCE', 50), - (99, '.') : ('REDUCE', 50), - (99, ')') : ('REDUCE', 50), - (99, 'then') : ('REDUCE', 50), - (99, 'else') : ('REDUCE', 50), - (99, '}') : ('REDUCE', 50), - (99, 'fi') : ('REDUCE', 50), - (99, '=') : ('REDUCE', 50), - (99, '+') : ('REDUCE', 50), - (99, 'of') : ('REDUCE', 50), - (99, '-') : ('REDUCE', 50), - (99, '*') : ('REDUCE', 50), - (100, 'in') : ('REDUCE', 22), - (100, ',') : ('SHIFT', 101), - (101, 'id') : ('SHIFT', 9), - (102, 'in') : ('REDUCE', 24), - (103, 'id') : ('SHIFT', 9), - (104, 'in') : ('REDUCE', 23), - (105, 'in') : ('SHIFT', 106), - (106, 'string') : ('SHIFT', 29), - (106, 'false') : ('SHIFT', 28), - (106, 'id') : ('SHIFT', 18), - (106, 'isvoid') : ('SHIFT', 34), - (106, '{') : ('SHIFT', 14), - (106, 'if') : ('SHIFT', 24), - (106, '~') : ('SHIFT', 15), - (106, 'case') : ('SHIFT', 25), - (106, 'new') : ('SHIFT', 22), - (106, 'let') : ('SHIFT', 8), - (106, 'int') : ('SHIFT', 21), - (106, 'while') : ('SHIFT', 20), - (106, 'not') : ('SHIFT', 26), - (106, 'true') : ('SHIFT', 27), - (106, '(') : ('SHIFT', 13), - (107, ',') : ('REDUCE', 20), - (107, 'fi') : ('REDUCE', 20), - (107, 'pool') : ('REDUCE', 20), - (107, 'in') : ('REDUCE', 20), - (107, ';') : ('REDUCE', 20), - (107, ')') : ('REDUCE', 20), - (107, 'of') : ('REDUCE', 20), - (107, 'then') : ('REDUCE', 20), - (107, 'loop') : ('REDUCE', 20), - (107, 'else') : ('REDUCE', 20), - (107, '}') : ('REDUCE', 20), - (108, ';') : ('REDUCE', 9), - (109, 'id') : ('SHIFT', 110), - (109, ',') : ('REDUCE', 13), - (109, ')') : ('REDUCE', 13), - (110, ':') : ('SHIFT', 111), - (111, 'type') : ('SHIFT', 112), - (112, ',') : ('REDUCE', 14), - (112, ')') : ('REDUCE', 14), - (113, ',') : ('SHIFT', 114), - (113, ')') : ('SHIFT', 116), - (114, 'id') : ('SHIFT', 110), - (115, ',') : ('REDUCE', 12), - (115, ')') : ('REDUCE', 12), - (116, ':') : ('SHIFT', 117), - (117, 'type') : ('SHIFT', 118), - (118, '{') : ('SHIFT', 119), - (119, 'not') : ('SHIFT', 26), - (119, 'case') : ('SHIFT', 25), - (119, 'let') : ('SHIFT', 8), - (119, 'new') : ('SHIFT', 22), - (119, 'int') : ('SHIFT', 21), - (119, 'while') : ('SHIFT', 20), - (119, 'true') : ('SHIFT', 27), - (119, '(') : ('SHIFT', 13), - (119, 'string') : ('SHIFT', 29), - (119, 'isvoid') : ('SHIFT', 34), - (119, 'false') : ('SHIFT', 28), - (119, 'id') : ('SHIFT', 18), - (119, '{') : ('SHIFT', 14), - (119, '~') : ('SHIFT', 15), - (119, 'if') : ('SHIFT', 24), - (120, '}') : ('SHIFT', 121), - (121, ';') : ('REDUCE', 10), - (122, ',') : ('REDUCE', 11), - (122, ')') : ('REDUCE', 11), - (123, '}') : ('SHIFT', 124), - (124, ';') : ('REDUCE', 3), - (125, ';') : ('SHIFT', 126), - (126, 'id') : ('SHIFT', 4), - (126, '}') : ('REDUCE', 7), - (127, '}') : ('REDUCE', 5), - (128, ';') : ('SHIFT', 129), - (129, 'id') : ('SHIFT', 4), - (129, '}') : ('REDUCE', 7), - (130, '}') : ('REDUCE', 6), - (131, 'type') : ('SHIFT', 132), - (132, '{') : ('SHIFT', 133), - (133, 'id') : ('SHIFT', 4), - (133, '}') : ('REDUCE', 7), - (134, '}') : ('SHIFT', 135), - (135, ';') : ('REDUCE', 4), - (136, '$') : ('REDUCE', 0), - (140, '$') : ('OK', None), - (137, ';') : ('SHIFT', 138), - (138, '$') : ('REDUCE', 1), - (138, 'class') : ('SHIFT', 1), - (139, '$') : ('REDUCE', 2) + (97, '(') : ('SHIFT', 13), + (97, 'let') : ('SHIFT', 8), + (97, '~') : ('SHIFT', 15), + (97, 'int') : ('SHIFT', 21), + (97, 'string') : ('SHIFT', 29), + (97, 'not') : ('SHIFT', 26), + (97, 'while') : ('SHIFT', 20), + (97, 'isvoid') : ('SHIFT', 34), + (97, 'case') : ('SHIFT', 25), + (97, 'false') : ('SHIFT', 28), + (97, '{') : ('SHIFT', 14), + (98, '}') : ('REDUCE', 20), + (99, ')') : ('SHIFT', 100), + (100, '-') : ('REDUCE', 51), + (100, 'of') : ('REDUCE', 51), + (100, '*') : ('REDUCE', 51), + (100, '/') : ('REDUCE', 51), + (100, '<') : ('REDUCE', 51), + (100, '<=') : ('REDUCE', 51), + (100, '@') : ('REDUCE', 51), + (100, 'in') : ('REDUCE', 51), + (100, ';') : ('REDUCE', 51), + (100, 'loop') : ('REDUCE', 51), + (100, 'pool') : ('REDUCE', 51), + (100, ',') : ('REDUCE', 51), + (100, '.') : ('REDUCE', 51), + (100, ')') : ('REDUCE', 51), + (100, 'then') : ('REDUCE', 51), + (100, 'else') : ('REDUCE', 51), + (100, '}') : ('REDUCE', 51), + (100, 'fi') : ('REDUCE', 51), + (100, '=') : ('REDUCE', 51), + (100, '+') : ('REDUCE', 51), + (101, 'in') : ('REDUCE', 23), + (101, ',') : ('SHIFT', 102), + (102, 'id') : ('SHIFT', 9), + (103, 'in') : ('REDUCE', 25), + (104, 'id') : ('SHIFT', 9), + (105, 'in') : ('REDUCE', 24), + (106, 'in') : ('SHIFT', 107), + (107, 'true') : ('SHIFT', 27), + (107, 'if') : ('SHIFT', 24), + (107, 'id') : ('SHIFT', 18), + (107, '(') : ('SHIFT', 13), + (107, '~') : ('SHIFT', 15), + (107, 'new') : ('SHIFT', 22), + (107, 'let') : ('SHIFT', 8), + (107, 'int') : ('SHIFT', 21), + (107, 'string') : ('SHIFT', 29), + (107, 'not') : ('SHIFT', 26), + (107, 'isvoid') : ('SHIFT', 34), + (107, 'while') : ('SHIFT', 20), + (107, 'case') : ('SHIFT', 25), + (107, 'false') : ('SHIFT', 28), + (107, '{') : ('SHIFT', 14), + (108, 'then') : ('REDUCE', 21), + (108, 'loop') : ('REDUCE', 21), + (108, 'of') : ('REDUCE', 21), + (108, 'else') : ('REDUCE', 21), + (108, 'pool') : ('REDUCE', 21), + (108, '}') : ('REDUCE', 21), + (108, ',') : ('REDUCE', 21), + (108, 'fi') : ('REDUCE', 21), + (108, 'in') : ('REDUCE', 21), + (108, ';') : ('REDUCE', 21), + (108, ')') : ('REDUCE', 21), + (109, ';') : ('REDUCE', 9), + (110, 'id') : ('SHIFT', 111), + (110, ')') : ('REDUCE', 11), + (111, ':') : ('SHIFT', 112), + (112, 'type') : ('SHIFT', 113), + (113, ',') : ('REDUCE', 15), + (113, ')') : ('REDUCE', 15), + (114, ')') : ('SHIFT', 115), + (115, ':') : ('SHIFT', 116), + (116, 'type') : ('SHIFT', 117), + (117, '{') : ('SHIFT', 118), + (118, 'let') : ('SHIFT', 8), + (118, 'new') : ('SHIFT', 22), + (118, 'if') : ('SHIFT', 24), + (118, '(') : ('SHIFT', 13), + (118, '~') : ('SHIFT', 15), + (118, 'int') : ('SHIFT', 21), + (118, 'string') : ('SHIFT', 29), + (118, 'not') : ('SHIFT', 26), + (118, 'while') : ('SHIFT', 20), + (118, 'id') : ('SHIFT', 18), + (118, 'isvoid') : ('SHIFT', 34), + (118, 'case') : ('SHIFT', 25), + (118, 'false') : ('SHIFT', 28), + (118, '{') : ('SHIFT', 14), + (118, 'true') : ('SHIFT', 27), + (119, '}') : ('SHIFT', 120), + (120, ';') : ('REDUCE', 10), + (121, ',') : ('SHIFT', 122), + (121, ')') : ('REDUCE', 13), + (122, 'id') : ('SHIFT', 111), + (123, ')') : ('REDUCE', 14), + (124, ')') : ('REDUCE', 12), + (125, '}') : ('SHIFT', 126), + (126, ';') : ('REDUCE', 3), + (127, ';') : ('SHIFT', 128), + (128, 'id') : ('SHIFT', 4), + (128, '}') : ('REDUCE', 7), + (129, '}') : ('REDUCE', 5), + (130, ';') : ('SHIFT', 131), + (131, 'id') : ('SHIFT', 4), + (131, '}') : ('REDUCE', 7), + (132, '}') : ('REDUCE', 6), + (133, 'type') : ('SHIFT', 134), + (134, '{') : ('SHIFT', 135), + (135, 'id') : ('SHIFT', 4), + (135, '}') : ('REDUCE', 7), + (136, '}') : ('SHIFT', 137), + (137, ';') : ('REDUCE', 4), + (138, '$') : ('REDUCE', 0), + (139, ';') : ('SHIFT', 140), + (140, '$') : ('REDUCE', 1), + (140, 'class') : ('SHIFT', 1), + (141, '$') : ('REDUCE', 2), + (142, '$') : ('OK', None) } self.goto = { - (0, '') : 136, - (0, '') : 140, - (0, '') : 137, - (3, '') : 125, - (3, '') : 123, - (3, '') : 128, + (0, '') : 139, + (0, '') : 142, + (0, '') : 138, + (3, '') : 130, + (3, '') : 127, + (3, '') : 125, (7, '') : 36, - (7, '') : 54, - (7, '') : 63, + (7, '') : 57, (7, '') : 44, + (7, '') : 54, + (7, '') : 64, + (7, '') : 109, (7, '') : 51, - (7, '') : 57, - (7, '') : 108, - (8, '') : 105, - (12, '') : 63, + (8, '') : 106, + (12, '') : 101, + (12, '') : 57, (12, '') : 54, - (12, '') : 36, (12, '') : 44, - (12, '') : 57, (12, '') : 51, - (12, '') : 100, - (13, '') : 57, + (12, '') : 36, + (12, '') : 64, + (13, '') : 64, (13, '') : 36, (13, '') : 51, - (13, '') : 63, + (13, '') : 57, (13, '') : 44, (13, '') : 54, - (13, '') : 98, + (13, '') : 99, + (14, '') : 96, (14, '') : 36, - (14, '') : 93, - (14, '') : 54, - (14, '') : 95, - (14, '') : 63, + (14, '') : 57, + (14, '') : 94, (14, '') : 44, + (14, '') : 54, + (14, '') : 64, (14, '') : 51, - (14, '') : 57, (15, '') : 36, + (15, '') : 93, (15, '') : 51, - (15, '') : 92, - (17, '') : 57, - (17, '') : 44, - (17, '') : 65, + (17, '') : 91, (17, '') : 36, - (17, '') : 90, - (17, '') : 63, + (17, '') : 64, + (17, '') : 62, + (17, '') : 66, + (17, '') : 57, (17, '') : 54, + (17, '') : 44, (17, '') : 51, - (19, '') : 44, - (19, '') : 63, (19, '') : 36, + (19, '') : 90, + (19, '') : 64, (19, '') : 57, - (19, '') : 51, - (19, '') : 89, (19, '') : 54, - (20, '') : 44, - (20, '') : 63, + (19, '') : 44, + (19, '') : 51, + (20, '') : 64, + (20, '') : 51, + (20, '') : 86, (20, '') : 36, + (20, '') : 44, (20, '') : 57, - (20, '') : 85, - (20, '') : 51, (20, '') : 54, (24, '') : 57, (24, '') : 44, - (24, '') : 79, (24, '') : 54, + (24, '') : 64, (24, '') : 36, + (24, '') : 80, (24, '') : 51, - (24, '') : 63, - (25, '') : 63, (25, '') : 36, - (25, '') : 51, + (25, '') : 69, + (25, '') : 64, (25, '') : 57, - (25, '') : 68, (25, '') : 44, + (25, '') : 51, (25, '') : 54, - (26, '') : 30, (26, '') : 51, - (33, '') : 57, - (33, '') : 44, - (33, '') : 65, + (26, '') : 30, + (33, '') : 67, (33, '') : 36, - (33, '') : 66, - (33, '') : 63, + (33, '') : 64, + (33, '') : 62, + (33, '') : 66, + (33, '') : 57, (33, '') : 54, + (33, '') : 44, (33, '') : 51, (34, '') : 36, (34, '') : 51, (34, '') : 35, - (41, '') : 57, - (41, '') : 44, - (41, '') : 65, (41, '') : 36, - (41, '') : 42, - (41, '') : 63, + (41, '') : 64, + (41, '') : 62, + (41, '') : 66, + (41, '') : 57, (41, '') : 54, + (41, '') : 44, (41, '') : 51, - (43, '') : 57, - (43, '') : 44, - (43, '') : 36, - (43, '') : 62, - (43, '') : 63, - (43, '') : 54, - (43, '') : 51, + (41, '') : 42, (45, '') : 36, - (45, '') : 51, (45, '') : 46, (45, '') : 57, (45, '') : 54, + (45, '') : 51, (47, '') : 36, - (47, '') : 51, (47, '') : 48, (47, '') : 54, + (47, '') : 51, (49, '') : 36, (49, '') : 51, (49, '') : 50, (52, '') : 36, - (52, '') : 51, (52, '') : 53, + (52, '') : 51, (55, '') : 36, - (55, '') : 51, (55, '') : 56, (55, '') : 54, + (55, '') : 51, (58, '') : 36, - (58, '') : 51, - (58, '') : 57, (58, '') : 59, + (58, '') : 57, (58, '') : 54, + (58, '') : 51, (60, '') : 36, - (60, '') : 51, - (60, '') : 57, (60, '') : 61, + (60, '') : 57, (60, '') : 54, - (69, '') : 77, - (73, '') : 36, - (73, '') : 54, - (73, '') : 74, - (73, '') : 63, - (73, '') : 44, - (73, '') : 51, - (73, '') : 57, - (75, '') : 76, - (80, '') : 63, - (80, '') : 57, - (80, '') : 44, - (80, '') : 81, - (80, '') : 36, - (80, '') : 51, - (80, '') : 54, - (82, '') : 63, - (82, '') : 57, - (82, '') : 44, - (82, '') : 54, - (82, '') : 51, - (82, '') : 83, - (82, '') : 36, - (86, '') : 36, - (86, '') : 51, - (86, '') : 63, - (86, '') : 44, - (86, '') : 57, - (86, '') : 87, - (86, '') : 54, - (96, '') : 36, - (96, '') : 54, - (96, '') : 95, - (96, '') : 63, - (96, '') : 44, - (96, '') : 97, - (96, '') : 51, - (96, '') : 57, - (101, '') : 102, - (103, '') : 104, - (106, '') : 44, - (106, '') : 63, - (106, '') : 36, - (106, '') : 57, - (106, '') : 51, - (106, '') : 107, - (106, '') : 54, - (109, '') : 113, - (109, '') : 122, - (114, '') : 115, - (119, '') : 54, - (119, '') : 63, - (119, '') : 36, - (119, '') : 44, - (119, '') : 57, - (119, '') : 51, - (119, '') : 120, - (126, '') : 125, - (126, '') : 127, - (126, '') : 128, - (129, '') : 125, - (129, '') : 128, - (129, '') : 130, - (133, '') : 134, - (133, '') : 125, - (133, '') : 128, - (138, '') : 139, - (138, '') : 137 + (60, '') : 51, + (63, '') : 36, + (63, '') : 64, + (63, '') : 62, + (63, '') : 57, + (63, '') : 54, + (63, '') : 65, + (63, '') : 44, + (63, '') : 51, + (70, '') : 78, + (74, '') : 36, + (74, '') : 57, + (74, '') : 44, + (74, '') : 75, + (74, '') : 54, + (74, '') : 64, + (74, '') : 51, + (76, '') : 77, + (81, '') : 44, + (81, '') : 64, + (81, '') : 36, + (81, '') : 51, + (81, '') : 57, + (81, '') : 82, + (81, '') : 54, + (83, '') : 44, + (83, '') : 36, + (83, '') : 64, + (83, '') : 57, + (83, '') : 84, + (83, '') : 51, + (83, '') : 54, + (87, '') : 88, + (87, '') : 36, + (87, '') : 64, + (87, '') : 44, + (87, '') : 57, + (87, '') : 54, + (87, '') : 51, + (97, '') : 96, + (97, '') : 98, + (97, '') : 36, + (97, '') : 57, + (97, '') : 44, + (97, '') : 54, + (97, '') : 64, + (97, '') : 51, + (102, '') : 103, + (104, '') : 105, + (107, '') : 36, + (107, '') : 64, + (107, '') : 57, + (107, '') : 54, + (107, '') : 44, + (107, '') : 108, + (107, '') : 51, + (110, '') : 124, + (110, '') : 121, + (110, '') : 114, + (118, '') : 36, + (118, '') : 64, + (118, '') : 57, + (118, '') : 44, + (118, '') : 54, + (118, '') : 119, + (118, '') : 51, + (122, '') : 121, + (122, '') : 123, + (128, '') : 130, + (128, '') : 129, + (128, '') : 127, + (131, '') : 130, + (131, '') : 132, + (131, '') : 127, + (135, '') : 130, + (135, '') : 136, + (135, '') : 127, + (140, '') : 139, + (140, '') : 141 } From 9768b4f621a8dc65031a0c4b5f2aa89b1a9cc9da Mon Sep 17 00:00:00 2001 From: Ale Date: Tue, 15 Feb 2022 23:53:05 -0800 Subject: [PATCH 34/83] writing errors like test --- src/main.py | 2 +- src/utils/semantic_check/type_builder.py | 8 +++++--- src/utils/semantic_check/type_checker.py | 8 +++++--- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main.py b/src/main.py index 4983b1b1e..699bb79c5 100644 --- a/src/main.py +++ b/src/main.py @@ -13,7 +13,7 @@ from utils.parser.LALR_1 import LALR1_Parser if __name__ == "__main__": - add = "parser/dispatch8.cl" + add = "semantic/self4.cl" path: str = f"{Path.cwd()}/tests/{add}" if os.path.exists( f"{Path.cwd()}/tests/{add}") else f"{Path.cwd()}/../tests/{add}" diff --git a/src/utils/semantic_check/type_builder.py b/src/utils/semantic_check/type_builder.py index 556c12060..829d10388 100644 --- a/src/utils/semantic_check/type_builder.py +++ b/src/utils/semantic_check/type_builder.py @@ -2,7 +2,9 @@ from utils.ast.AST_Nodes import ast_nodes as nodes from cmp.semantic import SemanticError, ErrorType -NOT_INHERIT_FROM_BASICS_TYPES = '(%s, %s) - SemanticError: Class %s cannot inherit class %s. ' +NOT_INHERIT_FROM_BASICS_TYPES = '(%s, %s) - SemanticError: Class %s cannot inherit class %s.' +MULTIDEFINED_METHOD = '(%s, %s) - SemanticError: Method %s is multiply defined.' +INHERIT_ERROR = '(%s, %s) - TypeError: Class %s inherits from an undefined class %s.' class TypeBuilder: @@ -36,7 +38,7 @@ def visit(self,node): parent_type = self.context.get_type(node.parent) except SemanticError as se: parent_type = ErrorType() - self.errors.append(se.text) + self.errors.append(INHERIT_ERROR % (node.line, node.parent_column, node.id, node.parent)) try: self.current_type.set_parent(parent_type) @@ -87,6 +89,6 @@ def visit(self,node): try: self.current_type.define_method(node.id, param_names, param_types, returnType) except SemanticError as se: - self.errors.append(se.text) + self.errors.append(MULTIDEFINED_METHOD % (node.line, node.column, node.id)) return \ No newline at end of file diff --git a/src/utils/semantic_check/type_checker.py b/src/utils/semantic_check/type_checker.py index b910b92cc..6a80c3d5a 100644 --- a/src/utils/semantic_check/type_checker.py +++ b/src/utils/semantic_check/type_checker.py @@ -6,7 +6,7 @@ MAIN_METHOD_DONT_EXISTS = '(%s, %s) - TypeError: Main class must have a method main()' MAIN_METHOD_DONT_HAVE_PARAMS = '(%s, %s) - TypeError: main method must not have params' -SELF_ERROR = '(%s, %s) - TypeError: self cannot be used as an attribute name' +SELF_ERROR = '(%s, %s) - SemanticError: \'self\' cannot be the name of an attribute.' SELF_IS_READONLY = '(%s, %s) - TypeError: Variable "self" is read-only.' SELF_TYPE_ERROR = '(%s, %s) - TypeError: SELF_TYPE cannot be used as a parameter type in method %s' SELF_TYPE_IN_DISPATCH = '(%s, %s) - TypeError: SELF_TYPE cannot be used as a type of a dispatch' @@ -101,14 +101,16 @@ def visit(self, node, scope): def visit(self, node, scope): attr_type = self.context.get_type(node.type) if node.type != 'SELF_TYPE' else self.current_type + if node.id == 'self': + self.errors.append(SELF_ERROR % (node.line, node.column)) + if node.expr: type_expr = self.visit(node.expr, scope.create_child()) if not type_expr.conforms_to(attr_type): self.errors.append(INCOMPATIBLE_TYPES_ATTR % (node.line, node.column, type_expr.name, node.id, attr_type.name)) - if node.id == 'self': - self.errors.append(SELF_ERROR % (node.line, node.column)) + scope.define_variable(node.id, attr_type) From e677043e646418aa0b81776c4e6984ae849d7960 Mon Sep 17 00:00:00 2001 From: Ale Date: Tue, 15 Feb 2022 23:58:01 -0800 Subject: [PATCH 35/83] updating semantic --- src/main.py | 2 +- src/utils/semantic_check/type_checker.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main.py b/src/main.py index 699bb79c5..314f2bcb3 100644 --- a/src/main.py +++ b/src/main.py @@ -13,7 +13,7 @@ from utils.parser.LALR_1 import LALR1_Parser if __name__ == "__main__": - add = "semantic/self4.cl" + add = "semantic/methods1.cl" path: str = f"{Path.cwd()}/tests/{add}" if os.path.exists( f"{Path.cwd()}/tests/{add}") else f"{Path.cwd()}/../tests/{add}" diff --git a/src/utils/semantic_check/type_checker.py b/src/utils/semantic_check/type_checker.py index 6a80c3d5a..dc4bebfba 100644 --- a/src/utils/semantic_check/type_checker.py +++ b/src/utils/semantic_check/type_checker.py @@ -18,7 +18,7 @@ INCOMPATIBLE_TYPES_IF = '(%s, %s) - TypeError: Predicate of \'%s\' does not have type %s.' INCOMPATIBLE_TYPES = '(%s, %s) - TypeError: Cannot convert %s into %s.' WRONG_SIGNATURE = '(%s, %s) - TypeError: Method %s already defined in %s with a different signature.' -LOCAL_ALREADY_DEFINED = '(%s, %s) - TypeError: Variable %s is already defined in method %s.' +LOCAL_ALREADY_DEFINED = '(%s, %s) - SemanticError: Variable %s is already defined in method %s.' INVALID_OPERATION = '(%s, %s) - TypeError: non-Int arguments: %s %s %s' VARIABLE_NOT_DEFINED = '(%s, %s) - NameError: Undeclared identifier %s.' INHERIT_ERROR = '(%s, %s) - TypeError: Class %s cannot inherit from class %s because they form a cycle.' @@ -103,7 +103,7 @@ def visit(self, node, scope): if node.id == 'self': self.errors.append(SELF_ERROR % (node.line, node.column)) - + if node.expr: type_expr = self.visit(node.expr, scope.create_child()) From 4c2642e43fe6a82107d2ac806497b3a01dc0ec63 Mon Sep 17 00:00:00 2001 From: Ale Date: Wed, 16 Feb 2022 00:41:07 -0800 Subject: [PATCH 36/83] acopling errors --- src/main.py | 2 +- src/utils/semantic_check/type_builder.py | 7 ++++--- src/utils/semantic_check/type_checker.py | 10 ++++++---- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/main.py b/src/main.py index 314f2bcb3..117982218 100644 --- a/src/main.py +++ b/src/main.py @@ -13,7 +13,7 @@ from utils.parser.LALR_1 import LALR1_Parser if __name__ == "__main__": - add = "semantic/methods1.cl" + add = "semantic/let1.cl" path: str = f"{Path.cwd()}/tests/{add}" if os.path.exists( f"{Path.cwd()}/tests/{add}") else f"{Path.cwd()}/../tests/{add}" diff --git a/src/utils/semantic_check/type_builder.py b/src/utils/semantic_check/type_builder.py index 829d10388..41eada589 100644 --- a/src/utils/semantic_check/type_builder.py +++ b/src/utils/semantic_check/type_builder.py @@ -5,6 +5,8 @@ NOT_INHERIT_FROM_BASICS_TYPES = '(%s, %s) - SemanticError: Class %s cannot inherit class %s.' MULTIDEFINED_METHOD = '(%s, %s) - SemanticError: Method %s is multiply defined.' INHERIT_ERROR = '(%s, %s) - TypeError: Class %s inherits from an undefined class %s.' +PARAMETER_TYPE_UNDEFINED = '(%s, %s) - TypeError: Class %s of formal parameter %s is undefined.' +REDEFINED_ATTRIBUTES = '(%s, %s) - SemanticError: Attribute %s is an attribute of an inherited class.' class TypeBuilder: @@ -60,8 +62,7 @@ def visit(self,node): attrType = self.context.get_type(node.type) self.current_type.define_attribute(node.id, attrType) except SemanticError as se: - self.errors.append(se.text) - self.current_type.define_attribute(node.id, ErrorType()) + self.errors.append(REDEFINED_ATTRIBUTES % (node.line, node.column, node.id)) return @@ -77,7 +78,7 @@ def visit(self,node): try: param_types.append(self.context.get_type(typex)) except SemanticError as se: - self.errors.append(se.text) + self.errors.append(PARAMETER_TYPE_UNDEFINED % (node.line, node.column, typex, name)) param_types.append(ErrorType()) try: diff --git a/src/utils/semantic_check/type_checker.py b/src/utils/semantic_check/type_checker.py index dc4bebfba..e0b2ac437 100644 --- a/src/utils/semantic_check/type_checker.py +++ b/src/utils/semantic_check/type_checker.py @@ -16,8 +16,9 @@ INCOMPATIBLE_TYPES_ARG = '(%s, %s) - TypeError: Argument of \'%s\' has type %s instead of %s.' INCOMPATIBLE_TYPES_METH = '(%s, %s) - TypeError: Inferred return type %s of method %s does not conform to declared return type %s.' INCOMPATIBLE_TYPES_IF = '(%s, %s) - TypeError: Predicate of \'%s\' does not have type %s.' +INCOMPATIBLE_TYPES_LET = '(%s, %s) - TypeError: Inferred type %s of initialization of %s does not conform to identifier\'s declared type %s.' INCOMPATIBLE_TYPES = '(%s, %s) - TypeError: Cannot convert %s into %s.' -WRONG_SIGNATURE = '(%s, %s) - TypeError: Method %s already defined in %s with a different signature.' +WRONG_SIGNATURE = '(%s, %s) - SemanticError: Incompatible number of formal parameters in redefined method %s.' LOCAL_ALREADY_DEFINED = '(%s, %s) - SemanticError: Variable %s is already defined in method %s.' INVALID_OPERATION = '(%s, %s) - TypeError: non-Int arguments: %s %s %s' VARIABLE_NOT_DEFINED = '(%s, %s) - NameError: Undeclared identifier %s.' @@ -132,7 +133,7 @@ def visit(self, node, scope): try: parent_method = current_parent.get_method(node.id) if parent_method != self.current_method: - self.errors.append(WRONG_SIGNATURE % (node.line, node.column, self.current_method.name, self.current_type.name)) + self.errors.append(WRONG_SIGNATURE % (node.line, node.column, self.current_method.name)) break except: pass @@ -271,14 +272,15 @@ def visit(self, node, scope): self.errors.append(se.text) if scope.is_local(idx): - self.errors.append(LOCAL_ALREADY_DEFINED % (node.line, node.column, idx, self.current_method.name)) + scope = scope.create_child() + scope.define_variable(idx, id_type) else: scope.define_variable(idx, id_type) if id_expr is not None: id_expr_type = self.visit(id_expr, scope.create_child()) if not id_expr_type.conforms_to(id_type): - self.errors.append(INCOMPATIBLE_TYPES % (node.line, node.column, id_expr_type.name, id_type.name)) + self.errors.append(INCOMPATIBLE_TYPES_LET % (node.line, node.column, id_expr_type.name, idx, id_type.name)) body_type = self.visit(node.in_expr, scope.create_child()) From 87c4a6642c2c70817cc155b9cf0e6d9950e278ac Mon Sep 17 00:00:00 2001 From: Ale Date: Wed, 16 Feb 2022 01:34:23 -0800 Subject: [PATCH 37/83] update semantic errors --- src/cmp/semantic.py | 9 ++++++--- src/main.py | 2 +- src/utils/semantic_check/type_builder.py | 3 ++- src/utils/semantic_check/type_checker.py | 3 +-- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/cmp/semantic.py b/src/cmp/semantic.py index 3cf8c49a6..dc72bc7fc 100644 --- a/src/cmp/semantic.py +++ b/src/cmp/semantic.py @@ -48,20 +48,23 @@ def set_parent(self, parent): raise SemanticError(f'Parent type is already set for {self.name}.') self.parent = parent - def get_attribute(self, name:str): + def get_attribute(self, name:str, typex:str): try: return next(attr for attr in self.attributes if attr.name == name) except StopIteration: if self.parent is None: raise SemanticError(f'Attribute "{name}" is not defined in {self.name}.') try: - return self.parent.get_attribute(name) + if self.parent.name != typex: + return self.parent.get_attribute(name, typex) + raise SemanticError() + except SemanticError: raise SemanticError(f'Attribute "{name}" is not defined in {self.name}.') def define_attribute(self, name:str, typex): try: - self.get_attribute(name) + self.get_attribute(name, self.name) except SemanticError: attribute = Attribute(name, typex) self.attributes.append(attribute) diff --git a/src/main.py b/src/main.py index 117982218..c7c12d654 100644 --- a/src/main.py +++ b/src/main.py @@ -13,7 +13,7 @@ from utils.parser.LALR_1 import LALR1_Parser if __name__ == "__main__": - add = "semantic/let1.cl" + add = "semantic/inheritance4.cl" path: str = f"{Path.cwd()}/tests/{add}" if os.path.exists( f"{Path.cwd()}/tests/{add}") else f"{Path.cwd()}/../tests/{add}" diff --git a/src/utils/semantic_check/type_builder.py b/src/utils/semantic_check/type_builder.py index 41eada589..c10325368 100644 --- a/src/utils/semantic_check/type_builder.py +++ b/src/utils/semantic_check/type_builder.py @@ -7,6 +7,7 @@ INHERIT_ERROR = '(%s, %s) - TypeError: Class %s inherits from an undefined class %s.' PARAMETER_TYPE_UNDEFINED = '(%s, %s) - TypeError: Class %s of formal parameter %s is undefined.' REDEFINED_ATTRIBUTES = '(%s, %s) - SemanticError: Attribute %s is an attribute of an inherited class.' +RETURN_TYPE_UNDEFINED = '(%s, %s) - TypeError: Undefined return type %s in method %s.' class TypeBuilder: @@ -84,7 +85,7 @@ def visit(self,node): try: returnType = self.context.get_type(node.type) except SemanticError as se: - self.errors.append(se.text) + self.errors.append(RETURN_TYPE_UNDEFINED % (node.line, node.column, node.type, node.id)) returnType = ErrorType() try: diff --git a/src/utils/semantic_check/type_checker.py b/src/utils/semantic_check/type_checker.py index e0b2ac437..9dec5bd63 100644 --- a/src/utils/semantic_check/type_checker.py +++ b/src/utils/semantic_check/type_checker.py @@ -22,7 +22,7 @@ LOCAL_ALREADY_DEFINED = '(%s, %s) - SemanticError: Variable %s is already defined in method %s.' INVALID_OPERATION = '(%s, %s) - TypeError: non-Int arguments: %s %s %s' VARIABLE_NOT_DEFINED = '(%s, %s) - NameError: Undeclared identifier %s.' -INHERIT_ERROR = '(%s, %s) - TypeError: Class %s cannot inherit from class %s because they form a cycle.' +INHERIT_ERROR = '(%s, %s) - SemanticError: Class %s cannot inherit from class %s because they form a cycle.' METHOD_PARAMETERS = '(%s, %s) - TypeError: Method %s defined in %s receive %d parameters' DUPLICATE_BRANCH = '(%s, %s) - SemanticError: Duplicate branch %s in case statement.' @@ -157,7 +157,6 @@ def visit(self, node, scope): try: returnType = self.context.get_type(node.type) if node.type != 'SELF_TYPE' else self.current_type except SemanticError as se: - self.errors.append(se.text) returnType = ErrorType() if not body_type.conforms_to(returnType): From f3e581895a79ac844d547125a767e1ea8f718974 Mon Sep 17 00:00:00 2001 From: Ale Date: Wed, 16 Feb 2022 14:51:05 -0800 Subject: [PATCH 38/83] updating code --- src/main.py | 7 +- src/utils/COOL_Grammar.py | 5 +- src/utils/parser/COOL_parser.py | 1895 ++++++++++---------- src/utils/semantic_check/type_checker.py | 24 +- src/utils/semantic_check/type_collector.py | 4 +- 5 files changed, 972 insertions(+), 963 deletions(-) diff --git a/src/main.py b/src/main.py index c7c12d654..3714e9728 100644 --- a/src/main.py +++ b/src/main.py @@ -13,7 +13,7 @@ from utils.parser.LALR_1 import LALR1_Parser if __name__ == "__main__": - add = "semantic/inheritance4.cl" + add = "semantic/arithmetic12.cl" path: str = f"{Path.cwd()}/tests/{add}" if os.path.exists( f"{Path.cwd()}/tests/{add}") else f"{Path.cwd()}/../tests/{add}" @@ -23,6 +23,11 @@ with open(_in) as file: code = file.read() + code = '''class Main { + main(): Object { + if true = not false then 4 else 5 fi + }; +};''' G = build_COOL_Grammar() diff --git a/src/utils/COOL_Grammar.py b/src/utils/COOL_Grammar.py index 25fe8b993..0cae24564 100644 --- a/src/utils/COOL_Grammar.py +++ b/src/utils/COOL_Grammar.py @@ -68,11 +68,13 @@ def build_COOL_Grammar(): case_list %= idx + colon + typex + darrow + expr + semi, lambda h,s: [(s[1],s[3],s[5])] case_list %= idx + colon + typex + darrow + expr + semi + case_list, lambda h,s: [(s[1],s[3],s[5])] + s[7] + expr %= notx + expr, lambda h,s: node.NotNode(s[2],s[1]) + expr %= comp + equal + expr, lambda h,s: node.EqualNode(s[1],s[3],s[2]) + expr %= comp, lambda h,s: s[1] comp %= comp + less + arith, lambda h,s: node.LessThanNode(s[1],s[3],s[2]) comp %= comp + lesse + arith, lambda h,s: node.LessEqualNode(s[1],s[3],s[2]) - comp %= comp + equal + arith, lambda h,s: node.EqualNode(s[1],s[3],s[2]) comp %= arith, lambda h,s: s[1] arith %= arith + plus + term, lambda h,s: node.PlusNode(s[1],s[3],s[2]) @@ -85,7 +87,6 @@ def build_COOL_Grammar(): factor %= isvoid + factor, lambda h,s: node.IsVoidNode(s[2]) factor %= tilde + factor, lambda h,s: node.ComplementNode(s[2], s[1]) - factor %= notx + atom, lambda h,s: node.NotNode(s[2],s[1]) factor %= atom, lambda h,s: s[1] atom %= true, lambda h,s: node.ConstantBoolNode(s[1]) diff --git a/src/utils/parser/COOL_parser.py b/src/utils/parser/COOL_parser.py index edaa3ba96..6f2958843 100644 --- a/src/utils/parser/COOL_parser.py +++ b/src/utils/parser/COOL_parser.py @@ -30,93 +30,85 @@ def __init__(self, G): (4, '(') : ('SHIFT', 110), (4, ':') : ('SHIFT', 5), (5, 'type') : ('SHIFT', 6), - (6, '<-') : ('SHIFT', 7), (6, ';') : ('REDUCE', 8), + (6, '<-') : ('SHIFT', 7), (7, 'id') : ('SHIFT', 18), - (7, 'true') : ('SHIFT', 27), - (7, 'new') : ('SHIFT', 22), + (7, 'isvoid') : ('SHIFT', 27), + (7, 'false') : ('SHIFT', 29), (7, 'if') : ('SHIFT', 24), - (7, '(') : ('SHIFT', 13), - (7, 'let') : ('SHIFT', 8), (7, '~') : ('SHIFT', 15), + (7, 'string') : ('SHIFT', 30), + (7, '{') : ('SHIFT', 14), + (7, 'case') : ('SHIFT', 25), + (7, 'new') : ('SHIFT', 22), + (7, 'true') : ('SHIFT', 28), (7, 'int') : ('SHIFT', 21), - (7, 'string') : ('SHIFT', 29), + (7, '(') : ('SHIFT', 13), (7, 'not') : ('SHIFT', 26), + (7, 'let') : ('SHIFT', 8), (7, 'while') : ('SHIFT', 20), - (7, 'isvoid') : ('SHIFT', 34), - (7, 'case') : ('SHIFT', 25), - (7, 'false') : ('SHIFT', 28), - (7, '{') : ('SHIFT', 14), (8, 'id') : ('SHIFT', 9), (9, ':') : ('SHIFT', 10), (10, 'type') : ('SHIFT', 11), - (11, ',') : ('SHIFT', 104), (11, '<-') : ('SHIFT', 12), + (11, ',') : ('SHIFT', 104), (11, 'in') : ('REDUCE', 22), - (12, 'false') : ('SHIFT', 28), - (12, 'not') : ('SHIFT', 26), - (12, 'while') : ('SHIFT', 20), (12, 'id') : ('SHIFT', 18), - (12, 'isvoid') : ('SHIFT', 34), + (12, '{') : ('SHIFT', 14), + (12, 'false') : ('SHIFT', 29), (12, 'case') : ('SHIFT', 25), - (12, 'true') : ('SHIFT', 27), - (12, 'new') : ('SHIFT', 22), (12, 'if') : ('SHIFT', 24), - (12, '(') : ('SHIFT', 13), - (12, '{') : ('SHIFT', 14), - (12, 'int') : ('SHIFT', 21), - (12, 'string') : ('SHIFT', 29), + (12, 'string') : ('SHIFT', 30), + (12, 'isvoid') : ('SHIFT', 27), + (12, 'new') : ('SHIFT', 22), + (12, 'not') : ('SHIFT', 26), (12, 'let') : ('SHIFT', 8), (12, '~') : ('SHIFT', 15), + (12, 'true') : ('SHIFT', 28), + (12, 'while') : ('SHIFT', 20), + (12, 'int') : ('SHIFT', 21), + (12, '(') : ('SHIFT', 13), (13, 'id') : ('SHIFT', 18), (13, 'let') : ('SHIFT', 8), - (13, 'false') : ('SHIFT', 28), - (13, '~') : ('SHIFT', 15), - (13, 'true') : ('SHIFT', 27), - (13, 'if') : ('SHIFT', 24), - (13, '(') : ('SHIFT', 13), - (13, 'new') : ('SHIFT', 22), (13, 'not') : ('SHIFT', 26), + (13, 'false') : ('SHIFT', 29), + (13, 'isvoid') : ('SHIFT', 27), + (13, 'if') : ('SHIFT', 24), (13, 'while') : ('SHIFT', 20), - (13, 'case') : ('SHIFT', 25), - (13, 'isvoid') : ('SHIFT', 34), + (13, '~') : ('SHIFT', 15), + (13, 'string') : ('SHIFT', 30), + (13, 'new') : ('SHIFT', 22), + (13, 'true') : ('SHIFT', 28), (13, 'int') : ('SHIFT', 21), - (13, 'string') : ('SHIFT', 29), + (13, '(') : ('SHIFT', 13), (13, '{') : ('SHIFT', 14), + (13, 'case') : ('SHIFT', 25), (14, 'id') : ('SHIFT', 18), - (14, 'true') : ('SHIFT', 27), - (14, 'new') : ('SHIFT', 22), + (14, 'isvoid') : ('SHIFT', 27), + (14, 'false') : ('SHIFT', 29), (14, 'if') : ('SHIFT', 24), - (14, '(') : ('SHIFT', 13), - (14, 'let') : ('SHIFT', 8), (14, '~') : ('SHIFT', 15), + (14, 'string') : ('SHIFT', 30), + (14, '{') : ('SHIFT', 14), + (14, 'case') : ('SHIFT', 25), + (14, 'new') : ('SHIFT', 22), + (14, 'true') : ('SHIFT', 28), (14, 'int') : ('SHIFT', 21), - (14, 'string') : ('SHIFT', 29), + (14, '(') : ('SHIFT', 13), (14, 'not') : ('SHIFT', 26), + (14, 'let') : ('SHIFT', 8), (14, 'while') : ('SHIFT', 20), - (14, 'isvoid') : ('SHIFT', 34), - (14, 'case') : ('SHIFT', 25), - (14, 'false') : ('SHIFT', 28), - (14, '{') : ('SHIFT', 14), - (15, 'true') : ('SHIFT', 27), + (15, 'string') : ('SHIFT', 30), (15, 'id') : ('SHIFT', 16), - (15, 'if') : ('SHIFT', 24), - (15, '(') : ('SHIFT', 13), - (15, '~') : ('SHIFT', 15), (15, 'new') : ('SHIFT', 22), - (15, 'false') : ('SHIFT', 28), + (15, 'isvoid') : ('SHIFT', 27), + (15, 'true') : ('SHIFT', 28), + (15, '~') : ('SHIFT', 15), (15, 'int') : ('SHIFT', 21), - (15, 'string') : ('SHIFT', 29), - (15, 'not') : ('SHIFT', 26), - (15, 'isvoid') : ('SHIFT', 34), + (15, 'false') : ('SHIFT', 29), + (15, '(') : ('SHIFT', 13), + (15, 'if') : ('SHIFT', 24), (16, '(') : ('SHIFT', 17), - (16, '-') : ('REDUCE', 48), - (16, 'of') : ('REDUCE', 48), - (16, '*') : ('REDUCE', 48), - (16, '/') : ('REDUCE', 48), - (16, '<') : ('REDUCE', 48), - (16, '<=') : ('REDUCE', 48), - (16, '@') : ('REDUCE', 48), (16, 'in') : ('REDUCE', 48), (16, ';') : ('REDUCE', 48), (16, 'loop') : ('REDUCE', 48), @@ -130,31 +122,30 @@ def __init__(self, G): (16, 'fi') : ('REDUCE', 48), (16, '=') : ('REDUCE', 48), (16, '+') : ('REDUCE', 48), + (16, 'of') : ('REDUCE', 48), + (16, '-') : ('REDUCE', 48), + (16, '*') : ('REDUCE', 48), + (16, '/') : ('REDUCE', 48), + (16, '<') : ('REDUCE', 48), + (16, '<=') : ('REDUCE', 48), + (16, '@') : ('REDUCE', 48), + (17, 'not') : ('SHIFT', 26), (17, 'let') : ('SHIFT', 8), - (17, 'int') : ('SHIFT', 21), + (17, 'string') : ('SHIFT', 30), (17, '~') : ('SHIFT', 15), - (17, 'string') : ('SHIFT', 29), - (17, 'new') : ('SHIFT', 22), + (17, 'while') : ('SHIFT', 20), (17, ')') : ('REDUCE', 56), - (17, 'not') : ('SHIFT', 26), (17, 'id') : ('SHIFT', 18), - (17, 'isvoid') : ('SHIFT', 34), - (17, 'while') : ('SHIFT', 20), - (17, 'false') : ('SHIFT', 28), - (17, 'case') : ('SHIFT', 25), + (17, 'new') : ('SHIFT', 22), + (17, 'true') : ('SHIFT', 28), + (17, '(') : ('SHIFT', 13), + (17, 'int') : ('SHIFT', 21), (17, '{') : ('SHIFT', 14), - (17, 'true') : ('SHIFT', 27), + (17, 'isvoid') : ('SHIFT', 27), + (17, 'case') : ('SHIFT', 25), + (17, 'false') : ('SHIFT', 29), (17, 'if') : ('SHIFT', 24), - (17, '(') : ('SHIFT', 13), - (18, '<-') : ('SHIFT', 19), (18, '(') : ('SHIFT', 17), - (18, '-') : ('REDUCE', 48), - (18, 'of') : ('REDUCE', 48), - (18, '*') : ('REDUCE', 48), - (18, '/') : ('REDUCE', 48), - (18, '<') : ('REDUCE', 48), - (18, '<=') : ('REDUCE', 48), - (18, '@') : ('REDUCE', 48), (18, 'in') : ('REDUCE', 48), (18, ';') : ('REDUCE', 48), (18, 'loop') : ('REDUCE', 48), @@ -168,43 +159,44 @@ def __init__(self, G): (18, 'fi') : ('REDUCE', 48), (18, '=') : ('REDUCE', 48), (18, '+') : ('REDUCE', 48), - (19, 'true') : ('SHIFT', 27), - (19, 'if') : ('SHIFT', 24), - (19, 'id') : ('SHIFT', 18), - (19, '(') : ('SHIFT', 13), - (19, '~') : ('SHIFT', 15), - (19, 'new') : ('SHIFT', 22), - (19, 'let') : ('SHIFT', 8), - (19, 'int') : ('SHIFT', 21), - (19, 'string') : ('SHIFT', 29), + (18, 'of') : ('REDUCE', 48), + (18, '-') : ('REDUCE', 48), + (18, '*') : ('REDUCE', 48), + (18, '/') : ('REDUCE', 48), + (18, '<') : ('REDUCE', 48), + (18, '<=') : ('REDUCE', 48), + (18, '@') : ('REDUCE', 48), + (18, '<-') : ('SHIFT', 19), + (19, 'string') : ('SHIFT', 30), (19, 'not') : ('SHIFT', 26), - (19, 'isvoid') : ('SHIFT', 34), + (19, 'let') : ('SHIFT', 8), (19, 'while') : ('SHIFT', 20), - (19, 'case') : ('SHIFT', 25), - (19, 'false') : ('SHIFT', 28), + (19, 'new') : ('SHIFT', 22), + (19, 'id') : ('SHIFT', 18), + (19, 'true') : ('SHIFT', 28), + (19, 'int') : ('SHIFT', 21), + (19, '(') : ('SHIFT', 13), (19, '{') : ('SHIFT', 14), - (20, 'isvoid') : ('SHIFT', 34), - (20, 'id') : ('SHIFT', 18), - (20, '{') : ('SHIFT', 14), - (20, 'true') : ('SHIFT', 27), - (20, 'if') : ('SHIFT', 24), - (20, 'new') : ('SHIFT', 22), - (20, '(') : ('SHIFT', 13), + (19, 'isvoid') : ('SHIFT', 27), + (19, 'case') : ('SHIFT', 25), + (19, '~') : ('SHIFT', 15), + (19, 'false') : ('SHIFT', 29), + (19, 'if') : ('SHIFT', 24), (20, 'int') : ('SHIFT', 21), - (20, 'string') : ('SHIFT', 29), + (20, '(') : ('SHIFT', 13), + (20, 'not') : ('SHIFT', 26), + (20, 'isvoid') : ('SHIFT', 27), (20, 'let') : ('SHIFT', 8), - (20, '~') : ('SHIFT', 15), (20, 'while') : ('SHIFT', 20), - (20, 'false') : ('SHIFT', 28), - (20, 'not') : ('SHIFT', 26), + (20, '~') : ('SHIFT', 15), + (20, 'id') : ('SHIFT', 18), + (20, 'false') : ('SHIFT', 29), + (20, 'if') : ('SHIFT', 24), + (20, 'string') : ('SHIFT', 30), + (20, '{') : ('SHIFT', 14), + (20, 'new') : ('SHIFT', 22), (20, 'case') : ('SHIFT', 25), - (21, '-') : ('REDUCE', 47), - (21, 'of') : ('REDUCE', 47), - (21, '*') : ('REDUCE', 47), - (21, '/') : ('REDUCE', 47), - (21, '<') : ('REDUCE', 47), - (21, '<=') : ('REDUCE', 47), - (21, '@') : ('REDUCE', 47), + (20, 'true') : ('SHIFT', 28), (21, 'in') : ('REDUCE', 47), (21, ';') : ('REDUCE', 47), (21, 'loop') : ('REDUCE', 47), @@ -218,14 +210,14 @@ def __init__(self, G): (21, 'fi') : ('REDUCE', 47), (21, '=') : ('REDUCE', 47), (21, '+') : ('REDUCE', 47), + (21, 'of') : ('REDUCE', 47), + (21, '-') : ('REDUCE', 47), + (21, '*') : ('REDUCE', 47), + (21, '/') : ('REDUCE', 47), + (21, '<') : ('REDUCE', 47), + (21, '<=') : ('REDUCE', 47), + (21, '@') : ('REDUCE', 47), (22, 'type') : ('SHIFT', 23), - (23, '-') : ('REDUCE', 49), - (23, 'of') : ('REDUCE', 49), - (23, '*') : ('REDUCE', 49), - (23, '/') : ('REDUCE', 49), - (23, '<') : ('REDUCE', 49), - (23, '<=') : ('REDUCE', 49), - (23, '@') : ('REDUCE', 49), (23, 'in') : ('REDUCE', 49), (23, ';') : ('REDUCE', 49), (23, 'loop') : ('REDUCE', 49), @@ -239,631 +231,621 @@ def __init__(self, G): (23, 'fi') : ('REDUCE', 49), (23, '=') : ('REDUCE', 49), (23, '+') : ('REDUCE', 49), + (23, 'of') : ('REDUCE', 49), + (23, '-') : ('REDUCE', 49), + (23, '*') : ('REDUCE', 49), + (23, '/') : ('REDUCE', 49), + (23, '<') : ('REDUCE', 49), + (23, '<=') : ('REDUCE', 49), + (23, '@') : ('REDUCE', 49), + (24, 'true') : ('SHIFT', 28), + (24, '(') : ('SHIFT', 13), (24, 'int') : ('SHIFT', 21), - (24, 'not') : ('SHIFT', 26), - (24, 'string') : ('SHIFT', 29), - (24, 'isvoid') : ('SHIFT', 34), - (24, 'while') : ('SHIFT', 20), + (24, '{') : ('SHIFT', 14), (24, 'id') : ('SHIFT', 18), (24, 'case') : ('SHIFT', 25), - (24, '{') : ('SHIFT', 14), - (24, 'false') : ('SHIFT', 28), - (24, 'let') : ('SHIFT', 8), + (24, 'false') : ('SHIFT', 29), (24, 'if') : ('SHIFT', 24), + (24, 'string') : ('SHIFT', 30), + (24, 'not') : ('SHIFT', 26), + (24, 'let') : ('SHIFT', 8), + (24, 'isvoid') : ('SHIFT', 27), + (24, 'while') : ('SHIFT', 20), (24, '~') : ('SHIFT', 15), - (24, 'true') : ('SHIFT', 27), (24, 'new') : ('SHIFT', 22), - (24, '(') : ('SHIFT', 13), - (25, 'let') : ('SHIFT', 8), - (25, 'id') : ('SHIFT', 18), - (25, '~') : ('SHIFT', 15), - (25, 'while') : ('SHIFT', 20), - (25, 'false') : ('SHIFT', 28), - (25, 'case') : ('SHIFT', 25), - (25, 'not') : ('SHIFT', 26), - (25, 'true') : ('SHIFT', 27), (25, '{') : ('SHIFT', 14), - (25, 'new') : ('SHIFT', 22), + (25, 'false') : ('SHIFT', 29), + (25, 'case') : ('SHIFT', 25), (25, 'if') : ('SHIFT', 24), - (25, '(') : ('SHIFT', 13), - (25, 'isvoid') : ('SHIFT', 34), + (25, 'string') : ('SHIFT', 30), + (25, 'new') : ('SHIFT', 22), + (25, 'id') : ('SHIFT', 18), + (25, 'not') : ('SHIFT', 26), + (25, 'let') : ('SHIFT', 8), + (25, 'while') : ('SHIFT', 20), + (25, 'true') : ('SHIFT', 28), (25, 'int') : ('SHIFT', 21), - (25, 'string') : ('SHIFT', 29), - (26, 'true') : ('SHIFT', 27), + (25, '(') : ('SHIFT', 13), + (25, 'isvoid') : ('SHIFT', 27), + (25, '~') : ('SHIFT', 15), + (26, 'string') : ('SHIFT', 30), + (26, 'not') : ('SHIFT', 26), + (26, 'let') : ('SHIFT', 8), + (26, 'while') : ('SHIFT', 20), + (26, 'new') : ('SHIFT', 22), + (26, 'id') : ('SHIFT', 18), + (26, 'true') : ('SHIFT', 28), (26, 'int') : ('SHIFT', 21), - (26, 'id') : ('SHIFT', 16), - (26, 'string') : ('SHIFT', 29), - (26, 'if') : ('SHIFT', 24), (26, '(') : ('SHIFT', 13), - (26, 'new') : ('SHIFT', 22), - (26, 'false') : ('SHIFT', 28), - (27, '-') : ('REDUCE', 44), - (27, 'of') : ('REDUCE', 44), - (27, '*') : ('REDUCE', 44), - (27, '/') : ('REDUCE', 44), - (27, '<') : ('REDUCE', 44), - (27, '<=') : ('REDUCE', 44), - (27, '@') : ('REDUCE', 44), - (27, 'in') : ('REDUCE', 44), - (27, ';') : ('REDUCE', 44), - (27, 'loop') : ('REDUCE', 44), - (27, 'pool') : ('REDUCE', 44), - (27, ',') : ('REDUCE', 44), - (27, '.') : ('REDUCE', 44), - (27, ')') : ('REDUCE', 44), - (27, 'then') : ('REDUCE', 44), - (27, 'else') : ('REDUCE', 44), - (27, '}') : ('REDUCE', 44), - (27, 'fi') : ('REDUCE', 44), - (27, '=') : ('REDUCE', 44), - (27, '+') : ('REDUCE', 44), - (28, '-') : ('REDUCE', 45), - (28, 'of') : ('REDUCE', 45), - (28, '*') : ('REDUCE', 45), - (28, '/') : ('REDUCE', 45), - (28, '<') : ('REDUCE', 45), - (28, '<=') : ('REDUCE', 45), - (28, '@') : ('REDUCE', 45), - (28, 'in') : ('REDUCE', 45), - (28, ';') : ('REDUCE', 45), - (28, 'loop') : ('REDUCE', 45), - (28, 'pool') : ('REDUCE', 45), - (28, ',') : ('REDUCE', 45), - (28, '.') : ('REDUCE', 45), - (28, ')') : ('REDUCE', 45), - (28, 'then') : ('REDUCE', 45), - (28, 'else') : ('REDUCE', 45), - (28, '}') : ('REDUCE', 45), - (28, 'fi') : ('REDUCE', 45), - (28, '=') : ('REDUCE', 45), - (28, '+') : ('REDUCE', 45), - (29, '-') : ('REDUCE', 46), - (29, 'of') : ('REDUCE', 46), - (29, '*') : ('REDUCE', 46), - (29, '/') : ('REDUCE', 46), - (29, '<') : ('REDUCE', 46), - (29, '<=') : ('REDUCE', 46), - (29, '@') : ('REDUCE', 46), - (29, 'in') : ('REDUCE', 46), - (29, ';') : ('REDUCE', 46), - (29, 'loop') : ('REDUCE', 46), - (29, 'pool') : ('REDUCE', 46), - (29, ',') : ('REDUCE', 46), - (29, '.') : ('REDUCE', 46), - (29, ')') : ('REDUCE', 46), - (29, 'then') : ('REDUCE', 46), - (29, 'else') : ('REDUCE', 46), - (29, '}') : ('REDUCE', 46), - (29, 'fi') : ('REDUCE', 46), - (29, '=') : ('REDUCE', 46), - (29, '+') : ('REDUCE', 46), - (30, '@') : ('SHIFT', 37), - (30, '.') : ('SHIFT', 31), - (30, '-') : ('REDUCE', 42), - (30, 'then') : ('REDUCE', 42), - (30, 'loop') : ('REDUCE', 42), - (30, 'of') : ('REDUCE', 42), - (30, ';') : ('REDUCE', 42), - (30, '*') : ('REDUCE', 42), - (30, 'else') : ('REDUCE', 42), - (30, 'pool') : ('REDUCE', 42), - (30, '}') : ('REDUCE', 42), - (30, ',') : ('REDUCE', 42), - (30, '/') : ('REDUCE', 42), - (30, 'fi') : ('REDUCE', 42), - (30, '<') : ('REDUCE', 42), - (30, 'in') : ('REDUCE', 42), - (30, '=') : ('REDUCE', 42), - (30, '<=') : ('REDUCE', 42), - (30, '+') : ('REDUCE', 42), - (30, ')') : ('REDUCE', 42), - (31, 'id') : ('SHIFT', 32), - (32, '(') : ('SHIFT', 33), - (33, 'let') : ('SHIFT', 8), - (33, 'int') : ('SHIFT', 21), - (33, '~') : ('SHIFT', 15), - (33, 'string') : ('SHIFT', 29), - (33, 'new') : ('SHIFT', 22), - (33, ')') : ('REDUCE', 56), - (33, 'not') : ('SHIFT', 26), - (33, 'id') : ('SHIFT', 18), - (33, 'isvoid') : ('SHIFT', 34), - (33, 'while') : ('SHIFT', 20), - (33, 'false') : ('SHIFT', 28), - (33, 'case') : ('SHIFT', 25), - (33, '{') : ('SHIFT', 14), - (33, 'true') : ('SHIFT', 27), - (33, 'if') : ('SHIFT', 24), - (33, '(') : ('SHIFT', 13), - (34, 'true') : ('SHIFT', 27), - (34, 'id') : ('SHIFT', 16), - (34, 'if') : ('SHIFT', 24), - (34, '(') : ('SHIFT', 13), - (34, '~') : ('SHIFT', 15), - (34, 'new') : ('SHIFT', 22), - (34, 'false') : ('SHIFT', 28), - (34, 'int') : ('SHIFT', 21), - (34, 'string') : ('SHIFT', 29), - (34, 'not') : ('SHIFT', 26), - (34, 'isvoid') : ('SHIFT', 34), - (35, '-') : ('REDUCE', 40), - (35, 'then') : ('REDUCE', 40), - (35, 'loop') : ('REDUCE', 40), - (35, 'of') : ('REDUCE', 40), - (35, ';') : ('REDUCE', 40), - (35, '*') : ('REDUCE', 40), - (35, 'else') : ('REDUCE', 40), - (35, 'pool') : ('REDUCE', 40), - (35, '}') : ('REDUCE', 40), - (35, ',') : ('REDUCE', 40), - (35, '/') : ('REDUCE', 40), - (35, 'fi') : ('REDUCE', 40), - (35, '<') : ('REDUCE', 40), - (35, 'in') : ('REDUCE', 40), - (35, '=') : ('REDUCE', 40), - (35, '<=') : ('REDUCE', 40), - (35, '+') : ('REDUCE', 40), - (35, ')') : ('REDUCE', 40), - (36, '@') : ('SHIFT', 37), - (36, '.') : ('SHIFT', 31), - (36, '-') : ('REDUCE', 43), - (36, 'then') : ('REDUCE', 43), - (36, 'loop') : ('REDUCE', 43), - (36, 'of') : ('REDUCE', 43), - (36, ';') : ('REDUCE', 43), - (36, '*') : ('REDUCE', 43), - (36, 'else') : ('REDUCE', 43), - (36, 'pool') : ('REDUCE', 43), - (36, '}') : ('REDUCE', 43), - (36, ',') : ('REDUCE', 43), - (36, '/') : ('REDUCE', 43), - (36, 'fi') : ('REDUCE', 43), - (36, '<') : ('REDUCE', 43), - (36, 'in') : ('REDUCE', 43), - (36, '=') : ('REDUCE', 43), - (36, '<=') : ('REDUCE', 43), - (36, '+') : ('REDUCE', 43), - (36, ')') : ('REDUCE', 43), - (37, 'type') : ('SHIFT', 38), - (38, '.') : ('SHIFT', 39), - (39, 'id') : ('SHIFT', 40), - (40, '(') : ('SHIFT', 41), - (41, 'let') : ('SHIFT', 8), - (41, 'int') : ('SHIFT', 21), - (41, '~') : ('SHIFT', 15), - (41, 'string') : ('SHIFT', 29), - (41, 'new') : ('SHIFT', 22), - (41, ')') : ('REDUCE', 56), - (41, 'not') : ('SHIFT', 26), - (41, 'id') : ('SHIFT', 18), - (41, 'isvoid') : ('SHIFT', 34), - (41, 'while') : ('SHIFT', 20), - (41, 'false') : ('SHIFT', 28), - (41, 'case') : ('SHIFT', 25), - (41, '{') : ('SHIFT', 14), - (41, 'true') : ('SHIFT', 27), - (41, 'if') : ('SHIFT', 24), - (41, '(') : ('SHIFT', 13), - (42, ')') : ('SHIFT', 43), - (43, '-') : ('REDUCE', 55), - (43, 'of') : ('REDUCE', 55), - (43, '*') : ('REDUCE', 55), - (43, '/') : ('REDUCE', 55), - (43, '<') : ('REDUCE', 55), - (43, '<=') : ('REDUCE', 55), - (43, '@') : ('REDUCE', 55), - (43, 'in') : ('REDUCE', 55), - (43, ';') : ('REDUCE', 55), - (43, 'loop') : ('REDUCE', 55), - (43, 'pool') : ('REDUCE', 55), - (43, ',') : ('REDUCE', 55), - (43, '.') : ('REDUCE', 55), - (43, ')') : ('REDUCE', 55), - (43, 'then') : ('REDUCE', 55), - (43, 'else') : ('REDUCE', 55), - (43, '}') : ('REDUCE', 55), - (43, 'fi') : ('REDUCE', 55), - (43, '=') : ('REDUCE', 55), - (43, '+') : ('REDUCE', 55), - (44, '<=') : ('SHIFT', 60), - (44, 'then') : ('REDUCE', 29), - (44, 'loop') : ('REDUCE', 29), - (44, 'of') : ('REDUCE', 29), - (44, 'else') : ('REDUCE', 29), - (44, 'pool') : ('REDUCE', 29), - (44, '}') : ('REDUCE', 29), - (44, ',') : ('REDUCE', 29), - (44, 'fi') : ('REDUCE', 29), - (44, 'in') : ('REDUCE', 29), - (44, ';') : ('REDUCE', 29), - (44, ')') : ('REDUCE', 29), - (44, '<') : ('SHIFT', 58), - (44, '=') : ('SHIFT', 45), - (45, 'true') : ('SHIFT', 27), - (45, 'id') : ('SHIFT', 16), - (45, 'if') : ('SHIFT', 24), - (45, '(') : ('SHIFT', 13), - (45, '~') : ('SHIFT', 15), - (45, 'new') : ('SHIFT', 22), - (45, 'false') : ('SHIFT', 28), - (45, 'int') : ('SHIFT', 21), - (45, 'string') : ('SHIFT', 29), - (45, 'not') : ('SHIFT', 26), - (45, 'isvoid') : ('SHIFT', 34), - (46, '-') : ('SHIFT', 55), - (46, '+') : ('SHIFT', 47), - (46, 'then') : ('REDUCE', 32), - (46, 'loop') : ('REDUCE', 32), - (46, 'of') : ('REDUCE', 32), - (46, ';') : ('REDUCE', 32), - (46, 'else') : ('REDUCE', 32), - (46, 'pool') : ('REDUCE', 32), - (46, '}') : ('REDUCE', 32), - (46, ',') : ('REDUCE', 32), - (46, 'fi') : ('REDUCE', 32), - (46, '<') : ('REDUCE', 32), - (46, 'in') : ('REDUCE', 32), - (46, '=') : ('REDUCE', 32), - (46, '<=') : ('REDUCE', 32), - (46, ')') : ('REDUCE', 32), - (47, 'true') : ('SHIFT', 27), + (26, '{') : ('SHIFT', 14), + (26, 'isvoid') : ('SHIFT', 27), + (26, 'case') : ('SHIFT', 25), + (26, '~') : ('SHIFT', 15), + (26, 'false') : ('SHIFT', 29), + (26, 'if') : ('SHIFT', 24), + (27, 'string') : ('SHIFT', 30), + (27, 'id') : ('SHIFT', 16), + (27, 'new') : ('SHIFT', 22), + (27, 'isvoid') : ('SHIFT', 27), + (27, 'true') : ('SHIFT', 28), + (27, '~') : ('SHIFT', 15), + (27, 'int') : ('SHIFT', 21), + (27, 'false') : ('SHIFT', 29), + (27, '(') : ('SHIFT', 13), + (27, 'if') : ('SHIFT', 24), + (28, 'in') : ('REDUCE', 44), + (28, ';') : ('REDUCE', 44), + (28, 'loop') : ('REDUCE', 44), + (28, 'pool') : ('REDUCE', 44), + (28, ',') : ('REDUCE', 44), + (28, '.') : ('REDUCE', 44), + (28, ')') : ('REDUCE', 44), + (28, 'then') : ('REDUCE', 44), + (28, 'else') : ('REDUCE', 44), + (28, '}') : ('REDUCE', 44), + (28, 'fi') : ('REDUCE', 44), + (28, '=') : ('REDUCE', 44), + (28, '+') : ('REDUCE', 44), + (28, 'of') : ('REDUCE', 44), + (28, '-') : ('REDUCE', 44), + (28, '*') : ('REDUCE', 44), + (28, '/') : ('REDUCE', 44), + (28, '<') : ('REDUCE', 44), + (28, '<=') : ('REDUCE', 44), + (28, '@') : ('REDUCE', 44), + (29, 'in') : ('REDUCE', 45), + (29, ';') : ('REDUCE', 45), + (29, 'loop') : ('REDUCE', 45), + (29, 'pool') : ('REDUCE', 45), + (29, ',') : ('REDUCE', 45), + (29, '.') : ('REDUCE', 45), + (29, ')') : ('REDUCE', 45), + (29, 'then') : ('REDUCE', 45), + (29, 'else') : ('REDUCE', 45), + (29, '}') : ('REDUCE', 45), + (29, 'fi') : ('REDUCE', 45), + (29, '=') : ('REDUCE', 45), + (29, '+') : ('REDUCE', 45), + (29, 'of') : ('REDUCE', 45), + (29, '-') : ('REDUCE', 45), + (29, '*') : ('REDUCE', 45), + (29, '/') : ('REDUCE', 45), + (29, '<') : ('REDUCE', 45), + (29, '<=') : ('REDUCE', 45), + (29, '@') : ('REDUCE', 45), + (30, 'in') : ('REDUCE', 46), + (30, ';') : ('REDUCE', 46), + (30, 'loop') : ('REDUCE', 46), + (30, 'pool') : ('REDUCE', 46), + (30, ',') : ('REDUCE', 46), + (30, '.') : ('REDUCE', 46), + (30, ')') : ('REDUCE', 46), + (30, 'then') : ('REDUCE', 46), + (30, 'else') : ('REDUCE', 46), + (30, '}') : ('REDUCE', 46), + (30, 'fi') : ('REDUCE', 46), + (30, '=') : ('REDUCE', 46), + (30, '+') : ('REDUCE', 46), + (30, 'of') : ('REDUCE', 46), + (30, '-') : ('REDUCE', 46), + (30, '*') : ('REDUCE', 46), + (30, '/') : ('REDUCE', 46), + (30, '<') : ('REDUCE', 46), + (30, '<=') : ('REDUCE', 46), + (30, '@') : ('REDUCE', 46), + (31, 'fi') : ('REDUCE', 41), + (31, '/') : ('REDUCE', 41), + (31, '}') : ('REDUCE', 41), + (31, 'else') : ('REDUCE', 41), + (31, 'in') : ('REDUCE', 41), + (31, '<') : ('REDUCE', 41), + (31, '=') : ('REDUCE', 41), + (31, ';') : ('REDUCE', 41), + (31, '<=') : ('REDUCE', 41), + (31, '+') : ('REDUCE', 41), + (31, ')') : ('REDUCE', 41), + (31, 'of') : ('REDUCE', 41), + (31, '-') : ('REDUCE', 41), + (31, 'then') : ('REDUCE', 41), + (31, 'loop') : ('REDUCE', 41), + (31, '*') : ('REDUCE', 41), + (31, 'pool') : ('REDUCE', 41), + (31, ',') : ('REDUCE', 41), + (32, 'fi') : ('REDUCE', 43), + (32, '/') : ('REDUCE', 43), + (32, '}') : ('REDUCE', 43), + (32, 'else') : ('REDUCE', 43), + (32, 'in') : ('REDUCE', 43), + (32, '<') : ('REDUCE', 43), + (32, '=') : ('REDUCE', 43), + (32, ';') : ('REDUCE', 43), + (32, '<=') : ('REDUCE', 43), + (32, '+') : ('REDUCE', 43), + (32, ')') : ('REDUCE', 43), + (32, 'of') : ('REDUCE', 43), + (32, '-') : ('REDUCE', 43), + (32, 'then') : ('REDUCE', 43), + (32, 'loop') : ('REDUCE', 43), + (32, '*') : ('REDUCE', 43), + (32, 'pool') : ('REDUCE', 43), + (32, ',') : ('REDUCE', 43), + (32, '@') : ('SHIFT', 61), + (32, '.') : ('SHIFT', 33), + (33, 'id') : ('SHIFT', 34), + (34, '(') : ('SHIFT', 35), + (35, 'not') : ('SHIFT', 26), + (35, 'let') : ('SHIFT', 8), + (35, 'string') : ('SHIFT', 30), + (35, '~') : ('SHIFT', 15), + (35, 'while') : ('SHIFT', 20), + (35, ')') : ('REDUCE', 56), + (35, 'id') : ('SHIFT', 18), + (35, 'new') : ('SHIFT', 22), + (35, 'true') : ('SHIFT', 28), + (35, '(') : ('SHIFT', 13), + (35, 'int') : ('SHIFT', 21), + (35, '{') : ('SHIFT', 14), + (35, 'isvoid') : ('SHIFT', 27), + (35, 'case') : ('SHIFT', 25), + (35, 'false') : ('SHIFT', 29), + (35, 'if') : ('SHIFT', 24), + (36, ')') : ('SHIFT', 37), + (37, 'in') : ('REDUCE', 53), + (37, ';') : ('REDUCE', 53), + (37, 'loop') : ('REDUCE', 53), + (37, 'pool') : ('REDUCE', 53), + (37, ',') : ('REDUCE', 53), + (37, '.') : ('REDUCE', 53), + (37, ')') : ('REDUCE', 53), + (37, 'then') : ('REDUCE', 53), + (37, 'else') : ('REDUCE', 53), + (37, '}') : ('REDUCE', 53), + (37, 'fi') : ('REDUCE', 53), + (37, '=') : ('REDUCE', 53), + (37, '+') : ('REDUCE', 53), + (37, 'of') : ('REDUCE', 53), + (37, '-') : ('REDUCE', 53), + (37, '*') : ('REDUCE', 53), + (37, '/') : ('REDUCE', 53), + (37, '<') : ('REDUCE', 53), + (37, '<=') : ('REDUCE', 53), + (37, '@') : ('REDUCE', 53), + (38, '<=') : ('SHIFT', 55), + (38, 'fi') : ('REDUCE', 31), + (38, '}') : ('REDUCE', 31), + (38, 'in') : ('REDUCE', 31), + (38, ';') : ('REDUCE', 31), + (38, ')') : ('REDUCE', 31), + (38, 'of') : ('REDUCE', 31), + (38, 'then') : ('REDUCE', 31), + (38, 'loop') : ('REDUCE', 31), + (38, 'else') : ('REDUCE', 31), + (38, 'pool') : ('REDUCE', 31), + (38, ',') : ('REDUCE', 31), + (38, '=') : ('SHIFT', 39), + (38, '<') : ('SHIFT', 53), + (39, 'string') : ('SHIFT', 30), + (39, 'not') : ('SHIFT', 26), + (39, 'let') : ('SHIFT', 8), + (39, 'while') : ('SHIFT', 20), + (39, 'new') : ('SHIFT', 22), + (39, 'id') : ('SHIFT', 18), + (39, 'true') : ('SHIFT', 28), + (39, 'int') : ('SHIFT', 21), + (39, '(') : ('SHIFT', 13), + (39, '{') : ('SHIFT', 14), + (39, 'isvoid') : ('SHIFT', 27), + (39, 'case') : ('SHIFT', 25), + (39, '~') : ('SHIFT', 15), + (39, 'false') : ('SHIFT', 29), + (39, 'if') : ('SHIFT', 24), + (40, 'fi') : ('REDUCE', 30), + (40, '}') : ('REDUCE', 30), + (40, 'in') : ('REDUCE', 30), + (40, ';') : ('REDUCE', 30), + (40, ')') : ('REDUCE', 30), + (40, 'of') : ('REDUCE', 30), + (40, 'then') : ('REDUCE', 30), + (40, 'loop') : ('REDUCE', 30), + (40, 'else') : ('REDUCE', 30), + (40, 'pool') : ('REDUCE', 30), + (40, ',') : ('REDUCE', 30), + (41, '+') : ('SHIFT', 42), + (41, '-') : ('SHIFT', 50), + (41, 'fi') : ('REDUCE', 34), + (41, '}') : ('REDUCE', 34), + (41, 'in') : ('REDUCE', 34), + (41, '<') : ('REDUCE', 34), + (41, '=') : ('REDUCE', 34), + (41, ';') : ('REDUCE', 34), + (41, '<=') : ('REDUCE', 34), + (41, ')') : ('REDUCE', 34), + (41, 'of') : ('REDUCE', 34), + (41, 'then') : ('REDUCE', 34), + (41, 'loop') : ('REDUCE', 34), + (41, 'else') : ('REDUCE', 34), + (41, 'pool') : ('REDUCE', 34), + (41, ',') : ('REDUCE', 34), + (42, 'string') : ('SHIFT', 30), + (42, 'id') : ('SHIFT', 16), + (42, 'new') : ('SHIFT', 22), + (42, 'isvoid') : ('SHIFT', 27), + (42, 'true') : ('SHIFT', 28), + (42, '~') : ('SHIFT', 15), + (42, 'int') : ('SHIFT', 21), + (42, 'false') : ('SHIFT', 29), + (42, '(') : ('SHIFT', 13), + (42, 'if') : ('SHIFT', 24), + (43, '*') : ('SHIFT', 44), + (43, '/') : ('SHIFT', 47), + (43, 'fi') : ('REDUCE', 35), + (43, '}') : ('REDUCE', 35), + (43, 'in') : ('REDUCE', 35), + (43, '<') : ('REDUCE', 35), + (43, '=') : ('REDUCE', 35), + (43, ';') : ('REDUCE', 35), + (43, '<=') : ('REDUCE', 35), + (43, '+') : ('REDUCE', 35), + (43, ')') : ('REDUCE', 35), + (43, 'of') : ('REDUCE', 35), + (43, '-') : ('REDUCE', 35), + (43, 'then') : ('REDUCE', 35), + (43, 'loop') : ('REDUCE', 35), + (43, 'else') : ('REDUCE', 35), + (43, 'pool') : ('REDUCE', 35), + (43, ',') : ('REDUCE', 35), + (44, 'string') : ('SHIFT', 30), + (44, 'id') : ('SHIFT', 16), + (44, 'new') : ('SHIFT', 22), + (44, 'isvoid') : ('SHIFT', 27), + (44, 'true') : ('SHIFT', 28), + (44, '~') : ('SHIFT', 15), + (44, 'int') : ('SHIFT', 21), + (44, 'false') : ('SHIFT', 29), + (44, '(') : ('SHIFT', 13), + (44, 'if') : ('SHIFT', 24), + (45, 'fi') : ('REDUCE', 38), + (45, '/') : ('REDUCE', 38), + (45, '}') : ('REDUCE', 38), + (45, 'else') : ('REDUCE', 38), + (45, 'in') : ('REDUCE', 38), + (45, '<') : ('REDUCE', 38), + (45, '=') : ('REDUCE', 38), + (45, ';') : ('REDUCE', 38), + (45, '<=') : ('REDUCE', 38), + (45, '+') : ('REDUCE', 38), + (45, ')') : ('REDUCE', 38), + (45, 'of') : ('REDUCE', 38), + (45, '-') : ('REDUCE', 38), + (45, 'then') : ('REDUCE', 38), + (45, 'loop') : ('REDUCE', 38), + (45, '*') : ('REDUCE', 38), + (45, 'pool') : ('REDUCE', 38), + (45, ',') : ('REDUCE', 38), + (46, 'in') : ('REDUCE', 52), + (46, ';') : ('REDUCE', 52), + (46, 'loop') : ('REDUCE', 52), + (46, 'pool') : ('REDUCE', 52), + (46, ',') : ('REDUCE', 52), + (46, '.') : ('REDUCE', 52), + (46, ')') : ('REDUCE', 52), + (46, 'then') : ('REDUCE', 52), + (46, 'else') : ('REDUCE', 52), + (46, '}') : ('REDUCE', 52), + (46, 'fi') : ('REDUCE', 52), + (46, '=') : ('REDUCE', 52), + (46, '+') : ('REDUCE', 52), + (46, 'of') : ('REDUCE', 52), + (46, '-') : ('REDUCE', 52), + (46, '*') : ('REDUCE', 52), + (46, '/') : ('REDUCE', 52), + (46, '<') : ('REDUCE', 52), + (46, '<=') : ('REDUCE', 52), + (46, '@') : ('REDUCE', 52), + (47, 'string') : ('SHIFT', 30), (47, 'id') : ('SHIFT', 16), - (47, 'if') : ('SHIFT', 24), - (47, '(') : ('SHIFT', 13), - (47, '~') : ('SHIFT', 15), (47, 'new') : ('SHIFT', 22), - (47, 'false') : ('SHIFT', 28), + (47, 'isvoid') : ('SHIFT', 27), + (47, 'true') : ('SHIFT', 28), + (47, '~') : ('SHIFT', 15), (47, 'int') : ('SHIFT', 21), - (47, 'string') : ('SHIFT', 29), - (47, 'not') : ('SHIFT', 26), - (47, 'isvoid') : ('SHIFT', 34), - (48, '-') : ('REDUCE', 34), - (48, 'then') : ('REDUCE', 34), - (48, 'loop') : ('REDUCE', 34), - (48, 'of') : ('REDUCE', 34), - (48, ';') : ('REDUCE', 34), - (48, 'else') : ('REDUCE', 34), - (48, 'pool') : ('REDUCE', 34), - (48, '}') : ('REDUCE', 34), - (48, ',') : ('REDUCE', 34), - (48, 'fi') : ('REDUCE', 34), - (48, '<') : ('REDUCE', 34), - (48, 'in') : ('REDUCE', 34), - (48, '=') : ('REDUCE', 34), - (48, '<=') : ('REDUCE', 34), - (48, '+') : ('REDUCE', 34), - (48, ')') : ('REDUCE', 34), - (48, '*') : ('SHIFT', 49), - (48, '/') : ('SHIFT', 52), - (49, 'true') : ('SHIFT', 27), - (49, 'id') : ('SHIFT', 16), - (49, 'if') : ('SHIFT', 24), - (49, '(') : ('SHIFT', 13), - (49, '~') : ('SHIFT', 15), - (49, 'new') : ('SHIFT', 22), - (49, 'false') : ('SHIFT', 28), - (49, 'int') : ('SHIFT', 21), - (49, 'string') : ('SHIFT', 29), - (49, 'not') : ('SHIFT', 26), - (49, 'isvoid') : ('SHIFT', 34), - (50, '-') : ('REDUCE', 37), - (50, 'then') : ('REDUCE', 37), - (50, 'loop') : ('REDUCE', 37), - (50, 'of') : ('REDUCE', 37), - (50, ';') : ('REDUCE', 37), - (50, '*') : ('REDUCE', 37), - (50, 'else') : ('REDUCE', 37), - (50, 'pool') : ('REDUCE', 37), - (50, '}') : ('REDUCE', 37), - (50, ',') : ('REDUCE', 37), - (50, '/') : ('REDUCE', 37), - (50, 'fi') : ('REDUCE', 37), - (50, '<') : ('REDUCE', 37), - (50, 'in') : ('REDUCE', 37), - (50, '=') : ('REDUCE', 37), - (50, '<=') : ('REDUCE', 37), - (50, '+') : ('REDUCE', 37), - (50, ')') : ('REDUCE', 37), - (51, '-') : ('REDUCE', 52), - (51, 'of') : ('REDUCE', 52), - (51, '*') : ('REDUCE', 52), - (51, '/') : ('REDUCE', 52), - (51, '<') : ('REDUCE', 52), - (51, '<=') : ('REDUCE', 52), - (51, '@') : ('REDUCE', 52), - (51, 'in') : ('REDUCE', 52), - (51, ';') : ('REDUCE', 52), - (51, 'loop') : ('REDUCE', 52), - (51, 'pool') : ('REDUCE', 52), - (51, ',') : ('REDUCE', 52), - (51, '.') : ('REDUCE', 52), - (51, ')') : ('REDUCE', 52), - (51, 'then') : ('REDUCE', 52), - (51, 'else') : ('REDUCE', 52), - (51, '}') : ('REDUCE', 52), - (51, 'fi') : ('REDUCE', 52), - (51, '=') : ('REDUCE', 52), - (51, '+') : ('REDUCE', 52), - (52, 'true') : ('SHIFT', 27), - (52, 'id') : ('SHIFT', 16), - (52, 'if') : ('SHIFT', 24), - (52, '(') : ('SHIFT', 13), - (52, '~') : ('SHIFT', 15), - (52, 'new') : ('SHIFT', 22), - (52, 'false') : ('SHIFT', 28), - (52, 'int') : ('SHIFT', 21), - (52, 'string') : ('SHIFT', 29), - (52, 'not') : ('SHIFT', 26), - (52, 'isvoid') : ('SHIFT', 34), - (53, '-') : ('REDUCE', 38), - (53, 'then') : ('REDUCE', 38), - (53, 'loop') : ('REDUCE', 38), - (53, 'of') : ('REDUCE', 38), - (53, ';') : ('REDUCE', 38), - (53, '*') : ('REDUCE', 38), - (53, 'else') : ('REDUCE', 38), - (53, 'pool') : ('REDUCE', 38), - (53, '}') : ('REDUCE', 38), - (53, ',') : ('REDUCE', 38), - (53, '/') : ('REDUCE', 38), - (53, 'fi') : ('REDUCE', 38), - (53, '<') : ('REDUCE', 38), - (53, 'in') : ('REDUCE', 38), - (53, '=') : ('REDUCE', 38), - (53, '<=') : ('REDUCE', 38), - (53, '+') : ('REDUCE', 38), - (53, ')') : ('REDUCE', 38), - (54, '-') : ('REDUCE', 39), - (54, 'then') : ('REDUCE', 39), - (54, 'loop') : ('REDUCE', 39), - (54, 'of') : ('REDUCE', 39), - (54, ';') : ('REDUCE', 39), - (54, '*') : ('REDUCE', 39), - (54, 'else') : ('REDUCE', 39), - (54, 'pool') : ('REDUCE', 39), - (54, '}') : ('REDUCE', 39), - (54, ',') : ('REDUCE', 39), - (54, '/') : ('REDUCE', 39), - (54, 'fi') : ('REDUCE', 39), - (54, '<') : ('REDUCE', 39), - (54, 'in') : ('REDUCE', 39), - (54, '=') : ('REDUCE', 39), - (54, '<=') : ('REDUCE', 39), - (54, '+') : ('REDUCE', 39), - (54, ')') : ('REDUCE', 39), - (55, 'true') : ('SHIFT', 27), + (47, 'false') : ('SHIFT', 29), + (47, '(') : ('SHIFT', 13), + (47, 'if') : ('SHIFT', 24), + (48, 'fi') : ('REDUCE', 39), + (48, '/') : ('REDUCE', 39), + (48, '}') : ('REDUCE', 39), + (48, 'else') : ('REDUCE', 39), + (48, 'in') : ('REDUCE', 39), + (48, '<') : ('REDUCE', 39), + (48, '=') : ('REDUCE', 39), + (48, ';') : ('REDUCE', 39), + (48, '<=') : ('REDUCE', 39), + (48, '+') : ('REDUCE', 39), + (48, ')') : ('REDUCE', 39), + (48, 'of') : ('REDUCE', 39), + (48, '-') : ('REDUCE', 39), + (48, 'then') : ('REDUCE', 39), + (48, 'loop') : ('REDUCE', 39), + (48, '*') : ('REDUCE', 39), + (48, 'pool') : ('REDUCE', 39), + (48, ',') : ('REDUCE', 39), + (49, 'fi') : ('REDUCE', 40), + (49, '/') : ('REDUCE', 40), + (49, '}') : ('REDUCE', 40), + (49, 'else') : ('REDUCE', 40), + (49, 'in') : ('REDUCE', 40), + (49, '<') : ('REDUCE', 40), + (49, '=') : ('REDUCE', 40), + (49, ';') : ('REDUCE', 40), + (49, '<=') : ('REDUCE', 40), + (49, '+') : ('REDUCE', 40), + (49, ')') : ('REDUCE', 40), + (49, 'of') : ('REDUCE', 40), + (49, '-') : ('REDUCE', 40), + (49, 'then') : ('REDUCE', 40), + (49, 'loop') : ('REDUCE', 40), + (49, '*') : ('REDUCE', 40), + (49, 'pool') : ('REDUCE', 40), + (49, ',') : ('REDUCE', 40), + (50, 'string') : ('SHIFT', 30), + (50, 'id') : ('SHIFT', 16), + (50, 'new') : ('SHIFT', 22), + (50, 'isvoid') : ('SHIFT', 27), + (50, 'true') : ('SHIFT', 28), + (50, '~') : ('SHIFT', 15), + (50, 'int') : ('SHIFT', 21), + (50, 'false') : ('SHIFT', 29), + (50, '(') : ('SHIFT', 13), + (50, 'if') : ('SHIFT', 24), + (51, '*') : ('SHIFT', 44), + (51, 'fi') : ('REDUCE', 36), + (51, '}') : ('REDUCE', 36), + (51, 'in') : ('REDUCE', 36), + (51, '<') : ('REDUCE', 36), + (51, '=') : ('REDUCE', 36), + (51, ';') : ('REDUCE', 36), + (51, '<=') : ('REDUCE', 36), + (51, '+') : ('REDUCE', 36), + (51, ')') : ('REDUCE', 36), + (51, 'of') : ('REDUCE', 36), + (51, '-') : ('REDUCE', 36), + (51, 'then') : ('REDUCE', 36), + (51, 'loop') : ('REDUCE', 36), + (51, 'else') : ('REDUCE', 36), + (51, 'pool') : ('REDUCE', 36), + (51, ',') : ('REDUCE', 36), + (51, '/') : ('SHIFT', 47), + (52, '*') : ('SHIFT', 44), + (52, 'fi') : ('REDUCE', 37), + (52, '}') : ('REDUCE', 37), + (52, 'in') : ('REDUCE', 37), + (52, '<') : ('REDUCE', 37), + (52, '=') : ('REDUCE', 37), + (52, ';') : ('REDUCE', 37), + (52, '<=') : ('REDUCE', 37), + (52, '+') : ('REDUCE', 37), + (52, ')') : ('REDUCE', 37), + (52, 'of') : ('REDUCE', 37), + (52, '-') : ('REDUCE', 37), + (52, 'then') : ('REDUCE', 37), + (52, 'loop') : ('REDUCE', 37), + (52, 'else') : ('REDUCE', 37), + (52, 'pool') : ('REDUCE', 37), + (52, ',') : ('REDUCE', 37), + (52, '/') : ('SHIFT', 47), + (53, 'string') : ('SHIFT', 30), + (53, 'id') : ('SHIFT', 16), + (53, 'new') : ('SHIFT', 22), + (53, 'isvoid') : ('SHIFT', 27), + (53, 'true') : ('SHIFT', 28), + (53, '~') : ('SHIFT', 15), + (53, 'int') : ('SHIFT', 21), + (53, 'false') : ('SHIFT', 29), + (53, '(') : ('SHIFT', 13), + (53, 'if') : ('SHIFT', 24), + (54, '+') : ('SHIFT', 42), + (54, '-') : ('SHIFT', 50), + (54, 'fi') : ('REDUCE', 32), + (54, '}') : ('REDUCE', 32), + (54, 'in') : ('REDUCE', 32), + (54, '<') : ('REDUCE', 32), + (54, '=') : ('REDUCE', 32), + (54, ';') : ('REDUCE', 32), + (54, '<=') : ('REDUCE', 32), + (54, ')') : ('REDUCE', 32), + (54, 'of') : ('REDUCE', 32), + (54, 'then') : ('REDUCE', 32), + (54, 'loop') : ('REDUCE', 32), + (54, 'else') : ('REDUCE', 32), + (54, 'pool') : ('REDUCE', 32), + (54, ',') : ('REDUCE', 32), + (55, 'string') : ('SHIFT', 30), (55, 'id') : ('SHIFT', 16), - (55, 'if') : ('SHIFT', 24), - (55, '(') : ('SHIFT', 13), - (55, '~') : ('SHIFT', 15), (55, 'new') : ('SHIFT', 22), - (55, 'false') : ('SHIFT', 28), + (55, 'isvoid') : ('SHIFT', 27), + (55, 'true') : ('SHIFT', 28), + (55, '~') : ('SHIFT', 15), (55, 'int') : ('SHIFT', 21), - (55, 'string') : ('SHIFT', 29), - (55, 'not') : ('SHIFT', 26), - (55, 'isvoid') : ('SHIFT', 34), - (56, '-') : ('REDUCE', 35), - (56, 'then') : ('REDUCE', 35), - (56, 'loop') : ('REDUCE', 35), - (56, 'of') : ('REDUCE', 35), - (56, ';') : ('REDUCE', 35), - (56, 'else') : ('REDUCE', 35), - (56, 'pool') : ('REDUCE', 35), - (56, '}') : ('REDUCE', 35), - (56, ',') : ('REDUCE', 35), - (56, 'fi') : ('REDUCE', 35), - (56, '<') : ('REDUCE', 35), - (56, 'in') : ('REDUCE', 35), - (56, '=') : ('REDUCE', 35), - (56, '<=') : ('REDUCE', 35), - (56, '+') : ('REDUCE', 35), - (56, ')') : ('REDUCE', 35), - (56, '*') : ('SHIFT', 49), - (56, '/') : ('SHIFT', 52), - (57, '*') : ('SHIFT', 49), - (57, '/') : ('SHIFT', 52), - (57, '-') : ('REDUCE', 36), - (57, 'then') : ('REDUCE', 36), - (57, 'loop') : ('REDUCE', 36), - (57, 'of') : ('REDUCE', 36), - (57, ';') : ('REDUCE', 36), - (57, 'else') : ('REDUCE', 36), - (57, 'pool') : ('REDUCE', 36), - (57, '}') : ('REDUCE', 36), - (57, ',') : ('REDUCE', 36), - (57, 'fi') : ('REDUCE', 36), - (57, '<') : ('REDUCE', 36), - (57, 'in') : ('REDUCE', 36), - (57, '=') : ('REDUCE', 36), - (57, '<=') : ('REDUCE', 36), - (57, '+') : ('REDUCE', 36), - (57, ')') : ('REDUCE', 36), - (58, 'true') : ('SHIFT', 27), - (58, 'id') : ('SHIFT', 16), - (58, 'if') : ('SHIFT', 24), - (58, '(') : ('SHIFT', 13), + (55, 'false') : ('SHIFT', 29), + (55, '(') : ('SHIFT', 13), + (55, 'if') : ('SHIFT', 24), + (56, '+') : ('SHIFT', 42), + (56, '-') : ('SHIFT', 50), + (56, 'fi') : ('REDUCE', 33), + (56, '}') : ('REDUCE', 33), + (56, 'in') : ('REDUCE', 33), + (56, '<') : ('REDUCE', 33), + (56, '=') : ('REDUCE', 33), + (56, ';') : ('REDUCE', 33), + (56, '<=') : ('REDUCE', 33), + (56, ')') : ('REDUCE', 33), + (56, 'of') : ('REDUCE', 33), + (56, 'then') : ('REDUCE', 33), + (56, 'loop') : ('REDUCE', 33), + (56, 'else') : ('REDUCE', 33), + (56, 'pool') : ('REDUCE', 33), + (56, ',') : ('REDUCE', 33), + (57, ',') : ('SHIFT', 58), + (57, ')') : ('REDUCE', 58), + (58, 'not') : ('SHIFT', 26), + (58, 'let') : ('SHIFT', 8), + (58, 'string') : ('SHIFT', 30), (58, '~') : ('SHIFT', 15), + (58, 'while') : ('SHIFT', 20), (58, 'new') : ('SHIFT', 22), - (58, 'false') : ('SHIFT', 28), + (58, 'id') : ('SHIFT', 18), + (58, 'true') : ('SHIFT', 28), + (58, '(') : ('SHIFT', 13), (58, 'int') : ('SHIFT', 21), - (58, 'string') : ('SHIFT', 29), - (58, 'not') : ('SHIFT', 26), - (58, 'isvoid') : ('SHIFT', 34), - (59, '-') : ('SHIFT', 55), - (59, '+') : ('SHIFT', 47), - (59, 'then') : ('REDUCE', 30), - (59, 'loop') : ('REDUCE', 30), - (59, 'of') : ('REDUCE', 30), - (59, ';') : ('REDUCE', 30), - (59, 'else') : ('REDUCE', 30), - (59, 'pool') : ('REDUCE', 30), - (59, '}') : ('REDUCE', 30), - (59, ',') : ('REDUCE', 30), - (59, 'fi') : ('REDUCE', 30), - (59, '<') : ('REDUCE', 30), - (59, 'in') : ('REDUCE', 30), - (59, '=') : ('REDUCE', 30), - (59, '<=') : ('REDUCE', 30), - (59, ')') : ('REDUCE', 30), - (60, 'true') : ('SHIFT', 27), - (60, 'id') : ('SHIFT', 16), - (60, 'if') : ('SHIFT', 24), - (60, '(') : ('SHIFT', 13), - (60, '~') : ('SHIFT', 15), - (60, 'new') : ('SHIFT', 22), - (60, 'false') : ('SHIFT', 28), - (60, 'int') : ('SHIFT', 21), - (60, 'string') : ('SHIFT', 29), - (60, 'not') : ('SHIFT', 26), - (60, 'isvoid') : ('SHIFT', 34), - (61, '-') : ('SHIFT', 55), - (61, '+') : ('SHIFT', 47), - (61, 'then') : ('REDUCE', 31), - (61, 'loop') : ('REDUCE', 31), - (61, 'of') : ('REDUCE', 31), - (61, ';') : ('REDUCE', 31), - (61, 'else') : ('REDUCE', 31), - (61, 'pool') : ('REDUCE', 31), - (61, '}') : ('REDUCE', 31), - (61, ',') : ('REDUCE', 31), - (61, 'fi') : ('REDUCE', 31), - (61, '<') : ('REDUCE', 31), - (61, 'in') : ('REDUCE', 31), - (61, '=') : ('REDUCE', 31), - (61, '<=') : ('REDUCE', 31), - (61, ')') : ('REDUCE', 31), - (62, ',') : ('SHIFT', 63), - (62, ')') : ('REDUCE', 58), - (63, 'let') : ('SHIFT', 8), - (63, 'int') : ('SHIFT', 21), - (63, '~') : ('SHIFT', 15), - (63, 'string') : ('SHIFT', 29), - (63, 'not') : ('SHIFT', 26), - (63, 'id') : ('SHIFT', 18), - (63, 'isvoid') : ('SHIFT', 34), - (63, 'while') : ('SHIFT', 20), - (63, 'false') : ('SHIFT', 28), - (63, 'case') : ('SHIFT', 25), - (63, 'if') : ('SHIFT', 24), - (63, '{') : ('SHIFT', 14), - (63, 'true') : ('SHIFT', 27), - (63, 'new') : ('SHIFT', 22), - (63, '(') : ('SHIFT', 13), - (64, 'then') : ('REDUCE', 33), - (64, 'loop') : ('REDUCE', 33), - (64, 'of') : ('REDUCE', 33), - (64, '<=') : ('REDUCE', 33), - (64, 'else') : ('REDUCE', 33), - (64, 'pool') : ('REDUCE', 33), - (64, '}') : ('REDUCE', 33), - (64, ',') : ('REDUCE', 33), - (64, 'fi') : ('REDUCE', 33), - (64, '<') : ('REDUCE', 33), - (64, 'in') : ('REDUCE', 33), - (64, '=') : ('REDUCE', 33), - (64, ';') : ('REDUCE', 33), - (64, ')') : ('REDUCE', 33), - (64, '-') : ('SHIFT', 55), - (64, '+') : ('SHIFT', 47), - (65, ')') : ('REDUCE', 59), - (66, ')') : ('REDUCE', 57), - (67, ')') : ('SHIFT', 68), - (68, '-') : ('REDUCE', 53), - (68, 'of') : ('REDUCE', 53), - (68, '*') : ('REDUCE', 53), - (68, '/') : ('REDUCE', 53), - (68, '<') : ('REDUCE', 53), - (68, '<=') : ('REDUCE', 53), - (68, '@') : ('REDUCE', 53), - (68, 'in') : ('REDUCE', 53), - (68, ';') : ('REDUCE', 53), - (68, 'loop') : ('REDUCE', 53), - (68, 'pool') : ('REDUCE', 53), - (68, ',') : ('REDUCE', 53), - (68, '.') : ('REDUCE', 53), - (68, ')') : ('REDUCE', 53), - (68, 'then') : ('REDUCE', 53), - (68, 'else') : ('REDUCE', 53), - (68, '}') : ('REDUCE', 53), - (68, 'fi') : ('REDUCE', 53), - (68, '=') : ('REDUCE', 53), - (68, '+') : ('REDUCE', 53), + (58, '{') : ('SHIFT', 14), + (58, 'case') : ('SHIFT', 25), + (58, 'false') : ('SHIFT', 29), + (58, 'isvoid') : ('SHIFT', 27), + (58, 'if') : ('SHIFT', 24), + (59, ')') : ('REDUCE', 59), + (60, ')') : ('REDUCE', 57), + (61, 'type') : ('SHIFT', 62), + (62, '.') : ('SHIFT', 63), + (63, 'id') : ('SHIFT', 64), + (64, '(') : ('SHIFT', 65), + (65, 'not') : ('SHIFT', 26), + (65, 'let') : ('SHIFT', 8), + (65, 'string') : ('SHIFT', 30), + (65, '~') : ('SHIFT', 15), + (65, 'while') : ('SHIFT', 20), + (65, ')') : ('REDUCE', 56), + (65, 'id') : ('SHIFT', 18), + (65, 'new') : ('SHIFT', 22), + (65, 'true') : ('SHIFT', 28), + (65, '(') : ('SHIFT', 13), + (65, 'int') : ('SHIFT', 21), + (65, '{') : ('SHIFT', 14), + (65, 'isvoid') : ('SHIFT', 27), + (65, 'case') : ('SHIFT', 25), + (65, 'false') : ('SHIFT', 29), + (65, 'if') : ('SHIFT', 24), + (66, ')') : ('SHIFT', 67), + (67, 'in') : ('REDUCE', 55), + (67, ';') : ('REDUCE', 55), + (67, 'loop') : ('REDUCE', 55), + (67, 'pool') : ('REDUCE', 55), + (67, ',') : ('REDUCE', 55), + (67, '.') : ('REDUCE', 55), + (67, ')') : ('REDUCE', 55), + (67, 'then') : ('REDUCE', 55), + (67, 'else') : ('REDUCE', 55), + (67, '}') : ('REDUCE', 55), + (67, 'fi') : ('REDUCE', 55), + (67, '=') : ('REDUCE', 55), + (67, '+') : ('REDUCE', 55), + (67, 'of') : ('REDUCE', 55), + (67, '-') : ('REDUCE', 55), + (67, '*') : ('REDUCE', 55), + (67, '/') : ('REDUCE', 55), + (67, '<') : ('REDUCE', 55), + (67, '<=') : ('REDUCE', 55), + (67, '@') : ('REDUCE', 55), + (68, 'fi') : ('REDUCE', 29), + (68, '}') : ('REDUCE', 29), + (68, 'in') : ('REDUCE', 29), + (68, ';') : ('REDUCE', 29), + (68, ')') : ('REDUCE', 29), + (68, 'of') : ('REDUCE', 29), + (68, 'then') : ('REDUCE', 29), + (68, 'loop') : ('REDUCE', 29), + (68, 'else') : ('REDUCE', 29), + (68, 'pool') : ('REDUCE', 29), + (68, ',') : ('REDUCE', 29), (69, 'of') : ('SHIFT', 70), (70, 'id') : ('SHIFT', 71), (71, ':') : ('SHIFT', 72), (72, 'type') : ('SHIFT', 73), (73, '=>') : ('SHIFT', 74), (74, 'id') : ('SHIFT', 18), - (74, 'true') : ('SHIFT', 27), - (74, 'new') : ('SHIFT', 22), + (74, 'isvoid') : ('SHIFT', 27), + (74, 'false') : ('SHIFT', 29), (74, 'if') : ('SHIFT', 24), - (74, '(') : ('SHIFT', 13), - (74, 'let') : ('SHIFT', 8), (74, '~') : ('SHIFT', 15), + (74, 'string') : ('SHIFT', 30), + (74, '{') : ('SHIFT', 14), + (74, 'case') : ('SHIFT', 25), + (74, 'new') : ('SHIFT', 22), + (74, 'true') : ('SHIFT', 28), (74, 'int') : ('SHIFT', 21), - (74, 'string') : ('SHIFT', 29), + (74, '(') : ('SHIFT', 13), (74, 'not') : ('SHIFT', 26), + (74, 'let') : ('SHIFT', 8), (74, 'while') : ('SHIFT', 20), - (74, 'isvoid') : ('SHIFT', 34), - (74, 'case') : ('SHIFT', 25), - (74, 'false') : ('SHIFT', 28), - (74, '{') : ('SHIFT', 14), (75, ';') : ('SHIFT', 76), (76, 'id') : ('SHIFT', 71), (76, 'esac') : ('REDUCE', 27), (77, 'esac') : ('REDUCE', 28), (78, 'esac') : ('SHIFT', 79), + (79, 'fi') : ('REDUCE', 26), + (79, '}') : ('REDUCE', 26), + (79, 'in') : ('REDUCE', 26), + (79, ';') : ('REDUCE', 26), + (79, ')') : ('REDUCE', 26), + (79, 'of') : ('REDUCE', 26), (79, 'then') : ('REDUCE', 26), (79, 'loop') : ('REDUCE', 26), - (79, 'of') : ('REDUCE', 26), (79, 'else') : ('REDUCE', 26), (79, 'pool') : ('REDUCE', 26), - (79, '}') : ('REDUCE', 26), (79, ',') : ('REDUCE', 26), - (79, 'fi') : ('REDUCE', 26), - (79, 'in') : ('REDUCE', 26), - (79, ';') : ('REDUCE', 26), - (79, ')') : ('REDUCE', 26), (80, 'then') : ('SHIFT', 81), - (81, 'id') : ('SHIFT', 18), - (81, 'false') : ('SHIFT', 28), - (81, 'while') : ('SHIFT', 20), + (81, 'isvoid') : ('SHIFT', 27), + (81, 'false') : ('SHIFT', 29), (81, 'case') : ('SHIFT', 25), - (81, '~') : ('SHIFT', 15), - (81, '{') : ('SHIFT', 14), - (81, 'true') : ('SHIFT', 27), (81, 'if') : ('SHIFT', 24), - (81, '(') : ('SHIFT', 13), - (81, 'new') : ('SHIFT', 22), + (81, '~') : ('SHIFT', 15), + (81, 'string') : ('SHIFT', 30), (81, 'not') : ('SHIFT', 26), - (81, 'int') : ('SHIFT', 21), - (81, 'string') : ('SHIFT', 29), + (81, 'new') : ('SHIFT', 22), + (81, 'id') : ('SHIFT', 18), (81, 'let') : ('SHIFT', 8), - (81, 'isvoid') : ('SHIFT', 34), + (81, 'while') : ('SHIFT', 20), + (81, 'true') : ('SHIFT', 28), + (81, 'int') : ('SHIFT', 21), + (81, '(') : ('SHIFT', 13), + (81, '{') : ('SHIFT', 14), (82, 'else') : ('SHIFT', 83), (83, 'while') : ('SHIFT', 20), (83, 'id') : ('SHIFT', 18), - (83, 'case') : ('SHIFT', 25), + (83, 'new') : ('SHIFT', 22), + (83, 'true') : ('SHIFT', 28), + (83, '(') : ('SHIFT', 13), + (83, 'int') : ('SHIFT', 21), (83, '{') : ('SHIFT', 14), - (83, 'false') : ('SHIFT', 28), + (83, 'isvoid') : ('SHIFT', 27), + (83, 'case') : ('SHIFT', 25), (83, '~') : ('SHIFT', 15), - (83, 'true') : ('SHIFT', 27), - (83, 'let') : ('SHIFT', 8), - (83, 'new') : ('SHIFT', 22), + (83, 'false') : ('SHIFT', 29), (83, 'if') : ('SHIFT', 24), - (83, '(') : ('SHIFT', 13), + (83, 'string') : ('SHIFT', 30), (83, 'not') : ('SHIFT', 26), - (83, 'isvoid') : ('SHIFT', 34), - (83, 'int') : ('SHIFT', 21), - (83, 'string') : ('SHIFT', 29), + (83, 'let') : ('SHIFT', 8), (84, 'fi') : ('SHIFT', 85), - (85, '-') : ('REDUCE', 50), - (85, 'of') : ('REDUCE', 50), - (85, '*') : ('REDUCE', 50), - (85, '/') : ('REDUCE', 50), - (85, '<') : ('REDUCE', 50), - (85, '<=') : ('REDUCE', 50), - (85, '@') : ('REDUCE', 50), (85, 'in') : ('REDUCE', 50), (85, ';') : ('REDUCE', 50), (85, 'loop') : ('REDUCE', 50), @@ -877,53 +859,53 @@ def __init__(self, G): (85, 'fi') : ('REDUCE', 50), (85, '=') : ('REDUCE', 50), (85, '+') : ('REDUCE', 50), + (85, 'of') : ('REDUCE', 50), + (85, '-') : ('REDUCE', 50), + (85, '*') : ('REDUCE', 50), + (85, '/') : ('REDUCE', 50), + (85, '<') : ('REDUCE', 50), + (85, '<=') : ('REDUCE', 50), + (85, '@') : ('REDUCE', 50), (86, 'loop') : ('SHIFT', 87), - (87, 'id') : ('SHIFT', 18), - (87, 'new') : ('SHIFT', 22), - (87, 'if') : ('SHIFT', 24), + (87, 'true') : ('SHIFT', 28), + (87, 'int') : ('SHIFT', 21), (87, '(') : ('SHIFT', 13), + (87, 'not') : ('SHIFT', 26), (87, 'let') : ('SHIFT', 8), - (87, 'int') : ('SHIFT', 21), - (87, 'string') : ('SHIFT', 29), - (87, '~') : ('SHIFT', 15), + (87, 'id') : ('SHIFT', 18), (87, 'while') : ('SHIFT', 20), - (87, 'false') : ('SHIFT', 28), - (87, 'case') : ('SHIFT', 25), - (87, 'not') : ('SHIFT', 26), - (87, 'isvoid') : ('SHIFT', 34), + (87, 'false') : ('SHIFT', 29), + (87, 'isvoid') : ('SHIFT', 27), + (87, 'if') : ('SHIFT', 24), + (87, '~') : ('SHIFT', 15), + (87, 'string') : ('SHIFT', 30), + (87, 'new') : ('SHIFT', 22), (87, '{') : ('SHIFT', 14), - (87, 'true') : ('SHIFT', 27), + (87, 'case') : ('SHIFT', 25), (88, 'pool') : ('SHIFT', 89), + (89, 'fi') : ('REDUCE', 17), + (89, '}') : ('REDUCE', 17), + (89, 'in') : ('REDUCE', 17), + (89, ';') : ('REDUCE', 17), + (89, ')') : ('REDUCE', 17), + (89, 'of') : ('REDUCE', 17), (89, 'then') : ('REDUCE', 17), (89, 'loop') : ('REDUCE', 17), - (89, 'of') : ('REDUCE', 17), (89, 'else') : ('REDUCE', 17), (89, 'pool') : ('REDUCE', 17), - (89, '}') : ('REDUCE', 17), (89, ',') : ('REDUCE', 17), - (89, 'fi') : ('REDUCE', 17), - (89, 'in') : ('REDUCE', 17), - (89, ';') : ('REDUCE', 17), - (89, ')') : ('REDUCE', 17), + (90, 'fi') : ('REDUCE', 16), + (90, '}') : ('REDUCE', 16), + (90, 'in') : ('REDUCE', 16), + (90, ';') : ('REDUCE', 16), + (90, ')') : ('REDUCE', 16), + (90, 'of') : ('REDUCE', 16), (90, 'then') : ('REDUCE', 16), (90, 'loop') : ('REDUCE', 16), - (90, 'of') : ('REDUCE', 16), (90, 'else') : ('REDUCE', 16), (90, 'pool') : ('REDUCE', 16), - (90, '}') : ('REDUCE', 16), (90, ',') : ('REDUCE', 16), - (90, 'fi') : ('REDUCE', 16), - (90, 'in') : ('REDUCE', 16), - (90, ';') : ('REDUCE', 16), - (90, ')') : ('REDUCE', 16), (91, ')') : ('SHIFT', 92), - (92, '-') : ('REDUCE', 54), - (92, 'of') : ('REDUCE', 54), - (92, '*') : ('REDUCE', 54), - (92, '/') : ('REDUCE', 54), - (92, '<') : ('REDUCE', 54), - (92, '<=') : ('REDUCE', 54), - (92, '@') : ('REDUCE', 54), (92, 'in') : ('REDUCE', 54), (92, ';') : ('REDUCE', 54), (92, 'loop') : ('REDUCE', 54), @@ -937,62 +919,62 @@ def __init__(self, G): (92, 'fi') : ('REDUCE', 54), (92, '=') : ('REDUCE', 54), (92, '+') : ('REDUCE', 54), - (93, '-') : ('REDUCE', 41), - (93, 'then') : ('REDUCE', 41), - (93, 'loop') : ('REDUCE', 41), - (93, 'of') : ('REDUCE', 41), - (93, ';') : ('REDUCE', 41), - (93, '*') : ('REDUCE', 41), - (93, 'else') : ('REDUCE', 41), - (93, 'pool') : ('REDUCE', 41), - (93, '}') : ('REDUCE', 41), - (93, ',') : ('REDUCE', 41), - (93, '/') : ('REDUCE', 41), - (93, 'fi') : ('REDUCE', 41), - (93, '<') : ('REDUCE', 41), - (93, 'in') : ('REDUCE', 41), - (93, '=') : ('REDUCE', 41), - (93, '<=') : ('REDUCE', 41), - (93, '+') : ('REDUCE', 41), - (93, ')') : ('REDUCE', 41), + (92, 'of') : ('REDUCE', 54), + (92, '-') : ('REDUCE', 54), + (92, '*') : ('REDUCE', 54), + (92, '/') : ('REDUCE', 54), + (92, '<') : ('REDUCE', 54), + (92, '<=') : ('REDUCE', 54), + (92, '@') : ('REDUCE', 54), + (93, 'fi') : ('REDUCE', 42), + (93, '/') : ('REDUCE', 42), + (93, '}') : ('REDUCE', 42), + (93, 'else') : ('REDUCE', 42), + (93, 'in') : ('REDUCE', 42), + (93, '<') : ('REDUCE', 42), + (93, '=') : ('REDUCE', 42), + (93, ';') : ('REDUCE', 42), + (93, '<=') : ('REDUCE', 42), + (93, '+') : ('REDUCE', 42), + (93, ')') : ('REDUCE', 42), + (93, 'of') : ('REDUCE', 42), + (93, '-') : ('REDUCE', 42), + (93, 'then') : ('REDUCE', 42), + (93, 'loop') : ('REDUCE', 42), + (93, '*') : ('REDUCE', 42), + (93, 'pool') : ('REDUCE', 42), + (93, ',') : ('REDUCE', 42), (94, '}') : ('SHIFT', 95), + (95, 'fi') : ('REDUCE', 18), + (95, '}') : ('REDUCE', 18), + (95, 'in') : ('REDUCE', 18), + (95, ';') : ('REDUCE', 18), + (95, ')') : ('REDUCE', 18), + (95, 'of') : ('REDUCE', 18), (95, 'then') : ('REDUCE', 18), (95, 'loop') : ('REDUCE', 18), - (95, 'of') : ('REDUCE', 18), (95, 'else') : ('REDUCE', 18), (95, 'pool') : ('REDUCE', 18), - (95, '}') : ('REDUCE', 18), (95, ',') : ('REDUCE', 18), - (95, 'fi') : ('REDUCE', 18), - (95, 'in') : ('REDUCE', 18), - (95, ';') : ('REDUCE', 18), - (95, ')') : ('REDUCE', 18), (96, ';') : ('SHIFT', 97), (97, 'id') : ('SHIFT', 18), - (97, 'true') : ('SHIFT', 27), - (97, 'new') : ('SHIFT', 22), + (97, 'isvoid') : ('SHIFT', 27), + (97, 'false') : ('SHIFT', 29), (97, 'if') : ('SHIFT', 24), - (97, '}') : ('REDUCE', 19), - (97, '(') : ('SHIFT', 13), - (97, 'let') : ('SHIFT', 8), (97, '~') : ('SHIFT', 15), + (97, 'string') : ('SHIFT', 30), + (97, '{') : ('SHIFT', 14), + (97, 'case') : ('SHIFT', 25), + (97, 'new') : ('SHIFT', 22), + (97, '}') : ('REDUCE', 19), + (97, 'true') : ('SHIFT', 28), (97, 'int') : ('SHIFT', 21), - (97, 'string') : ('SHIFT', 29), + (97, '(') : ('SHIFT', 13), (97, 'not') : ('SHIFT', 26), + (97, 'let') : ('SHIFT', 8), (97, 'while') : ('SHIFT', 20), - (97, 'isvoid') : ('SHIFT', 34), - (97, 'case') : ('SHIFT', 25), - (97, 'false') : ('SHIFT', 28), - (97, '{') : ('SHIFT', 14), (98, '}') : ('REDUCE', 20), (99, ')') : ('SHIFT', 100), - (100, '-') : ('REDUCE', 51), - (100, 'of') : ('REDUCE', 51), - (100, '*') : ('REDUCE', 51), - (100, '/') : ('REDUCE', 51), - (100, '<') : ('REDUCE', 51), - (100, '<=') : ('REDUCE', 51), - (100, '@') : ('REDUCE', 51), (100, 'in') : ('REDUCE', 51), (100, ';') : ('REDUCE', 51), (100, 'loop') : ('REDUCE', 51), @@ -1006,6 +988,13 @@ def __init__(self, G): (100, 'fi') : ('REDUCE', 51), (100, '=') : ('REDUCE', 51), (100, '+') : ('REDUCE', 51), + (100, 'of') : ('REDUCE', 51), + (100, '-') : ('REDUCE', 51), + (100, '*') : ('REDUCE', 51), + (100, '/') : ('REDUCE', 51), + (100, '<') : ('REDUCE', 51), + (100, '<=') : ('REDUCE', 51), + (100, '@') : ('REDUCE', 51), (101, 'in') : ('REDUCE', 23), (101, ',') : ('SHIFT', 102), (102, 'id') : ('SHIFT', 9), @@ -1013,58 +1002,58 @@ def __init__(self, G): (104, 'id') : ('SHIFT', 9), (105, 'in') : ('REDUCE', 24), (106, 'in') : ('SHIFT', 107), - (107, 'true') : ('SHIFT', 27), - (107, 'if') : ('SHIFT', 24), - (107, 'id') : ('SHIFT', 18), - (107, '(') : ('SHIFT', 13), - (107, '~') : ('SHIFT', 15), - (107, 'new') : ('SHIFT', 22), - (107, 'let') : ('SHIFT', 8), - (107, 'int') : ('SHIFT', 21), - (107, 'string') : ('SHIFT', 29), + (107, 'string') : ('SHIFT', 30), (107, 'not') : ('SHIFT', 26), - (107, 'isvoid') : ('SHIFT', 34), + (107, 'let') : ('SHIFT', 8), (107, 'while') : ('SHIFT', 20), - (107, 'case') : ('SHIFT', 25), - (107, 'false') : ('SHIFT', 28), + (107, 'new') : ('SHIFT', 22), + (107, 'id') : ('SHIFT', 18), + (107, 'true') : ('SHIFT', 28), + (107, 'int') : ('SHIFT', 21), + (107, '(') : ('SHIFT', 13), (107, '{') : ('SHIFT', 14), + (107, 'isvoid') : ('SHIFT', 27), + (107, 'case') : ('SHIFT', 25), + (107, '~') : ('SHIFT', 15), + (107, 'false') : ('SHIFT', 29), + (107, 'if') : ('SHIFT', 24), + (108, 'fi') : ('REDUCE', 21), + (108, '}') : ('REDUCE', 21), + (108, 'in') : ('REDUCE', 21), + (108, ';') : ('REDUCE', 21), + (108, ')') : ('REDUCE', 21), + (108, 'of') : ('REDUCE', 21), (108, 'then') : ('REDUCE', 21), (108, 'loop') : ('REDUCE', 21), - (108, 'of') : ('REDUCE', 21), (108, 'else') : ('REDUCE', 21), (108, 'pool') : ('REDUCE', 21), - (108, '}') : ('REDUCE', 21), (108, ',') : ('REDUCE', 21), - (108, 'fi') : ('REDUCE', 21), - (108, 'in') : ('REDUCE', 21), - (108, ';') : ('REDUCE', 21), - (108, ')') : ('REDUCE', 21), (109, ';') : ('REDUCE', 9), - (110, 'id') : ('SHIFT', 111), (110, ')') : ('REDUCE', 11), + (110, 'id') : ('SHIFT', 111), (111, ':') : ('SHIFT', 112), (112, 'type') : ('SHIFT', 113), - (113, ',') : ('REDUCE', 15), (113, ')') : ('REDUCE', 15), + (113, ',') : ('REDUCE', 15), (114, ')') : ('SHIFT', 115), (115, ':') : ('SHIFT', 116), (116, 'type') : ('SHIFT', 117), (117, '{') : ('SHIFT', 118), - (118, 'let') : ('SHIFT', 8), + (118, 'id') : ('SHIFT', 18), (118, 'new') : ('SHIFT', 22), - (118, 'if') : ('SHIFT', 24), + (118, 'true') : ('SHIFT', 28), + (118, 'int') : ('SHIFT', 21), (118, '(') : ('SHIFT', 13), + (118, 'isvoid') : ('SHIFT', 27), (118, '~') : ('SHIFT', 15), - (118, 'int') : ('SHIFT', 21), - (118, 'string') : ('SHIFT', 29), + (118, '{') : ('SHIFT', 14), + (118, 'case') : ('SHIFT', 25), + (118, 'false') : ('SHIFT', 29), + (118, 'if') : ('SHIFT', 24), (118, 'not') : ('SHIFT', 26), + (118, 'let') : ('SHIFT', 8), + (118, 'string') : ('SHIFT', 30), (118, 'while') : ('SHIFT', 20), - (118, 'id') : ('SHIFT', 18), - (118, 'isvoid') : ('SHIFT', 34), - (118, 'case') : ('SHIFT', 25), - (118, 'false') : ('SHIFT', 28), - (118, '{') : ('SHIFT', 14), - (118, 'true') : ('SHIFT', 27), (119, '}') : ('SHIFT', 120), (120, ';') : ('REDUCE', 10), (121, ',') : ('SHIFT', 122), @@ -1090,220 +1079,224 @@ def __init__(self, G): (137, ';') : ('REDUCE', 4), (138, '$') : ('REDUCE', 0), (139, ';') : ('SHIFT', 140), - (140, '$') : ('REDUCE', 1), (140, 'class') : ('SHIFT', 1), + (140, '$') : ('REDUCE', 1), (141, '$') : ('REDUCE', 2), (142, '$') : ('OK', None) } - - - self.goto = { - (0, '') : 139, - (0, '') : 142, (0, '') : 138, + (0, '') : 142, + (0, '') : 139, (3, '') : 130, (3, '') : 127, (3, '') : 125, - (7, '') : 36, - (7, '') : 57, - (7, '') : 44, - (7, '') : 54, - (7, '') : 64, + (7, '') : 38, + (7, '') : 49, + (7, '') : 52, + (7, '') : 41, (7, '') : 109, - (7, '') : 51, + (7, '') : 46, + (7, '') : 32, (8, '') : 106, + (12, '') : 38, (12, '') : 101, - (12, '') : 57, - (12, '') : 54, - (12, '') : 44, - (12, '') : 51, - (12, '') : 36, - (12, '') : 64, - (13, '') : 64, - (13, '') : 36, - (13, '') : 51, - (13, '') : 57, - (13, '') : 44, - (13, '') : 54, + (12, '') : 32, + (12, '') : 41, + (12, '') : 46, + (12, '') : 49, + (12, '') : 52, + (13, '') : 38, (13, '') : 99, - (14, '') : 96, - (14, '') : 36, - (14, '') : 57, + (13, '') : 49, + (13, '') : 41, + (13, '') : 52, + (13, '') : 46, + (13, '') : 32, + (14, '') : 38, + (14, '') : 49, (14, '') : 94, - (14, '') : 44, - (14, '') : 54, - (14, '') : 64, - (14, '') : 51, - (15, '') : 36, + (14, '') : 52, + (14, '') : 41, + (14, '') : 46, + (14, '') : 96, + (14, '') : 32, + (15, '') : 32, + (15, '') : 46, (15, '') : 93, - (15, '') : 51, + (17, '') : 41, + (17, '') : 52, + (17, '') : 46, + (17, '') : 38, + (17, '') : 57, + (17, '') : 60, + (17, '') : 32, (17, '') : 91, - (17, '') : 36, - (17, '') : 64, - (17, '') : 62, - (17, '') : 66, - (17, '') : 57, - (17, '') : 54, - (17, '') : 44, - (17, '') : 51, - (19, '') : 36, + (17, '') : 49, + (19, '') : 41, + (19, '') : 52, + (19, '') : 46, + (19, '') : 38, + (19, '') : 32, (19, '') : 90, - (19, '') : 64, - (19, '') : 57, - (19, '') : 54, - (19, '') : 44, - (19, '') : 51, - (20, '') : 64, - (20, '') : 51, + (19, '') : 49, + (20, '') : 38, + (20, '') : 32, + (20, '') : 49, + (20, '') : 41, + (20, '') : 52, + (20, '') : 46, (20, '') : 86, - (20, '') : 36, - (20, '') : 44, - (20, '') : 57, - (20, '') : 54, - (24, '') : 57, - (24, '') : 44, - (24, '') : 54, - (24, '') : 64, - (24, '') : 36, + (24, '') : 41, + (24, '') : 32, + (24, '') : 38, (24, '') : 80, - (24, '') : 51, - (25, '') : 36, + (24, '') : 49, + (24, '') : 52, + (24, '') : 46, + (25, '') : 52, + (25, '') : 46, (25, '') : 69, - (25, '') : 64, - (25, '') : 57, - (25, '') : 44, - (25, '') : 51, - (25, '') : 54, - (26, '') : 51, - (26, '') : 30, - (33, '') : 67, - (33, '') : 36, - (33, '') : 64, - (33, '') : 62, - (33, '') : 66, - (33, '') : 57, - (33, '') : 54, - (33, '') : 44, - (33, '') : 51, - (34, '') : 36, - (34, '') : 51, - (34, '') : 35, - (41, '') : 36, - (41, '') : 64, - (41, '') : 62, - (41, '') : 66, - (41, '') : 57, - (41, '') : 54, - (41, '') : 44, - (41, '') : 51, - (41, '') : 42, - (45, '') : 36, - (45, '') : 46, - (45, '') : 57, - (45, '') : 54, - (45, '') : 51, - (47, '') : 36, - (47, '') : 48, - (47, '') : 54, - (47, '') : 51, - (49, '') : 36, - (49, '') : 51, - (49, '') : 50, - (52, '') : 36, - (52, '') : 53, - (52, '') : 51, - (55, '') : 36, - (55, '') : 56, - (55, '') : 54, - (55, '') : 51, - (58, '') : 36, - (58, '') : 59, - (58, '') : 57, - (58, '') : 54, - (58, '') : 51, - (60, '') : 36, - (60, '') : 61, - (60, '') : 57, - (60, '') : 54, - (60, '') : 51, - (63, '') : 36, - (63, '') : 64, - (63, '') : 62, - (63, '') : 57, - (63, '') : 54, - (63, '') : 65, - (63, '') : 44, - (63, '') : 51, + (25, '') : 38, + (25, '') : 41, + (25, '') : 32, + (25, '') : 49, + (26, '') : 41, + (26, '') : 52, + (26, '') : 46, + (26, '') : 38, + (26, '') : 32, + (26, '') : 68, + (26, '') : 49, + (27, '') : 32, + (27, '') : 46, + (27, '') : 31, + (35, '') : 41, + (35, '') : 52, + (35, '') : 46, + (35, '') : 38, + (35, '') : 57, + (35, '') : 60, + (35, '') : 32, + (35, '') : 36, + (35, '') : 49, + (39, '') : 41, + (39, '') : 52, + (39, '') : 40, + (39, '') : 46, + (39, '') : 38, + (39, '') : 32, + (39, '') : 49, + (42, '') : 32, + (42, '') : 43, + (42, '') : 46, + (42, '') : 49, + (44, '') : 32, + (44, '') : 45, + (44, '') : 46, + (47, '') : 32, + (47, '') : 48, + (47, '') : 46, + (50, '') : 32, + (50, '') : 51, + (50, '') : 46, + (50, '') : 49, + (53, '') : 54, + (53, '') : 32, + (53, '') : 52, + (53, '') : 46, + (53, '') : 49, + (55, '') : 56, + (55, '') : 32, + (55, '') : 52, + (55, '') : 46, + (55, '') : 49, + (58, '') : 41, + (58, '') : 52, + (58, '') : 46, + (58, '') : 38, + (58, '') : 57, + (58, '') : 32, + (58, '') : 59, + (58, '') : 49, + (65, '') : 41, + (65, '') : 52, + (65, '') : 46, + (65, '') : 38, + (65, '') : 57, + (65, '') : 60, + (65, '') : 32, + (65, '') : 66, + (65, '') : 49, (70, '') : 78, - (74, '') : 36, - (74, '') : 57, - (74, '') : 44, + (74, '') : 38, (74, '') : 75, - (74, '') : 54, - (74, '') : 64, - (74, '') : 51, + (74, '') : 49, + (74, '') : 52, + (74, '') : 41, + (74, '') : 46, + (74, '') : 32, (76, '') : 77, - (81, '') : 44, - (81, '') : 64, - (81, '') : 36, - (81, '') : 51, - (81, '') : 57, + (81, '') : 52, + (81, '') : 41, + (81, '') : 46, + (81, '') : 38, + (81, '') : 32, (81, '') : 82, - (81, '') : 54, - (83, '') : 44, - (83, '') : 36, - (83, '') : 64, - (83, '') : 57, + (81, '') : 49, + (83, '') : 38, + (83, '') : 32, + (83, '') : 41, + (83, '') : 49, + (83, '') : 52, (83, '') : 84, - (83, '') : 51, - (83, '') : 54, + (83, '') : 46, + (87, '') : 41, (87, '') : 88, - (87, '') : 36, - (87, '') : 64, - (87, '') : 44, - (87, '') : 57, - (87, '') : 54, - (87, '') : 51, + (87, '') : 32, + (87, '') : 38, + (87, '') : 52, + (87, '') : 49, + (87, '') : 46, + (97, '') : 38, + (97, '') : 49, + (97, '') : 52, + (97, '') : 41, + (97, '') : 46, (97, '') : 96, (97, '') : 98, - (97, '') : 36, - (97, '') : 57, - (97, '') : 44, - (97, '') : 54, - (97, '') : 64, - (97, '') : 51, + (97, '') : 32, (102, '') : 103, (104, '') : 105, - (107, '') : 36, - (107, '') : 64, - (107, '') : 57, - (107, '') : 54, - (107, '') : 44, + (107, '') : 41, + (107, '') : 52, + (107, '') : 46, + (107, '') : 38, + (107, '') : 32, (107, '') : 108, - (107, '') : 51, - (110, '') : 124, + (107, '') : 49, (110, '') : 121, (110, '') : 114, - (118, '') : 36, - (118, '') : 64, - (118, '') : 57, - (118, '') : 44, - (118, '') : 54, + (110, '') : 124, + (118, '') : 52, + (118, '') : 38, + (118, '') : 49, + (118, '') : 32, + (118, '') : 41, (118, '') : 119, - (118, '') : 51, + (118, '') : 46, (122, '') : 121, (122, '') : 123, - (128, '') : 130, (128, '') : 129, + (128, '') : 130, (128, '') : 127, (131, '') : 130, (131, '') : 132, (131, '') : 127, (135, '') : 130, - (135, '') : 136, (135, '') : 127, + (135, '') : 136, (140, '') : 139, (140, '') : 141 } diff --git a/src/utils/semantic_check/type_checker.py b/src/utils/semantic_check/type_checker.py index 9dec5bd63..4c28beb34 100644 --- a/src/utils/semantic_check/type_checker.py +++ b/src/utils/semantic_check/type_checker.py @@ -6,7 +6,8 @@ MAIN_METHOD_DONT_EXISTS = '(%s, %s) - TypeError: Main class must have a method main()' MAIN_METHOD_DONT_HAVE_PARAMS = '(%s, %s) - TypeError: main method must not have params' -SELF_ERROR = '(%s, %s) - SemanticError: \'self\' cannot be the name of an attribute.' +SELF_ERROR_ATTR = '(%s, %s) - SemanticError: \'self\' cannot be the name of an attribute.' +SELF_ERROR_LET = '(%s, %s) - SemanticError: \'self\' cannot be bound in a \'let\' expression.' SELF_IS_READONLY = '(%s, %s) - TypeError: Variable "self" is read-only.' SELF_TYPE_ERROR = '(%s, %s) - TypeError: SELF_TYPE cannot be used as a parameter type in method %s' SELF_TYPE_IN_DISPATCH = '(%s, %s) - TypeError: SELF_TYPE cannot be used as a type of a dispatch' @@ -17,16 +18,20 @@ INCOMPATIBLE_TYPES_METH = '(%s, %s) - TypeError: Inferred return type %s of method %s does not conform to declared return type %s.' INCOMPATIBLE_TYPES_IF = '(%s, %s) - TypeError: Predicate of \'%s\' does not have type %s.' INCOMPATIBLE_TYPES_LET = '(%s, %s) - TypeError: Inferred type %s of initialization of %s does not conform to identifier\'s declared type %s.' +INCOMPATIBLE_TYPES_CALL = '(%s, %s) - TypeError: Expression type %s does not conform to declared static dispatch type %s.' INCOMPATIBLE_TYPES = '(%s, %s) - TypeError: Cannot convert %s into %s.' + WRONG_SIGNATURE = '(%s, %s) - SemanticError: Incompatible number of formal parameters in redefined method %s.' LOCAL_ALREADY_DEFINED = '(%s, %s) - SemanticError: Variable %s is already defined in method %s.' INVALID_OPERATION = '(%s, %s) - TypeError: non-Int arguments: %s %s %s' VARIABLE_NOT_DEFINED = '(%s, %s) - NameError: Undeclared identifier %s.' -INHERIT_ERROR = '(%s, %s) - SemanticError: Class %s cannot inherit from class %s because they form a cycle.' +INHERIT_ERROR = '(%s, %s) - SemanticError: Class %s, or an ancestor of %s, is involved in an inheritance cycle.' METHOD_PARAMETERS = '(%s, %s) - TypeError: Method %s defined in %s receive %d parameters' DUPLICATE_BRANCH = '(%s, %s) - SemanticError: Duplicate branch %s in case statement.' UNDEFINED_TYPE_BRANCH = '(%s, %s) - TypeError: Class %s of case branch is undefined.' +UNDEFINED_TYPE_NEW = '(%s, %s) - TypeError: \'new\' used with undefined class %s.' +UNDEFINED_METHOD = '(%s, %s) - AttributeError: Dispatch to undefined method %s. ' @@ -79,7 +84,7 @@ def visit(self, node, scope): while current_parent != self.context.get_type('Object') and current_parent != None: if current_parent == self.current_type: - self.errors.append(INHERIT_ERROR % (node.line, node.column, self.current_type.name, self.current_type.parent.name)) + self.errors.append(INHERIT_ERROR % (self.current_type.parent.line, self.current_type.parent.column, self.current_type.parent.name, self.current_type.parent.name)) self.current_type.parent = ErrorType() break @@ -103,7 +108,7 @@ def visit(self, node, scope): attr_type = self.context.get_type(node.type) if node.type != 'SELF_TYPE' else self.current_type if node.id == 'self': - self.errors.append(SELF_ERROR % (node.line, node.column)) + self.errors.append(SELF_ERROR_ATTR % (node.line, node.column)) if node.expr: type_expr = self.visit(node.expr, scope.create_child()) @@ -197,20 +202,20 @@ def visit(self, node, scope): else: try: - typex = self.context.get_type(node.type) + typex = self.context.get_type(node.type.lex) except SemanticError as se: self.errors.append(se.text) typex = ErrorType() if not obj_type.conforms_to(typex): - self.errors.append(INCOMPATIBLE_TYPES % (node.line, node.column, obj_type.name, typex.name)) + self.errors.append(INCOMPATIBLE_TYPES_CALL % (node.line, node.column, obj_type.name, typex.name)) obj_type = typex try: meth = obj_type.get_method(node.id) except SemanticError as se: - if se.text: self.errors.append(se.text) + if se.text: self.errors.append(UNDEFINED_METHOD % (node.line, node.column, node.id)) for arg in node.args: self.visit(arg, scope) return ErrorType() @@ -270,6 +275,9 @@ def visit(self, node, scope): id_type = ErrorType() self.errors.append(se.text) + if idx == 'self': + self.errors.append(SELF_ERROR_LET % (node.line, node.column)) + if scope.is_local(idx): scope = scope.create_child() scope.define_variable(idx, id_type) @@ -361,7 +369,7 @@ def visit(self, node, scope): try: return self.context.get_type(node.lex) except SemanticError as se: - self.errors.append(se.text) + self.errors.append(UNDEFINED_TYPE_NEW % (node.line, node.column, node.lex)) return ErrorType() diff --git a/src/utils/semantic_check/type_collector.py b/src/utils/semantic_check/type_collector.py index dc160530f..18e247a3e 100644 --- a/src/utils/semantic_check/type_collector.py +++ b/src/utils/semantic_check/type_collector.py @@ -56,7 +56,9 @@ def visit(self,node): if node.id in ["Object", "Int", "String", "Bool", "IO"]: self.errors.append(NOT_REDEFINE_BASIC_TYPES % (node.line, node.column, node.id)) node.id = 'error_type' - self.context.create_type(node.id) + typex = self.context.create_type(node.id) + typex.line = node.line + typex.column = node.column except SemanticError as se: self.errors.append(NOT_REDEFINE_CLASSES % (node.classt_line, node.classt_column)) return \ No newline at end of file From 99b575a8ae5dd68ef04329b122a2d5fa98e526f6 Mon Sep 17 00:00:00 2001 From: Ale Date: Wed, 16 Feb 2022 14:55:14 -0800 Subject: [PATCH 39/83] darian is anormal --- src/main.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/main.py b/src/main.py index 3714e9728..ec1bd6b90 100644 --- a/src/main.py +++ b/src/main.py @@ -13,7 +13,7 @@ from utils.parser.LALR_1 import LALR1_Parser if __name__ == "__main__": - add = "semantic/arithmetic12.cl" + add = "lexer/iis5.cl" path: str = f"{Path.cwd()}/tests/{add}" if os.path.exists( f"{Path.cwd()}/tests/{add}") else f"{Path.cwd()}/../tests/{add}" @@ -23,12 +23,6 @@ with open(_in) as file: code = file.read() - code = '''class Main { - main(): Object { - if true = not false then 4 else 5 fi - }; -};''' - G = build_COOL_Grammar() # lexer From 22079ac5afc2192112e2f87bd046eaf5db1784e9 Mon Sep 17 00:00:00 2001 From: Ale Date: Wed, 16 Feb 2022 15:08:20 -0800 Subject: [PATCH 40/83] changing semantic errors format --- src/main.py | 2 +- src/utils/semantic_check/type_checker.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main.py b/src/main.py index ec1bd6b90..df7eaa6cc 100644 --- a/src/main.py +++ b/src/main.py @@ -13,7 +13,7 @@ from utils.parser.LALR_1 import LALR1_Parser if __name__ == "__main__": - add = "lexer/iis5.cl" + add = "lexer/let3.cl" path: str = f"{Path.cwd()}/tests/{add}" if os.path.exists( f"{Path.cwd()}/tests/{add}") else f"{Path.cwd()}/../tests/{add}" diff --git a/src/utils/semantic_check/type_checker.py b/src/utils/semantic_check/type_checker.py index 4c28beb34..9b6d6e15c 100644 --- a/src/utils/semantic_check/type_checker.py +++ b/src/utils/semantic_check/type_checker.py @@ -8,7 +8,7 @@ SELF_ERROR_ATTR = '(%s, %s) - SemanticError: \'self\' cannot be the name of an attribute.' SELF_ERROR_LET = '(%s, %s) - SemanticError: \'self\' cannot be bound in a \'let\' expression.' -SELF_IS_READONLY = '(%s, %s) - TypeError: Variable "self" is read-only.' +SELF_IS_READONLY = '(%s, %s) - SemanticError: Variable "self" is read-only.' SELF_TYPE_ERROR = '(%s, %s) - TypeError: SELF_TYPE cannot be used as a parameter type in method %s' SELF_TYPE_IN_DISPATCH = '(%s, %s) - TypeError: SELF_TYPE cannot be used as a type of a dispatch' SELF_TYPE_IN_CASE_BRANCH = '(%s, %s) - TypeError: SELF_TYPE cannot be used as a type of a case branch' @@ -31,6 +31,7 @@ DUPLICATE_BRANCH = '(%s, %s) - SemanticError: Duplicate branch %s in case statement.' UNDEFINED_TYPE_BRANCH = '(%s, %s) - TypeError: Class %s of case branch is undefined.' UNDEFINED_TYPE_NEW = '(%s, %s) - TypeError: \'new\' used with undefined class %s.' +UNDEFINED_TYPE_LET = '(%s, %s) - TypeError: Class %s of let-bound identifier %s is undefined.' UNDEFINED_METHOD = '(%s, %s) - AttributeError: Dispatch to undefined method %s. ' @@ -273,7 +274,7 @@ def visit(self, node, scope): id_type = self.context.get_type(typex) if typex != 'SELF_TYPE' else self.current_type except SemanticError as se: id_type = ErrorType() - self.errors.append(se.text) + self.errors.append(UNDEFINED_TYPE_LET % (node.line, node.column, typex, idx)) if idx == 'self': self.errors.append(SELF_ERROR_LET % (node.line, node.column)) From 5ee11cf0afa811196cadd8c6cdbbf60b3f5ab6ec Mon Sep 17 00:00:00 2001 From: Ale Date: Wed, 16 Feb 2022 15:24:17 -0800 Subject: [PATCH 41/83] errors like test --- src/main.py | 2 +- src/utils/semantic_check/type_builder.py | 6 ++++++ src/utils/semantic_check/type_checker.py | 7 +++++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main.py b/src/main.py index df7eaa6cc..92e2f9742 100644 --- a/src/main.py +++ b/src/main.py @@ -13,7 +13,7 @@ from utils.parser.LALR_1 import LALR1_Parser if __name__ == "__main__": - add = "lexer/let3.cl" + add = "semantic/features3.cl" path: str = f"{Path.cwd()}/tests/{add}" if os.path.exists( f"{Path.cwd()}/tests/{add}") else f"{Path.cwd()}/../tests/{add}" diff --git a/src/utils/semantic_check/type_builder.py b/src/utils/semantic_check/type_builder.py index c10325368..02e49e936 100644 --- a/src/utils/semantic_check/type_builder.py +++ b/src/utils/semantic_check/type_builder.py @@ -8,6 +8,7 @@ PARAMETER_TYPE_UNDEFINED = '(%s, %s) - TypeError: Class %s of formal parameter %s is undefined.' REDEFINED_ATTRIBUTES = '(%s, %s) - SemanticError: Attribute %s is an attribute of an inherited class.' RETURN_TYPE_UNDEFINED = '(%s, %s) - TypeError: Undefined return type %s in method %s.' +TYPE_NOT_DEFINED_ATTR = '(%s, %s) - TypeError: Class %s of attribute %s is undefined.' class TypeBuilder: @@ -61,6 +62,11 @@ def visit(self,node): def visit(self,node): try: attrType = self.context.get_type(node.type) + except SemanticError as se: + self.errors.append(TYPE_NOT_DEFINED_ATTR % (node.line, node.column, node.type, node.id)) + attrType = ErrorType() + + try: self.current_type.define_attribute(node.id, attrType) except SemanticError as se: self.errors.append(REDEFINED_ATTRIBUTES % (node.line, node.column, node.id)) diff --git a/src/utils/semantic_check/type_checker.py b/src/utils/semantic_check/type_checker.py index 9b6d6e15c..1dc821a75 100644 --- a/src/utils/semantic_check/type_checker.py +++ b/src/utils/semantic_check/type_checker.py @@ -26,7 +26,7 @@ INVALID_OPERATION = '(%s, %s) - TypeError: non-Int arguments: %s %s %s' VARIABLE_NOT_DEFINED = '(%s, %s) - NameError: Undeclared identifier %s.' INHERIT_ERROR = '(%s, %s) - SemanticError: Class %s, or an ancestor of %s, is involved in an inheritance cycle.' -METHOD_PARAMETERS = '(%s, %s) - TypeError: Method %s defined in %s receive %d parameters' +METHOD_PARAMETERS = '(%s, %s) - SemanticError: Method %s defined in %s receive %d parameters' DUPLICATE_BRANCH = '(%s, %s) - SemanticError: Duplicate branch %s in case statement.' UNDEFINED_TYPE_BRANCH = '(%s, %s) - TypeError: Class %s of case branch is undefined.' @@ -106,7 +106,10 @@ def visit(self, node, scope): @visitor.when(nodes.AttrDeclarationNode) def visit(self, node, scope): - attr_type = self.context.get_type(node.type) if node.type != 'SELF_TYPE' else self.current_type + try: + attr_type = self.context.get_type(node.type) if node.type != 'SELF_TYPE' else self.current_type + except SemanticError: + attr_type = ErrorType() if node.id == 'self': self.errors.append(SELF_ERROR_ATTR % (node.line, node.column)) From f65bdfce839b40cdf67d0cfd226cf26108788051 Mon Sep 17 00:00:00 2001 From: Ale Date: Wed, 16 Feb 2022 15:34:35 -0800 Subject: [PATCH 42/83] semantic ok --- src/cmp/semantic.py | 2 ++ src/main.py | 2 +- src/utils/semantic_check/type_checker.py | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/cmp/semantic.py b/src/cmp/semantic.py index dc72bc7fc..1476d66d4 100644 --- a/src/cmp/semantic.py +++ b/src/cmp/semantic.py @@ -42,11 +42,13 @@ def __init__(self, name:str): self.attributes = [] self.methods = [] self.parent = None + self.child = None def set_parent(self, parent): if self.parent is not None: raise SemanticError(f'Parent type is already set for {self.name}.') self.parent = parent + parent.child = self def get_attribute(self, name:str, typex:str): try: diff --git a/src/main.py b/src/main.py index 92e2f9742..35a9394b6 100644 --- a/src/main.py +++ b/src/main.py @@ -13,7 +13,7 @@ from utils.parser.LALR_1 import LALR1_Parser if __name__ == "__main__": - add = "semantic/features3.cl" + add = "semantic/inheritance4.cl" path: str = f"{Path.cwd()}/tests/{add}" if os.path.exists( f"{Path.cwd()}/tests/{add}") else f"{Path.cwd()}/../tests/{add}" diff --git a/src/utils/semantic_check/type_checker.py b/src/utils/semantic_check/type_checker.py index 1dc821a75..7801a937c 100644 --- a/src/utils/semantic_check/type_checker.py +++ b/src/utils/semantic_check/type_checker.py @@ -85,7 +85,7 @@ def visit(self, node, scope): while current_parent != self.context.get_type('Object') and current_parent != None: if current_parent == self.current_type: - self.errors.append(INHERIT_ERROR % (self.current_type.parent.line, self.current_type.parent.column, self.current_type.parent.name, self.current_type.parent.name)) + self.errors.append(INHERIT_ERROR % (self.current_type.child.line, self.current_type.child.column, self.current_type.child.name, self.current_type.child.name)) self.current_type.parent = ErrorType() break From 0aad48025c8d1d1ed8053f7aac5e2e3bb2f5143d Mon Sep 17 00:00:00 2001 From: Alejandro Campos Matanzas <74170015+Alexx-4@users.noreply.github.com> Date: Fri, 18 Feb 2022 07:58:20 -0800 Subject: [PATCH 43/83] Update requirements.txt --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 9eb0cad1a..152d5bf37 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ pytest pytest-ordering + From cf1f2f792311af7cc8bdf3a652d4255ee63e2cdd Mon Sep 17 00:00:00 2001 From: Alejandro Campos Matanzas <74170015+Alexx-4@users.noreply.github.com> Date: Fri, 18 Feb 2022 07:59:56 -0800 Subject: [PATCH 44/83] Update requirements.txt --- requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 152d5bf37..9eb0cad1a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,2 @@ pytest pytest-ordering - From eab9984ca18ac4c17a05cb55b6d2fabb2a194bdf Mon Sep 17 00:00:00 2001 From: darian10 Date: Fri, 18 Feb 2022 18:51:04 -0500 Subject: [PATCH 45/83] Creating Cool_to_Cil visitor template --- src/utils/code_generation/cil/COOL_to_CIL.py | 134 +++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 src/utils/code_generation/cil/COOL_to_CIL.py diff --git a/src/utils/code_generation/cil/COOL_to_CIL.py b/src/utils/code_generation/cil/COOL_to_CIL.py new file mode 100644 index 000000000..830506792 --- /dev/null +++ b/src/utils/code_generation/cil/COOL_to_CIL.py @@ -0,0 +1,134 @@ +import cmp.visitor as visitor +from utils.ast.AST_Nodes import ast_nodes as nodes + +class COOL_to_CIL: + def __init__(self, context, scope): + self.context = context + self.scope = scope + + + @visitor.on('node') + def visit(self, node, scope): + pass + + + @visitor.when(nodes.ProgramNode) + def visit(self, node, scope=None): + pass + + + @visitor.when(nodes.ClassDeclarationNode) + def visit(self, node, scope): + pass + + @visitor.when(nodes.AttrDeclarationNode) + def visit(self, node, scope): + pass + + + @visitor.when(nodes.MethDeclarationNode) + def visit(self, node, scope): + pass + + @visitor.when(nodes.AssignNode) + def visit(self, node, scope): + pass + + + @visitor.when(nodes.IfThenElseNode) + def visit(self, node, scope): + pass + + + @visitor.when(nodes.WhileNode) + def visit(self, node, scope): + pass + + + @visitor.when(nodes.BlockNode) + def visit(self, node, scope): + pass + + + @visitor.when(nodes.LetNode) + def visit(self, node, scope): + pass + + + @visitor.when(nodes.CaseNode) + def visit(self, node, scope): + pass + + + @visitor.when(nodes.NotNode) + def visit(self, node, scope): + pass + + + @visitor.when(nodes.ConstantNumNode) + def visit(self, node, scope): + pass + + + @visitor.when(nodes.ConstantBoolNode) + def visit(self, node, scope): + pass + + + @visitor.when(nodes.ConstantStringNode) + def visit(self, node, scope): + pass + + + @visitor.when(nodes.VariableNode) + def visit(self, node, scope): + pass + + + @visitor.when(nodes.InstantiateNode) + def visit(self, node, scope): + pass + + + @visitor.when(nodes.IsVoidNode) + def visit(self, node, scope): + pass + + @visitor.when(nodes.ComplementNode) + def visit(self, node, scope): + pass + + + @visitor.when(nodes.PlusNode) + def visit(self, node, scope): + pass + + + @visitor.when(nodes.MinusNode) + def visit(self, node, scope): + pass + + + @visitor.when(nodes.StarNode) + def visit(self, node, scope): + pass + + + @visitor.when(nodes.DivNode) + def visit(self, node, scope): + pass + + + @visitor.when(nodes.LessThanNode) + def visit(self, node, scope): + pass + + + @visitor.when(nodes.LessEqualNode) + def visit(self, node, scope): + pass + + + @visitor.when(nodes.EqualNode) + def visit(self, node, scope): + pass \ No newline at end of file From 1175eeeff26e2eb74155dcabac4dece2f980e325 Mon Sep 17 00:00:00 2001 From: Ale Date: Fri, 18 Feb 2022 18:30:55 -0800 Subject: [PATCH 46/83] creating cil ast --- src/utils/code_generation/cil/AST_CIL.py | 218 +++++++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100644 src/utils/code_generation/cil/AST_CIL.py diff --git a/src/utils/code_generation/cil/AST_CIL.py b/src/utils/code_generation/cil/AST_CIL.py new file mode 100644 index 000000000..542cb3805 --- /dev/null +++ b/src/utils/code_generation/cil/AST_CIL.py @@ -0,0 +1,218 @@ +class cil_ast: + + class Node: + pass + + class ProgramNode(Node): + def __init__(self, dottypes, dotdata, dotcode): + self.dottypes = dottypes + self.dotdata = dotdata + self.dotcode = dotcode + + class TypeNode(Node): + def __init__(self, idx): + self.id = idx + self.attributes = [] + self.methods = [] + + class DataNode(Node): + def __init__(self, vname, value): + self.name = vname + self.value = value + + class FunctionNode(Node): + def __init__(self, idx, params, localvars, instructions): + self.id = idx + self.params = params + self.localvars = localvars + self.instructions = instructions + self.ids = dict() + self.labels_count = 0 + + class ParamNode(Node): + def __init__(self, idx): + self.id = idx + + class LocalNode(Node): + def __init__(self, idx): + self.id = idx + + class InstructionNode(Node): + def __init__(self): + self.leader = False + + class AssignNode(InstructionNode): + def __init__(self, left, right): + self.left = left + self.right = right + + def __repr__(self): + return f"{self.left} = {self.right}" + + class ArithmeticNode(InstructionNode): + def __init__(self, dest, op_l, op_r): + self.dest = dest + self.op_l = op_l + self.op_r = op_r + + class PlusNode(ArithmeticNode): + pass + + class MinusNode(ArithmeticNode): + pass + + class StarNode(ArithmeticNode): + pass + + class DivNode(ArithmeticNode): + pass + + class LessThanNode(ArithmeticNode): + pass + + class LessEqualNode(ArithmeticNode): + pass + + class EqualNode(ArithmeticNode): + def __repr__(self): + return f"{self.dest} = {self.op_l} == {self.op_r}" + + # class EqualStrNode(ArithmeticNode): + # pass + + class GetAttrNode(InstructionNode): + def __init__(self, dest, idx, attr, computed_type): + self.dest = dest + self.idx = idx + self.attr = attr + self.computed_type = computed_type + + def __repr__(self): + return f"{self.dest} = GETATTR {self.idx} {self.attr}" + + class SetAttrNode(InstructionNode): + def __init__(self, idx, attr, value, computed_type): + self.idx = idx + self.attr = attr + self.value = value + self.computed_type = computed_type + + def __repr__(self): + return f"SETATTR {self.idx} {self.attr} {self.value}" + + # class GetIndexNode(InstructionNode): + # pass + + # class SetIndexNode(InstructionNode): + # pass + + class AllocateNode(InstructionNode): + def __init__(self, dest, typex): + self.dest = dest + self.type = typex + + def __repr__(self): + return f"{self.dest} = ALLOCATE {self.type}" + + # class ArrayNode(InstructionNode): + # pass + + class TypeOfNode(InstructionNode): + def __init__(self, idx, dest): + self.id = idx + self.dest = dest + + def __repr__(self): + return f"{self.dest} = TYPEOF {self.id}" + + class StaticCallNode(InstructionNode): + def __init__(self, function, dest): + self.function = function + self.dest = dest + + def __repr__(self): + return f"{self.dest} = CALL {self.function}" + + class DynamicCallNode(InstructionNode): + def __init__(self, typex, function, dest, computed_type): + self.type = typex + self.function = function + self.dest = dest + self.computed_type = computed_type + + def __repr__(self): + return f"{self.dest} = VCALL {self.type} {self.function}" + + class ArgNode(InstructionNode): + def __init__(self, idx): + self.id = idx + + def __repr__(self): + return f"ARG {self.id}" + + class IfGotoNode(InstructionNode): + def __init__(self, if_cond, label): + self.if_cond = if_cond + self.label = label + + def __repr__(self): + return f"GOTO {self.label} if {self.if_cond}" + + class LabelNode(InstructionNode): + def __init__(self, label): + self.label = label + + def __repr__(self): + return f"LABEL {self.label}:" + + class GotoNode(InstructionNode): + def __init__(self, label): + self.label = label + + def __repr__(self): + return f"GOTO {self.label}" + + class ReturnNode(InstructionNode): + def __init__(self, idx=None): + self.id = idx + + def __repr__(self): + return f"RETURN {self.id}" + + class LoadNode(InstructionNode): + def __init__(self, dest, msg): + self.dest = dest + self.msg = msg + + def __repr__(self): + return f"{self.dest} LOAD {self.msg}" + + class LengthNode(InstructionNode): + def __init__(self, dest, idx): + self.dest = dest + self.id = idx + + class ConcatNode(InstructionNode): + def __init__(self, dest, s1, s2, length): + self.dest = dest + self.s1 = s1 + self.s2 = s2 + self.length = length + + class SubstringNode(InstructionNode): + def __init__(self, dest, s, i, length): + self.dest = dest + self.s = s + self.i = i + self.length = length + + class ReadStrNode(InstructionNode): + def __init__(self, dest): + self.dest = dest + + class PrintStrNode(InstructionNode): + def __init__(self, value): + self.value = value + + def __repr__(self): + return f"PRINTSTR {self.value}" \ No newline at end of file From f5c123739c0f742450631e6a7943aa7c9cf515ed Mon Sep 17 00:00:00 2001 From: Ale Date: Fri, 18 Feb 2022 18:36:47 -0800 Subject: [PATCH 47/83] modifying cil ast --- src/utils/code_generation/cil/AST_CIL.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/utils/code_generation/cil/AST_CIL.py b/src/utils/code_generation/cil/AST_CIL.py index 542cb3805..2804ae26c 100644 --- a/src/utils/code_generation/cil/AST_CIL.py +++ b/src/utils/code_generation/cil/AST_CIL.py @@ -77,9 +77,6 @@ class EqualNode(ArithmeticNode): def __repr__(self): return f"{self.dest} = {self.op_l} == {self.op_r}" - # class EqualStrNode(ArithmeticNode): - # pass - class GetAttrNode(InstructionNode): def __init__(self, dest, idx, attr, computed_type): self.dest = dest @@ -100,12 +97,6 @@ def __init__(self, idx, attr, value, computed_type): def __repr__(self): return f"SETATTR {self.idx} {self.attr} {self.value}" - # class GetIndexNode(InstructionNode): - # pass - - # class SetIndexNode(InstructionNode): - # pass - class AllocateNode(InstructionNode): def __init__(self, dest, typex): self.dest = dest @@ -114,9 +105,6 @@ def __init__(self, dest, typex): def __repr__(self): return f"{self.dest} = ALLOCATE {self.type}" - # class ArrayNode(InstructionNode): - # pass - class TypeOfNode(InstructionNode): def __init__(self, idx, dest): self.id = idx From d672e86b0a25e9c72ba8ccebe45c5c63759ca359 Mon Sep 17 00:00:00 2001 From: darian10 Date: Sat, 19 Feb 2022 10:26:52 -0500 Subject: [PATCH 48/83] Creating print_cil_ast --- .../code_generation/cil/print_CIL_AST.py | 148 ++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 src/utils/code_generation/cil/print_CIL_AST.py diff --git a/src/utils/code_generation/cil/print_CIL_AST.py b/src/utils/code_generation/cil/print_CIL_AST.py new file mode 100644 index 000000000..58f5d48dd --- /dev/null +++ b/src/utils/code_generation/cil/print_CIL_AST.py @@ -0,0 +1,148 @@ +from utils.code_generation.cil.AST_CIL import cil_ast as nodes +import cmp.visitor as visitor + +def get_formatter(): + + class PrintVisitor(object): + @visitor.on('node') + def visit(self, node): + pass + + @visitor.when(nodes.ProgramNode) + def visit(self, node): + dottypes = '\n'.join(self.visit(t) for t in node.dottypes) + dotdata = '\n'.join(self.visit(t) for t in node.dotdata) + dotcode = '\n'.join(self.visit(t) for t in node.dotcode) + + return f'.TYPES\n{dottypes}\n\n.DATA\n{dotdata}\n\n.CODE\n{dotcode}' + + @visitor.when(nodes.TypeNode) + def visit(self, node): + attributes = '\n\t'.join(f'attribute {x}' for x in node.attributes) + methods = '\n\t'.join(f'method {x}: {y}' for x,y in node.methods) + + return f'type {node.name} {{\n\t{attributes}\n\n\t{methods}\n}}' + + @visitor.when(nodes.DataNode) + def visit(self, node): + return f'{node.idx} = {node.value}' + + @visitor.when(nodes.FunctionNode) + def visit(self, node): + params = '\n\t'.join(self.visit(x) for x in node.params) + localvars = '\n\t'.join(self.visit(x) for x in node.localvars) + instructions = '\n\t'.join(self.visit(x) for x in node.instructions if self.visit(x) != []) + + return f'function {node.id} {{\n\t{params}\n\n\t{localvars}\n\n\t{instructions}\n}}' + + @visitor.when(nodes.ParamNode) + def visit(self, node): + return f'PARAM {node.id}' + + @visitor.when(nodes.LocalNode) + def visit(self, node): + return f'LOCAL {node.id}' + + @visitor.when(nodes.AssignNode) + def visit(self, node): + return f'{node.left} = {node.right}' + + @visitor.when(nodes.PlusNode) + def visit(self, node): + return f'{node.dest} = {node.op_l} + {node.op_r}' + + @visitor.when(nodes.MinusNode) + def visit(self, node): + return f'{node.dest} = {node.op_l} - {node.op_r}' + + @visitor.when(nodes.StarNode) + def visit(self, node): + return f'{node.dest} = {node.op_l} * {node.op_r}' + + @visitor.when(nodes.DivNode) + def visit(self, node): + return f'{node.dest} = {node.op_l} / {node.op_r}' + + @visitor.when(nodes.LessEqualNode) + def visit(self, node): + return f'{node.dest} = {node.op_l} <= {node.op_r}' + + @visitor.when(nodes.LessNode) + def visit(self, node): + return f'{node.dest} = {node.op_l} < {node.op_r}' + + @visitor.when(nodes.EqualNode) + def visit(self, node): + return f'{node.dest} = {node.op_l} == {node.op_r}' + + @visitor.when(nodes.GetAttrNode) + def visit(self, node): + return f'{node.dest} = GETATTR {node.id} {node.attr}' + + @visitor.when(nodes.SetAttrNode) + def visit(self, node): + return f'SETATTR {node.idx} {node.attr} {node.value}' + + @visitor.when(nodes.AllocateNode) + def visit(self, node): + return f'{node.dest} = ALLOCATE {node.type}' + + @visitor.when(nodes.TypeOfNode) + def visit(self, node): + return f'{node.dest} = TYPEOF {node.id}' + + @visitor.when(nodes.StaticCallNode) + def visit(self, node): + return f'{node.dest} = CALL {node.function}' + + @visitor.when(nodes.DynamicCallNode) + def visit(self, node): + return f'{node.dest} = VCALL {node.type} {node.function}' + + @visitor.when(nodes.ArgNode) + def visit(self, node): + return f'ARG {node.id}' + + @visitor.when(nodes.IfGotoNode) + def visit(self, node): + return f'IF {node.if_cond} GOTO {node.label}' + + @visitor.when(nodes.LabelNode) + def visit(self, node): + return f'LABEL {node.label}' + + @visitor.when(nodes.GotoNode) + def visit(self, node): + return f'GOTO {node.label}' + + @visitor.when(nodes.ReturnNode) + def visit(self, node): + return f'RETURN {node.id if node.id is not None else ""}' + + @visitor.when(nodes.LoadNode) + def visit(self, node): + return f'{node.dest} = LOAD {node.msg}' + + @visitor.when(nodes.LengthNode) + def visit(self, node): + return f'{node.dest} = LENGTH {node.id}' + + @visitor.when(nodes.ConcatNode) + def visit(self, node): + return f'{node.dest} = CONCAT {node.s1} {node.s2}' + + @visitor.when(nodes.SubstringNode) + def visit(self, node): + return f'{node.dest} = SUBSTRING {node.s} {node.i} {node.length}' + + @visitor.when(nodes.ReadStrNode) + def visit(self, node): + return f'{node.dest} = READSTR' + + @visitor.when(nodes.PrintStrNode) + def visit(self, node): + return f'PRINT {node.value}' + + printer = PrintVisitor() + return (lambda ast: printer.visit(ast)) + \ No newline at end of file From 8380748c5b1d23e1c23836b7eab33da29a43245f Mon Sep 17 00:00:00 2001 From: Ale Date: Sat, 19 Feb 2022 10:21:21 -0800 Subject: [PATCH 49/83] updating cil ast --- src/utils/code_generation/cil/AST_CIL.py | 45 ++---------------------- 1 file changed, 3 insertions(+), 42 deletions(-) diff --git a/src/utils/code_generation/cil/AST_CIL.py b/src/utils/code_generation/cil/AST_CIL.py index 2804ae26c..128b8d597 100644 --- a/src/utils/code_generation/cil/AST_CIL.py +++ b/src/utils/code_generation/cil/AST_CIL.py @@ -16,8 +16,8 @@ def __init__(self, idx): self.methods = [] class DataNode(Node): - def __init__(self, vname, value): - self.name = vname + def __init__(self, idx, value): + self.id = idx self.value = value class FunctionNode(Node): @@ -83,9 +83,6 @@ def __init__(self, dest, idx, attr, computed_type): self.idx = idx self.attr = attr self.computed_type = computed_type - - def __repr__(self): - return f"{self.dest} = GETATTR {self.idx} {self.attr}" class SetAttrNode(InstructionNode): def __init__(self, idx, attr, value, computed_type): @@ -93,33 +90,21 @@ def __init__(self, idx, attr, value, computed_type): self.attr = attr self.value = value self.computed_type = computed_type - - def __repr__(self): - return f"SETATTR {self.idx} {self.attr} {self.value}" class AllocateNode(InstructionNode): def __init__(self, dest, typex): self.dest = dest self.type = typex - - def __repr__(self): - return f"{self.dest} = ALLOCATE {self.type}" class TypeOfNode(InstructionNode): def __init__(self, idx, dest): self.id = idx self.dest = dest - def __repr__(self): - return f"{self.dest} = TYPEOF {self.id}" - class StaticCallNode(InstructionNode): def __init__(self, function, dest): self.function = function self.dest = dest - - def __repr__(self): - return f"{self.dest} = CALL {self.function}" class DynamicCallNode(InstructionNode): def __init__(self, typex, function, dest, computed_type): @@ -127,54 +112,33 @@ def __init__(self, typex, function, dest, computed_type): self.function = function self.dest = dest self.computed_type = computed_type - - def __repr__(self): - return f"{self.dest} = VCALL {self.type} {self.function}" class ArgNode(InstructionNode): def __init__(self, idx): self.id = idx - - def __repr__(self): - return f"ARG {self.id}" class IfGotoNode(InstructionNode): def __init__(self, if_cond, label): self.if_cond = if_cond self.label = label - - def __repr__(self): - return f"GOTO {self.label} if {self.if_cond}" class LabelNode(InstructionNode): def __init__(self, label): self.label = label - - def __repr__(self): - return f"LABEL {self.label}:" class GotoNode(InstructionNode): def __init__(self, label): self.label = label - - def __repr__(self): - return f"GOTO {self.label}" class ReturnNode(InstructionNode): def __init__(self, idx=None): self.id = idx - - def __repr__(self): - return f"RETURN {self.id}" class LoadNode(InstructionNode): def __init__(self, dest, msg): self.dest = dest self.msg = msg - def __repr__(self): - return f"{self.dest} LOAD {self.msg}" - class LengthNode(InstructionNode): def __init__(self, dest, idx): self.dest = dest @@ -200,7 +164,4 @@ def __init__(self, dest): class PrintStrNode(InstructionNode): def __init__(self, value): - self.value = value - - def __repr__(self): - return f"PRINTSTR {self.value}" \ No newline at end of file + self.value = value \ No newline at end of file From f5a6749fde2be151b97231762a8f241c42c1697f Mon Sep 17 00:00:00 2001 From: Ale Date: Sat, 19 Feb 2022 10:46:39 -0800 Subject: [PATCH 50/83] uodating visitor to cil --- src/utils/code_generation/cil/COOL_to_CIL.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/utils/code_generation/cil/COOL_to_CIL.py b/src/utils/code_generation/cil/COOL_to_CIL.py index 830506792..f0d6cf089 100644 --- a/src/utils/code_generation/cil/COOL_to_CIL.py +++ b/src/utils/code_generation/cil/COOL_to_CIL.py @@ -1,10 +1,9 @@ import cmp.visitor as visitor from utils.ast.AST_Nodes import ast_nodes as nodes -class COOL_to_CIL: - def __init__(self, context, scope): +class COOLtoCIL: + def __init__(self, context): self.context = context - self.scope = scope @visitor.on('node') From 3b0dd3b8b0dbd9b3c271526ece8a99f2cd23efe0 Mon Sep 17 00:00:00 2001 From: Ale Date: Sat, 19 Feb 2022 11:15:13 -0800 Subject: [PATCH 51/83] adding ErrorNode --- src/utils/code_generation/cil/AST_CIL.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/utils/code_generation/cil/AST_CIL.py b/src/utils/code_generation/cil/AST_CIL.py index 128b8d597..6bc7fdfe6 100644 --- a/src/utils/code_generation/cil/AST_CIL.py +++ b/src/utils/code_generation/cil/AST_CIL.py @@ -164,4 +164,8 @@ def __init__(self, dest): class PrintStrNode(InstructionNode): def __init__(self, value): - self.value = value \ No newline at end of file + self.value = value + + class ErrorNode(InstructionNode): + def __init__(self, data_node): + self.data_node = data_node \ No newline at end of file From 629ffa26fe8ad35d81820aa815d0f65e85f1a48d Mon Sep 17 00:00:00 2001 From: Ale Date: Sat, 19 Feb 2022 11:15:57 -0800 Subject: [PATCH 52/83] adding ErrorNode --- src/utils/code_generation/cil/print_CIL_AST.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/utils/code_generation/cil/print_CIL_AST.py b/src/utils/code_generation/cil/print_CIL_AST.py index 58f5d48dd..8a660fbd6 100644 --- a/src/utils/code_generation/cil/print_CIL_AST.py +++ b/src/utils/code_generation/cil/print_CIL_AST.py @@ -143,6 +143,10 @@ def visit(self, node): def visit(self, node): return f'PRINT {node.value}' + @visitor.when(nodes.ErrorNode) + def visit(self, node): + return f'ERROR {node.data_node}' + printer = PrintVisitor() return (lambda ast: printer.visit(ast)) \ No newline at end of file From 3fea7a2ae4695e1243ca22cab80cdf350e74a0f9 Mon Sep 17 00:00:00 2001 From: Ale Date: Sat, 19 Feb 2022 11:17:35 -0800 Subject: [PATCH 53/83] base cool to cil --- .../code_generation/cil/Base_COOL_to_CIL.py | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 src/utils/code_generation/cil/Base_COOL_to_CIL.py diff --git a/src/utils/code_generation/cil/Base_COOL_to_CIL.py b/src/utils/code_generation/cil/Base_COOL_to_CIL.py new file mode 100644 index 000000000..ef2ede452 --- /dev/null +++ b/src/utils/code_generation/cil/Base_COOL_to_CIL.py @@ -0,0 +1,99 @@ +from utils.code_generation.cil.AST_CIL import cil_ast as nodes +from cmp.semantic import VariableInfo + + +class BaseCOOLToCIL: + def __init__(self, context): + self.dottypes = [] + self.dotdata = [] + self.dotcode = [] + + self.current_type = None + self.current_method = None + self.current_function = None + + self.context = context + self.vself = VariableInfo('self', None) + + @property + def params(self): + return self.current_function.params + + @property + def localvars(self): + return self.current_function.localvars + + @property + def ids(self): + return self.current_function.ids + + @property + def instructions(self): + return self.current_function.instructions + + def register_param(self, vinfo): + param_node = nodes.ParamNode(vinfo.name) + self.params.append(param_node) + return vinfo.name + + def register_local(self, vinfo, id=False): + if len(self.current_function.name) >= 8 and self.current_function.name[:8] == 'function': + name = f'local_{self.current_function.name[9:]}_{vinfo.name}_{len(self.localvars)}' + else: + name = f'local_{self.current_function.name[5:]}_{vinfo.name}_{len(self.localvars)}' + + new_vinfo = VariableInfo(name, None) + local_node = nodes.LocalNode(new_vinfo.name) + + if id: + self.ids[vinfo.name] = new_vinfo.name + + self.localvars.append(local_node) + return new_vinfo.name + + def define_internal_local(self): + vinfo = VariableInfo('internal', None) + return self.register_local(vinfo) + + def register_instruction(self, 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 init_name(self, type_name, attr=False): + if attr: + return f'init_attr_at_{type_name}' + return f'init_at_{type_name}' + + def register_function(self, function_name): + function_node = nodes.FunctionNode(function_name, [], [], []) + self.dotcode.append(function_node) + return function_node + + def register_type(self, name): + type_node = nodes.TypeNode(name) + self.dottypes.append(type_node) + return type_node + + def register_data(self, value): + vname = f'data_{len(self.dotdata)}' + data_node = nodes.DataNode(vname, value) + self.dotdata.append(data_node) + return data_node + + def register_label(self, label): + lname = f'{label}_{self.current_function.labels_count}' + self.current_function.labels_count += 1 + return nodes.LabelNode(lname) + + def register_runtime_error(self, condition, msg): + error_node = self.register_label('error_label') + continue_node = self.register_label('continue_label') + self.register_instruction(nodes.IfGotoNode(condition, error_node.label)) + self.register_instruction(nodes.GotoNode(continue_node.label)) + self.register_instruction(error_node) + data_node = self.register_data(msg) + self.register_instruction(nodes.ErrorNode(data_node)) + self.register_instruction(continue_node) \ No newline at end of file From 107bcc51f6d1909062868965bee8a3f91adc471b Mon Sep 17 00:00:00 2001 From: Ale Date: Sat, 19 Feb 2022 11:42:58 -0800 Subject: [PATCH 54/83] type name and name nodes --- src/utils/code_generation/cil/AST_CIL.py | 12 +++++++++++- src/utils/code_generation/cil/print_CIL_AST.py | 8 ++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/utils/code_generation/cil/AST_CIL.py b/src/utils/code_generation/cil/AST_CIL.py index 6bc7fdfe6..754237139 100644 --- a/src/utils/code_generation/cil/AST_CIL.py +++ b/src/utils/code_generation/cil/AST_CIL.py @@ -168,4 +168,14 @@ def __init__(self, value): class ErrorNode(InstructionNode): def __init__(self, data_node): - self.data_node = data_node \ No newline at end of file + self.data_node = data_node + + class TypeNameNode(InstructionNode): + def __init__(self, dest, typex): + self.dest = dest + self.type = typex + + class NameNode(InstructionNode): + def __init__(self, dest, idx): + self.dest = dest + self.id = idx \ No newline at end of file diff --git a/src/utils/code_generation/cil/print_CIL_AST.py b/src/utils/code_generation/cil/print_CIL_AST.py index 8a660fbd6..1ffcc2535 100644 --- a/src/utils/code_generation/cil/print_CIL_AST.py +++ b/src/utils/code_generation/cil/print_CIL_AST.py @@ -147,6 +147,14 @@ def visit(self, node): def visit(self, node): return f'ERROR {node.data_node}' + @visitor.when(nodes.TypeNameNode) + def visit(self, node): + return f'{node.dest} = TYPENAME {node.type}' + + @visitor.when(nodes.NameNode) + def visit(self, node): + return f'{node.dest} = NAME {node.id}' + printer = PrintVisitor() return (lambda ast: printer.visit(ast)) \ No newline at end of file From 071c25a989d31f34b9d35c7980f2efa0ef4ad649 Mon Sep 17 00:00:00 2001 From: Ale Date: Sat, 19 Feb 2022 11:55:41 -0800 Subject: [PATCH 55/83] modifying cil ast and register Object type --- src/main.py | 7 ++- src/utils/code_generation/cil/AST_CIL.py | 10 +++- .../code_generation/cil/Base_COOL_to_CIL.py | 48 ++++++++++++++++++- .../code_generation/cil/print_CIL_AST.py | 8 ++++ 4 files changed, 69 insertions(+), 4 deletions(-) diff --git a/src/main.py b/src/main.py index 35a9394b6..234d59e5e 100644 --- a/src/main.py +++ b/src/main.py @@ -13,7 +13,7 @@ from utils.parser.LALR_1 import LALR1_Parser if __name__ == "__main__": - add = "semantic/inheritance4.cl" + add = "codegen/arith.cl" path: str = f"{Path.cwd()}/tests/{add}" if os.path.exists( f"{Path.cwd()}/tests/{add}") else f"{Path.cwd()}/../tests/{add}" @@ -46,6 +46,7 @@ # ast ast = evaluate_reverse_parse(G, derivation, operations, lexer.fixed_tokens(tokens)) + # chequeo semantico context = Context() semantic_errors = [] @@ -61,4 +62,6 @@ if semantic_errors: for error in semantic_errors: print(error) - raise Exception() \ No newline at end of file + raise Exception() + +# generacion de codigo \ No newline at end of file diff --git a/src/utils/code_generation/cil/AST_CIL.py b/src/utils/code_generation/cil/AST_CIL.py index 754237139..807fc7345 100644 --- a/src/utils/code_generation/cil/AST_CIL.py +++ b/src/utils/code_generation/cil/AST_CIL.py @@ -178,4 +178,12 @@ def __init__(self, dest, typex): class NameNode(InstructionNode): def __init__(self, dest, idx): self.dest = dest - self.id = idx \ No newline at end of file + self.id = idx + + class AbortNode(InstructionNode): + pass + + class CopyNode(InstructionNode): + def __init__(self, dest, copy): + self.dest = dest + self.copy = copy \ No newline at end of file diff --git a/src/utils/code_generation/cil/Base_COOL_to_CIL.py b/src/utils/code_generation/cil/Base_COOL_to_CIL.py index ef2ede452..4b61d97e9 100644 --- a/src/utils/code_generation/cil/Base_COOL_to_CIL.py +++ b/src/utils/code_generation/cil/Base_COOL_to_CIL.py @@ -96,4 +96,50 @@ def register_runtime_error(self, condition, msg): self.register_instruction(error_node) data_node = self.register_data(msg) self.register_instruction(nodes.ErrorNode(data_node)) - self.register_instruction(continue_node) \ No newline at end of file + self.register_instruction(continue_node) + + + # tipos y funciones integrados en COOL + def _register_Object(self): + type_node = self.register_type('Object') + + self.current_function = self.register_function(self.init_name('Object')) + instance = self.define_internal_local() + self.register_instruction(nodes.AllocateNode('Object', instance)) + self.register_instruction(nodes.ReturnNode(instance)) + + self.current_function = self.register_function(self.to_function_name('abort', 'Object')) + self.register_param(self.vself) + vname = self.define_internal_local() + data_node = [dn for dn in self.dotdata if dn.value == 'Abort called from class '][0] + self.register_instruction(nodes.LoadNode(vname, data_node)) + self.register_instruction(nodes.PrintStrNode(vname)) + self.register_instruction(nodes.TypeNameNode(vname, self.vself.name)) + self.register_instruction(nodes.PrintStrNode(vname)) + data_node = self.register_data('\n') + self.register_instruction(nodes.LoadNode(vname, data_node)) + self.register_instruction(nodes.PrintStrNode(vname)) + self.register_instruction(nodes.AbortNode()) + + self.current_function = self.register_function(self.to_function_name('type_name', 'Object')) + self.register_param(self.vself) + result = self.define_internal_local() + self.register_instruction(nodes.TypeNameNode(result, self.vself.name)) + instance = self.define_internal_local() + self.register_instruction(nodes.ArgNode(result)) + self.register_instruction(nodes.StaticCallNode(self.init_name('String'), instance)) + self.register_instruction(nodes.ReturnNode(instance)) + + self.current_function = self.register_function(self.to_function_name('copy', 'Object')) + self.register_param(self.vself) + result = self.define_internal_local() + self.register_instruction(nodes.CopyNode(result, self.vself.name)) + self.register_instruction(nodes.ReturnNode(result)) + + type_node.methods = [(name, self.to_function_name(name, 'Object')) for name in ['abort', 'type_name', 'copy']] + type_node.methods += [('init', self.init_name('Object'))] + return ['abort', 'type_name', 'copy'] + + def register_built_in(self): + obj_methods = self._register_Object() + \ No newline at end of file diff --git a/src/utils/code_generation/cil/print_CIL_AST.py b/src/utils/code_generation/cil/print_CIL_AST.py index 1ffcc2535..b48e20b7d 100644 --- a/src/utils/code_generation/cil/print_CIL_AST.py +++ b/src/utils/code_generation/cil/print_CIL_AST.py @@ -154,6 +154,14 @@ def visit(self, node): @visitor.when(nodes.NameNode) def visit(self, node): return f'{node.dest} = NAME {node.id}' + + @visitor.when(nodes.AbortNode) + def visit(self, node): + return f'ABORT' + + @visitor.when(nodes.CopyNode) + def visit(self, node): + return f'{node.dest} = COPY {node.copy}' printer = PrintVisitor() return (lambda ast: printer.visit(ast)) From 1f0fc9e5d28b1c8da31af4f0454fcfbbbae167eb Mon Sep 17 00:00:00 2001 From: Ale Date: Sat, 19 Feb 2022 14:45:41 -0800 Subject: [PATCH 56/83] adding nodes cil ast - register IO --- src/utils/code_generation/cil/AST_CIL.py | 10 +++- .../code_generation/cil/Base_COOL_to_CIL.py | 55 +++++++++++++++++-- .../code_generation/cil/print_CIL_AST.py | 8 +++ 3 files changed, 68 insertions(+), 5 deletions(-) diff --git a/src/utils/code_generation/cil/AST_CIL.py b/src/utils/code_generation/cil/AST_CIL.py index 807fc7345..d0cd8fe3b 100644 --- a/src/utils/code_generation/cil/AST_CIL.py +++ b/src/utils/code_generation/cil/AST_CIL.py @@ -186,4 +186,12 @@ class AbortNode(InstructionNode): class CopyNode(InstructionNode): def __init__(self, dest, copy): self.dest = dest - self.copy = copy \ No newline at end of file + self.copy = copy + + class ReadIntNode(InstructionNode): + def __init__(self, dest): + self.dest = dest + + class PrintIntNode(InstructionNode): + def __init__(self, value): + self.value = value \ No newline at end of file diff --git a/src/utils/code_generation/cil/Base_COOL_to_CIL.py b/src/utils/code_generation/cil/Base_COOL_to_CIL.py index 4b61d97e9..66d0e6daa 100644 --- a/src/utils/code_generation/cil/Base_COOL_to_CIL.py +++ b/src/utils/code_generation/cil/Base_COOL_to_CIL.py @@ -97,6 +97,12 @@ def register_runtime_error(self, condition, msg): data_node = self.register_data(msg) self.register_instruction(nodes.ErrorNode(data_node)) self.register_instruction(continue_node) + + def register_built_in(self): + self._register_Object() + self._register_IO() + + # tipos y funciones integrados en COOL @@ -138,8 +144,49 @@ def _register_Object(self): type_node.methods = [(name, self.to_function_name(name, 'Object')) for name in ['abort', 'type_name', 'copy']] type_node.methods += [('init', self.init_name('Object'))] - return ['abort', 'type_name', 'copy'] + + def _register_IO(self): + type_node = self.register_type('IO') - def register_built_in(self): - obj_methods = self._register_Object() - \ No newline at end of file + self.current_function = self.register_function(self.init_name('IO')) + instance = self.define_internal_local() + self.register_instruction(nodes.AllocateNode('IO', instance)) + self.register_instruction(nodes.ReturnNode(instance)) + + self.current_function = self.register_function(self.to_function_name('out_string', 'IO')) + self.register_param(self.vself) + self.register_param(VariableInfo('x', None)) + vname = self.define_internal_local() + self.register_instruction(nodes.GetAttrNode(vname, 'x', 'value', 'String')) + self.register_instruction(nodes.PrintStrNode(vname)) + self.register_instruction(nodes.ReturnNode(self.vself.name)) + + self.current_function = self.register_function(self.to_function_name('out_int', 'IO')) + self.register_param(self.vself) + self.register_param(VariableInfo('x', None)) + vname = self.define_internal_local() + self.register_instruction(nodes.GetAttrNode(vname, 'x', 'value', 'Int')) + self.register_instruction(nodes.PrintIntNode(vname)) + self.register_instruction(nodes.ReturnNode(self.vself.name)) + + self.current_function = self.register_function(self.to_function_name('in_string', 'IO')) + self.register_param(self.vself) + result = self.define_internal_local() + self.register_instruction(nodes.ReadStrNode(result)) + instance = self.define_internal_local() + self.register_instruction(nodes.ArgNode(result)) + self.register_instruction(nodes.StaticCallNode(self.init_name('String'), instance)) + self.register_instruction(nodes.ReturnNode(instance)) + + self.current_function = self.register_function(self.to_function_name('in_int', 'IO')) + self.register_param(self.vself) + result = self.define_internal_local() + self.register_instruction(nodes.ReadIntNode(result)) + instance = self.define_internal_local() + self.register_instruction(nodes.ArgNode(result)) + self.register_instruction(nodes.StaticCallNode(self.init_name('Int'), instance)) + self.register_instruction(nodes.ReturnNode(instance)) + + type_node.methods = [(method, self.to_function_name(method, 'Object')) for method in ['type_name','abort','copy']] + type_node.methods += [(name, self.to_function_name(name, 'IO')) for name in ['out_string', 'out_int', 'in_string', 'in_int']] + type_node.methods += [('init', self.init_name('IO'))] \ No newline at end of file diff --git a/src/utils/code_generation/cil/print_CIL_AST.py b/src/utils/code_generation/cil/print_CIL_AST.py index b48e20b7d..7af87b1f5 100644 --- a/src/utils/code_generation/cil/print_CIL_AST.py +++ b/src/utils/code_generation/cil/print_CIL_AST.py @@ -163,6 +163,14 @@ def visit(self, node): def visit(self, node): return f'{node.dest} = COPY {node.copy}' + @visitor.when(nodes.ReadIntNode) + def visit(self, node): + return f'{node.dest} = READINT' + + @visitor.when(nodes.PrintIntNode) + def visit(self, node): + return f'PRINT {node.value}' + printer = PrintVisitor() return (lambda ast: printer.visit(ast)) \ No newline at end of file From ac0b0e2a3d3330124dfaa706cf52df2d18486b4e Mon Sep 17 00:00:00 2001 From: Ale Date: Sun, 20 Feb 2022 10:34:07 -0800 Subject: [PATCH 57/83] fixing issues on register COOL built-in --- .../code_generation/cil/Base_COOL_to_CIL.py | 121 +++++++++++++++++- 1 file changed, 114 insertions(+), 7 deletions(-) diff --git a/src/utils/code_generation/cil/Base_COOL_to_CIL.py b/src/utils/code_generation/cil/Base_COOL_to_CIL.py index 66d0e6daa..b270eb4a0 100644 --- a/src/utils/code_generation/cil/Base_COOL_to_CIL.py +++ b/src/utils/code_generation/cil/Base_COOL_to_CIL.py @@ -99,14 +99,19 @@ def register_runtime_error(self, condition, msg): self.register_instruction(continue_node) def register_built_in(self): - self._register_Object() - self._register_IO() + self.__register_Object() + self.__register_IO() + self.__register_Int() + self.__register_String() + self.__register_Bool() - # tipos y funciones integrados en COOL - def _register_Object(self): + + + # convirtiendo tipos y funciones integrados en COOL en CIL + def __register_Object(self): type_node = self.register_type('Object') self.current_function = self.register_function(self.init_name('Object')) @@ -117,7 +122,7 @@ def _register_Object(self): self.current_function = self.register_function(self.to_function_name('abort', 'Object')) self.register_param(self.vself) vname = self.define_internal_local() - data_node = [dn for dn in self.dotdata if dn.value == 'Abort called from class '][0] + data_node = [dn for dn in self.dotdata if dn.value == 'Aborting... in class '][0] self.register_instruction(nodes.LoadNode(vname, data_node)) self.register_instruction(nodes.PrintStrNode(vname)) self.register_instruction(nodes.TypeNameNode(vname, self.vself.name)) @@ -145,7 +150,7 @@ def _register_Object(self): type_node.methods = [(name, self.to_function_name(name, 'Object')) for name in ['abort', 'type_name', 'copy']] type_node.methods += [('init', self.init_name('Object'))] - def _register_IO(self): + def __register_IO(self): type_node = self.register_type('IO') self.current_function = self.register_function(self.init_name('IO')) @@ -189,4 +194,106 @@ def _register_IO(self): type_node.methods = [(method, self.to_function_name(method, 'Object')) for method in ['type_name','abort','copy']] type_node.methods += [(name, self.to_function_name(name, 'IO')) for name in ['out_string', 'out_int', 'in_string', 'in_int']] - type_node.methods += [('init', self.init_name('IO'))] \ No newline at end of file + type_node.methods += [('init', self.init_name('IO'))] + + def __register_Int(self): + type_node = self.register_type('Int') + type_node.attributes = ['value'] + + self.current_function = self.register_function(self.init_name('Int')) + self.register_param(VariableInfo('val', None)) + instance = self.define_internal_local() + self.register_instruction(nodes.AllocateNode('Int', instance)) + self.register_instruction(nodes.SetAttrNode(instance, 'value', 'val', 'Int')) + self.register_instruction(nodes.ReturnNode(instance)) + + type_node.methods = [(method, self.to_function_name(method, 'Object')) for method in ['type_name','abort','copy']] + type_node.methods += [('init', self.init_name('Int'))] + + def __register_String(self): + type_node = self.register_type('String') + type_node.attributes = ['value', 'length'] + + self.current_function = self.register_function(self.init_name('String')) + self.register_param(VariableInfo('val', None)) + instance = self.define_internal_local() + self.register_instruction(nodes.AllocateNode('String', instance)) + self.register_instruction(nodes.SetAttrNode(instance, 'value', 'val', 'String')) + result = self.define_internal_local() + self.register_instruction(nodes.LengthNode(result, 'val')) + attr = self.define_internal_local() + self.register_instruction(nodes.ArgNode(result)) + self.register_instruction(nodes.StaticCallNode(self.init_name('Int'), attr)) + self.register_instruction(nodes.SetAttrNode(instance, 'length', attr, 'String')) + self.register_instruction(nodes.ReturnNode(instance)) + + self.current_function = self.register_function(self.to_function_name('length', 'String')) + self.register_param(self.vself) + result = self.define_internal_local() + self.register_instruction(nodes.GetAttrNode(result, self.vself.name, 'length', 'String')) + self.register_instruction(nodes.ReturnNode(result)) + + self.current_function = self.register_function(self.to_function_name('concat', 'String')) + self.register_param(self.vself) + self.register_param(VariableInfo('s', None)) + str_1 = self.define_internal_local() + str_2 = self.define_internal_local() + length_1 = self.define_internal_local() + length_2 = self.define_internal_local() + self.register_instruction(nodes.GetAttrNode(str_1, self.vself.name, 'value', 'String')) + self.register_instruction(nodes.GetAttrNode(str_2, 's', 'value', 'String')) + self.register_instruction(nodes.GetAttrNode(length_1, self.vself.name, 'length', 'String')) + self.register_instruction(nodes.GetAttrNode(length_2, 's', 'length', 'String')) + self.register_instruction(nodes.GetAttrNode(length_1, length_1, 'value', 'Int')) + self.register_instruction(nodes.GetAttrNode(length_2, length_2, 'value', 'Int')) + self.register_instruction(nodes.PlusNode(length_1, length_1, length_2)) + + result = self.define_internal_local() + self.register_instruction(nodes.ConcatNode(result, str_1, str_2, length_1)) + instance = self.define_internal_local() + self.register_instruction(nodes.ArgNode(result)) + self.register_instruction(nodes.StaticCallNode(self.init_name('String'), instance)) + self.register_instruction(nodes.ReturnNode(instance)) + + self.current_function = self.register_function(self.to_function_name('substr', 'String')) + self.register_param(self.vself) + self.register_param(VariableInfo('i', None)) + self.register_param(VariableInfo('l', None)) + result = self.define_internal_local() + index_value = self.define_internal_local() + length_value = self.define_internal_local() + length_attr = self.define_internal_local() + length_substr = self.define_internal_local() + less_value = self.define_internal_local() + str_value = self.define_internal_local() + self.register_instruction(nodes.GetAttrNode(str_value, self.vself.name, 'value', 'String')) + self.register_instruction(nodes.GetAttrNode(index_value, 'i', 'value', 'Int')) + self.register_instruction(nodes.GetAttrNode(length_value, 'l', 'value', 'Int')) + + self.register_instruction(nodes.GetAttrNode(length_attr, self.vself.name, 'length', 'String')) + self.register_instruction(nodes.PlusNode(length_substr, length_value, index_value)) + self.register_instruction(nodes.LessThanNode(less_value, length_attr, length_substr)) + self.register_runtime_error(less_value, 'Substring out of range') + self.register_instruction(nodes.SubstringNode(result, str_value, index_value, length_value)) + instance = self.define_internal_local() + self.register_instruction(nodes.ArgNode(result)) + self.register_instruction(nodes.StaticCallNode(self.init_name('String'), instance)) + self.register_instruction(nodes.ReturnNode(instance)) + + type_node.methods = [(method, self.to_function_name(method, 'Object')) for method in ['type_name','abort','copy']] + type_node.methods += [(name, self.to_function_name(name, 'String')) for name in ['length', 'concat', 'substr']] + type_node.methods += [('init', self.init_name('String'))] + + def __register_Bool(self): + type_node = self.register_type('Bool') + type_node.attributes = ['value'] + + self.current_function = self.register_function(self.init_name('Bool')) + self.register_param(VariableInfo('val', None)) + instance = self.define_internal_local() + self.register_instruction(nodes.AllocateNode('Bool', instance)) + self.register_instruction(nodes.SetAttrNode(instance, 'value', 'val', 'Bool')) + self.register_instruction(nodes.ReturnNode(instance)) + + type_node.methods = [(method, self.to_function_name(method, 'Object')) for method in ['type_name','abort','copy']] + type_node.methods += [('init', self.init_name('Bool'))] \ No newline at end of file From 0b14d596801c4fb764081a5993832fbcc0ab65e8 Mon Sep 17 00:00:00 2001 From: Ale Date: Sun, 20 Feb 2022 11:16:17 -0800 Subject: [PATCH 58/83] programNode - classDecNode --- src/main.py | 10 +++- src/utils/code_generation/cil/AST_CIL.py | 4 +- .../code_generation/cil/Base_COOL_to_CIL.py | 6 +- src/utils/code_generation/cil/COOL_to_CIL.py | 60 +++++++++++++++++-- .../code_generation/cil/print_CIL_AST.py | 13 ++-- 5 files changed, 75 insertions(+), 18 deletions(-) diff --git a/src/main.py b/src/main.py index 234d59e5e..1253c3984 100644 --- a/src/main.py +++ b/src/main.py @@ -9,8 +9,8 @@ from utils.semantic_check.type_collector import TypeCollector from utils.semantic_check.type_builder import TypeBuilder from utils.semantic_check.type_checker import TypeChecker - -from utils.parser.LALR_1 import LALR1_Parser +from utils.code_generation.cil.COOL_to_CIL import COOLtoCIL +from utils.code_generation.cil.print_CIL_AST import get_formatter if __name__ == "__main__": add = "codegen/arith.cl" @@ -64,4 +64,8 @@ print(error) raise Exception() -# generacion de codigo \ No newline at end of file +# generacion de codigo +cil_visitor = COOLtoCIL(context) +cil_ast = cil_visitor.visit(ast, scope) + +print(get_formatter()(cil_ast)) \ No newline at end of file diff --git a/src/utils/code_generation/cil/AST_CIL.py b/src/utils/code_generation/cil/AST_CIL.py index d0cd8fe3b..d0e9ca608 100644 --- a/src/utils/code_generation/cil/AST_CIL.py +++ b/src/utils/code_generation/cil/AST_CIL.py @@ -80,13 +80,13 @@ def __repr__(self): class GetAttrNode(InstructionNode): def __init__(self, dest, idx, attr, computed_type): self.dest = dest - self.idx = idx + self.id = idx self.attr = attr self.computed_type = computed_type class SetAttrNode(InstructionNode): def __init__(self, idx, attr, value, computed_type): - self.idx = idx + self.id = idx self.attr = attr self.value = value self.computed_type = computed_type diff --git a/src/utils/code_generation/cil/Base_COOL_to_CIL.py b/src/utils/code_generation/cil/Base_COOL_to_CIL.py index b270eb4a0..74a037557 100644 --- a/src/utils/code_generation/cil/Base_COOL_to_CIL.py +++ b/src/utils/code_generation/cil/Base_COOL_to_CIL.py @@ -37,10 +37,10 @@ def register_param(self, vinfo): return vinfo.name def register_local(self, vinfo, id=False): - if len(self.current_function.name) >= 8 and self.current_function.name[:8] == 'function': - name = f'local_{self.current_function.name[9:]}_{vinfo.name}_{len(self.localvars)}' + if len(self.current_function.id) >= 8 and self.current_function.id[:8] == 'function': + name = f'local_{self.current_function.id[9:]}_{vinfo.name}_{len(self.localvars)}' else: - name = f'local_{self.current_function.name[5:]}_{vinfo.name}_{len(self.localvars)}' + name = f'local_{self.current_function.id[5:]}_{vinfo.name}_{len(self.localvars)}' new_vinfo = VariableInfo(name, None) local_node = nodes.LocalNode(new_vinfo.name) diff --git a/src/utils/code_generation/cil/COOL_to_CIL.py b/src/utils/code_generation/cil/COOL_to_CIL.py index f0d6cf089..343ad42d4 100644 --- a/src/utils/code_generation/cil/COOL_to_CIL.py +++ b/src/utils/code_generation/cil/COOL_to_CIL.py @@ -1,9 +1,12 @@ import cmp.visitor as visitor +from cmp.semantic import VariableInfo from utils.ast.AST_Nodes import ast_nodes as nodes +from utils.code_generation.cil.AST_CIL import cil_ast as nodes_cil +from utils.code_generation.cil.Base_COOL_to_CIL import BaseCOOLToCIL -class COOLtoCIL: +class COOLtoCIL(BaseCOOLToCIL): def __init__(self, context): - self.context = context + BaseCOOLToCIL.__init__(self, context) @visitor.on('node') @@ -13,12 +16,61 @@ def visit(self, node, scope): @visitor.when(nodes.ProgramNode) def visit(self, node, scope=None): - pass + self.current_function = self.register_function('entry') + result = self.define_internal_local() + instance = self.register_local(VariableInfo('instance', None)) + self.register_instruction(nodes_cil.StaticCallNode(self.init_name('Main'), instance)) + self.register_instruction(nodes_cil.ArgNode(instance)) + self.register_instruction(nodes_cil.StaticCallNode(self.to_function_name('main', 'Main'), result)) + self.register_instruction(nodes_cil.ReturnNode(0)) + + self.register_data('Aborting... in class ') + self.register_built_in() + self.current_function = None + + for declaration, child_scope in zip(node.declarations, scope.children): + self.visit(declaration, child_scope) + + return nodes_cil.ProgramNode(self.dottypes, self.dotdata, self.dotcode) @visitor.when(nodes.ClassDeclarationNode) def visit(self, node, scope): - pass + self.current_type = self.context.get_type(node.id) + + type_node = self.register_type(node.id) + type_node.attributes = [attr.name for attr, _ in self.current_type.all_attributes()] + type_node.methods = [(method.name, self.to_function_name(method.name, xtype.name)) for method, xtype in self.current_type.all_methods()] + + func_declarations = (f for f in node.features if isinstance(f, nodes.MethDeclarationNode)) + for feature, child_scope in zip(func_declarations, scope.children): + self.visit(feature, child_scope) + + self.current_function = self.register_function(self.init_name(node.id)) + + instance = self.register_local(VariableInfo('instance', None)) + self.register_instruction(nodes_cil.AllocateNode(node.id, instance)) + + func = self.current_function + vtemp = self.define_internal_local() + + self.current_function = self.register_function(self.init_name(node.id, attr=True)) + self.register_param(self.vself) + if node.parent != 'Object' and node.parent != 'IO': + self.register_instruction(nodes_cil.ArgNode(self.vself.name)) + self.register_instruction(nodes_cil.StaticCallNode(self.init_name(node.parent, attr=True), vtemp)) + attr_declarations = (f for f in node.features if isinstance(f, nodes.AttrDeclarationNode)) + for feature in attr_declarations: + self.visit(feature, scope) + + self.current_function = func + self.register_instruction(nodes_cil.ArgNode(instance)) + self.register_instruction(nodes_cil.StaticCallNode(self.init_name(node.id, attr=True), vtemp)) + + self.register_instruction(nodes_cil.ReturnNode(instance)) + self.current_function = None + + self.current_type = None @visitor.when(nodes.AttrDeclarationNode) def visit(self, node, scope): diff --git a/src/utils/code_generation/cil/print_CIL_AST.py b/src/utils/code_generation/cil/print_CIL_AST.py index 7af87b1f5..d4909ef39 100644 --- a/src/utils/code_generation/cil/print_CIL_AST.py +++ b/src/utils/code_generation/cil/print_CIL_AST.py @@ -3,7 +3,8 @@ def get_formatter(): - class PrintVisitor(object): + class PrintCIL(object): + @visitor.on('node') def visit(self, node): pass @@ -21,11 +22,11 @@ def visit(self, node): attributes = '\n\t'.join(f'attribute {x}' for x in node.attributes) methods = '\n\t'.join(f'method {x}: {y}' for x,y in node.methods) - return f'type {node.name} {{\n\t{attributes}\n\n\t{methods}\n}}' + return f'type {node.id} {{\n\t{attributes}\n\n\t{methods}\n}}' @visitor.when(nodes.DataNode) def visit(self, node): - return f'{node.idx} = {node.value}' + return f'{node.id} = {node.value}' @visitor.when(nodes.FunctionNode) def visit(self, node): @@ -67,7 +68,7 @@ def visit(self, node): def visit(self, node): return f'{node.dest} = {node.op_l} <= {node.op_r}' - @visitor.when(nodes.LessNode) + @visitor.when(nodes.LessThanNode) def visit(self, node): return f'{node.dest} = {node.op_l} < {node.op_r}' @@ -81,7 +82,7 @@ def visit(self, node): @visitor.when(nodes.SetAttrNode) def visit(self, node): - return f'SETATTR {node.idx} {node.attr} {node.value}' + return f'SETATTR {node.id} {node.attr} {node.value}' @visitor.when(nodes.AllocateNode) def visit(self, node): @@ -171,6 +172,6 @@ def visit(self, node): def visit(self, node): return f'PRINT {node.value}' - printer = PrintVisitor() + printer = PrintCIL() return (lambda ast: printer.visit(ast)) \ No newline at end of file From e6f4852237003adfebc893d15e7cb39f1b9cf8aa Mon Sep 17 00:00:00 2001 From: Ale Date: Sun, 20 Feb 2022 11:59:21 -0800 Subject: [PATCH 59/83] working on cool to cil visitor --- src/utils/code_generation/cil/COOL_to_CIL.py | 60 +++++++++++++++++--- 1 file changed, 53 insertions(+), 7 deletions(-) diff --git a/src/utils/code_generation/cil/COOL_to_CIL.py b/src/utils/code_generation/cil/COOL_to_CIL.py index 343ad42d4..84c49ef7a 100644 --- a/src/utils/code_generation/cil/COOL_to_CIL.py +++ b/src/utils/code_generation/cil/COOL_to_CIL.py @@ -51,7 +51,7 @@ def visit(self, node, scope): instance = self.register_local(VariableInfo('instance', None)) self.register_instruction(nodes_cil.AllocateNode(node.id, instance)) - func = self.current_function + temp_f = self.current_function vtemp = self.define_internal_local() self.current_function = self.register_function(self.init_name(node.id, attr=True)) @@ -63,23 +63,46 @@ def visit(self, node, scope): for feature in attr_declarations: self.visit(feature, scope) - self.current_function = func + self.current_function = temp_f self.register_instruction(nodes_cil.ArgNode(instance)) self.register_instruction(nodes_cil.StaticCallNode(self.init_name(node.id, attr=True), vtemp)) - self.register_instruction(nodes_cil.ReturnNode(instance)) self.current_function = None - self.current_type = None + @visitor.when(nodes.AttrDeclarationNode) def visit(self, node, scope): - pass + if node.expr: + self.visit(node.expr, scope) + self.register_instruction(nodes_cil.SetAttrNode(self.vself.name, node.id, scope._return, self.current_type)) + elif node.type in self.value_types: + vtemp = self.define_internal_local() + self.register_instruction(nodes_cil.AllocateNode(node.type, vtemp)) + self.register_instruction(nodes_cil.SetAttrNode(self.vself.name, node.id, vtemp, self.current_type)) @visitor.when(nodes.MethDeclarationNode) def visit(self, node, scope): - pass + self.current_method = self.current_type.get_method(node.id) + self.current_function = self.register_function(self.to_function_name(self.current_method.name, self.current_type.name)) + + self.register_param(self.vself) + for param_name, _ in node.params: + self.register_param(VariableInfo(param_name, None)) + + scope._return = None + self.visit(node.body, scope) + + if scope._return is None: + self.register_instruction(nodes_cil.ReturnNode('')) + elif self.current_function.name == 'entry': + self.register_instruction(nodes_cil.ReturnNode(0)) + else: + self.register_instruction(nodes_cil.ReturnNode(scope._return)) + + self.current_method = None + @visitor.when(nodes.AssignNode) def visit(self, node, scope): @@ -88,7 +111,30 @@ def visit(self, node, scope): @visitor.when(nodes.IfThenElseNode) def visit(self, node, scope): - pass + vresult = self.register_local(VariableInfo('if_then_else_value', None)) + vcondition = self.define_internal_local() + + then_label_node = self.register_label('then_label') + else_label_node = self.register_label('else_label') + continue_label_node = self.register_label('continue_label') + + self.visit(node.if_expr, scope) + self.register_instruction(nodes_cil.GetAttrNode(vcondition, scope._return, 'value', 'Bool')) + self.register_instruction(nodes_cil.IfGotoNode(vcondition, then_label_node.label)) + + self.register_instruction(nodes_cil.GotoNode(else_label_node.label)) + + self.register_instruction(then_label_node) + self.visit(node.then_expr, scope) + self.register_instruction(nodes_cil.AssignNode(vresult, scope._return)) + self.register_instruction(nodes_cil.GotoNode(continue_label_node.label)) + + self.register_instruction(else_label_node) + self.visit(node.else_expr, scope) + self.register_instruction(nodes_cil.AssignNode(vresult, scope._return)) + + self.register_instruction(continue_label_node) + scope._return = vresult @visitor.when(nodes.WhileNode) From 29872f4deb0fb02bbd7a7d92f50a823c34178fc1 Mon Sep 17 00:00:00 2001 From: Ale Date: Sun, 20 Feb 2022 12:23:37 -0800 Subject: [PATCH 60/83] modifying cil ast --- src/cmp/semantic.py | 2 ++ src/utils/code_generation/cil/AST_CIL.py | 5 ++++- src/utils/code_generation/cil/print_CIL_AST.py | 4 ++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/cmp/semantic.py b/src/cmp/semantic.py index 1476d66d4..41b90fa85 100644 --- a/src/cmp/semantic.py +++ b/src/cmp/semantic.py @@ -210,6 +210,8 @@ def __init__(self, parent=None): self.children = [] self.index = 0 if parent is None else len(parent) + self._return = None + def __len__(self): return len(self.locals) diff --git a/src/utils/code_generation/cil/AST_CIL.py b/src/utils/code_generation/cil/AST_CIL.py index d0e9ca608..21c5e3d21 100644 --- a/src/utils/code_generation/cil/AST_CIL.py +++ b/src/utils/code_generation/cil/AST_CIL.py @@ -194,4 +194,7 @@ def __init__(self, dest): class PrintIntNode(InstructionNode): def __init__(self, value): - self.value = value \ No newline at end of file + self.value = value + + class VoidNode(InstructionNode): + pass \ No newline at end of file diff --git a/src/utils/code_generation/cil/print_CIL_AST.py b/src/utils/code_generation/cil/print_CIL_AST.py index d4909ef39..275b206fc 100644 --- a/src/utils/code_generation/cil/print_CIL_AST.py +++ b/src/utils/code_generation/cil/print_CIL_AST.py @@ -172,6 +172,10 @@ def visit(self, node): def visit(self, node): return f'PRINT {node.value}' + @visitor.when(nodes.VoidNode) + def visit(self, node): + return 'VOID' + printer = PrintCIL() return (lambda ast: printer.visit(ast)) \ No newline at end of file From 182b96a9b50377a0e4648feb0a2cc2dd19c44b58 Mon Sep 17 00:00:00 2001 From: Ale Date: Sun, 20 Feb 2022 12:29:25 -0800 Subject: [PATCH 61/83] working on cil visitor --- src/utils/code_generation/cil/COOL_to_CIL.py | 23 +++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/utils/code_generation/cil/COOL_to_CIL.py b/src/utils/code_generation/cil/COOL_to_CIL.py index 84c49ef7a..17fb4c99c 100644 --- a/src/utils/code_generation/cil/COOL_to_CIL.py +++ b/src/utils/code_generation/cil/COOL_to_CIL.py @@ -76,7 +76,7 @@ def visit(self, node, scope): if node.expr: self.visit(node.expr, scope) self.register_instruction(nodes_cil.SetAttrNode(self.vself.name, node.id, scope._return, self.current_type)) - elif node.type in self.value_types: + elif node.type in ['String', 'Int', 'Bool']: vtemp = self.define_internal_local() self.register_instruction(nodes_cil.AllocateNode(node.type, vtemp)) self.register_instruction(nodes_cil.SetAttrNode(self.vself.name, node.id, vtemp, self.current_type)) @@ -96,7 +96,7 @@ def visit(self, node, scope): if scope._return is None: self.register_instruction(nodes_cil.ReturnNode('')) - elif self.current_function.name == 'entry': + elif self.current_function.id == 'entry': self.register_instruction(nodes_cil.ReturnNode(0)) else: self.register_instruction(nodes_cil.ReturnNode(scope._return)) @@ -139,7 +139,24 @@ def visit(self, node, scope): @visitor.when(nodes.WhileNode) def visit(self, node, scope): - pass + vcondition = self.define_internal_local() + while_label_node = self.register_label('while_label') + loop_label_node = self.register_label('loop_label') + pool_label_node = self.register_label('pool_label') + + self.register_instruction(while_label_node) + self.visit(node.conditional_expr, scope) + self.register_instruction(nodes_cil.GetAttrNode(vcondition, scope.ret_expr, 'value', 'Bool')) + self.register_instruction(nodes_cil.IfGotoNode(vcondition, loop_label_node.label)) + + self.register_instruction(nodes_cil.GotoNode(pool_label_node.label)) + self.register_instruction(loop_label_node) + self.visit(node.loop_expr, scope) + + self.register_instruction(nodes_cil.GotoNode(while_label_node.label)) + self.register_instruction(pool_label_node) + + scope.ret_expr = nodes_cil.VoidNode() @visitor.when(nodes.BlockNode) From 0d06518e7d89a839e1211cb475f992bdbaf05da2 Mon Sep 17 00:00:00 2001 From: Ale Date: Sun, 20 Feb 2022 14:55:25 -0800 Subject: [PATCH 62/83] working on cil visitor --- src/utils/code_generation/cil/COOL_to_CIL.py | 58 ++++++++++++++++++-- 1 file changed, 52 insertions(+), 6 deletions(-) diff --git a/src/utils/code_generation/cil/COOL_to_CIL.py b/src/utils/code_generation/cil/COOL_to_CIL.py index 17fb4c99c..8721030c6 100644 --- a/src/utils/code_generation/cil/COOL_to_CIL.py +++ b/src/utils/code_generation/cil/COOL_to_CIL.py @@ -106,7 +106,26 @@ def visit(self, node, scope): @visitor.when(nodes.AssignNode) def visit(self, node, scope): - pass + self.visit(node.expr, scope) + + try: + self.current_type.get_attribute(node.id) + self.register_instruction(nodes_cil.SetAttrNode(self.vself.name, node.id, scope._return, self.current_type.name)) + + except AttributeError: + vname = None + param_names = [pn.name for pn in self.current_function.params] + if node.id in param_names: + for n in param_names: + if node.id in n.split("_"): + vname = n + break + else: + for n in [lv.name for lv in self.current_function.localvars]: + if node.id in n.split("_"): + vname = n + break + self.register_instruction(nodes_cil.AssignNode(vname, scope._return)) @visitor.when(nodes.IfThenElseNode) @@ -146,7 +165,7 @@ def visit(self, node, scope): self.register_instruction(while_label_node) self.visit(node.conditional_expr, scope) - self.register_instruction(nodes_cil.GetAttrNode(vcondition, scope.ret_expr, 'value', 'Bool')) + self.register_instruction(nodes_cil.GetAttrNode(vcondition, scope._return, 'value', 'Bool')) self.register_instruction(nodes_cil.IfGotoNode(vcondition, loop_label_node.label)) self.register_instruction(nodes_cil.GotoNode(pool_label_node.label)) @@ -156,17 +175,34 @@ def visit(self, node, scope): self.register_instruction(nodes_cil.GotoNode(while_label_node.label)) self.register_instruction(pool_label_node) - scope.ret_expr = nodes_cil.VoidNode() + scope._return = nodes_cil.VoidNode() @visitor.when(nodes.BlockNode) def visit(self, node, scope): - pass + for expr in node.exprs: + self.visit(node.expr_list, scope) @visitor.when(nodes.LetNode) def visit(self, node, scope): - pass + vresult = self.register_local(VariableInfo('let_in_value', None)) + + for idx, typex, id_expr in node.identifiers: + if idx in self.ids: + vname = self.ids[idx] + else: + vname = self.register_local(VariableInfo(idx, typex), id=True) + + if id_expr: + self.visit(id_expr, scope) + self.register_instruction(nodes_cil.AssignNode(vname, scope._return)) + elif typex in self.value_types: + self.register_instruction(nodes_cil.AllocateNode(typex, vname)) + + self.visit(node.in_expr, scope) + self.register_instruction(nodes_cil.AssignNode(vresult, scope._return)) + scope._return = vresult @visitor.when(nodes.CaseNode) @@ -176,7 +212,17 @@ def visit(self, node, scope): @visitor.when(nodes.NotNode) def visit(self, node, scope): - pass + vname = self.define_internal_local() + value = self.define_internal_local() + instance = self.define_internal_local() + + self.visit(node.expr, scope) + self.register_instruction(nodes_cil.GetAttrNode(value, scope._return, 'value', 'Bool')) + self.register_instruction(nodes_cil.MinusNode(vname, 1, value)) + + self.register_instruction(nodes_cil.ArgNode(vname)) + self.register_instruction(nodes_cil.StaticCallNode(self.init_name('Bool'), instance)) + scope._return = instance @visitor.when(nodes.ConstantNumNode) From 3aa7c4dc64a2256db5b2b186f7446d23d5b79acc Mon Sep 17 00:00:00 2001 From: Ale Date: Sun, 20 Feb 2022 15:21:52 -0800 Subject: [PATCH 63/83] modifying cil ast - begin with aritmectic --- src/utils/code_generation/cil/AST_CIL.py | 9 +- src/utils/code_generation/cil/COOL_to_CIL.py | 92 +++++++++++++++++++- 2 files changed, 93 insertions(+), 8 deletions(-) diff --git a/src/utils/code_generation/cil/AST_CIL.py b/src/utils/code_generation/cil/AST_CIL.py index 21c5e3d21..eb5f5cf55 100644 --- a/src/utils/code_generation/cil/AST_CIL.py +++ b/src/utils/code_generation/cil/AST_CIL.py @@ -45,9 +45,6 @@ class AssignNode(InstructionNode): def __init__(self, left, right): self.left = left self.right = right - - def __repr__(self): - return f"{self.left} = {self.right}" class ArithmeticNode(InstructionNode): def __init__(self, dest, op_l, op_r): @@ -74,8 +71,10 @@ class LessEqualNode(ArithmeticNode): pass class EqualNode(ArithmeticNode): - def __repr__(self): - return f"{self.dest} = {self.op_l} == {self.op_r}" + pass + + class EqualStrNode(EqualNode): + pass class GetAttrNode(InstructionNode): def __init__(self, dest, idx, attr, computed_type): diff --git a/src/utils/code_generation/cil/COOL_to_CIL.py b/src/utils/code_generation/cil/COOL_to_CIL.py index 8721030c6..db242a7db 100644 --- a/src/utils/code_generation/cil/COOL_to_CIL.py +++ b/src/utils/code_generation/cil/COOL_to_CIL.py @@ -281,14 +281,100 @@ def visit(self, node, scope): @visitor.when(nodes.LessThanNode) def visit(self, node, scope): - pass + vname = self.define_internal_local() + left_value = self.define_internal_local() + right_value = self.define_internal_local() + instance = self.define_internal_local() + + self.visit(node.left, scope) + left = scope._return + + self.visit(node.right, scope) + right = scope._return + + self.register_instruction(nodes_cil.GetAttrNode(left_value, left, 'value', 'Bool')) + self.register_instruction(nodes_cil.GetAttrNode(right_value, right, 'value', 'Bool')) + self.register_instruction(nodes_cil.LessThanNode(vname, left_value, right_value)) + + self.register_instruction(nodes_cil.ArgNode(vname)) + self.register_instruction(nodes_cil.StaticCallNode(self.init_name('Bool'), instance)) + scope._return = instance @visitor.when(nodes.LessEqualNode) def visit(self, node, scope): - pass + vname = self.define_internal_local() + left_value = self.define_internal_local() + right_value = self.define_internal_local() + instance = self.define_internal_local() + + self.visit(node.left, scope) + left = scope._return + + self.visit(node.right, scope) + right = scope._return + + self.register_instruction(nodes_cil.GetAttrNode(left_value, left, 'value', 'Bool')) + self.register_instruction(nodes_cil.GetAttrNode(right_value, right, 'value', 'Bool')) + self.register_instruction(nodes_cil.LessEqualNode(vname, left_value, right_value)) + + self.register_instruction(nodes_cil.ArgNode(vname)) + self.register_instruction(nodes_cil.StaticCallNode(self.init_name('Bool'), instance)) + scope._return = instance @visitor.when(nodes.EqualNode) def visit(self, node, scope): - pass \ No newline at end of file + vname = self.define_internal_local() + type_left = self.define_internal_local() + _bool = self.define_internal_local() + _string = self.define_internal_local() + _int = self.define_internal_local() + left_value = self.define_internal_local() + right_value = self.define_internal_local() + vresult = self.define_internal_local() + instance = self.define_internal_local() + + self.visit(node.left, scope) + left = scope._return + + self.visit(node.right, scope) + right = scope._return + + self.register_instruction(nodes_cil.TypeNameNode(type_left, left)) + self.register_instruction(nodes_cil.NameNode(_int, 'Int')) + self.register_instruction(nodes_cil.NameNode(_bool, 'Bool')) + self.register_instruction(nodes_cil.NameNode(_string, 'String')) + + string_node = self.register_label('string_label') + int_node = self.register_label('int_label') + reference_node = self.register_label('reference_label') + continue_node = self.register_label('continue_label') + + self.register_instruction(nodes_cil.EqualNode(vresult, type_left, _int)) + self.register_instruction(nodes_cil.IfGotoNode(vresult, int_node.label)) + self.register_instruction(nodes_cil.EqualNode(vresult, type_left, _bool)) + self.register_instruction(nodes_cil.IfGotoNode(vresult, int_node.label)) + self.register_instruction(nodes_cil.EqualNode(vresult, type_left, _string)) + self.register_instruction(nodes_cil.IfGotoNode(vresult, string_node.label)) + self.register_instruction(nodes_cil.GotoNode(reference_node.label)) + + self.register_instruction(int_node) + self.register_instruction(nodes_cil.GetAttrNode(left_value, left, 'value', 'Int')) + self.register_instruction(nodes_cil.GetAttrNode(right_value, right, 'value', 'Int')) + self.register_instruction(nodes_cil.EqualNode(vname, left_value, right_value)) + self.register_instruction(nodes_cil.GotoNode(continue_node.label)) + + self.register_instruction(string_node) + self.register_instruction(nodes_cil.GetAttrNode(left_value, left, 'value', 'String')) + self.register_instruction(nodes_cil.GetAttrNode(right_value, right, 'value', 'String')) + self.register_instruction(nodes_cil.EqualStrNode(vname, left_value, right_value)) + self.register_instruction(nodes_cil.GotoNode(continue_node.label)) + + self.register_instruction(reference_node) + self.register_instruction(nodes_cil.EqualNode(vname, left, right)) + + self.register_instruction(continue_node) + self.register_instruction(nodes_cil.ArgNode(vname)) + self.register_instruction(nodes_cil.StaticCallNode(self.init_name('Bool'), instance)) + scope._return = instance \ No newline at end of file From 0eeacedb91f5709cfeebaaf21e6962cd51a48e47 Mon Sep 17 00:00:00 2001 From: Ale Date: Sun, 20 Feb 2022 15:57:26 -0800 Subject: [PATCH 64/83] arith to cil --- src/utils/code_generation/cil/COOL_to_CIL.py | 68 ++++++++++++++++++-- 1 file changed, 64 insertions(+), 4 deletions(-) diff --git a/src/utils/code_generation/cil/COOL_to_CIL.py b/src/utils/code_generation/cil/COOL_to_CIL.py index db242a7db..4a9dcd084 100644 --- a/src/utils/code_generation/cil/COOL_to_CIL.py +++ b/src/utils/code_generation/cil/COOL_to_CIL.py @@ -261,22 +261,82 @@ def visit(self, node, scope): @visitor.when(nodes.PlusNode) def visit(self, node, scope): - pass + vname = self.define_internal_local() + left_value = self.define_internal_local() + right_value = self.define_internal_local() + + self.visit(node.left, scope) + self.register_instruction(nodes_cil.GetAttrNode(left_value, scope._return, 'value', 'Int')) + self.visit(node.right, scope) + self.register_instruction(nodes_cil.GetAttrNode(right_value, scope._return, 'value', 'Int')) + + self.register_instruction(nodes_cil.PlusNode(vname, left_value, right_value)) + instance = self.define_internal_local() + + self.register_instruction(nodes_cil.ArgNode(vname)) + self.register_instruction(nodes_cil.StaticCallNode(self.init_name('Int'), instance)) + scope._return = instance @visitor.when(nodes.MinusNode) def visit(self, node, scope): - pass + vname = self.define_internal_local() + left_value = self.define_internal_local() + right_value = self.define_internal_local() + + self.visit(node.left, scope) + self.register_instruction(nodes_cil.GetAttrNode(left_value, scope._return, 'value', 'Int')) + self.visit(node.right, scope) + self.register_instruction(nodes_cil.GetAttrNode(right_value, scope._return, 'value', 'Int')) + + self.register_instruction(nodes_cil.MinusNode(vname, left_value, right_value)) + instance = self.define_internal_local() + + self.register_instruction(nodes_cil.ArgNode(vname)) + self.register_instruction(nodes_cil.StaticCallNode(self.init_name('Int'), instance)) + scope._return = instance @visitor.when(nodes.StarNode) def visit(self, node, scope): - pass + vname = self.define_internal_local() + left_value = self.define_internal_local() + right_value = self.define_internal_local() + + self.visit(node.left, scope) + self.register_instruction(nodes_cil.GetAttrNode(left_value, scope._return, 'value', 'Int')) + self.visit(node.right, scope) + self.register_instruction(nodes_cil.GetAttrNode(right_value, scope._return, 'value', 'Int')) + + self.register_instruction(nodes_cil.StarNode(vname, left_value, right_value)) + instance = self.define_internal_local() + + self.register_instruction(nodes_cil.ArgNode(vname)) + self.register_instruction(nodes_cil.StaticCallNode(self.init_name('Int'), instance)) + scope._return = instance @visitor.when(nodes.DivNode) def visit(self, node, scope): - pass + vname = self.define_internal_local() + left_value = self.define_internal_local() + right_value = self.define_internal_local() + + self.visit(node.left, scope) + self.register_instruction(nodes_cil.GetAttrNode(left_value, scope._return, 'value', 'Int')) + self.visit(node.right, scope) + self.register_instruction(nodes_cil.GetAttrNode(right_value, scope._return, 'value', 'Int')) + + vresult = self.define_internal_local() + self.register_instruction(nodes_cil.EqualNode(vresult, right_value, 0)) + self.register_runtime_error(vresult, f'({node.line},{node.column}) - RuntimeError: Division by zero\n') + + self.register_instruction(nodes_cil.DivNode(vname, left_value, right_value)) + instance = self.define_internal_local() + + self.register_instruction(nodes_cil.ArgNode(vname)) + self.register_instruction(nodes_cil.StaticCallNode(self.init_name('Int'), instance)) + scope._return = instance @visitor.when(nodes.LessThanNode) From 8653e933a638b3fc20aa8d6a4595f65871170ecd Mon Sep 17 00:00:00 2001 From: Ale Date: Sun, 20 Feb 2022 16:04:42 -0800 Subject: [PATCH 65/83] adding complNode to cil ast --- src/utils/code_generation/cil/AST_CIL.py | 7 ++++++- src/utils/code_generation/cil/print_CIL_AST.py | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/utils/code_generation/cil/AST_CIL.py b/src/utils/code_generation/cil/AST_CIL.py index eb5f5cf55..24f439d6b 100644 --- a/src/utils/code_generation/cil/AST_CIL.py +++ b/src/utils/code_generation/cil/AST_CIL.py @@ -196,4 +196,9 @@ def __init__(self, value): self.value = value class VoidNode(InstructionNode): - pass \ No newline at end of file + pass + + class ComplementNode(InstructionNode): + def __init__(self, dest, idx): + self.dest = dest + self.id = idx \ No newline at end of file diff --git a/src/utils/code_generation/cil/print_CIL_AST.py b/src/utils/code_generation/cil/print_CIL_AST.py index 275b206fc..ac54779de 100644 --- a/src/utils/code_generation/cil/print_CIL_AST.py +++ b/src/utils/code_generation/cil/print_CIL_AST.py @@ -176,6 +176,10 @@ def visit(self, node): def visit(self, node): return 'VOID' + @visitor.when(nodes.ComplementNode) + def visit(self, node): + return f'{node.dest} = COMPLEMENT {node.id}' + printer = PrintCIL() return (lambda ast: printer.visit(ast)) \ No newline at end of file From bf6beba27e46bc6d3bda5259be0c7f2e26d4bbbb Mon Sep 17 00:00:00 2001 From: Ale Date: Sun, 20 Feb 2022 16:26:01 -0800 Subject: [PATCH 66/83] atomic nodes to cil --- src/utils/code_generation/cil/COOL_to_CIL.py | 95 ++++++++++++++++++-- 1 file changed, 87 insertions(+), 8 deletions(-) diff --git a/src/utils/code_generation/cil/COOL_to_CIL.py b/src/utils/code_generation/cil/COOL_to_CIL.py index 4a9dcd084..262cdfdca 100644 --- a/src/utils/code_generation/cil/COOL_to_CIL.py +++ b/src/utils/code_generation/cil/COOL_to_CIL.py @@ -126,6 +126,11 @@ def visit(self, node, scope): vname = n break self.register_instruction(nodes_cil.AssignNode(vname, scope._return)) + + + @visitor.when(nodes.CallNode) + def visit(self, node, scope): + pass @visitor.when(nodes.IfThenElseNode) @@ -227,36 +232,110 @@ def visit(self, node, scope): @visitor.when(nodes.ConstantNumNode) def visit(self, node, scope): - pass + instance = self.define_internal_local() + self.register_instruction(nodes_cil.ArgNode(int(node.lex))) + self.register_instruction(nodes_cil.StaticCallNode(self.init_name('Int'), instance)) + scope._return = instance @visitor.when(nodes.ConstantBoolNode) def visit(self, node, scope): - pass + if node.lex == 'true': + value = 1 + + else: + value = 0 + + instance = self.define_internal_local() + self.register_instruction(nodes_cil.ArgNode(value)) + self.register_instruction(nodes_cil.StaticCallNode(self.init_name('Bool'), instance)) + scope._return = instance @visitor.when(nodes.ConstantStringNode) def visit(self, node, scope): - pass + try: + data_node = [dn for dn in self.dotdata if dn.value == node.lex][0] + + except IndexError: + data_node = self.register_data(node.lex) + vmsg = self.register_local(VariableInfo('msg', None)) + instance = self.define_internal_local() + + self.register_instruction(nodes_cil.LoadNode(vmsg, data_node)) + self.register_instruction(nodes_cil.ArgNode(vmsg)) + self.register_instruction(nodes_cil.StaticCallNode(self.init_name('String'), instance)) + scope._return = instance @visitor.when(nodes.VariableNode) def visit(self, node, scope): - pass + try: + self.current_type.get_attribute(node.lex) + attr = self.register_local(VariableInfo(node.lex, None), id=True) + self.register_instruction(nodes_cil.GetAttrNode(attr, self.vself.name, node.lex, self.current_type.name)) + scope._return = attr + + except AttributeError: + param_names = [pn.name for pn in self.current_function.params] + if node.lex in param_names: + for n in param_names: + if node.lex == n: + scope._return = n + break + else: + scope._return = self.ids[node.lex] @visitor.when(nodes.InstantiateNode) def visit(self, node, scope): - pass + instance = self.define_internal_local() + + if node.lex == 'SELF_TYPE': + vtype = self.define_internal_local() + self.register_instruction(nodes_cil.TypeOfNode(self.vself.name, vtype)) + self.register_instruction(nodes_cil.AllocateNode(vtype, instance)) + + elif node.lex == 'Int' or node.lex == 'Bool': + self.register_instruction(nodes_cil.ArgNode(0)) + + elif node.lex == 'String': + data_node = [dn for dn in self.dotdata if dn.value == ''][0] + vmsg = self.register_local(VariableInfo('msg', None)) + self.register_instruction(nodes_cil.LoadNode(vmsg, data_node)) + self.register_instruction(nodes_cil.ArgNode(vmsg)) + + self.register_instruction(nodes_cil.StaticCallNode(self.init_name(node.lex), instance)) + scope._return = instance @visitor.when(nodes.IsVoidNode) def visit(self, node, scope): - pass + void = nodes_cil.VoidNode() + value = self.define_internal_local() + + self.visit(node.lex, scope) + self.register_instruction(nodes_cil.AssignNode(value, scope._return)) + vresult = self.define_internal_local() + + self.register_instruction(nodes_cil.EqualNode(vresult, value, void)) + self.register_instruction(nodes_cil.ArgNode(vresult)) + self.register_instruction(nodes_cil.StaticCallNode(self.init_name("Bool"), vresult)) + scope._return = vresult + @visitor.when(nodes.ComplementNode) def visit(self, node, scope): - pass + vname = self.define_internal_local() + value = self.define_internal_local() + instance = self.define_internal_local() + + self.visit(node.lex, scope) + self.register_instruction(nodes_cil.GetAttrNode(value, scope._return, 'value', 'Int')) + self.register_instruction(nodes_cil.ComplementNode(vname, value)) + self.register_instruction(nodes_cil.ArgNode(vname)) + self.register_instruction(nodes_cil.StaticCallNode(self.init_name('Int'), instance)) + scope._return = instance @visitor.when(nodes.PlusNode) @@ -333,7 +412,7 @@ def visit(self, node, scope): self.register_instruction(nodes_cil.DivNode(vname, left_value, right_value)) instance = self.define_internal_local() - + self.register_instruction(nodes_cil.ArgNode(vname)) self.register_instruction(nodes_cil.StaticCallNode(self.init_name('Int'), instance)) scope._return = instance From f8d1fe3b3f7e9be2df624fd50ea781c14d0d9938 Mon Sep 17 00:00:00 2001 From: Ale Date: Sun, 20 Feb 2022 21:34:35 -0800 Subject: [PATCH 67/83] call node to cil --- src/utils/code_generation/cil/COOL_to_CIL.py | 21 +++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/utils/code_generation/cil/COOL_to_CIL.py b/src/utils/code_generation/cil/COOL_to_CIL.py index 262cdfdca..4522da024 100644 --- a/src/utils/code_generation/cil/COOL_to_CIL.py +++ b/src/utils/code_generation/cil/COOL_to_CIL.py @@ -130,7 +130,26 @@ def visit(self, node, scope): @visitor.when(nodes.CallNode) def visit(self, node, scope): - pass + if node.obj == None and node.type == None: + args = [] + for arg in node.args: + vname = self.register_local(VariableInfo(f'{node.id}_arg', None), id=True) + self.visit(arg, scope) + self.register_instruction(nodes_cil.AssignNode(vname, scope._return)) + args.append(nodes_cil.ArgNode(vname)) + result = self.register_local(VariableInfo(f'return_value_of_{node.id}', None), id=True) + + self.register_instruction(nodes_cil.ArgNode(self.vself.name)) + for arg in args: + self.register_instruction(arg) + + type_of_node = self.register_local(VariableInfo(f'{self.vself.name}_type', None)) + self.register_instruction(nodes_cil.TypeOfNode(self.vself.name, type_of_node)) + self.register_instruction(nodes_cil.DynamicCallNode(type_of_node, node.id, result, self.current_type.name)) + scope._return = result + + else: + pass @visitor.when(nodes.IfThenElseNode) From 2d03d23e2c84af8a2177ad371e1ea43e7ebc0d6e Mon Sep 17 00:00:00 2001 From: Ale Date: Sun, 20 Feb 2022 22:38:24 -0800 Subject: [PATCH 68/83] cool to cil --- src/main.py | 2 +- src/utils/code_generation/cil/COOL_to_CIL.py | 122 +++++++++++++++++-- src/utils/semantic_check/type_checker.py | 1 + 3 files changed, 111 insertions(+), 14 deletions(-) diff --git a/src/main.py b/src/main.py index 1253c3984..2f244acb5 100644 --- a/src/main.py +++ b/src/main.py @@ -13,7 +13,7 @@ from utils.code_generation.cil.print_CIL_AST import get_formatter if __name__ == "__main__": - add = "codegen/arith.cl" + add = "codegen/graph.cl" path: str = f"{Path.cwd()}/tests/{add}" if os.path.exists( f"{Path.cwd()}/tests/{add}") else f"{Path.cwd()}/../tests/{add}" diff --git a/src/utils/code_generation/cil/COOL_to_CIL.py b/src/utils/code_generation/cil/COOL_to_CIL.py index 4522da024..7c8dd1d3a 100644 --- a/src/utils/code_generation/cil/COOL_to_CIL.py +++ b/src/utils/code_generation/cil/COOL_to_CIL.py @@ -1,5 +1,5 @@ import cmp.visitor as visitor -from cmp.semantic import VariableInfo +from cmp.semantic import SemanticError, VariableInfo from utils.ast.AST_Nodes import ast_nodes as nodes from utils.code_generation.cil.AST_CIL import cil_ast as nodes_cil from utils.code_generation.cil.Base_COOL_to_CIL import BaseCOOLToCIL @@ -109,19 +109,19 @@ def visit(self, node, scope): self.visit(node.expr, scope) try: - self.current_type.get_attribute(node.id) + self.current_type.get_attribute(node.id, None) self.register_instruction(nodes_cil.SetAttrNode(self.vself.name, node.id, scope._return, self.current_type.name)) - except AttributeError: + except SemanticError: vname = None - param_names = [pn.name for pn in self.current_function.params] + param_names = [pn.id for pn in self.current_function.params] if node.id in param_names: for n in param_names: if node.id in n.split("_"): vname = n break else: - for n in [lv.name for lv in self.current_function.localvars]: + for n in [lv.id for lv in self.current_function.localvars]: if node.id in n.split("_"): vname = n break @@ -149,7 +149,40 @@ def visit(self, node, scope): scope._return = result else: - pass + args = [] + for arg in node.args: + vname = self.register_local(VariableInfo(f'{node.id}_arg', None), id=True) + self.visit(arg, scope) + self.register_instruction(nodes_cil.AssignNode(vname, scope._return)) + args.append(nodes_cil.ArgNode(vname)) + + result = self.register_local(VariableInfo(f'return_value_of_{node.id}', None), id=True) + + vobj = self.define_internal_local() + self.visit(node.obj, scope) + self.register_instruction(nodes_cil.AssignNode(vobj, scope._return)) + + void = nodes_cil.VoidNode() + equal_result = self.define_internal_local() + self.register_instruction(nodes_cil.EqualNode(equal_result, vobj, void)) + + self.register_runtime_error(equal_result, f'({node.line},{node.column}) - RuntimeError: Dispatch on void\n') + + self.register_instruction(nodes_cil.ArgNode(vobj)) + for arg in args: + self.register_instruction(arg) + + if node.type: + self.register_instruction(nodes_cil.StaticCallNode(self.to_function_name(node.id, node.type), result)) + else: + type_of_node = self.register_local(VariableInfo(f'{node.id}_type', None), id=True) + self.register_instruction(nodes_cil.TypeOfNode(vobj, type_of_node)) + typex = node.obj.computed_type + if typex.name == 'SELF_TYPE': + typex = self.current_type + self.register_instruction(nodes_cil.DynamicCallNode(type_of_node, node.id, result, typex.name)) + + scope._return = result @visitor.when(nodes.IfThenElseNode) @@ -204,8 +237,8 @@ def visit(self, node, scope): @visitor.when(nodes.BlockNode) def visit(self, node, scope): - for expr in node.exprs: - self.visit(node.expr_list, scope) + for expr in node.expr_list: + self.visit(expr, scope) @visitor.when(nodes.LetNode) @@ -221,7 +254,7 @@ def visit(self, node, scope): if id_expr: self.visit(id_expr, scope) self.register_instruction(nodes_cil.AssignNode(vname, scope._return)) - elif typex in self.value_types: + elif typex in ['String','Int','Bool']: self.register_instruction(nodes_cil.AllocateNode(typex, vname)) self.visit(node.in_expr, scope) @@ -231,7 +264,70 @@ def visit(self, node, scope): @visitor.when(nodes.CaseNode) def visit(self, node, scope): - pass + _condition = self.register_local(VariableInfo('equal_value', None)) + _type = self.register_local(VariableInfo('typeName_value', None)) + _expr = self.register_local(VariableInfo('case_expr_value', None)) + vresult = self.register_local(VariableInfo('case_value', None)) + + self.visit(node.predicate, scope) + self.register_instruction(nodes_cil.AssignNode(_expr, scope._return)) + self.register_instruction(nodes_cil.TypeNameNode(_type, scope._return)) + + void = nodes_cil.VoidNode() + equal_result = self.define_internal_local() + self.register_instruction(nodes_cil.EqualNode(equal_result, _expr, void)) + + self.register_runtime_error(equal_result, f'({node.line},{node.column}) - RuntimeError: Case on void\n') + + end_label = self.register_label('end_label') + labels = [] + + order = [] + for branch in node.branches: + (_,typex,_) = branch + count = 0 + t1 = self.context.get_type(typex) + + for other_branch in node.branches: + (_,other_typex,_) = other_branch + t2 = self.context.get_type(other_typex) + count += t2.conforms_to(t1) + + order.append((count, branch)) + order.sort(key=lambda x: x[0]) + + for i, (_, branch) in enumerate(order): + (_,typex,_) = branch + labels.append(self.register_label(f'{i}_label')) + h = {x.name for x in self.context.types.values() if x.name != 'AUTO_TYPE' and + x.conforms_to(self.context.get_type(typex))} if typex != 'Object' else None + if not h: + self.register_instruction(nodes_cil.GotoNode(labels[-1].label)) + break + h.add(typex) + for t in h: + vbranch_type_name = self.register_local(VariableInfo('branch_type_name', None)) + self.register_instruction(nodes_cil.NameNode(vbranch_type_name, t)) + self.register_instruction(nodes_cil.EqualNode(_condition, _type, vbranch_type_name)) + self.register_instruction(nodes_cil.IfGotoNode(_condition, labels[-1].label)) + + (line,column) = node.branchesPos[i] + data_node = self.register_data(f'({line},{column}) - RuntimeError: Execution of a case statement without a matching branch\n') + self.register_instruction(nodes_cil.ErrorNode(data_node)) + + for i, l in enumerate(labels): + self.register_instruction(l) + + (idx, typex, expr) = order[i][1] + vid = self.register_local(VariableInfo(idx, None), id=True) + self.register_instruction(nodes_cil.AssignNode(vid, _expr)) + + self.visit(expr, scope) + self.register_instruction(nodes_cil.AssignNode(vresult, scope._return)) + self.register_instruction(nodes_cil.GotoNode(end_label.label)) + + scope._return = vresult + self.register_instruction(end_label) @visitor.when(nodes.NotNode) @@ -290,13 +386,13 @@ def visit(self, node, scope): @visitor.when(nodes.VariableNode) def visit(self, node, scope): try: - self.current_type.get_attribute(node.lex) + self.current_type.get_attribute(node.lex, None) attr = self.register_local(VariableInfo(node.lex, None), id=True) self.register_instruction(nodes_cil.GetAttrNode(attr, self.vself.name, node.lex, self.current_type.name)) scope._return = attr - except AttributeError: - param_names = [pn.name for pn in self.current_function.params] + except SemanticError: + param_names = [pn.id for pn in self.current_function.params] if node.lex in param_names: for n in param_names: if node.lex == n: diff --git a/src/utils/semantic_check/type_checker.py b/src/utils/semantic_check/type_checker.py index 7801a937c..bc5d32857 100644 --- a/src/utils/semantic_check/type_checker.py +++ b/src/utils/semantic_check/type_checker.py @@ -198,6 +198,7 @@ def visit(self, node, scope): obj_type = self.current_type else: obj_type = self.visit(node.obj, scope) + node.obj.computed_type = obj_type if node.type is not None: if node.type == 'SELF_TYPE': From c114563dced1fc24449453781256e9ce9603efeb Mon Sep 17 00:00:00 2001 From: Ale Date: Sun, 20 Feb 2022 22:41:32 -0800 Subject: [PATCH 69/83] fixing some issues --- src/utils/code_generation/cil/COOL_to_CIL.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/utils/code_generation/cil/COOL_to_CIL.py b/src/utils/code_generation/cil/COOL_to_CIL.py index 7c8dd1d3a..140146854 100644 --- a/src/utils/code_generation/cil/COOL_to_CIL.py +++ b/src/utils/code_generation/cil/COOL_to_CIL.py @@ -299,8 +299,7 @@ def visit(self, node, scope): for i, (_, branch) in enumerate(order): (_,typex,_) = branch labels.append(self.register_label(f'{i}_label')) - h = {x.name for x in self.context.types.values() if x.name != 'AUTO_TYPE' and - x.conforms_to(self.context.get_type(typex))} if typex != 'Object' else None + h = {x.name for x in self.context.types.values() if x.conforms_to(self.context.get_type(typex))} if typex != 'Object' else None if not h: self.register_instruction(nodes_cil.GotoNode(labels[-1].label)) break From f99bcd8135d910ec1f89bb77736c2f2cec3e7869 Mon Sep 17 00:00:00 2001 From: Ale Date: Mon, 21 Feb 2022 17:38:15 -0800 Subject: [PATCH 70/83] modifying code to generate cil --- src/main.py | 13 +++++++++++-- src/utils/ast/AST_Nodes.py | 2 +- src/utils/code_generation/cil/AST_CIL.py | 2 +- src/utils/semantic_check/type_builder.py | 1 + src/utils/semantic_check/type_checker.py | 2 +- 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/main.py b/src/main.py index 2f244acb5..076cfd445 100644 --- a/src/main.py +++ b/src/main.py @@ -3,6 +3,8 @@ from pathlib import Path from utils.COOL_Grammar import build_COOL_Grammar from utils.COOL_Lexer import COOL_Lexer +from utils.code_generation.mips.CIL_to_MIPS import CILToMIPS +from utils.code_generation.mips.print_MIPS_AST import PrintMIPS from utils.parser.COOL_parser import COOL_Parser from cmp.evaluation import evaluate_reverse_parse from cmp.semantic import Context @@ -13,7 +15,7 @@ from utils.code_generation.cil.print_CIL_AST import get_formatter if __name__ == "__main__": - add = "codegen/graph.cl" + add = "lexer/mixed1.cl" path: str = f"{Path.cwd()}/tests/{add}" if os.path.exists( f"{Path.cwd()}/tests/{add}") else f"{Path.cwd()}/../tests/{add}" @@ -68,4 +70,11 @@ cil_visitor = COOLtoCIL(context) cil_ast = cil_visitor.visit(ast, scope) -print(get_formatter()(cil_ast)) \ No newline at end of file +print(get_formatter()(cil_ast)) + +mips_visitor = CILToMIPS() +mips_ast = mips_visitor.visit(cil_ast) + +print_mips = PrintMIPS() +mips = print_mips.visit(mips_ast) +print(mips) \ No newline at end of file diff --git a/src/utils/ast/AST_Nodes.py b/src/utils/ast/AST_Nodes.py index 41f76e6a3..9678c3939 100644 --- a/src/utils/ast/AST_Nodes.py +++ b/src/utils/ast/AST_Nodes.py @@ -58,7 +58,7 @@ def __init__(self, token, expr, token_pos): class CallNode(ExpressionNode): def __init__(self, token, args, obj = None, typex = None): self.obj = obj.lex if isinstance(obj, Token) else obj - self.type = typex + self.type = typex.lex if typex else typex self.id = token.lex self.line = obj.line if obj else token.line self.column = obj.column if obj else token.column diff --git a/src/utils/code_generation/cil/AST_CIL.py b/src/utils/code_generation/cil/AST_CIL.py index 24f439d6b..446efe0cb 100644 --- a/src/utils/code_generation/cil/AST_CIL.py +++ b/src/utils/code_generation/cil/AST_CIL.py @@ -91,7 +91,7 @@ def __init__(self, idx, attr, value, computed_type): self.computed_type = computed_type class AllocateNode(InstructionNode): - def __init__(self, dest, typex): + def __init__(self, typex, dest): self.dest = dest self.type = typex diff --git a/src/utils/semantic_check/type_builder.py b/src/utils/semantic_check/type_builder.py index 02e49e936..d480a92cc 100644 --- a/src/utils/semantic_check/type_builder.py +++ b/src/utils/semantic_check/type_builder.py @@ -51,6 +51,7 @@ def visit(self,node): elif not self.current_type.parent: self.current_type.set_parent(self.context.get_type('Object')) + node.parent = 'Object' for feat in node.features: self.visit(feat) diff --git a/src/utils/semantic_check/type_checker.py b/src/utils/semantic_check/type_checker.py index bc5d32857..6ce52c263 100644 --- a/src/utils/semantic_check/type_checker.py +++ b/src/utils/semantic_check/type_checker.py @@ -207,7 +207,7 @@ def visit(self, node, scope): else: try: - typex = self.context.get_type(node.type.lex) + typex = self.context.get_type(node.type) except SemanticError as se: self.errors.append(se.text) typex = ErrorType() From b73b34c74a42493a542686f8857407727200d055 Mon Sep 17 00:00:00 2001 From: Ale Date: Mon, 21 Feb 2022 17:41:24 -0800 Subject: [PATCH 71/83] fixing main --- src/main.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main.py b/src/main.py index 076cfd445..5fdd5621d 100644 --- a/src/main.py +++ b/src/main.py @@ -3,8 +3,8 @@ from pathlib import Path from utils.COOL_Grammar import build_COOL_Grammar from utils.COOL_Lexer import COOL_Lexer -from utils.code_generation.mips.CIL_to_MIPS import CILToMIPS -from utils.code_generation.mips.print_MIPS_AST import PrintMIPS +# from utils.code_generation.mips.CIL_to_MIPS import CILToMIPS +# from utils.code_generation.mips.print_MIPS_AST import PrintMIPS from utils.parser.COOL_parser import COOL_Parser from cmp.evaluation import evaluate_reverse_parse from cmp.semantic import Context @@ -72,9 +72,9 @@ print(get_formatter()(cil_ast)) -mips_visitor = CILToMIPS() -mips_ast = mips_visitor.visit(cil_ast) +# mips_visitor = CILToMIPS() +# mips_ast = mips_visitor.visit(cil_ast) -print_mips = PrintMIPS() -mips = print_mips.visit(mips_ast) -print(mips) \ No newline at end of file +# print_mips = PrintMIPS() +# mips = print_mips.visit(mips_ast) +# print(mips) \ No newline at end of file From a68e4bec314b01021bdfa5a00f58341a9e31902a Mon Sep 17 00:00:00 2001 From: darian10 Date: Wed, 23 Feb 2022 16:00:08 -0500 Subject: [PATCH 72/83] Adding instruction to code_generation --- src/utils/COOL_Lexer.py | 206 ++++++++++++----------- src/utils/ast/AST_Nodes.py | 54 +++--- src/utils/semantic_check/type_checker.py | 193 +++++++++++---------- 3 files changed, 244 insertions(+), 209 deletions(-) diff --git a/src/utils/COOL_Lexer.py b/src/utils/COOL_Lexer.py index 7f7f4e860..8aabc5f11 100644 --- a/src/utils/COOL_Lexer.py +++ b/src/utils/COOL_Lexer.py @@ -3,24 +3,29 @@ ''' Recibe como parametros el lexema, tipo, linea y columna donde se encuentra ''' + + class Token: - - def __init__(self, lex, ttype, line, column): - - self.lex = lex + + def __init__(self, lex, ttype, line, column): + + self.lex = lex self.token_type = ttype self.line = line self.column = column self.next_token = None - - def __str__(self): + + def __str__(self): return f'({self.line}, {self.column}) - {self.token_type}: {self.lex}' - + + ''' El lexer es el resultado de la union de todas las expresiones regulares que forman el lenguaje ''' -class Lexer: + + +class Lexer: def __init__(self, table, keywords, ignored_tokens, tokens_toFix, eof): self.line = 1 @@ -32,23 +37,26 @@ def __init__(self, table, keywords, ignored_tokens, tokens_toFix, eof): self.regex = self._build_regex(table) self.errors = [] self.eof = eof - - def tokenize(self,text): + + def tokenize(self, text): while len(text) > 0: match = self.regex.match(text) error_token = '' - + while not match: error_token += text[0] text = text[1:] - if len(text) <= 0: break + if len(text) <= 0: + break match = self.regex.match(text) if error_token: - self.errors.append(f'({self.line}, {self.column + 1}) - LexicographicError: ERROR "{error_token}"') + self.errors.append( + f'({self.line}, {self.column + 1}) - LexicographicError: ERROR "{error_token}"') self.column += len(error_token) - if len(text) <= 0: continue + if len(text) <= 0: + continue lexeme = match.group() self.column += len(lexeme) if lexeme != '\t' else 4 @@ -80,7 +88,8 @@ def tokenize(self,text): break else: - self.errors.append(f'({self.line}, {self.column + 1}) - LexicographicError: EOF in comment') + self.errors.append( + f'({self.line}, {self.column + 1}) - LexicographicError: EOF in comment') # STRINGS elif lexeme == '"': @@ -97,123 +106,128 @@ def tokenize(self,text): self.column = 0 elif text[0] == 'b': - lexeme += '\\b' + lexeme += '\b' elif text[0] == 't': - lexeme += '\\t' + lexeme += '\t' elif text[0] == 'n': - lexeme += '\\n' + lexeme += '\n' elif text[0] == 'f': - lexeme += '\\f' - + lexeme += '\f' + else: lexeme += text[0] text = text[1:] self.column += 1 - + elif c == '\n': - self.errors.append(f'({self.line}, {self.column}) - LexicographicError: Unterminated string constant') + self.errors.append( + f'({self.line}, {self.column}) - LexicographicError: Unterminated string constant') self.line += 1 self.column = 0 break - + elif c == '\0': - self.errors.append(f'({self.line}, {self.column}) - LexicographicError: String contains null character') - + self.errors.append( + f'({self.line}, {self.column}) - LexicographicError: String contains null character') + else: lexeme += c if c == '"': break - - else: - self.errors.append(f'({self.line}, {self.column}) - LexicographicError: EOF in string constant') - + else: + self.errors.append( + f'({self.line}, {self.column}) - LexicographicError: EOF in string constant') - token_type = match.lastgroup if lexeme.lower() not in self.keywords and match.lastgroup is not None else match.group().lower() + token_type = match.lastgroup if lexeme.lower( + ) not in self.keywords and match.lastgroup is not None else match.group().lower() yield lexeme, token_type, self.line, self.column - len(lexeme) + 1 - - text = text[match.end():] if lexeme[:2] != '(*' and lexeme[0] != '"' else text + + text = text[match.end( + ):] if lexeme[:2] != '(*' and lexeme[0] != '"' else text yield '$', self.eof, 0, 0 - - def _build_regex(sef,table): - return re.compile('|'.join([f'(?P<{name}>{regex})' if name != regex else f'({name})' for name,regex in table.items()])) - - def __call__(self, text): + + def _build_regex(sef, table): + return re.compile('|'.join([f'(?P<{name}>{regex})' if name != regex else f'({name})' for name, regex in table.items()])) + + def __call__(self, text): return [Token(lex, ttype, line, column) for lex, ttype, line, column in self.tokenize(text) if ttype not in self.ignored_tokens] def fixed_tokens(self, tokens): for i, token in enumerate(tokens[:(len(tokens) - 1)]): - token.next_token = tokens[i+1] + token.next_token = tokens[i+1] return tokens - - ''' Esta clase guarda las propiedades sintacticas de COOL ''' + + class COOL_Lexer(Lexer): def __init__(self): self.regexs = { - 'id' : r'[a-z][a-zA-Z0-9_]*' , - 'type' : r'[A-Z][a-zA-Z0-9_]*' , - 'string' : r'\"' , - 'int' : r'\d+' , - 'comment' : r'(\(\*)|--.*' , - 'newline' : r'\n' , - 'whitespace': r' +' , - 'tabulation': r'\t' , - 'inherits' : r'inherits' , - 'isvoid' : r'isvoid' , - 'class' : r'class' , - 'while' : r'while' , - 'false' : r'false' , - 'then' : r'then' , - 'else' : r'else' , - 'loop' : r'loop' , - 'pool' : r'pool' , - 'case' : r'case' , - 'esac' : r'esac' , - 'true' : r'true' , - '<\-' : r'<\-' , - 'let' : r'let' , - 'new' : r'new' , - 'not' : r'not' , - '\{' : r'\{' , - '\}' : r'\}' , - '\(' : r'\(' , - '\)' : r'\)' , - '\.' : r'\.' , - '=>' : r'=>' , - 'if' : r'if' , - 'fi' : r'fi' , - 'in' : r'in' , - 'of' : r'of' , - '\+' : r'\+' , - '\-' : r'\-' , - '\*' : r'\*' , - '<=' : r'<=' , - '\~' : r'\~' , - ',' : r',' , - ':' : r':' , - ';' : r';' , - '@' : r'@' , - '/' : r'/' , - '<' : r'<' , - '=' : r'=' } - - self.keywords = ['inherits','isvoid','class','while','false','then','else','loop', - 'pool','case','esac','true','let','new','not','if','fi','in','of'] - - self.ignored_tokens = ['newline','whitespace','tabulation','comment'] - - self.tokens_toFix = ['inherits','isvoid','class','while','then','else','loop','case', - 'let','new','not','if','in','of', '<-'] - - Lexer.__init__(self, self.regexs, self.keywords, self.ignored_tokens, self.tokens_toFix, 'eof') \ No newline at end of file + 'id': r'[a-z][a-zA-Z0-9_]*', + 'type': r'[A-Z][a-zA-Z0-9_]*', + 'string': r'\"', + 'int': r'\d+', + 'comment': r'(\(\*)|--.*', + 'newline': r'\n', + 'whitespace': r' +', + 'tabulation': r'\t', + 'inherits': r'inherits', + 'isvoid': r'isvoid', + 'class': r'class', + 'while': r'while', + 'false': r'false', + 'then': r'then', + 'else': r'else', + 'loop': r'loop', + 'pool': r'pool', + 'case': r'case', + 'esac': r'esac', + 'true': r'true', + '<\-': r'<\-', + 'let': r'let', + 'new': r'new', + 'not': r'not', + '\{': r'\{', + '\}': r'\}', + '\(': r'\(', + '\)': r'\)', + '\.': r'\.', + '=>': r'=>', + 'if': r'if', + 'fi': r'fi', + 'in': r'in', + 'of': r'of', + '\+': r'\+', + '\-': r'\-', + '\*': r'\*', + '<=': r'<=', + '\~': r'\~', + ',': r',', + ':': r':', + ';': r';', + '@': r'@', + '/': r'/', + '<': r'<', + '=': r'='} + + self.keywords = ['inherits', 'isvoid', 'class', 'while', 'false', 'then', 'else', 'loop', + 'pool', 'case', 'esac', 'true', 'let', 'new', 'not', 'if', 'fi', 'in', 'of'] + + self.ignored_tokens = ['newline', + 'whitespace', 'tabulation', 'comment'] + + self.tokens_toFix = ['inherits', 'isvoid', 'class', 'while', 'then', 'else', 'loop', 'case', + 'let', 'new', 'not', 'if', 'in', 'of', '<-'] + + Lexer.__init__(self, self.regexs, self.keywords, + self.ignored_tokens, self.tokens_toFix, 'eof') diff --git a/src/utils/ast/AST_Nodes.py b/src/utils/ast/AST_Nodes.py index 9678c3939..bdc6d1925 100644 --- a/src/utils/ast/AST_Nodes.py +++ b/src/utils/ast/AST_Nodes.py @@ -7,17 +7,16 @@ class Node: line = 0 column = 0 - class ProgramNode(Node): def __init__(self, declarations): self.declarations = declarations class DeclarationNode(Node): pass + class ExpressionNode(Node): pass - class ClassDeclarationNode(DeclarationNode): def __init__(self, idx, features, token, parent=None): self.id = idx.lex @@ -36,12 +35,13 @@ def __init__(self, idx, params, return_type, body, ocurToken): self.column = idx.column self.body_line = ocurToken.next_token.line self.body_column = ocurToken.next_token.column - self.params = [[item.lex if isinstance(item, Token) else item for item in _list] for _list in params] + self.params = [[item.lex if isinstance( + item, Token) else item for item in _list] for _list in params] self.type = return_type.lex self.body = body class AttrDeclarationNode(DeclarationNode): - def __init__(self, idx, typex, arrowToken = None, expr = None): + def __init__(self, idx, typex, arrowToken=None, expr=None): self.id = idx.lex self.line = arrowToken.next_token.line if expr else typex.line self.column = arrowToken.next_token.column if expr else typex.column @@ -56,22 +56,22 @@ def __init__(self, token, expr, token_pos): self.expr = expr class CallNode(ExpressionNode): - def __init__(self, token, args, obj = None, typex = None): + def __init__(self, token, args, obj=None, typex=None): self.obj = obj.lex if isinstance(obj, Token) else obj self.type = typex.lex if typex else typex self.id = token.lex self.line = obj.line if obj else token.line self.column = obj.column if obj else token.column self.args = args - + class IfThenElseNode(ExpressionNode): - def __init__(self, if_expr, then_expr, else_expr,token): + def __init__(self, if_expr, then_expr, else_expr, token): self.if_expr = if_expr self.then_expr = then_expr self.else_expr = else_expr self.line = token.next_token.line self.column = token.next_token.column - + class WhileNode(ExpressionNode): def __init__(self, conditional_expr, loop_expr, token): self.conditional_expr = conditional_expr @@ -84,10 +84,11 @@ def __init__(self, expr_list, token): self.expr_list = expr_list self.line = token.line self.column = token.column - + class LetNode(ExpressionNode): def __init__(self, identifiers, in_expr, token): - self.identifiers = [tuple([item.lex if isinstance(item, Token) else item for item in _list]) for _list in identifiers] + self.identifiers = [tuple([item.lex if isinstance( + item, Token) else item for item in _list]) for _list in identifiers] self.in_expr = in_expr self.line = token.line self.column = token.column @@ -98,12 +99,13 @@ def __init__(self, predicate, branches, token): self.branches = [] self.branchesPos = [] for branch in branches: - self.branches.append(tuple([item.lex if isinstance(item, Token) else item for item in branch])) - _,typex,_ = branch - self.branchesPos.append((typex.line,typex.column)) + self.branches.append( + tuple([item.lex if isinstance(item, Token) else item for item in branch])) + _, typex, _ = branch + self.branchesPos.append((typex.line, typex.column)) self.line = token.line self.column = token.column - + class NotNode(ExpressionNode): def __init__(self, expr, token): self.expr = expr @@ -121,42 +123,54 @@ def __init__(self, left, right, token): self.left = left self.right = right self.line = token.line - self.column = token.column - + self.column = token.column class ConstantNumNode(AtomicNode): pass + class ConstantBoolNode(AtomicNode): pass + class ConstantStringNode(AtomicNode): - pass + def __init__(self, expr): + expr.lex = expr.lex[1:-1] + super().__init__(expr) + class VariableNode(AtomicNode): pass + class InstantiateNode(AtomicNode): def __init__(self, typex, token): - self.lex = typex.lex + self.lex = typex.lex self.line = token.next_token.line self.column = token.next_token.column + class IsVoidNode(AtomicNode): pass + class ComplementNode(AtomicNode): def __init__(self, expr, token): self.lex = expr.lex if isinstance(expr, Token) else expr self.line = token.next_token.line self.column = token.next_token.column - class PlusNode(BinaryNode): pass + class MinusNode(BinaryNode): pass + class StarNode(BinaryNode): pass + class DivNode(BinaryNode): pass + class LessThanNode(BinaryNode): pass + class LessEqualNode(BinaryNode): pass + class EqualNode(BinaryNode): - pass \ No newline at end of file + pass diff --git a/src/utils/semantic_check/type_checker.py b/src/utils/semantic_check/type_checker.py index 6ce52c263..dd57367e9 100644 --- a/src/utils/semantic_check/type_checker.py +++ b/src/utils/semantic_check/type_checker.py @@ -35,7 +35,6 @@ UNDEFINED_METHOD = '(%s, %s) - AttributeError: Dispatch to undefined method %s. ' - class TypeChecker: def __init__(self, context, errors): self.context = context @@ -47,28 +46,26 @@ def __init__(self, context, errors): def visit(self, node, scope): pass - @visitor.when(nodes.ProgramNode) def visit(self, node, scope=None): # verificando que el programa tenga una clase Main try: self.context.get_type('Main') - - except SemanticError: - self.errors.append(MAIN_DONT_EXISTS) + except SemanticError: + self.errors.append(MAIN_DONT_EXISTS) scope = Scope() if scope == None else scope for dec in node.declarations: self.visit(dec, scope.create_child()) - + return scope - @visitor.when(nodes.ClassDeclarationNode) def visit(self, node, scope): self.current_type = self.context.get_type(node.id) + scope.define_variable('self', self.current_type) # verificando la existencia del metodo main if self.current_type.name == 'Main': @@ -76,16 +73,16 @@ def visit(self, node, scope): self.current_type.get_method('main') except SemanticError: - self.errors.append(MAIN_METHOD_DONT_EXISTS % (node.line, node.column)) - - + self.errors.append(MAIN_METHOD_DONT_EXISTS % + (node.line, node.column)) # verficando herencia circular en los ancestros de current_type (deben llegar a object sin pasar por el nuevamente) current_parent = self.current_type.parent while current_parent != self.context.get_type('Object') and current_parent != None: if current_parent == self.current_type: - self.errors.append(INHERIT_ERROR % (self.current_type.child.line, self.current_type.child.column, self.current_type.child.name, self.current_type.child.name)) + self.errors.append(INHERIT_ERROR % (self.current_type.child.line, self.current_type.child.column, + self.current_type.child.name, self.current_type.child.name)) self.current_type.parent = ErrorType() break @@ -93,12 +90,14 @@ def visit(self, node, scope): scope.define_variable(attr.name, attr.type) current_parent = current_parent.parent - - attrs = [feat for feat in node.features if isinstance(feat, nodes.AttrDeclarationNode)] + + attrs = [feat for feat in node.features if isinstance( + feat, nodes.AttrDeclarationNode)] for attr in attrs: self.visit(attr, scope) - meths = [feat for feat in node.features if isinstance(feat, nodes.MethDeclarationNode)] + meths = [feat for feat in node.features if isinstance( + feat, nodes.MethDeclarationNode)] for meth in meths: self.visit(meth, scope.create_child()) @@ -107,7 +106,8 @@ def visit(self, node, scope): @visitor.when(nodes.AttrDeclarationNode) def visit(self, node, scope): try: - attr_type = self.context.get_type(node.type) if node.type != 'SELF_TYPE' else self.current_type + attr_type = self.context.get_type( + node.type) if node.type != 'SELF_TYPE' else self.current_type except SemanticError: attr_type = ErrorType() @@ -118,14 +118,12 @@ def visit(self, node, scope): type_expr = self.visit(node.expr, scope.create_child()) if not type_expr.conforms_to(attr_type): - self.errors.append(INCOMPATIBLE_TYPES_ATTR % (node.line, node.column, type_expr.name, node.id, attr_type.name)) - - + self.errors.append(INCOMPATIBLE_TYPES_ATTR % ( + node.line, node.column, type_expr.name, node.id, attr_type.name)) scope.define_variable(node.id, attr_type) - return - + return @visitor.when(nodes.MethDeclarationNode) def visit(self, node, scope): @@ -133,7 +131,8 @@ def visit(self, node, scope): # verificando que el metodo main no tenga parametros if self.current_method.name == 'main' and self.current_method.param_names: - self.errors.append(MAIN_METHOD_DONT_HAVE_PARAMS % (node.line, node.column)) + self.errors.append(MAIN_METHOD_DONT_HAVE_PARAMS % + (node.line, node.column)) # verificabdo redefinicion de metodos current_parent = self.current_type.parent @@ -142,38 +141,41 @@ def visit(self, node, scope): try: parent_method = current_parent.get_method(node.id) if parent_method != self.current_method: - self.errors.append(WRONG_SIGNATURE % (node.line, node.column, self.current_method.name)) + self.errors.append(WRONG_SIGNATURE % ( + node.line, node.column, self.current_method.name)) break except: pass - current_parent = current_parent.parent - + current_parent = current_parent.parent scope.define_variable('self', self.current_type) for name, typex in zip(self.current_method.param_names, self.current_method.param_types): if scope.is_local(name): - self.errors.append(LOCAL_ALREADY_DEFINED % (node.line, node.column, name,self.current_method.name)) + self.errors.append(LOCAL_ALREADY_DEFINED % ( + node.line, node.column, name, self.current_method.name)) elif typex == 'SELF_TYPE': - self.errors.append(SELF_TYPE_ERROR % (node.line, node.column, self.current_method.name)) + self.errors.append(SELF_TYPE_ERROR % ( + node.line, node.column, self.current_method.name)) scope.define_variable(name, ErrorType()) else: scope.define_variable(name, self.context.get_type(typex.name)) - + body_type = self.visit(node.body, scope) try: - returnType = self.context.get_type(node.type) if node.type != 'SELF_TYPE' else self.current_type + returnType = self.context.get_type( + node.type) if node.type != 'SELF_TYPE' else self.current_type except SemanticError as se: returnType = ErrorType() if not body_type.conforms_to(returnType): - self.errors.append(INCOMPATIBLE_TYPES_METH % (node.body_line, node.body_column, body_type.name , node.id, returnType.name )) + self.errors.append(INCOMPATIBLE_TYPES_METH % ( + node.body_line, node.body_column, body_type.name, node.id, returnType.name)) return - @visitor.when(nodes.AssignNode) def visit(self, node, scope): var = scope.find_variable(node.id) @@ -181,17 +183,18 @@ def visit(self, node, scope): type_expr = self.visit(node.expr, scope.create_child()) if var is None: - self.errors.append(VARIABLE_NOT_DEFINED % (node.line, node.column, node.id)) + self.errors.append(VARIABLE_NOT_DEFINED % + (node.line, node.column, node.id)) elif var.name == 'self': self.errors.append(SELF_IS_READONLY % (node.line, node.column)) elif not type_expr.conforms_to(var.type): - self.errors.append(INCOMPATIBLE_TYPES % (node.line, node.column, type_expr.name, var.type.name)) + self.errors.append(INCOMPATIBLE_TYPES % ( + node.line, node.column, type_expr.name, var.type.name)) return type_expr - @visitor.when(nodes.CallNode) def visit(self, node, scope): if node.obj is None: @@ -202,7 +205,8 @@ def visit(self, node, scope): if node.type is not None: if node.type == 'SELF_TYPE': - self.errors.append(SELF_TYPE_IN_DISPATCH % (node.line, node.column)) + self.errors.append(SELF_TYPE_IN_DISPATCH % + (node.line, node.column)) typex = ErrorType() else: @@ -213,53 +217,57 @@ def visit(self, node, scope): typex = ErrorType() if not obj_type.conforms_to(typex): - self.errors.append(INCOMPATIBLE_TYPES_CALL % (node.line, node.column, obj_type.name, typex.name)) + self.errors.append(INCOMPATIBLE_TYPES_CALL % ( + node.line, node.column, obj_type.name, typex.name)) obj_type = typex try: meth = obj_type.get_method(node.id) except SemanticError as se: - if se.text: self.errors.append(UNDEFINED_METHOD % (node.line, node.column, node.id)) + if se.text: + self.errors.append(UNDEFINED_METHOD % + (node.line, node.column, node.id)) for arg in node.args: self.visit(arg, scope) return ErrorType() - + if len(node.args) != len(meth.param_names): - self.errors.append(METHOD_PARAMETERS % (node.line, node.column, meth.name, obj_type.name, len(meth.param_names))) + self.errors.append(METHOD_PARAMETERS % ( + node.line, node.column, meth.name, obj_type.name, len(meth.param_names))) - for i,arg in enumerate(node.args): + for i, arg in enumerate(node.args): type_arg = self.visit(arg, scope) - if i< len(meth.param_types) and not type_arg.conforms_to(meth.param_types[i]): - self.errors.append(INCOMPATIBLE_TYPES % (node.line, node.column, type_arg.name, meth.param_types[i].name)) - - return meth.return_type if meth.return_type.name != 'SELF_TYPE' else obj_type + if i < len(meth.param_types) and not type_arg.conforms_to(meth.param_types[i]): + self.errors.append(INCOMPATIBLE_TYPES % ( + node.line, node.column, type_arg.name, meth.param_types[i].name)) + return meth.return_type if meth.return_type.name != 'SELF_TYPE' else obj_type @visitor.when(nodes.IfThenElseNode) def visit(self, node, scope): if_type = self.visit(node.if_expr, scope.create_child()) if not if_type.conforms_to(self.context.get_type('Bool')): - self.errors.append(INCOMPATIBLE_TYPES_IF % (node.line, node.column,'if','Bool')) - + self.errors.append(INCOMPATIBLE_TYPES_IF % + (node.line, node.column, 'if', 'Bool')) + then_type = self.visit(node.then_expr, scope.create_child()) else_type = self.visit(node.else_expr, scope.create_child()) return then_type.join(else_type) - @visitor.when(nodes.WhileNode) def visit(self, node, scope): type_conditional = self.visit(node.conditional_expr, scope) if not type_conditional.conforms_to(self.context.get_type('Bool')): - self.errors.append(INCOMPATIBLE_TYPES % (node.line, node.column, type_conditional.name, 'Bool')) - + self.errors.append(INCOMPATIBLE_TYPES % ( + node.line, node.column, type_conditional.name, 'Bool')) + self.visit(node.loop_expr, scope.create_child()) return self.context.get_type('Object') - @visitor.when(nodes.BlockNode) def visit(self, node, scope): @@ -270,143 +278,141 @@ def visit(self, node, scope): return type_expr - @visitor.when(nodes.LetNode) def visit(self, node, scope): for idx, typex, id_expr in node.identifiers: try: - id_type = self.context.get_type(typex) if typex != 'SELF_TYPE' else self.current_type + id_type = self.context.get_type( + typex) if typex != 'SELF_TYPE' else self.current_type except SemanticError as se: id_type = ErrorType() - self.errors.append(UNDEFINED_TYPE_LET % (node.line, node.column, typex, idx)) - + self.errors.append(UNDEFINED_TYPE_LET % + (node.line, node.column, typex, idx)) + if idx == 'self': self.errors.append(SELF_ERROR_LET % (node.line, node.column)) - + if scope.is_local(idx): scope = scope.create_child() scope.define_variable(idx, id_type) else: scope.define_variable(idx, id_type) - + if id_expr is not None: id_expr_type = self.visit(id_expr, scope.create_child()) if not id_expr_type.conforms_to(id_type): - self.errors.append(INCOMPATIBLE_TYPES_LET % (node.line, node.column, id_expr_type.name, idx, id_type.name)) - + self.errors.append(INCOMPATIBLE_TYPES_LET % ( + node.line, node.column, id_expr_type.name, idx, id_type.name)) + body_type = self.visit(node.in_expr, scope.create_child()) return body_type - @visitor.when(nodes.CaseNode) def visit(self, node, scope): self.visit(node.predicate, scope) case_type = None - for i,branch in enumerate(node.branches): + for i, branch in enumerate(node.branches): (idx, typex, expr) = branch - (line,column) = node.branchesPos[i] + (line, column) = node.branchesPos[i] if typex in [b[1] for b in node.branches[:i]]: self.errors.append(DUPLICATE_BRANCH % (line, column, typex)) if typex == 'SELF_TYPE': self.errors.append(SELF_TYPE_IN_CASE_BRANCH % (line, column)) id_type = ErrorType() - + else: try: id_type = self.context.get_type(typex) except SemanticError as se: id_type = ErrorType() - self.errors.append(UNDEFINED_TYPE_BRANCH % (line, column, typex)) - + self.errors.append(UNDEFINED_TYPE_BRANCH % + (line, column, typex)) + inner_scope = scope.create_child() inner_scope.define_variable(idx, id_type) type_expr = self.visit(expr, inner_scope) - case_type = case_type.join(type_expr) if case_type is not None else type_expr + case_type = case_type.join( + type_expr) if case_type is not None else type_expr return case_type - @visitor.when(nodes.NotNode) def visit(self, node, scope): typex = self.visit(node.expr, scope) if not typex.conforms_to(self.context.get_type('Bool')): - self.errors.append(INCOMPATIBLE_TYPES_ARG % (node.line, node.column, 'not' ,typex.name, 'Bool')) + self.errors.append(INCOMPATIBLE_TYPES_ARG % ( + node.line, node.column, 'not', typex.name, 'Bool')) return ErrorType() return typex - @visitor.when(nodes.ConstantNumNode) def visit(self, node, scope): return self.context.get_type('Int') - @visitor.when(nodes.ConstantBoolNode) def visit(self, node, scope): return self.context.get_type('Bool') - @visitor.when(nodes.ConstantStringNode) def visit(self, node, scope): return self.context.get_type('String') - @visitor.when(nodes.VariableNode) def visit(self, node, scope): var = scope.find_variable(node.lex) if var is None: - self.errors.append(VARIABLE_NOT_DEFINED % (node.line, node.column, node.lex)) + self.errors.append(VARIABLE_NOT_DEFINED % + (node.line, node.column, node.lex)) return ErrorType() return var.type - @visitor.when(nodes.InstantiateNode) def visit(self, node, scope): if node.lex == 'SELF_TYPE': return self.current_type - + try: return self.context.get_type(node.lex) except SemanticError as se: - self.errors.append(UNDEFINED_TYPE_NEW % (node.line, node.column, node.lex)) + self.errors.append(UNDEFINED_TYPE_NEW % + (node.line, node.column, node.lex)) return ErrorType() - @visitor.when(nodes.IsVoidNode) def visit(self, node, scope): self.visit(node.lex, scope) return self.context.get_type('Bool') - @visitor.when(nodes.ComplementNode) def visit(self, node, scope): typex = self.visit(node.lex, scope) if not typex.conforms_to(self.context.get_type('Int')): - self.errors.append(INCOMPATIBLE_TYPES_ARG % (node.line, node.column, '~' ,typex.name, 'Int')) + self.errors.append(INCOMPATIBLE_TYPES_ARG % ( + node.line, node.column, '~', typex.name, 'Int')) return ErrorType() return typex - @visitor.when(nodes.PlusNode) def visit(self, node, scope): type_left = self.visit(node.left, scope) type_right = self.visit(node.right, scope) if not type_left.conforms_to(self.context.get_type('Int')) or not type_right.conforms_to(self.context.get_type('Int')): - self.errors.append(INVALID_OPERATION % (node.line, node.column, type_left.name, '+', type_right.name)) + self.errors.append(INVALID_OPERATION % ( + node.line, node.column, type_left.name, '+', type_right.name)) return ErrorType() else: return self.context.get_type('Int') - @visitor.when(nodes.MinusNode) def visit(self, node, scope): @@ -414,38 +420,38 @@ def visit(self, node, scope): type_right = self.visit(node.right, scope) if not type_left.conforms_to(self.context.get_type('Int')) or not type_right.conforms_to(self.context.get_type('Int')): - self.errors.append(INVALID_OPERATION % (node.line, node.column, type_left.name, '-', type_right.name)) + self.errors.append(INVALID_OPERATION % ( + node.line, node.column, type_left.name, '-', type_right.name)) return ErrorType() else: return self.context.get_type('Int') - @visitor.when(nodes.StarNode) def visit(self, node, scope): type_left = self.visit(node.left, scope) type_right = self.visit(node.right, scope) if not type_left.conforms_to(self.context.get_type('Int')) or not type_right.conforms_to(self.context.get_type('Int')): - self.errors.append(INVALID_OPERATION % (node.line, node.column, type_left.name, '*', type_right.name)) + self.errors.append(INVALID_OPERATION % ( + node.line, node.column, type_left.name, '*', type_right.name)) return ErrorType() else: return self.context.get_type('Int') - @visitor.when(nodes.DivNode) def visit(self, node, scope): type_left = self.visit(node.left, scope) type_right = self.visit(node.right, scope) if not type_left.conforms_to(self.context.get_type('Int')) or not type_right.conforms_to(self.context.get_type('Int')): - self.errors.append(INVALID_OPERATION % (node.line, node.column, type_left.name, '/', type_right.name)) + self.errors.append(INVALID_OPERATION % ( + node.line, node.column, type_left.name, '/', type_right.name)) return ErrorType() else: return self.context.get_type('Int') - @visitor.when(nodes.LessThanNode) def visit(self, node, scope): @@ -453,25 +459,25 @@ def visit(self, node, scope): type_right = self.visit(node.right, scope) if not type_left.conforms_to(self.context.get_type('Int')) or not type_right.conforms_to(self.context.get_type('Int')): - self.errors.append(INVALID_OPERATION % (node.line, node.column, type_left.name, '<', type_right.name)) + self.errors.append(INVALID_OPERATION % ( + node.line, node.column, type_left.name, '<', type_right.name)) return ErrorType() else: return self.context.get_type('Bool') - @visitor.when(nodes.LessEqualNode) def visit(self, node, scope): type_left = self.visit(node.left, scope) type_right = self.visit(node.right, scope) if not type_left.conforms_to(self.context.get_type('Int')) or not type_right.conforms_to(self.context.get_type('Int')): - self.errors.append(INVALID_OPERATION % (node.line, node.column, type_left.name, '<=', type_right.name)) + self.errors.append(INVALID_OPERATION % ( + node.line, node.column, type_left.name, '<=', type_right.name)) return ErrorType() else: return self.context.get_type('Bool') - @visitor.when(nodes.EqualNode) def visit(self, node, scope): @@ -481,11 +487,12 @@ def visit(self, node, scope): int_type = self.context.get_type('Int') bool_type = self.context.get_type('Bool') string_type = self.context.get_type('String') - + if type_left.name == 'AUTO_TYPE' or type_right.name == 'AUTO_TYPE': pass elif (type_left == int_type and not type_right.conforms_to(int_type)) or (type_right == int_type and not type_left.conforms_to(int_type)) or (type_left == bool_type and not type_right.conforms_to(bool_type)) or (type_right == bool_type and not type_left.conforms_to(bool_type)) or (type_left == string_type and not type_right.conforms_to(string_type)) or (type_right == string_type and not type_left.conforms_to(string_type)): - self.errors.append(INVALID_OPERATION % (node.line, node.column, type_left.name, '=', type_right.name)) + self.errors.append(INVALID_OPERATION % ( + node.line, node.column, type_left.name, '=', type_right.name)) return ErrorType() - return bool_type \ No newline at end of file + return bool_type From 0b0e40a7a42fc7814c212abefaa220b150ac1a61 Mon Sep 17 00:00:00 2001 From: Ale Date: Thu, 24 Feb 2022 16:57:38 -0800 Subject: [PATCH 73/83] files --- doc/Informe/files/SPIM_Manual.pdf | Bin 0 -> 518753 bytes doc/Informe/files/compilers.pdf | Bin 0 -> 864789 bytes doc/{ => Informe/files}/cool-manual.pdf | Bin .../files}/github-git-cheat-sheet.pdf | Bin 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 doc/Informe/files/SPIM_Manual.pdf create mode 100644 doc/Informe/files/compilers.pdf rename doc/{ => Informe/files}/cool-manual.pdf (100%) rename doc/{ => Informe/files}/github-git-cheat-sheet.pdf (100%) diff --git a/doc/Informe/files/SPIM_Manual.pdf b/doc/Informe/files/SPIM_Manual.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b785613c8afa1a36aceadee59326205abd729b94 GIT binary patch literal 518753 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

|vsGhftq|S3x<-Cq#3)oR}!ZJIb#knC} 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 cEZ` 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

TAN|` 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 vsG(5SgAS;`=>u-8{=-UrRxl1-9?a z4FLTpiG&9i$|wHvu9R-0KmpE$W4wf@uMR6Gr5Zl-b()-e6xCk5qRdn6Y>P`f+}Rjs zyE{hs6EKmv=Zb*#H6(ODB+`Upd$6;%n#Wovk6XnxY)aHqn9^PHHmL(LJdjj~VOUXJ z%=gdBa4Mt)o=f^v^_DF({nw8vQUFPJ);$mk8Dj|G8RNQe#rm1_b`gm=B?UQ=;q(L$ zJJzgsFKPofxhFCuDaXy5wP_b zD{SNnq0i8t-Aqgq-aGX~Jnrk#&6jDLYN5Za%+L7<}owk}YLSU;H7xmEXWwkq

a9Jqc}DcOM?U&|QJ4*bPmF^Usu2MV?C8{v|q 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

&>fJv8 zB^^4DoX=??W4At zbS~DNRE0Gcq~#fPVfRq@bhOGuzs#7SRgleETDoE5$V7Pd?nI&e!x*wP@b6!db@t7O zi^v@E4&Skf5TKK6C#7CP>4X;M8wf*WC~ey=Vsn&>^kmnUMtN|ZbUIFmCGwn)Nkxi3!=PxJ|?Q7ghDox}#MfBfu~TAd`oNYsLH? zF6Shs1VZz_)3Ui@@L_Cm6^te!3V`p*pwGIRSFEw;30btpimEJcn=2i8I?tuo6bj)Z z_9IPyAA9ZKNMMt%WYoR=>wAQxG!K&oMPf>_cNg$xfxMNHkib$6=E)cI7_1foItK+>f|3MsIDk~FCvMqOPKoB&QccZ0$2DyQl_{8%@G)DfuBMy!aDa=cV~ez+ zdT0MeOo@=`GGgFd%fprp@Hj!9bulxZ;vj~D`=}?cLY7lIAH$8C;O@y?pXUG@ao$+f zuR25@xcM)^|DdpJ>a!2)FCBmj!b9}LROVPm!@ZnJexq2T2th|5KLX^NY3*s@md6It zHkSp2S1!#sAZ@*)=5b_#UVEKb`2htfH^w`Pi1VEd5jjAkF;lINnNcv<-06;%W@AE^ zV9A>8>_>ss|8+-Ww}=s|}_0TesID{xbA zq)cUUgeK7s62knsEXC-AbWjA|!BEoe99$X<@uku7UUK(m_gXtg*we>4BK2-4?y1

xt?3AqnF90dAsHVH37&$w1x{!_5S!fC?hHD$ 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 z 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 z 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

A}_o2*i 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�pB)i{Arn;%-*F5$ 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 GsQ(YR^^Hvc literal 0 HcmV?d00001 diff --git a/doc/cool-manual.pdf b/doc/Informe/files/cool-manual.pdf similarity index 100% rename from doc/cool-manual.pdf rename to doc/Informe/files/cool-manual.pdf diff --git a/doc/github-git-cheat-sheet.pdf b/doc/Informe/files/github-git-cheat-sheet.pdf similarity index 100% rename from doc/github-git-cheat-sheet.pdf rename to doc/Informe/files/github-git-cheat-sheet.pdf From 4d060804fdd6a14800ebb8d3d0b6447252e56a22 Mon Sep 17 00:00:00 2001 From: darian10 Date: Fri, 25 Feb 2022 15:14:20 -0500 Subject: [PATCH 74/83] Adding mips --- src/main.py | 62 +- src/utils/code_generation/mips/AST_MIPS.py | 234 +++ src/utils/code_generation/mips/CIL_to_MIPS.py | 1076 +++++++++++++ .../code_generation/mips/print_MIPS_AST.py | 1396 +++++++++++++++++ src/utils/code_generation/mips/utils_mips.py | 547 +++++++ 5 files changed, 3291 insertions(+), 24 deletions(-) create mode 100644 src/utils/code_generation/mips/AST_MIPS.py create mode 100644 src/utils/code_generation/mips/CIL_to_MIPS.py create mode 100644 src/utils/code_generation/mips/print_MIPS_AST.py create mode 100644 src/utils/code_generation/mips/utils_mips.py diff --git a/src/main.py b/src/main.py index 5fdd5621d..3b9bbd73b 100644 --- a/src/main.py +++ b/src/main.py @@ -3,32 +3,33 @@ from pathlib import Path from utils.COOL_Grammar import build_COOL_Grammar from utils.COOL_Lexer import COOL_Lexer -# from utils.code_generation.mips.CIL_to_MIPS import CILToMIPS -# from utils.code_generation.mips.print_MIPS_AST import PrintMIPS +from utils.code_generation.mips.CIL_to_MIPS import CILToMIPS +from utils.code_generation.mips.print_MIPS_AST import PrintMIPS from utils.parser.COOL_parser import COOL_Parser from cmp.evaluation import evaluate_reverse_parse from cmp.semantic import Context from utils.semantic_check.type_collector import TypeCollector from utils.semantic_check.type_builder import TypeBuilder -from utils.semantic_check.type_checker import TypeChecker +from utils.semantic_check.type_checker import TypeChecker from utils.code_generation.cil.COOL_to_CIL import COOLtoCIL from utils.code_generation.cil.print_CIL_AST import get_formatter if __name__ == "__main__": - add = "lexer/mixed1.cl" + add = "codegen/" + _file = "cells.cl" path: str = f"{Path.cwd()}/tests/{add}" if os.path.exists( - f"{Path.cwd()}/tests/{add}") else f"{Path.cwd()}/../tests/{add}" + f"{Path.cwd()}/tests/{add}") else f"{Path.cwd()}/../tests/{add}{_file}" _in = sys.argv[1] if len(sys.argv) > 1 else path - + with open(_in) as file: code = file.read() G = build_COOL_Grammar() # lexer - lexer = COOL_Lexer() + lexer = COOL_Lexer() tokens = lexer(code) if lexer.errors: @@ -38,16 +39,17 @@ # parser parser = COOL_Parser(G) - + derivation, operations = parser(tokens) - + if parser.error: print(parser.error) raise Exception() - - # ast - ast = evaluate_reverse_parse(G, derivation, operations, lexer.fixed_tokens(tokens)) - + + # ast + ast = evaluate_reverse_parse( + G, derivation, operations, lexer.fixed_tokens(tokens)) + # chequeo semantico context = Context() semantic_errors = [] @@ -60,21 +62,33 @@ checker = TypeChecker(context, semantic_errors) scope = checker.visit(ast) - + if semantic_errors: for error in semantic_errors: - print(error) + print(error) raise Exception() -# generacion de codigo -cil_visitor = COOLtoCIL(context) -cil_ast = cil_visitor.visit(ast, scope) + # generacion de codigo + cil_visitor = COOLtoCIL(context) + cil_ast = cil_visitor.visit(ast, scope) + + # print(get_formatter()(cil_ast)) + + mips_visitor = CILToMIPS() + mips_ast = mips_visitor.visit(cil_ast) + + print_mips = PrintMIPS() + mips = print_mips.visit(mips_ast) + + # print(mips) + + _file = sys.argv[1] if len(sys.argv) > 1 else _file -print(get_formatter()(cil_ast)) + output = _file.split(".") + output[-1] = "mips" + output = ".".join(output) -# mips_visitor = CILToMIPS() -# mips_ast = mips_visitor.visit(cil_ast) + with open(output, 'w') as f: + f.write(mips) -# print_mips = PrintMIPS() -# mips = print_mips.visit(mips_ast) -# print(mips) \ No newline at end of file + exit(0) diff --git a/src/utils/code_generation/mips/AST_MIPS.py b/src/utils/code_generation/mips/AST_MIPS.py new file mode 100644 index 000000000..02ec14ec1 --- /dev/null +++ b/src/utils/code_generation/mips/AST_MIPS.py @@ -0,0 +1,234 @@ + +class mips_ast: + class Node: + pass + + class ProgramNode(Node): + def __init__(self, data, types, functions): + self._data = data + self._types = types + self._functions = functions + + @property + def data(self): + return self._data + + @property + def types(self): + return self._types + + @property + def functions(self): + return self._functions + + class DataNode(Node): + def __init__(self, label): + self._label = label + + @property + def label(self): + return self._label + + class FunctionNode(Node): + def __init__(self, label, params, localvars): + self._label = label + self._instructions = [] + self._params = params + self._localvars = localvars + + @property + def label(self): + return self._label + + @property + def instructions(self): + return self._instructions + + def add_instructions(self, instructions): + self._instructions.extend(instructions) + + def get_param_stack_location(self, name): + index = self._params.index(name) + offset = ((len(self._params) - 1) - index) * 4 + return RegisterRelativeLocation(Register('fp'), offset) + + def get_local_stack_location(self, name): + index = self._localvars.index(name) + offset = (index + 2) * -4 + return RegisterRelativeLocation(Register('fp'), offset) + + def get_var_location(self, name): + try: + return self.get_param_stack_location(name) + except ValueError: + return self.get_local_stack_location(name) + + class InstructionNode(Node): + pass + + class AddNode(InstructionNode): + def __init__(self, reg1, reg2, reg3): + self.reg1 = reg1 + self.reg2 = reg2 + self.reg3 = reg3 + + class SubNode(InstructionNode): + def __init__(self, reg1, reg2, reg3): + self.reg1 = reg1 + self.reg2 = reg2 + self.reg3 = reg3 + + class MultiplyNode(InstructionNode): + def __init__(self, reg1, reg2, reg3): + self.reg1 = reg1 + self.reg2 = reg2 + self.reg3 = reg3 + + class DivideNode(InstructionNode): + def __init__(self, reg1, reg2): + self.reg1 = reg1 + self.reg2 = reg2 + + class LabelNode(InstructionNode): + def __init__(self, name): + self.name = name + + class ComplementNode(InstructionNode): + def __init__(self, reg1, reg2): + self.reg1 = reg1 + self.reg2 = reg2 + + class StringConst(DataNode): + def __init__(self, label, string): + super().__init__(label) + self._string = string + + @property + def string(self): + return self._string + + class MoveNode(InstructionNode): + def __init__(self, reg1, reg2): + self.reg1 = reg1 + self.reg2 = reg2 + + class LoadInmediateNode(InstructionNode): + def __init__(self, reg, value): + self.reg = reg + self.value = value + + class LoadWordNode(InstructionNode): + def __init__(self, reg, addr): + self.reg = reg + self.addr = addr + + class SyscallNode(InstructionNode): + pass + + class LoadAddressNode(InstructionNode): + def __init__(self, reg, label): + self.reg = reg + self.label = label + + class StoreWordNode(InstructionNode): + def __init__(self, reg, addr): + self.reg = reg + self.addr = addr + + class JumpAndLinkNode(InstructionNode): + def __init__(self, label): + self.label = label + + class JumpRegisterAndLinkNode(InstructionNode): + def __init__(self, reg): + self.reg = reg + + class JumpRegisterNode(InstructionNode): + def __init__(self, reg): + self.reg = reg + + class AddInmediateNode(InstructionNode): + def __init__(self, dest, src, value): + self.dest = dest + self.src = src + self.value = value + + class AddInmediateUnsignedNode(InstructionNode): + def __init__(self, dest, src, value): + self.dest = dest + self.src = src + self.value = value + + class AddUnsignedNode(InstructionNode): + def __init__(self, dest, sum1, sum2): + self.dest = dest + self.sum1 = sum1 + self.sum2 = sum2 + + class ShiftLeftLogicalNode(InstructionNode): + def __init__(self, dest, src, bits): + self.dest = dest + self.src = src + self.bits = bits + + class BranchOnNotEqualNode(InstructionNode): + def __init__(self, reg1, reg2, label): + self.reg1 = reg1 + self.reg2 = reg2 + self.label = label + + class JumpNode(InstructionNode): + def __init__(self, label): + self.label = label + + class MoveFromLowNode(InstructionNode): + def __init__(self, reg): + self.reg = reg + + +class Register(): + def __init__(self, name): + self.name = name + + +ARG_REGISTERS = [Register(name) for name in ['a0', 'a1', 'a2', 'a3']] + + +SP_REG = Register('sp') +RA_REG = Register('ra') +V0_REG = Register('v0') +V1_REG = Register('v1') +ZERO_REG = Register('zero') +LOW_REG = Register('low') + + +class MemoryLocation: + pass + + +class RegisterRelativeLocation(MemoryLocation): + def __init__(self, register, offset): + self._register = register + self._offset = offset + + @property + def register(self): + return self._register + + @property + def offset(self): + return self._offset + + +class LabelRelativeLocation(MemoryLocation): + def __init__(self, label, offset): + self._label = label + self._offset = offset + + @property + def label(self): + return self._label + + @property + def offset(self): + return self._offset diff --git a/src/utils/code_generation/mips/CIL_to_MIPS.py b/src/utils/code_generation/mips/CIL_to_MIPS.py new file mode 100644 index 000000000..5019a305b --- /dev/null +++ b/src/utils/code_generation/mips/CIL_to_MIPS.py @@ -0,0 +1,1076 @@ +import itertools as itt +import cmp.visitor as visitor +from utils.code_generation.cil.AST_CIL import cil_ast as cil +from utils.code_generation.mips.AST_MIPS import mips_ast as mips +from utils.code_generation.mips.AST_MIPS import * +from utils.code_generation.mips.utils_mips import * + + +class CILToMIPS: + def __init__(self, label_generator=LabelGenerator()): + self._label_generator = label_generator + self.memory_manager = None + self._types = {} + self._data_section = {} + self._functions = {} + self._actual_function = None + self._name_func_map = {} + self._pushed_args = 0 + self._labels_map = {} + + def generate_type_label(self): + return self._label_generator.generate_type_label() + + def generate_data_label(self): + return self._label_generator.generate_data_label() + + def generate_code_label(self): + return self._label_generator.generate_code_label() + + def get_var_location(self, name): + return self._actual_function.get_var_location(name) + + def register_function(self, name, function): + self._functions[name] = function + + def init_function(self, function): + self._actual_function = function + self._labels_map = {} + + def finish_functions(self): + self._actual_function = None + + def push_arg(self): + self._pushed_args += 1 + + def clean_pushed_args(self): + self._pushed_args = 0 + + def get_free_reg(self): + return self._registers_manager.get_free_reg() + + def free_reg(self, reg): + self._registers_manager.free_reg(reg) + + def in_entry_function(self): + return self._actual_function.label == 'main' + + def register_label(self, cil_label, mips_label): + self._labels_map[cil_label] = mips_label + + def get_mips_label(self, label): + return self._labels_map[label] + + @visitor.on('node') + def collect_func_names(self, node): + pass + + @visitor.when(cil.ProgramNode) + def collect_func_names(self, node): + for func in node.dotcode: + self.collect_func_names(func) + + @visitor.when(cil.FunctionNode) + def collect_func_names(self, node): + if node.id == "entry": + self._name_func_map[node.id] = 'main' + else: + self._name_func_map[node.id] = self.generate_code_label() + + @visitor.on('node') + def collect_labels_in_func(self, node): + pass + + @visitor.when(cil.LabelNode) + def collect_labels_in_func(self, node): + mips_label = self.generate_code_label() + self.register_label(node.label, mips_label) + + @visitor.on('node') + def visit(self, node): + pass + + @visitor.when(cil.ProgramNode) + def visit(self, node): + + self.collect_func_names(node) + + self._data_section["default_str"] = mips.StringConst("default_str", "") + for tp in node.dottypes: + self.visit(tp) + + for data in node.dotdata: + self.visit(data) + + for func in node.dotcode: + self.visit(func) + + return mips.ProgramNode([data for data in self._data_section.values()], [tp for tp in self._types.values()], [func for func in self._functions.values()]) + + @visitor.when(cil.TypeNode) + def visit(self, node): + name_label = self.generate_data_label() + self._data_section[node.id] = mips.StringConst(name_label, node.id) + + type_label = self.generate_type_label() + methods = {key: self._name_func_map[value] + for key, value in node.methods} + defaults = [] + if node.id == "String": + defaults = [('value', 'default_str'), ('length', 'type_4_proto')] + new_type = MIPSType(type_label, name_label, node.attributes, methods, len( + self._types), default=defaults) + + self._types[node.id] = new_type + + @visitor.when(cil.DataNode) + def visit(self, node): + label = self.generate_data_label() + self._data_section[node.id] = mips.StringConst(label, node.value) + + @visitor.when(cil.FunctionNode) + def visit(self, node): + used_regs_finder = UsedRegisterFinder() + + label = self._name_func_map[node.id] + params = [param.id for param in node.params] + localvars = [local.id for local in node.localvars] + size_for_locals = len(localvars) * 4 + + new_func = mips.FunctionNode(label, params, localvars) + self.register_function(node.id, new_func) + self.init_function(new_func) + + ra = RegistersAllocator() + + if len(node.instructions): + reg_for_var = ra.get_registers_for_variables( + node.instructions, node.params, 10) + self.memory_manager = MemoryManager( + [Register(name) for name in ['t0', 't1', 't2', + 't3', 't4', 't5', 't6', 't7', 't8', 't9']], lambda x: reg_for_var[x]) + + for instruction in node.instructions: + self.collect_labels_in_func(instruction) + + initial_instructions = [] + if self.in_entry_function(): + initial_instructions.append( + mips.JumpAndLinkNode("mem_manager_init")) + + initial_instructions.extend(push_register(Register('fp'))) + initial_instructions.append( + mips.AddInmediateNode(Register('fp'), SP_REG, 4)) + initial_instructions.append(mips.AddInmediateNode( + SP_REG, SP_REG, -size_for_locals)) + + code_instructions = [] + + code_instructions = list(itt.chain.from_iterable( + [self.visit(instruction) for instruction in node.instructions])) + + final_instructions = [] + + for param in params: + reg = self.memory_manager.get_reg_for_var(param) + if reg is not None: + code_instructions.insert(0, mips.LoadWordNode( + reg, self.get_var_location(param))) + + if not self.in_entry_function(): + used_regs = used_regs_finder.get_used_registers(code_instructions) + for reg in used_regs: + initial_instructions.extend(push_register(reg)) + + for reg in used_regs[::-1]: + final_instructions.extend(pop_register(reg)) + + final_instructions.append(mips.AddInmediateNode( + SP_REG, SP_REG, size_for_locals)) + final_instructions.extend(pop_register(Register('fp'))) + + if not self.in_entry_function(): + final_instructions.append(mips.JumpRegisterNode(RA_REG)) + else: + final_instructions.extend(exit_program()) + + func_instructions = list( + itt.chain(initial_instructions, code_instructions, final_instructions)) + new_func.add_instructions(func_instructions) + + self.finish_functions() + + @visitor.when(cil.InstructionNode) + def visit(self, node): + print(type(node)) + + @visitor.when(cil.AssignNode) + def visit(self, node): + instructions = [] + + reg1 = None + if type(node.right) == cil.VoidNode: + reg1 = ZERO_REG + elif node.right.isnumeric(): + reg1 = ARG_REGISTERS[0] + instructions.append(mips.LoadInmediateNode(reg1, int(node.right))) + else: + reg1 = self.memory_manager.get_reg_for_var(node.right) + if reg1 is None: + reg1 = ARG_REGISTERS[0] + instructions.append(mips.LoadWordNode( + reg1, self.get_var_location(node.right))) + + reg2 = self.memory_manager.get_reg_for_var(node.left) + if reg2 is None: + instructions.append(mips.StoreWordNode( + reg1, self.get_var_location(node.left))) + else: + instructions.append(mips.MoveNode(reg2, reg1)) + + return instructions + + @visitor.when(cil.PlusNode) + def visit(self, node): + instructions = [] + + reg1, reg2 = None, None + if type(node.op_l) == int: + reg1 = ARG_REGISTERS[0] + instructions.append(mips.LoadInmediateNode(reg1, node.op_l)) + else: + reg1 = self.memory_manager.get_reg_for_var(node.op_l) + if reg1 is None: + reg1 = ARG_REGISTERS[0] + instructions.append(mips.LoadWordNode( + reg1, self.get_var_location(node.op_l))) + + if type(node.op_r) == int: + reg2 = ARG_REGISTERS[1] + instructions.append(mips.LoadInmediateNode(reg2, node.op_r)) + else: + reg2 = self.memory_manager.get_reg_for_var(node.op_r) + if reg2 is None: + reg2 = ARG_REGISTERS[1] + instructions.append(mips.LoadWordNode( + reg2, self.get_var_location(node.op_r))) + + reg3 = self.memory_manager.get_reg_for_var(node.dest) + if reg3 is None: + instructions.append(mips.AddNode( + ARG_REGISTERS[0], reg1, reg2)) + instructions.append(mips.StoreWordNode( + ARG_REGISTERS[0], self.get_var_location(node.dest))) + else: + instructions.append(mips.AddNode(reg3, reg1, reg2)) + + return instructions + + @visitor.when(cil.MinusNode) + def visit(self, node): + instructions = [] + + reg1, reg2 = None, None + if type(node.op_l) == int: + reg1 = ARG_REGISTERS[0] + instructions.append(mips.LoadInmediateNode(reg1, node.op_l)) + else: + reg1 = self.memory_manager.get_reg_for_var(node.op_l) + if reg1 is None: + reg1 = ARG_REGISTERS[0] + instructions.append(mips.LoadWordNode( + reg1, self.get_var_location(node.op_l))) + + if type(node.op_r) == int: + instructions.append(mips.LoadInmediateNode(reg2, node.op_r)) + else: + reg2 = self.memory_manager.get_reg_for_var(node.op_r) + if reg2 is None: + reg2 = ARG_REGISTERS[1] + instructions.append(mips.LoadWordNode( + reg2, self.get_var_location(node.op_r))) + + reg3 = self.memory_manager.get_reg_for_var(node.dest) + if reg3 is None: + instructions.append(mips.SubNode( + ARG_REGISTERS[0], reg1, reg2)) + instructions.append(mips.StoreWordNode( + ARG_REGISTERS[0], self.get_var_location(node.dest))) + else: + instructions.append(mips.SubNode(reg3, reg1, reg2)) + + return instructions + + @visitor.when(cil.StarNode) + def visit(self, node): + instructions = [] + + reg1, reg2 = None, None + if type(node.op_l) == int: + reg1 = ARG_REGISTERS[0] + instructions.append(mips.LoadInmediateNode(reg1, node.op_l)) + else: + reg1 = self.memory_manager.get_reg_for_var(node.op_l) + if reg1 is None: + reg1 = ARG_REGISTERS[0] + instructions.append(mips.LoadWordNode( + reg1, self.get_var_location(node.op_l))) + + if type(node.op_r) == int: + reg2 = ARG_REGISTERS[1] + instructions.append(mips.LoadInmediateNode(reg2, node.op_r)) + else: + reg2 = self.memory_manager.get_reg_for_var(node.op_r) + if reg2 is None: + reg2 = ARG_REGISTERS[1] + instructions.append(mips.LoadWordNode( + reg2, self.get_var_location(node.op_r))) + + reg3 = self.memory_manager.get_reg_for_var(node.dest) + if reg3 is None: + instructions.append(mips.MultiplyNode( + ARG_REGISTERS[0], reg1, reg2)) + instructions.append(mips.StoreWordNode( + ARG_REGISTERS[0], self.get_var_location(node.dest))) + else: + instructions.append(mips.MultiplyNode(reg3, reg1, reg2)) + + return instructions + + @visitor.when(cil.DivNode) + def visit(self, node): + instructions = [] + + reg1, reg2 = None, None + if type(node.op_l) == int: + reg1 = ARG_REGISTERS[0] + instructions.append(mips.LoadInmediateNode(reg1, node.op_l)) + else: + reg1 = self.memory_manager.get_reg_for_var(node.op_l) + if reg1 is None: + reg1 = ARG_REGISTERS[0] + instructions.append(mips.LoadWordNode( + reg1, self.get_var_location(node.op_l))) + + if type(node.op_r) == int: + reg2 = ARG_REGISTERS[1] + instructions.append(mips.LoadInmediateNode(reg2, node.op_r)) + else: + reg2 = self.memory_manager.get_reg_for_var(node.op_r) + if reg2 is None: + reg2 = ARG_REGISTERS[1] + instructions.append(mips.LoadWordNode( + reg2, self.get_var_location(node.op_r))) + + instructions.append(mips.DivideNode(reg1, reg2)) + reg3 = self.memory_manager.get_reg_for_var(node.dest) + if reg3 is None: + instructions.append(mips.MoveFromLowNode(ARG_REGISTERS[0])) + instructions.append(mips.StoreWordNode( + ARG_REGISTERS[0], self.get_var_location(node.dest))) + else: + instructions.append(mips.MoveFromLowNode(reg3)) + + return instructions + + @visitor.when(cil.LessThanNode) + def visit(self, node): + instructions = [] + + if type(node.op_l) == int: + instructions.append(mips.LoadInmediateNode( + ARG_REGISTERS[0], node.op_l)) + else: + reg = self.memory_manager.get_reg_for_var(node.op_l) + if reg is None: + instructions.append(mips.LoadWordNode( + ARG_REGISTERS[0], self.get_var_location(node.op_l))) + else: + instructions.append(mips.MoveNode(ARG_REGISTERS[0], reg)) + + if type(node.op_r) == int: + instructions.append(mips.LoadInmediateNode( + ARG_REGISTERS[1], node.op_r)) + else: + reg = self.memory_manager.get_reg_for_var(node.op_r) + if reg is None: + instructions.append(mips.LoadWordNode( + ARG_REGISTERS[1], self.get_var_location(node.op_r))) + else: + instructions.append(mips.MoveNode(ARG_REGISTERS[1], reg)) + + instructions.append(mips.JumpAndLinkNode('less')) + reg = self.memory_manager.get_reg_for_var(node.dest) + if reg is None: + instructions.append(mips.StoreWordNode( + V0_REG, self.get_var_location(node.dest))) + else: + instructions.append(mips.MoveNode(reg, V0_REG)) + + return instructions + + @visitor.when(cil.LessEqualNode) + def visit(self, node): + instructions = [] + + if type(node.op_l) == int: + instructions.append(mips.LoadInmediateNode( + ARG_REGISTERS[0], node.op_l)) + else: + reg = self.memory_manager.get_reg_for_var(node.op_l) + if reg is None: + instructions.append(mips.LoadWordNode( + ARG_REGISTERS[0], self.get_var_location(node.op_l))) + else: + instructions.append(mips.MoveNode(ARG_REGISTERS[0], reg)) + + if type(node.op_r) == int: + instructions.append(mips.LoadInmediateNode( + ARG_REGISTERS[1], node.op_r)) + else: + reg = self.memory_manager.get_reg_for_var(node.op_r) + if reg is None: + instructions.append(mips.LoadWordNode( + ARG_REGISTERS[1], self.get_var_location(node.op_r))) + else: + instructions.append(mips.MoveNode(ARG_REGISTERS[1], reg)) + + instructions.append(mips.JumpAndLinkNode('less_eq')) + reg = self.memory_manager.get_reg_for_var(node.dest) + if reg is None: + instructions.append(mips.StoreWordNode( + V0_REG, self.get_var_location(node.dest))) + else: + instructions.append(mips.MoveNode(reg, V0_REG)) + + return instructions + + @visitor.when(cil.EqualNode) + def visit(self, node): + instructions = [] + + if type(node.op_l) == int: + instructions.append(mips.LoadInmediateNode( + ARG_REGISTERS[0], node.op_l)) + elif type(node.op_l) == cil.VoidNode: + instructions.append( + mips.LoadInmediateNode(ARG_REGISTERS[0], 0)) + else: + reg = self.memory_manager.get_reg_for_var(node.op_l) + if reg is None: + instructions.append(mips.LoadWordNode( + ARG_REGISTERS[0], self.get_var_location(node.op_l))) + else: + instructions.append(mips.MoveNode(ARG_REGISTERS[0], reg)) + + if type(node.op_r) == int: + instructions.append(mips.LoadInmediateNode( + ARG_REGISTERS[1], node.op_r)) + elif type(node.op_r) == cil.VoidNode: + instructions.append( + mips.LoadInmediateNode(ARG_REGISTERS[1], 0)) + else: + reg = self.memory_manager.get_reg_for_var(node.op_r) + if reg is None: + instructions.append(mips.LoadWordNode( + ARG_REGISTERS[1], self.get_var_location(node.op_r))) + else: + instructions.append(mips.MoveNode(ARG_REGISTERS[1], reg)) + + instructions.append(mips.JumpAndLinkNode("eqs")) + + reg = self.memory_manager.get_reg_for_var(node.dest) + if reg is None: + instructions.append(mips.StoreWordNode( + V0_REG, self.get_var_location(node.dest))) + else: + instructions.append(mips.MoveNode(reg, V0_REG)) + + return instructions + + @visitor.when(cil.EqualStrNode) + def visit(self, node): + instructions = [] + + reg = self.memory_manager.get_reg_for_var(node.op_l) + if reg is None: + instructions.append(mips.LoadWordNode( + ARG_REGISTERS[0], self.get_var_location(node.op_l))) + else: + instructions.append(mips.MoveNode(ARG_REGISTERS[0], reg)) + + reg = self.memory_manager.get_reg_for_var(node.op_r) + if reg is None: + instructions.append(mips.LoadWordNode( + ARG_REGISTERS[1], self.get_var_location(node.op_r))) + else: + instructions.append(mips.MoveNode(ARG_REGISTERS[1], reg)) + + instructions.append(mips.JumpAndLinkNode("eq_string")) + + reg = self.memory_manager.get_reg_for_var(node.dest) + if reg is None: + instructions.append(mips.StoreWordNode( + V0_REG, self.get_var_location(node.dest))) + else: + instructions.append(mips.MoveNode(reg, V0_REG)) + + return instructions + + @visitor.when(cil.GetAttrNode) + def visit(self, node): + instructions = [] + + dest = node.dest if type(node.dest) == str else node.dest.id + idx = node.id if type(node.id) == str else node.id.id + comp_type = node.computed_type if type( + node.computed_type) == str else node.computed_type.id + + reg = self.memory_manager.get_reg_for_var(idx) + if reg is None: + reg = ARG_REGISTERS[0] + instructions.append(mips.LoadWordNode( + reg, self.get_var_location(idx))) + + tp = self._types[comp_type] + offset = (tp.attributes.index(node.attr) + 3) * 4 + instructions.append(mips.LoadWordNode( + ARG_REGISTERS[1], RegisterRelativeLocation(reg, offset))) + + reg = self.memory_manager.get_reg_for_var(dest) + if reg is None: + instructions.append(mips.StoreWordNode( + ARG_REGISTERS[1], self.get_var_location(dest))) + else: + instructions.append(mips.MoveNode(reg, ARG_REGISTERS[1])) + + return instructions + + @visitor.when(cil.SetAttrNode) + def visit(self, node): + instructions = [] + + idx = node.id if type(node.id) == str else node.id.id + comp_type = node.computed_type if type( + node.computed_type) == str else node.computed_type.name + + tp = self._types[comp_type] + offset = (tp.attributes.index(node.attr) + 3) * 4 + + reg1 = self.memory_manager.get_reg_for_var(idx) + if reg1 is None: + reg1 = ARG_REGISTERS[0] + instructions.append(mips.LoadWordNode( + ARG_REGISTERS[0], self.get_var_location(idx))) + + reg2 = None + if type(node.value) == int: + reg2 = instructions.append(mips.LoadInmediateNode( + ARG_REGISTERS[1], node.value)) + else: + reg2 = self.memory_manager.get_reg_for_var(node.value) + if reg2 is None: + reg2 = ARG_REGISTERS[1] + instructions.append(mips.LoadWordNode( + reg2, self.get_var_location(node.value))) + + instructions.append(mips.StoreWordNode( + reg2, RegisterRelativeLocation(reg1, offset))) + + return instructions + + @visitor.when(cil.AllocateNode) + def visit(self, node): + instructions = [] + + tp = 0 + if node.type.isnumeric(): + tp = node.type + else: + tp = self._types[node.type].index + + reg1 = self.memory_manager.get_reg_unusued() + reg2 = self.memory_manager.get_reg_unusued([reg1]) + instructions.extend(push_register(reg1)) + instructions.extend(push_register(reg2)) + + instructions.append(mips.LoadInmediateNode(reg1, tp)) + + instructions.extend(create_object(reg1, reg2)) + + instructions.extend(pop_register(reg2)) + instructions.extend(pop_register(reg1)) + + reg3 = self.memory_manager.get_reg_for_var(node.dest) + if reg3 is None: + instructions.append(mips.StoreWordNode( + V0_REG, self.get_var_location(node.dest))) + else: + instructions.append(mips.MoveNode(reg3, V0_REG)) + + return instructions + + @visitor.when(cil.TypeOfNode) + def visit(self, node): + instructions = [] + + reg1 = self.memory_manager.get_reg_for_var(node.id) + if reg1 is None: + reg1 = ARG_REGISTERS[0] + instructions.append(mips.LoadWordNode( + reg1, self.get_var_location(node.id))) + + reg2 = self.memory_manager.get_reg_for_var(node.dest) + if reg2 is None: + instructions.append(mips.LoadWordNode( + ARG_REGISTERS[1], RegisterRelativeLocation(reg1, 0))) + instructions.append(mips.StoreWordNode( + ARG_REGISTERS[1], self.get_var_location(node.dest))) + else: + instructions.append(mips.LoadWordNode( + reg2, RegisterRelativeLocation(reg1, 0))) + + return instructions + + @visitor.when(cil.StaticCallNode) + def visit(self, node): + instructions = [] + label = self._name_func_map[node.function] + instructions.append(mips.JumpAndLinkNode(label)) + + reg = self.memory_manager.get_reg_for_var(node.dest) + if reg is None: + instructions.append(mips.StoreWordNode( + V0_REG, self.get_var_location(node.dest))) + else: + instructions.append(mips.MoveNode(reg, V0_REG)) + + if self._pushed_args > 0: + instructions.append(mips.AddInmediateNode( + SP_REG, SP_REG, self._pushed_args * 4)) + self.clean_pushed_args() + return instructions + + @visitor.when(cil.DynamicCallNode) + def visit(self, node): + instructions = [] + + comp_tp = self._types[node.computed_type] + method_index = list(comp_tp.methods).index(node.function) + reg = self.memory_manager.get_reg_for_var(node.type) + if reg is None: + reg = ARG_REGISTERS[0] + instructions.append(mips.LoadWordNode( + reg, self.get_var_location(node.type))) + + instructions.append(mips.LoadAddressNode( + ARG_REGISTERS[1], "proto_table")) + instructions.append(mips.ShiftLeftLogicalNode( + ARG_REGISTERS[2], reg, 2)) + instructions.append(mips.AddUnsignedNode( + ARG_REGISTERS[1], ARG_REGISTERS[1], ARG_REGISTERS[2])) + instructions.append(mips.LoadWordNode( + ARG_REGISTERS[1], RegisterRelativeLocation(ARG_REGISTERS[1], 0))) + instructions.append(mips.LoadWordNode( + ARG_REGISTERS[1], RegisterRelativeLocation(ARG_REGISTERS[1], 8))) + instructions.append(mips.AddInmediateUnsignedNode( + ARG_REGISTERS[1], ARG_REGISTERS[1], method_index * 4)) + instructions.append(mips.LoadWordNode( + ARG_REGISTERS[1], RegisterRelativeLocation(ARG_REGISTERS[1], 0))) + instructions.append( + mips.JumpRegisterAndLinkNode(ARG_REGISTERS[1])) + + reg = self.memory_manager.get_reg_for_var(node.dest) + if reg is None: + instructions.append(mips.StoreWordNode( + V0_REG, self.get_var_location(node.dest))) + else: + instructions.append(mips.MoveNode(reg, V0_REG)) + + if self._pushed_args > 0: + instructions.append(mips.AddInmediateNode( + SP_REG, SP_REG, self._pushed_args * 4)) + self.clean_pushed_args() + + return instructions + + @visitor.when(cil.ArgNode) + def visit(self, node): + self.push_arg() + instructions = [] + if type(node.id) == int: + instructions.append(mips.LoadInmediateNode( + ARG_REGISTERS[0], node.id)) + instructions.extend(push_register(ARG_REGISTERS[0])) + else: + reg = self.memory_manager.get_reg_for_var(node.id) + if reg is None: + reg = ARG_REGISTERS[0] + instructions.append(mips.LoadWordNode( + reg, self.get_var_location(node.id))) + instructions.extend(push_register(reg)) + return instructions + + @visitor.when(cil.IfGotoNode) + def visit(self, node): + instructions = [] + + mips_label = self.get_mips_label(node.label) + + reg = self.memory_manager.get_reg_for_var(node.if_cond) + if reg is None: + reg = ARG_REGISTERS[0] + instructions.append(mips.LoadWordNode( + ARG_REGISTERS[0], self.get_var_location(node.if_cond))) + + instructions.append(mips.BranchOnNotEqualNode( + reg, ZERO_REG, mips_label)) + + return instructions + + @visitor.when(cil.LabelNode) + def visit(self, node): + return [mips.LabelNode(self.get_mips_label(node.label))] + + @visitor.when(cil.GotoNode) + def visit(self, node): + mips_label = self.get_mips_label(node.label) + return [mips.JumpNode(mips_label)] + + @visitor.when(cil.ReturnNode) + def visit(self, node): + instructions = [] + + if node.id is None: + instructions.append(mips.LoadInmediateNode(V0_REG, 0)) + elif isinstance(node.id, int): + instructions.append( + mips.LoadInmediateNode(V0_REG, node.id)) + elif isinstance(node.id, cil.VoidNode): + instructions.append(mips.LoadInmediateNode(V0_REG, 0)) + else: + reg = self.memory_manager.get_reg_for_var(node.id) + if reg is None: + instructions.append(mips.LoadWordNode( + V0_REG, self.get_var_location(node.id))) + else: + instructions.append(mips.MoveNode(V0_REG, reg)) + return instructions + + @visitor.when(cil.LoadNode) + def visit(self, node): + instructions = [] + + string_location = LabelRelativeLocation( + self._data_section[node.msg.id].label, 0) + reg = self.memory_manager.get_reg_for_var(node.dest) + if reg is None: + instructions.append(mips.LoadAddressNode( + ARG_REGISTERS[0], string_location)) + instructions.append(mips.StoreWordNode( + ARG_REGISTERS[0], self.get_var_location(node.dest))) + else: + instructions.append(mips.LoadAddressNode(reg, string_location)) + + return instructions + + @visitor.when(cil.LengthNode) + def visit(self, node): + instructions = [] + + reg = self.memory_manager.get_reg_for_var(node.id) + if reg is None: + reg = ARG_REGISTERS[0] + instructions.append(mips.LoadWordNode( + reg, self.get_var_location(node.id))) + + instructions.append(mips.MoveNode(ARG_REGISTERS[0], reg)) + instructions.append(mips.JumpAndLinkNode("len")) + + reg = self.memory_manager.get_reg_for_var(node.dest) + if reg is None: + instructions.append(mips.StoreWordNode( + V0_REG, self.get_var_location(node.dest))) + else: + instructions.append(mips.MoveNode(reg, V0_REG)) + + return instructions + + @visitor.when(cil.ConcatNode) + def visit(self, node): + instructions = [] + + reg = self.memory_manager.get_reg_for_var(node.s1) + if reg is None: + instructions.append(mips.LoadWordNode( + ARG_REGISTERS[0], self.get_var_location(node.s1))) + else: + instructions.append(mips.MoveNode(ARG_REGISTERS[0], reg)) + + reg = self.memory_manager.get_reg_for_var(node.s2) + if reg is None: + instructions.append(mips.LoadWordNode( + ARG_REGISTERS[1], self.get_var_location(node.s2))) + else: + instructions.append(mips.MoveNode(ARG_REGISTERS[1], reg)) + + reg = self.memory_manager.get_reg_for_var(node.length) + if reg is None: + instructions.append(mips.LoadWordNode( + ARG_REGISTERS[2], self.get_var_location(node.lenght))) + else: + instructions.append(mips.MoveNode(ARG_REGISTERS[2], reg)) + + instructions.append(mips.JumpAndLinkNode("concat")) + + reg = self.memory_manager.get_reg_for_var(node.dest) + if reg is None: + instructions.append(mips.StoreWordNode( + V0_REG, self.get_var_location(node.dest))) + else: + instructions.append(mips.MoveNode(reg, V0_REG)) + + return instructions + + @visitor.when(cil.SubstringNode) + def visit(self, node): + instructions = [] + + reg = self.memory_manager.get_reg_for_var(node.s) + if reg is None: + instructions.append(mips.LoadWordNode( + ARG_REGISTERS[0], self.get_var_location(node.s))) + else: + instructions.append(mips.MoveNode(ARG_REGISTERS[0], reg)) + + if type(node.i) == int: + instructions.append(mips.LoadInmediateNode( + ARG_REGISTERS[1], node.i)) + else: + reg = self.memory_manager.get_reg_for_var(node.i) + if reg is None: + instructions.append(mips.LoadWordNode( + ARG_REGISTERS[1], self.get_var_location(node.i))) + else: + instructions.append(mips.MoveNode(ARG_REGISTERS[1], reg)) + + if type(node.length) == int: + instructions.append(mips.LoadInmediateNode( + ARG_REGISTERS[2], node.length)) + else: + reg = self.memory_manager.get_reg_for_var(node.length) + if reg is None: + instructions.append(mips.LoadWordNode( + ARG_REGISTERS[2], self.get_var_location(node.length))) + else: + instructions.append(mips.MoveNode(ARG_REGISTERS[2], reg)) + + instructions.append(mips.JumpAndLinkNode("sub_string")) + reg = self.memory_manager.get_reg_for_var(node.dest) + if reg is None: + instructions.append(mips.StoreWordNode( + V0_REG, self.get_var_location(node.dest))) + else: + instructions.append(mips.MoveNode(reg, V0_REG)) + return instructions + + @visitor.when(cil.ReadStrNode) + def visit(self, node): + instructions = [] + instructions.append(mips.JumpAndLinkNode("get_string")) + + reg = self.memory_manager.get_reg_for_var(node.dest) + if reg is None: + instructions.append(mips.StoreWordNode( + V0_REG, self.get_var_location(node.dest))) + else: + instructions.append(mips.MoveNode(reg, V0_REG)) + + return instructions + + @visitor.when(cil.PrintStrNode) + def visit(self, node): + instructions = [] + instructions.append(mips.LoadInmediateNode(V0_REG, 4)) + + reg = self.memory_manager.get_reg_for_var(node.value) + if reg is None: + instructions.append(mips.LoadWordNode( + ARG_REGISTERS[0]. self.get_var_location(node.value))) + else: + instructions.append(mips.MoveNode(ARG_REGISTERS[0], reg)) + instructions.append(mips.SyscallNode()) + + return instructions + + @visitor.when(cil.ErrorNode) + def visit(self, node): + instructions = [] + + mips_label = self._data_section[node.data_node.id].label + + instructions.append(mips.LoadInmediateNode(V0_REG, 4)) + instructions.append(mips.LoadAddressNode( + ARG_REGISTERS[0], mips_label)) + instructions.append(mips.SyscallNode()) + instructions.append(mips.LoadInmediateNode(V0_REG, 10)) + instructions.append(mips.SyscallNode()) + + return instructions + + @visitor.when(cil.TypeNameNode) + def visit(self, node): + instructions = [] + + reg1 = self.memory_manager.get_reg_for_var(node.type) + pushed = False + if reg1 is None: + reg1 = self.memory_manager.get_reg_unusued() + instructions.extend(push_register(reg1)) + instructions.append(mips.LoadWordNode( + reg1, self.get_var_location(node.type))) + pushed = True + + instructions.append(mips.LoadWordNode( + ARG_REGISTERS[0], RegisterRelativeLocation(reg1, 0))) + + if pushed: + instructions.extend(pop_register(reg1)) + + instructions.append(mips.ShiftLeftLogicalNode( + ARG_REGISTERS[0], ARG_REGISTERS[0], 2)) + instructions.append(mips.LoadAddressNode( + ARG_REGISTERS[1], "type_name_table")) + instructions.append(mips.AddUnsignedNode( + ARG_REGISTERS[0], ARG_REGISTERS[0], ARG_REGISTERS[1])) + instructions.append(mips.LoadWordNode( + ARG_REGISTERS[0], RegisterRelativeLocation(ARG_REGISTERS[0], 0))) + + reg2 = self.memory_manager.get_reg_for_var(node.dest) + if reg2 is None: + instructions.append(mips.StoreWordNode( + ARG_REGISTERS[0], self.get_var_location(node.dest))) + else: + instructions.append(mips.MoveNode(reg2, ARG_REGISTERS[0])) + + return instructions + + @visitor.when(cil.NameNode) + def visit(self, node): + instructions = [] + + save = False + reg = self.memory_manager.get_reg_for_var(node.dest) + if reg is None: + reg = ARG_REGISTERS[0] + save = True + + instructions.append(mips.LoadAddressNode( + reg, "type_name_table")) + + tp_number = self._types[node.id].index + instructions.append( + mips.AddInmediateUnsignedNode(reg, reg, tp_number*4)) + instructions.append(mips.LoadWordNode( + reg, RegisterRelativeLocation(reg, 0))) + + if save: + instructions.append(mips.StoreWordNode( + reg, self.get_var_location(node.dest))) + + return instructions + + @visitor.when(cil.AbortNode) + def visit(self, node): + instructions = [] + instructions.append(mips.LoadInmediateNode(V0_REG, 10)) + instructions.append(mips.SyscallNode()) + + return instructions + + @visitor.when(cil.CopyNode) + def visit(self, node): + instructions = [] + + pushed = False + reg = self.memory_manager.get_reg_for_var(node.copy) + if reg is None: + reg = self.memory_manager.get_reg_unusued() + instructions.extend(push_register(reg)) + instructions.append(mips.LoadWordNode( + reg, self.get_var_location(node.copy))) + pushed = True + + instructions.extend(copy_object(reg, ARG_REGISTERS[3])) + + if pushed: + instructions.extend(pop_register(reg)) + + reg = self.memory_manager.get_reg_for_var(node.dest) + if reg is None: + instructions.append(mips.StoreWordNode( + V0_REG, self.get_var_location(node.dest))) + else: + instructions.append(mips.MoveNode(reg, V0_REG)) + + return instructions + + @visitor.when(cil.ReadIntNode) + def visit(self, node): + instructions = [] + + instructions.append(mips.LoadInmediateNode(V0_REG, 5)) + instructions.append(mips.SyscallNode()) + reg = self.memory_manager.get_reg_for_var(node.dest) + if reg is None: + instructions.append(mips.StoreWordNode( + V0_REG, self.get_var_location(node.dest))) + else: + instructions.append(mips.MoveNode(reg, V0_REG)) + + return instructions + + @visitor.when(cil.PrintIntNode) + def visit(self, node): + instructions = [] + instructions.append(mips.LoadInmediateNode(V0_REG, 1)) + + reg = self.memory_manager.get_reg_for_var(node.value) + if reg is None: + instructions.append(mips.LoadWordNode( + ARG_REGISTERS[0], self.get_var_location(node.value))) + else: + instructions.append(mips.MoveNode(ARG_REGISTERS[0], reg)) + + instructions.append(mips.SyscallNode()) + + return instructions + + @visitor.when(cil.ComplementNode) + def visit(self, node): + instructions = [] + + reg1 = None + + if type(node.id) == int: + reg1 = ARG_REGISTERS[0] + instructions.append(mips.LoadInmediateNode(reg1, node.id)) + else: + reg1 = self.memory_manager.get_reg_for_var(node.id) + if reg1 is None: + reg1 = ARG_REGISTERS[0] + instructions.append(mips.LoadWordNode( + reg1, self.get_var_location(node.id))) + + reg2 = self.memory_manager.get_reg_for_var(node.dest) + if reg2 is None: + reg2 = ARG_REGISTERS[1] + instructions.append(mips.ComplementNode(reg2, reg1)) + instructions.append(mips.AddInmediateNode(reg2, reg2, 1)) + instructions.append(mips.StoreWordNode( + reg2, self.get_var_location(node.dest))) + else: + instructions.append(mips.ComplementNode(reg2, reg1)) + instructions.append(mips.AddInmediateNode(reg2, reg2, 1)) + + return instructions diff --git a/src/utils/code_generation/mips/print_MIPS_AST.py b/src/utils/code_generation/mips/print_MIPS_AST.py new file mode 100644 index 000000000..4c807ad54 --- /dev/null +++ b/src/utils/code_generation/mips/print_MIPS_AST.py @@ -0,0 +1,1396 @@ +from utils.code_generation.mips.AST_MIPS import * +import cmp.visitor as visitor +from utils.code_generation.mips.AST_MIPS import mips_ast as nodes +from utils.code_generation.mips.utils_mips import * + + +class PrintMIPS: + + @visitor.on('node') + def visit(self, node): + pass + + @visitor.when(nodes.ProgramNode) + def visit(self, node): + data_section_header = "\t.data" + static_strings = '\n'.join([self.visit(string_const) + for string_const in node.data]) + + names_table = f'{"type_name_table"}:\n' + \ + "\n".join( + [f"\t.word\t{tp.string_name_label}" for tp in node.types]) + proto_table = f'{"proto_table"}:\n' + \ + "\n".join([f"\t.word\t{tp.label}_proto" for tp in node.types]) + + types = "\n\n".join([self.visit(tp) for tp in node.types]) + + code = "\n".join([self.visit(func) for func in node.functions]) + return f'{data_section_header}\n{static_strings}\n\n{names_table}\n\n{proto_table}\n\n{types}\n\t.text\n\t.globl main\n{code}\n\n{mips_static_code()}' + + @visitor.when(nodes.FunctionNode) + def visit(self, node): + instr = [self.visit(instruction) for instruction in node.instructions] + instr2 = [inst for inst in instr if type(inst) == str] + instructions = "\n\t".join(instr2) + return f'{node.label}:\n\t{instructions}' + + @visitor.when(nodes.AddNode) + def visit(self, node): + return f"add {self.visit(node.reg1)} {self.visit(node.reg2)} {self.visit(node.reg3)}" + + @visitor.when(nodes.SubNode) + def visit(self, node): + return f"sub {self.visit(node.reg1)} {self.visit(node.reg2)} {self.visit(node.reg3)}" + + @visitor.when(nodes.MultiplyNode) + def visit(self, node): + return f"mul {self.visit(node.reg1)} {self.visit(node.reg2)} {self.visit(node.reg3)}" + + @visitor.when(nodes.DivideNode) + def visit(self, node): + return f"div {self.visit(node.reg1)} {self.visit(node.reg2)}" + + @visitor.when(nodes.LabelNode) + def visit(self, node): + return f"{node.name}:" + + @visitor.when(nodes.ComplementNode) + def visit(self, node): + return f"not {self.visit(node.reg1)} {self.visit(node.reg2)}" + + @visitor.when(nodes.StringConst) + def visit(self, node): + return f'{node.label}: .asciiz "{node.string}"' + + @visitor.when(nodes.MoveNode) + def visit(self, node): + return f'move {self.visit(node.reg1)} {self.visit(node.reg2 )}' + + @visitor.when(nodes.LoadInmediateNode) + def visit(self, node): + return f'li {self.visit(node.reg)}, {self.visit(node.value)}' + + @visitor.when(nodes.LoadWordNode) + def visit(self, node): + return f'lw {self.visit(node.reg)}, {self.visit(node.addr)}' + + @visitor.when(nodes.SyscallNode) + def visit(self, node): + return 'syscall' + + @visitor.when(nodes.LoadAddressNode) + def visit(self, node): + return f'la {self.visit(node.reg)}, {self.visit(node.label)}' + + @visitor.when(nodes.StoreWordNode) + def visit(self, node): + return f'sw {self.visit(node.reg)}, {self.visit(node.addr)}' + + @visitor.when(nodes.JumpAndLinkNode) + def visit(self, node): + return f'jal {node.label}' + + @visitor.when(nodes.JumpRegisterAndLinkNode) + def visit(self, node): + return f'jal {self.visit(node.reg)}' + + @visitor.when(nodes.JumpRegisterNode) + def visit(self, node): + return f'jr {self.visit(node.reg)}' + + @visitor.when(nodes.AddInmediateNode) + def visit(self, node): + return f'addi {self.visit(node.dest)}, {self.visit(node.src)}, {self.visit(node.value)}' + + @visitor.when(nodes.AddInmediateUnsignedNode) + def visit(self, node): + return f"addiu {self.visit(node.dest)} {self.visit(node.src)} {self.visit(node.value)}" + + @visitor.when(nodes.AddUnsignedNode) + def visit(self, node): + return f"addu {self.visit(node.dest)} {self.visit(node.sum1)} {self.visit(node.sum2)}" + + @visitor.when(nodes.ShiftLeftLogicalNode) + def visit(self, node): + return f"sll {self.visit(node.dest)} {self.visit(node.src)} {node.bits}" + + @visitor.when(nodes.BranchOnNotEqualNode) + def visit(self, node): + return f"bne {self.visit(node.reg1)} {self.visit(node.reg2)} {node.label}" + + @visitor.when(nodes.JumpNode) + def visit(self, node): + return f"j {node.label}" + + @visitor.when(nodes.MoveFromLowNode) + def visit(self, node): + return f"mflo {self.visit(node.reg)}" + + @visitor.when(Register) + def visit(self, node): + return f'${node.name}' + + @visitor.when(LabelRelativeLocation) + def visit(self, node): + return f'{node.label} + {node.offset}' + + @visitor.when(RegisterRelativeLocation) + def visit(self, node): + return f'{node.offset}({self.visit(node.register)})' + + @visitor.when(MIPSType) + def visit(self, node): + methods = "\n".join( + [f"\t.word\t {node.methods[k]}" for k in node.methods]) + dispatch_table = f"{node.label}_dispatch:\n{methods}" + proto_begin = f"{node.label}_proto:\n\t.word\t{node.index}\n\t.word\t{node.size}\n\t.word\t{node.label}_dispatch" + proto_attr = "\n".join( + [f'\t.word\t{node._default_attributes.get(attr, "0")}' for attr in node.attributes]) + proto_finish = f"\t.word\t{-1}" + proto = f"{proto_begin}\n{proto_attr}\n{proto_finish}" if proto_attr != "" else f"{proto_begin}\n{proto_finish}" + + return f'{dispatch_table}\n\n{proto}' + + @visitor.when(int) + def visit(self, node): + return str(node) + + @visitor.when(str) + def visit(self, node): + return node + + +def mips_static_code(): + return \ + local_vars() +\ + verify_obj() +\ + verify_obj_not_obj() +\ + verify_obj_is_obj() +\ + verify_obj_finish() +\ + concat() +\ + concat_size_alligned() +\ + concat_allign_size() +\ + concat_copy_first_cycle() +\ + concat_copy_second_cycle() +\ + concat_finish() +\ + copy() +\ + copy_cycle() +\ + copy_finish() +\ + eqs() +\ + eqs_eq() +\ + eqs_finish() +\ + eq_string() +\ + eq_string_cycle() +\ + eq_string_not_eq() +\ + eq_string_eq() +\ + eq_string_finish() +\ + extend_block() +\ + extend_block_extend() +\ + extend_block_finish() +\ + extend_heap() +\ + free_block() +\ + free_block_cycle_used_list() +\ + free_block_cycle_free_list() +\ + free_block_founded_prev() +\ + free_block_finish() +\ + get_gc() +\ + get_gc_cycle() +\ + get_gc_dfs() +\ + get_gc_outer_cycle() +\ + get_gc_extend() +\ + get_gc_free() +\ + get_gc_free_cycle() +\ + get_gc_free_cycle_free() +\ + get_gc_finish() +\ + get_gc_rec_extend() +\ + get_gc_rec_extend_attr_cycle() +\ + get_gc_rec_extend_string_obj() +\ + get_gc_rec_extend_finish() +\ + less_eq() +\ + less_eq_true() +\ + less_eq_finish() +\ + less() +\ + less_true() +\ + less_finish() +\ + lenx() +\ + len_cycle() +\ + len_finish() +\ + malloc() +\ + malloc_finish() +\ + malloc_cycle() +\ + malloc_search_finish() +\ + malloc_alloc_new_block() +\ + malloc_big_block() +\ + malloc_verify_valid_block() +\ + malloc_valid_block() +\ + malloc_first_valid_block() +\ + mem_manager_init() + \ + get_string() +\ + get_string_larger_block_cycle() +\ + get_string_reading() +\ + get_string_look_nl() +\ + get_string_zero_founded() +\ + get_string_nl_founded() +\ + get_string_nl_founded_alligned() +\ + get_string_no_nl() +\ + get_string_dup() +\ + get_string_extend_heap() +\ + get_string_last_block_cycle() +\ + get_string_last_block_founded() +\ + get_string_copy_prev() +\ + get_string_copy_cycle() +\ + get_string_copy_finish() +\ + get_string_finish() +\ + get_string_new_block() +\ + get_string_new_block_search_last() +\ + get_string_new_block_create() +\ + get_string_new_block_extended() +\ + divide_block() +\ + divide_block_same_size() +\ + divide_block_error_small() +\ + divide_block_finish() +\ + sub_string() +\ + sub_string_allign_size() +\ + sub_string_new_block() +\ + sub_string_copy_cycle() +\ + sub_string_finish() +\ + use_block() +\ + use_block_cycle() +\ + use_block_founded() +\ + use_block_finish() + + +# Mips labels + +def local_vars(): + return ''' + + alloc_size = 2048 + free_list = 0 + header_size = 12 + header_size_slot = 0 + header_next_slot = 4 + header_reachable_slot = 8 + init_alloc_size = 28 + int_type = 0 + meta_data_obj_size = 4 + neg_header_size = -12 + new_line = 10 + obj_mark = -1 + obj_extended = -2 + reachable = 1 + state_size = 4 + stack_base = -4 + string_size_treshold = 1024 + string_type = 0 + total_alloc_size = 2060 + num_type = 0 + used_list = header_size\n\n''' + + +def verify_obj(): + return '''verify_obj: + addiu $sp $sp -20 + sw $t0 0($sp) + sw $t1 4($sp) + sw $t2 8($sp) + sw $t3 12($sp) + sw $a0 16($sp) + + move $t0 $a0 + + li $v0 9 + move $a0 $zero + syscall + + addiu $t1 $v0 -4 + + + blt $t0 $gp verify_obj_not_obj + bgt $t0 $t1 verify_obj_not_obj + lw $t2 0($t0) + blt $t2 $zero verify_obj_not_obj + la $t3 num_type + lw $t3 0($t3) + bge $t2 $t3 verify_obj_not_obj + + addiu $t0 $t0 4 + blt $t0 $gp verify_obj_not_obj + bgt $t0 $t1 verify_obj_not_obj + lw $t2 0($t0) + + addiu $t0 $t0 8 + + + li $t3 meta_data_obj_size + sub $t2 $t2 $t3 + sll $t2 $t2 2 + addu $t0 $t0 $t2 + + + blt $t0 $gp verify_obj_not_obj + bgt $t0 $t1 verify_obj_not_obj + lw $t2 0($t0) + beq $t2 obj_mark verify_obj_is_obj + beq $t2 obj_extended verify_obj_is_obj\n\n''' + + +def verify_obj_not_obj(): + return '''verify_obj_not_obj: + li $v0 0 + j verify_obj_finish\n\n''' + + +def verify_obj_is_obj(): + return '''verify_obj_is_obj: + li $v0 1\n\n''' + + +def verify_obj_finish(): + return '''verify_obj_finish: + lw $t0 0($sp) + lw $t1 4($sp) + lw $t2 8($sp) + lw $t3 12($sp) + lw $a0 16($sp) + addiu $sp $sp 20 + + jr $ra\n\n''' + + +def concat(): + return '''concat: + addiu $sp $sp -24 + sw $t0 0($sp) + sw $t1 4($sp) + sw $t2 8($sp) + sw $a0 12($sp) + sw $a1 16($sp) + sw $ra 20($sp) + + move $t0 $a0 + move $t1 $a1 + + + addiu $a0 $a2 1 + li $t2 4 + div $a0 $t2 + mfhi $a0 + bne $a0 $zero concat_allign_size + addiu $a0 $a2 1\n\n''' + + +def concat_size_alligned(): + return '''concat_size_alligned: + jal malloc + move $t2 $v0 + j concat_copy_first_cycle\n\n''' + + +def concat_allign_size(): + return '''concat_allign_size: + sub $t2 $t2 $a0 + add $a0 $a2 $t2 + addiu $a0 $a0 1 + j concat_size_alligned\n\n''' + + +def concat_copy_first_cycle(): + return '''concat_copy_first_cycle: + lb $a0 0($t0) + beq $a0 $zero concat_copy_second_cycle + sb $a0 0($t2) + addiu $t0 $t0 1 + addiu $t2 $t2 1 + j concat_copy_first_cycle\n\n''' + + +def concat_copy_second_cycle(): + return '''concat_copy_second_cycle: + lb $a0 0($t1) + beq $a0 $zero concat_finish + sb $a0 0($t2) + addiu $t1 $t1 1 + addiu $t2 $t2 1 + j concat_copy_second_cycle\n\n''' + + +def concat_finish(): + return '''concat_finish: + sb $zero 0($t2) + lw $t0 0($sp) + lw $t1 4($sp) + lw $t2 8($sp) + lw $a0 12($sp) + lw $a1 16($sp) + lw $ra 20($sp) + addiu $sp $sp 24 + + jr $ra\n\n''' + + +def copy(): + return '''copy: + addiu $sp $sp -16 + sw $a0 0($sp) + sw $a1 4($sp) + sw $a2 8($sp) + sw $t0 12($sp)\n\n''' + + +def copy_cycle(): + return '''copy_cycle: + beq $a2 $zero copy_finish + lw $t0 0($a0) + sw $t0 0($a1) + addiu $a0 $a0 4 + addiu $a1 $a1 4 + addi $a2 $a2 -4 + j copy_cycle\n\n''' + + +def copy_finish(): + return '''copy_finish: + lw $a0 0($sp) + lw $a1 4($sp) + lw $a2 8($sp) + lw $t0 12($sp) + addiu $sp $sp 16 + + jr $ra\n\n''' + + +def eqs(): + return '''eqs: + beq $a0 $a1 eqs_eq + li $v0 0 + j eqs_finish\n\n''' + + +def eqs_eq(): + return '''eqs_eq: + li $v0 1\n\n''' + + +def eqs_finish(): + return '''eqs_finish: + jr $ra\n\n''' + + +def eq_string(): + return '''eq_string: + addiu $sp $sp -16 + sw $t0 0($sp) + sw $t1 4($sp) + sw $t2 8($sp) + sw $t3 12($sp) + + move $t0 $a0 + move $t1 $a1\n\n''' + + +def eq_string_cycle(): + return '''eq_string_cycle: + lb $t2 0($t0) + lb $t3 0($t1) + bne $t2 $t3 eq_string_not_eq + beq $t2 $zero eq_string_eq + + addiu $t0 $t0 1 + addiu $t1 $t1 1 + j eq_string_cycle\n\n''' + + +def eq_string_not_eq(): + return '''eq_string_not_eq: + move $v0 $zero + j eq_string_finish\n\n''' + + +def eq_string_eq(): + return '''eq_string_eq: + li $v0 1\n\n''' + + +def eq_string_finish(): + return '''eq_string_finish: + lw $t0 0($sp) + lw $t1 4($sp) + lw $t2 8($sp) + lw $t3 12($sp) + addiu $sp $sp 16 + + jr $ra\n\n''' + + +def extend_block(): + return '''extend_block: + addiu $sp $sp -16 + sw $t0 0($sp) + sw $t1 4($sp) + sw $t2 8($sp) + sw $t3 12($sp) + + + addiu $t0 $gp free_list + + beq $t0 $a0 extend_block_finish + move $t0 $a0 + + lw $t1 header_next_slot($t0) + lw $t2 header_size_slot($t0) + move $t3 $t2 + addiu $t2 $t2 header_size + addu $t2 $t2 $t0 + beq $t2 $t1 extend_block_extend + j extend_block_finish\n\n''' + + +def extend_block_extend(): + return '''extend_block_extend: + lw $t2 header_size_slot($t1) + addi $t2 $t2 header_size + add $t2 $t2 $t3 + sw $t2 header_size_slot($t0) + lw $t1 header_next_slot($t1) + sw $t1 header_next_slot($t0)\n\n''' + + +def extend_block_finish(): + return '''extend_block_finish: + lw $t0 0($sp) + lw $t1 4($sp) + lw $t2 8($sp) + lw $t3 12($sp) + addiu $sp $sp 16 + + jr $ra\n\n''' + + +def extend_heap(): + return '''extend_heap: + addiu $sp $sp -12 + sw $a0 0($sp) + sw $a1 4($sp) + sw $t0 8($sp) + + + li $v0 9 + addiu $a0 $a1 header_size + syscall + + + move $t0 $a1 + sw $t0 header_size_slot($v0) + sw $zero header_next_slot($v0) + sw $zero header_reachable_slot($v0) + + + lw $t0, 0($sp) + sw $v0 header_next_slot($t0) + + move $a0 $t0 + lw $a1 4($sp) + lw $t0 8($sp) + addiu $sp $sp 12 + + jr $ra\n\n''' + + +def free_block(): + return '''free_block: + addiu $sp $sp -28 + sw $t0 0($sp) + sw $t1 4($sp) + sw $t2 8($sp) + sw $a0 12($sp) + sw $ra 16($sp) + sw $t3 20($sp) + sw $t4 24($sp) + + move $t0 $a0 + + addiu $t1 $gp free_list + + addiu $t3 $gp used_list\n\n''' + + +def free_block_cycle_used_list(): + return '''free_block_cycle_used_list: + lw $t4 header_next_slot($t3) + beq $t4 $t0 free_block_cycle_free_list + move $t3 $t4 + j free_block_cycle_used_list\n\n''' + + +def free_block_cycle_free_list(): + return '''free_block_cycle_free_list: + lw $t2 header_next_slot($t1) + beq $t2 $zero free_block_founded_prev + bge $t2 $t0 free_block_founded_prev + move $t1 $t2 + j free_block_cycle_free_list\n\n''' + + +def free_block_founded_prev(): + return '''free_block_founded_prev: + lw $t4 header_next_slot($t0) + sw $t4 header_next_slot($t3) + + + sw $t2 header_next_slot($t0) + sw $t0 header_next_slot($t1)\n\n''' + + +def free_block_finish(): + return '''free_block_finish: + + move $a0 $t0 + jal extend_block + move $a0 $t1 + jal extend_block + + lw $t0 0($sp) + lw $t1 4($sp) + lw $t2 8($sp) + lw $a0 12($sp) + lw $ra 16($sp) + lw $t3 20($sp) + lw $t4 24($sp) + addiu $sp $sp 28 + + jr $ra\n\n''' + + +def get_gc(): + return '''get_gc: + addiu $sp $sp -24 + sw $t0 0($sp) + sw $t1 4($sp) + sw $t2 8($sp) + sw $t3 12($sp) + sw $a0 16($sp) + sw $ra 20($sp) + + li $t3 reachable + addiu $t0 $sp 20 + lw $t1 stack_base($gp) + + li $t2 1\n\n''' + + +def get_gc_cycle(): + return '''get_gc_cycle: + + addiu $t0 $t0 4 + beq $t0 $t1 get_gc_dfs + + lw $a0 0($t0) + jal verify_obj + + bne $v0 $t2 get_gc_cycle + + addiu $a0 $a0 neg_header_size + sw $t3 header_reachable_slot($a0) + + j get_gc_cycle\n\n''' + + +def get_gc_dfs(): + return '''get_gc_dfs: + addiu $t1 $gp used_list\n\n''' + + +def get_gc_outer_cycle(): + return '''get_gc_outer_cycle: + lw $t1 header_next_slot($t1) + beq $t1 $zero get_gc_free + lw $t2 header_reachable_slot($t1) + beq $t2 reachable get_gc_extend + j get_gc_outer_cycle\n\n''' + + +def get_gc_extend(): + return '''get_gc_extend: + addiu $a0 $t1 header_size + jal get_gc_rec_extend + j get_gc_outer_cycle\n\n''' + + +def get_gc_free(): + return '''get_gc_free: + addiu $t0 $gp used_list + lw $t0 header_next_slot($t0)\n\n''' + + +def get_gc_free_cycle(): + return '''get_gc_free_cycle: + beq $t0 $zero get_gc_finish + lw $t1 header_reachable_slot($t0) + bne $t1 reachable get_gc_free_cycle_free + sw $zero header_reachable_slot($t0) + move $a0 $t0 + jal verify_obj + beq $v0 $zero get_gc_free_cycle + li $t1 obj_mark + addiu $t2 $t0 header_size + lw $t3 4($t2) + sll $t3 $t3 2 + addu $t2 $t2 $t3 + sw $t1 -4($t2) + lw $t0 header_next_slot($t0) + j get_gc_free_cycle\n\n''' + + +def get_gc_free_cycle_free(): + return '''get_gc_free_cycle_free: + move $a0 $t0 + lw $t0 header_next_slot($t0) + jal free_block + j get_gc_free_cycle\n\n''' + + +def get_gc_finish(): + return '''get_gc_finish: + lw $t0 0($sp) + lw $t1 4($sp) + lw $t2 8($sp) + lw $t3 12($sp) + lw $a0 16($sp) + lw $ra 20($sp) + addiu $sp $sp 24 + + jr $ra\n\n''' + + +def get_gc_rec_extend(): + return '''get_gc_rec_extend: + addiu $sp $sp -16 + sw $a0 0($sp) + sw $t0 4($sp) + sw $t1 8($sp) + sw $ra 12($sp) + + jal verify_obj + beq $v0 $zero get_gc_rec_extend_finish + + lw $t0 4($a0) + sll $t0 $t0 2 + addiu $t0 $t0 -4 + addu $t0 $a0 $t0 + lw $t1 0($t0) + beq $t1 obj_extended get_gc_rec_extend_finish + + + li $t1 reachable + addiu $a0 $a0 neg_header_size + sw $t1 header_reachable_slot($a0) + addiu $a0 $a0 header_size + + + li $t1 obj_extended + sw $t1 0($t0) + + lw $t0 0($a0) + + + la $t1 int_type + lw $t1 0($t1) + beq $t0 $t1 get_gc_rec_extend_finish + + la $t1 string_type + lw $t1 0($t1) + beq $t0 $t1 get_gc_rec_extend_string_obj + + lw $t0 4($a0) + li $t1 meta_data_obj_size + sub $t0 $t0 $t1 + + addiu $t1 $a0 12\n\n''' + + +def get_gc_rec_extend_attr_cycle(): + return '''get_gc_rec_extend_attr_cycle: + beq $t0 $zero get_gc_rec_extend_finish + lw $a0 0($t1) + jal get_gc_rec_extend + addiu $t1 $t1 4 + sub $t0 $t0 1 + j get_gc_rec_extend_attr_cycle\n\n''' + + +def get_gc_rec_extend_string_obj(): + return '''get_gc_rec_extend_string_obj: + lw $t0 8($a0) + addiu $t0 $t0 neg_header_size + li $t1 reachable + sw $t1 header_reachable_slot($t0)\n\n''' + + +def get_gc_rec_extend_finish(): + return '''get_gc_rec_extend_finish: + lw $a0 0($sp) + lw $t0 4($sp) + lw $t1 8($sp) + lw $ra 12($sp) + addiu $sp $sp 16 + + jr $ra\n\n''' + + +def less_eq(): + return '''less_eq: + ble $a0 $a1 less_eq_true + li $v0 0 + j less_eq_finish\n\n''' + + +def less_eq_true(): + return '''less_eq_true: + li $v0 1\n\n''' + + +def less_eq_finish(): + return '''less_eq_finish: + jr $ra\n\n''' + + +def less(): + return '''less: + blt $a0 $a1 less_true + li $v0 0 + j less_finish\n\n''' + + +def less_true(): + return '''less_true: + li $v0 1\n\n''' + + +def less_finish(): + return '''less_finish: + jr $ra\n\n''' + + +def lenx(): + return '''len: + addiu $sp $sp -8 + sw $t0 0($sp) + sw $t1 4($sp) + + move $t0 $a0 + move $v0 $zero\n\n''' + + +def len_cycle(): + return '''len_cycle: + lb $t1 0($t0) + beq $t1 $zero len_finish + addi $v0 $v0 1 + addiu $t0 $t0 1 + j len_cycle\n\n''' + + +def len_finish(): + return '''len_finish: + lw $t0 0($sp) + lw $t1 4($sp) + addiu $sp $sp 8 + + jr $ra\n\n''' + + +def malloc(): + return '''malloc: + move $v0 $zero + addiu $sp $sp -28 + sw $t1 0($sp) + sw $t0 4($sp) + sw $a0 8($sp) + sw $a1 12($sp) + sw $ra 16($sp) + sw $t2 20($sp) + sw $t3 24($sp) + + addiu $t0 $gp free_list + j malloc_cycle\n\n''' + + +def malloc_finish(): + return '''malloc_finish: + move $a0 $v0 + lw $a1 8($sp) + jal divide_block + + lw $t1 header_next_slot($v0) + sw $t1 header_next_slot($t3) + + addiu $t1 $gp used_list + lw $a0 header_next_slot($t1) + + sw $a0 header_next_slot($v0) + sw $v0 header_next_slot($t1) + + addiu $v0 $v0 header_size + + lw $t3 24($sp) + lw $t2 20($sp) + lw $ra 16($sp) + lw $a1 12($sp) + lw $a0 8($sp) + lw $t0 4($sp) + lw $t1 0($sp) + addiu $sp $sp 28 + + jr $ra\n\n''' + + +def malloc_cycle(): + return '''malloc_cycle: + move $t2 $t0 + lw $t0 header_next_slot($t0) + beq $t0 $zero malloc_search_finish + j malloc_verify_valid_block\n\n''' + + +def malloc_search_finish(): + return '''malloc_search_finish: + beq $v0 $zero malloc_alloc_new_block + j malloc_finish\n\n''' + + +def malloc_alloc_new_block(): + return '''malloc_alloc_new_block: + li $t1 alloc_size + move $t3 $t2 + move $a1 $a0 + move $a0 $t2 + bge $a1 $t1 malloc_big_block + li $a1 alloc_size + jal extend_heap + + j malloc_finish\n\n''' + + +def malloc_big_block(): + return '''malloc_big_block: + jal extend_heap + j malloc_finish\n\n''' + + +def malloc_verify_valid_block(): + return '''malloc_verify_valid_block: + lw $t1 header_size_slot($t0) + bge $t1 $a0 malloc_valid_block + j malloc_cycle\n\n''' + + +def malloc_valid_block(): + return '''malloc_valid_block: + beq $v0 $zero malloc_first_valid_block + bge $t1 $v1 malloc_cycle + move $v0 $t0 + move $v1 $t1 + move $t3 $t2 + j malloc_cycle\n\n''' + + +def malloc_first_valid_block(): + return '''malloc_first_valid_block: + move $v0 $t0 + move $v1 $t1 + move $t3 $t2 + j malloc_cycle\n\n''' + + +def mem_manager_init(): + return '''mem_manager_init: + addiu $sp $sp -16 + sw $v0 0($sp) + sw $a0 4($sp) + sw $a1 8($sp) + sw $ra 12($sp) + li $v0 9 + li $a0 init_alloc_size + syscall + move $gp $v0 + addiu $gp $gp state_size + + sw $zero header_size_slot($gp) + sw $zero header_reachable_slot($gp) + + move $a0 $gp + li $a1 alloc_size + jal extend_heap + + addiu $a0 $a0 header_size + sw $zero header_size_slot($a0) + sw $zero header_next_slot($a0) + sw $zero header_reachable_slot($a0) + + + + lw $v0 0($sp) + lw $a0 4($sp) + lw $a1 8($sp) + lw $ra 12($sp) + addiu $sp $sp 16 + + sw $sp stack_base($gp) + + jr $ra\n\n''' + + +def get_string(): + return '''get_string: + addiu $sp $sp -36 + sw $t0 0($sp) + sw $t1 4($sp) + sw $t2 8($sp) + sw $t3 12($sp) + sw $t4 16($sp) + sw $t5 20($sp) + sw $a0 24($sp) + sw $a1 28($sp) + sw $ra 32($sp) + + addiu $t0 $gp free_list + move $t1 $zero + move $t2 $t0\n\n''' + + +def get_string_larger_block_cycle(): + return '''get_string_larger_block_cycle: + lw $t0 header_next_slot($t0) + beq $t0 $zero get_string_reading + lw $t3 header_size_slot($t0) + bge $t1 $t3 get_string_larger_block_cycle + move $t1 $t3 + move $t2 $t0 + j get_string_larger_block_cycle\n\n''' + + +def get_string_reading(): + return '''get_string_reading: + beq $t1 $zero get_string_new_block + move $a1 $t1 + li $v0 8 + addiu $a0 $t2 header_size + syscall + move $t0 $a0 + move $t1 $zero\n\n''' + + +def get_string_look_nl(): + return '''get_string_look_nl: + lb $t2 0($t0) + beq $t2 new_line get_string_nl_founded + beq $t2 $zero get_string_zero_founded + addi $t1 $t1 1 + addi $t0 $t0 1 + j get_string_look_nl\n\n''' + + +def get_string_zero_founded(): + return '''get_string_zero_founded: + blt $t1 $t3 get_string_nl_founded + j get_string_no_nl\n\n''' + + +def get_string_nl_founded(): + return '''get_string_nl_founded: + sb $zero 0($t0) + addi $t1 $t1 1 + li $t2 4 + div $t1 $t2 + mfhi $t3 + beq $t3 $zero get_string_nl_founded_alligned + sub $t2 $t2 $t3 + add $t1 $t1 $t2\n\n''' + + +def get_string_nl_founded_alligned(): + return '''get_string_nl_founded_alligned: + move $a1 $t1 + addiu $a0 $a0 neg_header_size + jal divide_block + jal use_block + + addiu $v0 $a0 header_size + j get_string_finish\n\n''' + + +def get_string_no_nl(): + return '''get_string_no_nl: + addi $t1 $t1 1 + blt $t1 string_size_treshold get_string_dup + addi $t1 $t1 alloc_size + j get_string_extend_heap\n\n''' + + +def get_string_dup(): + return '''get_string_dup: + sll $t1 $t1 1\n\n''' + + +def get_string_extend_heap(): + return '''get_string_extend_heap: + move $a1 $t1 + move $t0 $a0 + addiu $a0 $gp free_list\n\n''' + + +def get_string_last_block_cycle(): + return '''get_string_last_block_cycle: + lw $t1 header_next_slot($a0) + beq $t1 $zero get_string_last_block_founded + lw $a0 header_next_slot($a0) + j get_string_last_block_cycle\n\n''' + + +def get_string_last_block_founded(): + return '''get_string_last_block_founded: + jal extend_heap + jal extend_block + lw $t1 header_next_slot($a0) + bne $t1 $zero get_string_copy_prev + move $t1 $a0\n\n''' + + +def get_string_copy_prev(): + return '''get_string_copy_prev: + lw $t3 header_size_slot($t1) + move $t2 $zero + move $t5 $t1 + addiu $t1 $t1 header_size\n\n''' + + +def get_string_copy_cycle(): + return '''get_string_copy_cycle: + lb $t4 0($t0) + beq $t4 $zero get_string_copy_finish + sb $t4 0($t1) + addi $t2 $t2 1 + addi $t0 $t0 1 + addi $t1 $t1 1 + j get_string_copy_cycle\n\n''' + + +def get_string_copy_finish(): + return '''get_string_copy_finish: + sub $t3 $t3 $t2 + move $a0 $t1 + move $a1 $t3 + li $v0 8 + syscall + move $t0 $a0 + move $t1 $t2 + addiu $a0 $t5 header_size + j get_string_look_nl\n\n''' + + +def get_string_finish(): + return '''get_string_finish: + lw $t0 0($sp) + lw $t1 4($sp) + lw $t2 8($sp) + lw $t3 12($sp) + lw $t4 16($sp) + lw $t5 20($sp) + lw $a0 24($sp) + lw $a1 28($sp) + lw $ra 32($sp) + addiu $sp $sp 36 + + jr $ra\n\n''' + + +def get_string_new_block(): + return '''get_string_new_block: + addiu $t0 $gp free_list\n\n''' + + +def get_string_new_block_search_last(): + return '''get_string_new_block_search_last: + lw $t1 header_next_slot($t0) + beq $t1 $zero get_string_new_block_create + move $t0 $t1 + j get_string_new_block_search_last\n\n''' + + +def get_string_new_block_create(): + return '''get_string_new_block_create: + move $a0 $t0 + li $a1 alloc_size + jal extend_heap + jal extend_block + lw $t2 header_next_slot($a0) + beq $t2 $zero get_string_new_block_extended + lw $t1 header_size_slot($t2) + j get_string_reading\n\n''' + + +def get_string_new_block_extended(): + return '''get_string_new_block_extended: + move $t2 $a0 + lw $t1 header_size_slot($a0) + j get_string_reading\n\n''' + + +def divide_block(): + return '''divide_block: + addiu $sp $sp -16 + sw $t0 0($sp) + sw $t1 4($sp) + sw $a0 8($sp) + sw $a1 12($sp) + + + lw $t0 header_size_slot($a0) + bgt $a1 $t0 divide_block_error_small + + + sub $t0 $t0 $a1 + li $t1 header_size + ble $t0 $t1 divide_block_same_size + + + addu $t0 $a0 $a1 + addiu $t0 $t0 header_size + + + lw $t1 header_next_slot($a0) + sw $t1 header_next_slot($t0) + sw $t0 header_next_slot($a0) + + lw $t1 header_size_slot($a0) + sub $t1 $t1 $a1 + + addi $t1 $t1 neg_header_size + sw $t1 header_size_slot($t0) + sw $a1 header_size_slot($a0) + move $v0 $a0 + j divide_block_finish\n\n''' + + +def divide_block_same_size(): + return '''divide_block_same_size: + move $v0 $a0 + j divide_block_finish\n\n''' + + +def divide_block_error_small(): + return '''divide_block_error_small: + j divide_block_finish\n\n''' + + +def divide_block_finish(): + return '''divide_block_finish: + lw $t0 0($sp) + lw $t1 4($sp) + lw $a0 8($sp) + lw $a1 12($sp) + addiu $sp $sp 16 + + jr $ra\n\n''' + + +def sub_string(): + return '''sub_string: + addiu $sp $sp -24 + sw $t0 0($sp) + sw $t1 4($sp) + sw $t2 8($sp) + sw $t3 12($sp) + sw $a0 16($sp) + sw $ra 20($sp) + + move $t0 $a0 + li $t1 4 + addiu $t3 $a2 1 + div $t3 $t1 + + mfhi $t2 + bne $t2 $zero sub_string_allign_size + move $t1 $t3 + j sub_string_new_block\n\n''' + + +def sub_string_allign_size(): + return '''sub_string_allign_size: + sub $t1 $t1 $t2 + add $t1 $t1 $t3\n\n''' + + +def sub_string_new_block(): + return '''sub_string_new_block: + move $a0 $t1 + jal malloc + move $t3 $v0 + move $t1 $zero + addu $t0 $t0 $a1\n\n''' + + +def sub_string_copy_cycle(): + return '''sub_string_copy_cycle: + beq $t1 $a2 sub_string_finish + lb $t2 0($t0) + sb $t2 0($t3) + addiu $t0 $t0 1 + addiu $t3 $t3 1 + addiu $t1 $t1 1 + j sub_string_copy_cycle\n\n''' + + +def sub_string_finish(): + return '''sub_string_finish: + sb $zero 0($t3) + lw $t0 0($sp) + lw $t1 4($sp) + lw $t2 8($sp) + lw $t3 12($sp) + lw $a0 16($sp) + lw $ra 20($sp) + addiu $sp $sp 24 + + jr $ra\n\n''' + + +def use_block(): + return '''use_block: + addiu $sp $sp -12 + sw $t0 0($sp) + sw $t1 4($sp) + sw $t2 8($sp) + + addiu $t0 $gp free_list\n\n''' + + +def use_block_cycle(): + return '''use_block_cycle: + move $t1 $t0 + lw $t0 header_next_slot($t0) + beq $t0 $zero use_block_finish + beq $t0 $a0 use_block_founded + j use_block_cycle\n\n''' + + +def use_block_founded(): + return '''use_block_founded: + lw $t2 header_next_slot($t0) + sw $t2 header_next_slot($t1) + + addiu $t1 $gp used_list + lw $t2 header_next_slot($t1) + sw $t0 header_next_slot($t1) + sw $t2 header_next_slot($t0)\n\n''' + + +def use_block_finish(): + return '''use_block_finish: + lw $t0 0($sp) + lw $t1 4($sp) + lw $t2 8($sp) + addiu $sp $sp 12 + + jr $ra\n\n''' diff --git a/src/utils/code_generation/mips/utils_mips.py b/src/utils/code_generation/mips/utils_mips.py new file mode 100644 index 000000000..1f2106e59 --- /dev/null +++ b/src/utils/code_generation/mips/utils_mips.py @@ -0,0 +1,547 @@ +from collections import defaultdict +import cmp.visitor as visitor +from utils.code_generation.cil.AST_CIL import cil_ast as cil +from utils.code_generation.mips.AST_MIPS import mips_ast as mips +from utils.code_generation.mips.AST_MIPS import mips_ast as nodes +from utils.code_generation.mips.AST_MIPS import * +from random import choice + + +def push_register(reg): + move_stack = nodes.AddInmediateNode(SP_REG, SP_REG, -4) + save_location = RegisterRelativeLocation(SP_REG, 0) + save_register = nodes.StoreWordNode(reg, save_location) + return [move_stack, save_register] + + +def pop_register(reg): + load_value = nodes.LoadWordNode(reg, RegisterRelativeLocation(SP_REG, 0)) + move_stack = nodes.AddInmediateNode(SP_REG, SP_REG, 4) + return [load_value, move_stack] + + +def alloc_memory(size): + instructions = [] + instructions.append(nodes.LoadInmediateNode(V0_REG, 9)) + instructions.append(nodes.LoadInmediateNode(ARG_REGISTERS[0], size)) + instructions.append(nodes.SyscallNode()) + return instructions + + +def exit_program(): + instructions = [] + instructions.append(nodes.LoadInmediateNode(V0_REG, 10)) + instructions.append(nodes.SyscallNode()) + return instructions + + +def create_object(reg1, reg2): + instructions = [] + + instructions.append(nodes.ShiftLeftLogicalNode(reg1, reg1, 2)) + instructions.append(nodes.LoadAddressNode(reg2, "proto_table")) + instructions.append(nodes.AddUnsignedNode(reg2, reg2, reg1)) + instructions.append(nodes.LoadWordNode( + reg2, RegisterRelativeLocation(reg2, 0))) + instructions.append(nodes.LoadWordNode( + ARG_REGISTERS[0], RegisterRelativeLocation(reg2, 4))) + instructions.append(nodes.ShiftLeftLogicalNode( + ARG_REGISTERS[0], ARG_REGISTERS[0], 2)) + instructions.append(nodes.JumpAndLinkNode("malloc")) + instructions.append(nodes.MoveNode(ARG_REGISTERS[2], ARG_REGISTERS[0])) + instructions.append(nodes.MoveNode(ARG_REGISTERS[0], reg2)) + instructions.append(nodes.MoveNode(ARG_REGISTERS[1], V0_REG)) + instructions.append(nodes.JumpAndLinkNode("copy")) + + return instructions + + +def copy_object(reg1, reg2): + instructions = [] + + instructions.append(nodes.LoadWordNode( + ARG_REGISTERS[0], RegisterRelativeLocation(reg1, 4))) + instructions.append(nodes.ShiftLeftLogicalNode( + ARG_REGISTERS[0], ARG_REGISTERS[0], 2)) + instructions.append(nodes.JumpAndLinkNode("malloc")) + instructions.append(nodes.MoveNode(ARG_REGISTERS[2], ARG_REGISTERS[0])) + instructions.append(nodes.MoveNode(ARG_REGISTERS[0], reg1)) + instructions.append(nodes.MoveNode(ARG_REGISTERS[1], V0_REG)) + instructions.append(nodes.JumpAndLinkNode("copy")) + + return instructions + + +class MemoryManager: + def __init__(self, registers, function_for_assign): + self.registers = registers + self.func = function_for_assign + + def get_reg_for_var(self, var): + index = self.func(var) + if index == -1: + return None + return self.registers[index] + + def get_reg_unusued(self, used=[]): + possibles = list(set(self.registers).difference(set(used))) + return choice(possibles) + + +class LabelGenerator: + def __init__(self): + self.data_count = 0 + self.type_count = 0 + self.code_count = 0 + + def generate_type_label(self): + self.type_count += 1 + return f'type_{self.type_count}' + + def generate_data_label(self): + self.data_count += 1 + return f'data_{self.data_count}' + + def generate_code_label(self): + self.code_count += 1 + return f'L_{self.code_count}' + + +class UsedRegisterFinder: + def __init__(self): + self.used_registers = set() + + def get_used_registers(self, instructions): + self.used_registers = set() + + for inst in instructions: + self.visit(inst) + self.used_registers = set.difference( + self.used_registers, set([SP_REG, Register('fp'), V0_REG])) + return [reg for reg in self.used_registers] + + @visitor.on('node') + def visit(self, node): + pass + + @visitor.when(mips.LoadInmediateNode) + def visit(self, node): + self.used_registers.add(node.reg) + + @visitor.when(mips.LoadAddressNode) + def visit(self, node): + self.used_registers.add(node.reg) + + @visitor.when(mips.AddInmediateNode) + def visit(self, node): + self.used_registers.add(node.dest) + + @visitor.when(mips.MoveNode) + def visit(self, node): + self.used_registers.add(node.reg1) + + @visitor.when(mips.LoadWordNode) + def visit(self, node): + self.used_registers.add(node.reg) + + @visitor.when(mips.JumpAndLinkNode) + def visit(self, node): + self.used_registers.add(RA_REG) + + @visitor.when(mips.JumpRegisterAndLinkNode) + def visit(self, node): + self.used_registers.add(RA_REG) + + @visitor.when(mips.AddUnsignedNode) + def visit(self, node): + self.used_registers.add(node.dest) + + @visitor.when(mips.ShiftLeftLogicalNode) + def visit(self, node): + self.used_registers.add(node.dest) + + @visitor.when(mips.AddNode) + def visit(self, node): + self.used_registers.add(node.reg1) + + @visitor.when(mips.SubNode) + def visit(self, node): + self.used_registers.add(node.reg1) + + @visitor.when(mips.MultiplyNode) + def visit(self, node): + self.used_registers.add(node.reg1) + + @visitor.when(mips.ComplementNode) + def visit(self, node): + self.used_registers.add(node.reg1) + + @visitor.when(mips.MoveFromLowNode) + def visit(self, node): + self.used_registers.add(node.reg) + + +class RegistersAllocator: + def __init__(self): + self.mark = False + + def get_registers_for_variables(self, instructions, params, n): + self.numbered_instructions(instructions) + basic_blocks = self.divide_basics_blocks(instructions) + flow_graph = RegistersAllocator.create_flow_graph(basic_blocks) + gk, io = self.liveness_analysis((basic_blocks, flow_graph), params) + interference = RegistersAllocator.interference_compute(gk, io) + return RegistersAllocator.assign_registers(interference, n) + + def divide_basics_blocks(self, instructions): + self.mark = True + for instruction in instructions: + self.mark_leaders(instruction) + + blocks = [] + + for instruction in instructions: + if instruction.leader: + blocks.append([instruction]) + else: + blocks[-1].append(instruction) + + return blocks + + def liveness_analysis(self, graph, params): + blocks, ady_list = graph + + instructions = [] + for block in blocks: + instructions.extend(block) + instructions_total = len(instructions) + + suc = [0 for _ in range(instructions_total)] + for block_index, block in enumerate(blocks): + for ins_index, instruction in enumerate(block): + if ins_index == len(block) - 1: + ady = [i for i in range(len(blocks)) + if ady_list[block_index][i] == 1] + suc[instruction.number] = [ + blocks[b][0].number for b in ady] + else: + suc[instruction.number] = [block[ins_index + 1].number] + + gk = [self.gen_kill(inst) for inst in instructions] + io = RegistersAllocator.out_in_compute(suc, gk) + gk = [([], [param.id for param in params])] + gk + io = [([], io[0][0])] + io + + return gk, io + + @staticmethod + def interference_compute(gk, in_out): + neigs = {} + for g, k in gk: + for v in g: + neigs[v] = set() + for v in k: + neigs[v] = set() + + for i, (_, k) in enumerate(gk): + for v in k: + neigs[v].update(in_out[i][1]) + + for k, v in neigs.items(): + for n in v: + neigs[n].add(k) + + for k, v in neigs.items(): + neigs[k] = list(v.difference([k])) + + return neigs + + @staticmethod + def assign_registers(interference_graph, n): + stack = [] + var_registers = defaultdict(lambda: -1) + nodes = set(interference_graph.keys()) + + def myLen(l): + count = 0 + for v in l: + if v in nodes: + count += 1 + return count + + while nodes: + to_remove = None + for node in nodes: + if myLen(interference_graph[node]) < n: + stack.append((node, interference_graph[node])) + to_remove = node + break + + if to_remove: + nodes.remove(to_remove) + else: + selection = choice(list(nodes)) + stack.append((selection, interference_graph[selection])) + nodes.remove(selection) + + while stack: + node, ady = stack.pop() + regs = set(range(n)) + for neig in ady: + reg = var_registers[neig] + if reg != -1: + try: + regs.remove(reg) + except: + pass + if regs: + var_registers[node] = min(regs) + else: + var_registers[node] = -1 + + return var_registers + + @staticmethod + def out_in_compute(suc, gk): + n_instructions = len(gk) + in_out = [[set(), set()] for _ in range(n_instructions)] + next_in_out = [[set(), set()] for _ in range(n_instructions)] + + def add(set1, set2): + return not set2.issubset(set1) + + changed = True + while changed: + changed = False + for i in range(n_instructions)[::-1]: + for i_suc in suc[i]: + if i_suc < i: + changed |= add(next_in_out[i][1], in_out[i_suc][0]) + next_in_out[i][1] = next_in_out[i][1].union( + in_out[i_suc][0]) + else: + changed |= add( + next_in_out[i][1], next_in_out[i_suc][0]) + next_in_out[i][1] = next_in_out[i][1].union( + next_in_out[i_suc][0]) + + g_i = set(gk[i][0]) + k_i = set(gk[i][1]) + new = g_i.union(next_in_out[i][1].difference(k_i)) + changed |= add(next_in_out[i][0], new) + next_in_out[i][0] = next_in_out[i][0].union(new) + + in_out = next_in_out + + return in_out + + @staticmethod + def create_flow_graph(blocks): + graph = [[-1 for _ in range(len(blocks))] for _ in range(len(blocks))] + labels = {b[0].label: i for i, b in enumerate( + blocks) if isinstance(b[0], cil.LabelNode)} + + for i, block in enumerate(blocks): + if isinstance(block[-1], cil.GotoNode): + graph[i][labels[block[-1].label]] = 1 + elif isinstance(block[-1], cil.IfGotoNode): + graph[i][labels[block[-1].label]] = 1 + graph[i][i + 1] = 1 if i + 1 < len(blocks) else -1 + elif i != len(blocks) - 1: + graph[i][i + 1] = 1 + + return graph + + @staticmethod + def numbered_instructions(instructions): + for i, instr in enumerate(instructions): + instr.number = i + + @visitor.on('instruction') + def gen_kill(self, instruction): + pass + + @visitor.when(cil.ArgNode) + def gen_kill(self, instruction): + if isinstance(instruction.id, int): + return ([], []) + return ([instruction.id], []) + + @visitor.when(cil.StaticCallNode) + def gen_kill(self, instruction): + return ([], [instruction.dest]) + + @visitor.when(cil.AssignNode) + def gen_kill(self, instruction): + gen = [] + if isinstance(instruction.right, str): + if not instruction.right.isnumeric(): + gen = [instruction.right] + return (gen, [instruction.left]) + + @visitor.when(cil.AllocateNode) + def gen_kill(self, instruction): + return ([], [instruction.dest]) + + @visitor.when(cil.ReturnNode) + def gen_kill(self, instruction): + gen = [instruction.id] if isinstance(instruction.id, str) else [] + return (gen, []) + + @visitor.when(cil.LoadNode) + def gen_kill(self, instruction): + return ([], [instruction.dest]) + + @visitor.when(cil.PrintIntNode) + def gen_kill(self, instruction): + return ([instruction.value], []) + + @visitor.when(cil.PrintStrNode) + def gen_kill(self, instruction): + return ([instruction.value], []) + + @visitor.when(cil.TypeNameNode) + def gen_kill(self, instruction): + return ([instruction.type], [instruction.dest]) + + @visitor.when(cil.AbortNode) + def gen_kill(self, instruction): + return ([], []) + + @visitor.when(cil.GetAttrNode) + def gen_kill(self, instruction): + return ([instruction.id], [instruction.dest]) + + @visitor.when(cil.SetAttrNode) + def gen_kill(self, instruction): + gen = [instruction.id] + if not isinstance(instruction.value, int): + gen.append(instruction.value) + return (gen, []) + + @visitor.when(cil.CopyNode) + def gen_kill(self, instruction): + return ([instruction.copy], [instruction.dest]) + + @visitor.when(cil.ArithmeticNode) + def gen_kill(self, instruction): + gen = [x for x in [instruction.op_l, + instruction.op_r] if isinstance(x, str)] + return (gen, [instruction.dest]) + + @visitor.when(cil.IfGotoNode) + def gen_kill(self, instruction): + return ([instruction.if_cond], []) + + @visitor.when(cil.GotoNode) + def gen_kill(self, instruction): + return ([], []) + + @visitor.when(cil.TypeOfNode) + def gen_kill(self, instruction): + return ([instruction.id], [instruction.dest]) + + @visitor.when(cil.DynamicCallNode) + def gen_kill(self, instruction): + return ([], [instruction.dest]) + + @visitor.when(cil.NameNode) + def gen_kill(self, instruction): + return ([], [instruction.dest]) + + @visitor.when(cil.ComplementNode) + def gen_kill(self, instruction): + gen = [instruction.id] if isinstance(instruction.id, str) else [] + return (gen, [instruction.dest]) + + @visitor.when(cil.ReadStrNode) + def gen_kill(self, instruction): + return ([], [instruction.dest]) + + @visitor.when(cil.LengthNode) + def gen_kill(self, instruction): + return ([instruction.id], [instruction.dest]) + + @visitor.when(cil.ReadIntNode) + def gen_kill(self, instruction): + return ([], [instruction.dest]) + + @visitor.when(cil.ConcatNode) + def gen_kill(self, instruction): + return ([instruction.s1, instruction.s2], [instruction.dest]) + + @visitor.when(cil.SubstringNode) + def gen_kill(self, instruction): + gen = [instruction.s] + if isinstance(instruction.i, str): + gen.append(instruction.i) + if isinstance(instruction.length, str): + gen.append(instruction.length) + + return (gen, [instruction.dest]) + + @visitor.when(cil.LabelNode) + def gen_kill(self, instruction): + return ([], []) + + @visitor.when(cil.ErrorNode) + def gen_kill(self, instruction): + return ([], []) + + @visitor.on('instruction') + def mark_leaders(self, instruction): + pass + + @visitor.when(cil.LabelNode) + def mark_leaders(self, instruction): + instruction.leader = True + self.mark = False + + @visitor.when(cil.GotoNode) + def mark_leaders(self, instruction): + instruction.leader = self.mark + self.mark = True + + @visitor.when(cil.IfGotoNode) + def mark_leaders(self, instruction): + instruction.leader = self.mark + self.mark = True + + @visitor.when(cil.InstructionNode) + def mark_leaders(self, instruction): + instruction.leader = self.mark + self.mark = False + + +class MIPSType: + def __init__(self, label, name_addr, attributes, methods, index, default=[]): + self._label = label + self._name = name_addr + self._attributes = attributes + self._default_attributes = dict(default) + self._methods = methods + self._index = index + + @property + def size(self): + return len(self.attributes) + 4 + + @property + def label(self): + return self._label + + @property + def string_name_label(self): + return self._name + + @property + def methods(self): + return self._methods + + @property + def attributes(self): + return self._attributes + + @property + def index(self): + return self._index \ No newline at end of file From 08b60927c6ccffcd19f3ec87d0882138a6c057f0 Mon Sep 17 00:00:00 2001 From: Alejandro Campos Matanzas <74170015+Alexx-4@users.noreply.github.com> Date: Fri, 25 Feb 2022 12:15:43 -0800 Subject: [PATCH 75/83] Update Readme.md --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index a47d48b9e..73af6506c 100644 --- a/Readme.md +++ b/Readme.md @@ -123,7 +123,7 @@ Verá la indicación **Some checks haven't completed yet**. ![](img/img8.png) -Es posible que tenga que actualizar los cambios que se hayan hecho en el repositorio original, por ejemplo, si se han agregado nuevos tests. En este caso obtendrá el siguiente mensaje: +Es posible que tenga que actualizar los cambios que se hayan hecho en el repositorio original, por ejemplo, si se han agregado nuevos tests. En este caso obtendrá el siguiente mensaje: > **This branch is out-of-date with base branch** From a35cc671ad3faf6ab90201218d44cbc72123c5de Mon Sep 17 00:00:00 2001 From: darian10 Date: Fri, 25 Feb 2022 15:33:30 -0500 Subject: [PATCH 76/83] Fixing size ldata issue --- src/cells.mips | 3661 +++++++++++++++++ .../code_generation/cil/Base_COOL_to_CIL.py | 190 +- src/utils/code_generation/cil/COOL_to_CIL.py | 375 +- 3 files changed, 4000 insertions(+), 226 deletions(-) create mode 100644 src/cells.mips diff --git a/src/cells.mips b/src/cells.mips new file mode 100644 index 000000000..bf951bd30 --- /dev/null +++ b/src/cells.mips @@ -0,0 +1,3661 @@ + .data +default_str: .asciiz "" +data_1: .asciiz "Object" +data_2: .asciiz "IO" +data_3: .asciiz "String" +data_4: .asciiz "Int" +data_5: .asciiz "Bool" +data_6: .asciiz "CellularAutomaton" +data_7: .asciiz "Main" +data_8: .asciiz "Aborting... in class " +data_9: .asciiz " +" +data_10: .asciiz "Substring out of range" +data_11: .asciiz "(17,24) - RuntimeError: Dispatch on void +" +data_12: .asciiz "(23,9) - RuntimeError: Dispatch on void +" +data_13: .asciiz "(27,9) - RuntimeError: Dispatch on void +" +data_14: .asciiz "X" +data_15: .asciiz "." +data_16: .asciiz "(67,33) - RuntimeError: Dispatch on void +" +data_17: .asciiz " X " +data_18: .asciiz "(83,27) - RuntimeError: Dispatch on void +" +data_19: .asciiz "(84,13) - RuntimeError: Dispatch on void +" +data_20: .asciiz "(88,25) - RuntimeError: Dispatch on void +" +data_21: .asciiz "(89,25) - RuntimeError: Dispatch on void +" + +type_name_table: + .word data_1 + .word data_2 + .word data_3 + .word data_4 + .word data_5 + .word data_6 + .word data_7 + +proto_table: + .word type_1_proto + .word type_2_proto + .word type_3_proto + .word type_4_proto + .word type_5_proto + .word type_6_proto + .word type_7_proto + +type_1_dispatch: + .word L_2 + .word L_3 + .word L_4 + .word L_1 + +type_1_proto: + .word 0 + .word 4 + .word type_1_dispatch + .word -1 + +type_2_dispatch: + .word L_3 + .word L_2 + .word L_4 + .word L_6 + .word L_7 + .word L_8 + .word L_9 + .word L_5 + +type_2_proto: + .word 1 + .word 4 + .word type_2_dispatch + .word -1 + +type_3_dispatch: + .word L_3 + .word L_2 + .word L_4 + .word L_11 + .word L_12 + .word L_13 + .word L_10 + +type_3_proto: + .word 2 + .word 6 + .word type_3_dispatch + .word default_str + .word type_4_proto + .word -1 + +type_4_dispatch: + .word L_3 + .word L_2 + .word L_4 + .word L_14 + +type_4_proto: + .word 3 + .word 5 + .word type_4_dispatch + .word 0 + .word -1 + +type_5_dispatch: + .word L_3 + .word L_2 + .word L_4 + .word L_15 + +type_5_proto: + .word 4 + .word 5 + .word type_5_dispatch + .word 0 + .word -1 + +type_6_dispatch: + .word L_2 + .word L_3 + .word L_4 + .word L_6 + .word L_7 + .word L_8 + .word L_9 + .word L_16 + .word L_17 + .word L_18 + .word L_19 + .word L_20 + .word L_21 + .word L_22 + .word L_23 + +type_6_proto: + .word 5 + .word 5 + .word type_6_dispatch + .word 0 + .word -1 + +type_7_dispatch: + .word L_2 + .word L_3 + .word L_4 + .word L_26 + +type_7_proto: + .word 6 + .word 5 + .word type_7_dispatch + .word 0 + .word -1 + .text + .globl main +main: + jal mem_manager_init + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -8 + jal L_27 + move $t0 $v0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_26 + move $t0 $v0 + addi $sp, $sp, 4 + li $v0, 0 + addi $sp, $sp, 8 + lw $fp, 0($sp) + addi $sp, $sp, 4 + li $v0, 10 + syscall +L_1: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -4 + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $t5, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $a2, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + addi $sp, $sp, -4 + sw $t5, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + li $t5, 0 + sll $t5 $t5 2 + la $t1, proto_table + addu $t1 $t1 $t5 + lw $t1, 0($t1) + lw $a0, 4($t1) + sll $a0 $a0 2 + jal malloc + move $a2 $a0 + move $a0 $t1 + move $a1 $v0 + jal copy + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $t5, 0($sp) + addi $sp, $sp, 4 + move $t0 $v0 + move $v0 $t0 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $a2, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t5, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 4 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_2: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -4 + addi $sp, $sp, -4 + sw $a1, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + lw $t1, 0($fp) + la $t0, data_8 + 0 + li $v0, 4 + move $a0 $t0 + syscall + lw $a0, 0($t1) + sll $a0 $a0 2 + la $a1, type_name_table + addu $a0 $a0 $a1 + lw $a0, 0($a0) + move $t0 $a0 + li $v0, 4 + move $a0 $t0 + syscall + la $t0, data_9 + 0 + li $v0, 4 + move $a0 $t0 + syscall + li $v0, 10 + syscall + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $a1, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 4 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_3: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -8 + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + lw $t0, 0($fp) + lw $a0, 0($t0) + sll $a0 $a0 2 + la $a1, type_name_table + addu $a0 $a0 $a1 + lw $a0, 0($a0) + move $t0 $a0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_10 + move $t0 $v0 + addi $sp, $sp, 4 + move $v0 $t0 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 8 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_4: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -4 + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + addi $sp, $sp, -4 + sw $a2, 0($sp) + lw $t0, 0($fp) + lw $a0, 4($t0) + sll $a0 $a0 2 + jal malloc + move $a2 $a0 + move $a0 $t0 + move $a1 $v0 + jal copy + move $t0 $v0 + move $v0 $t0 + lw $a2, 0($sp) + addi $sp, $sp, 4 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 4 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_5: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -4 + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $t5, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + addi $sp, $sp, -4 + sw $a2, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $t5, 0($sp) + li $t1, 1 + sll $t1 $t1 2 + la $t5, proto_table + addu $t5 $t5 $t1 + lw $t5, 0($t5) + lw $a0, 4($t5) + sll $a0 $a0 2 + jal malloc + move $a2 $a0 + move $a0 $t5 + move $a1 $v0 + jal copy + lw $t5, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + move $t0 $v0 + move $v0 $t0 + lw $a2, 0($sp) + addi $sp, $sp, 4 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $t5, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 4 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_6: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -4 + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + lw $t0, 0($fp) + lw $t1, 4($fp) + lw $a1, 12($t0) + move $t0 $a1 + li $v0, 4 + move $a0 $t0 + syscall + move $v0 $t1 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 4 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_7: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -4 + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + lw $t0, 0($fp) + lw $t1, 4($fp) + lw $a1, 12($t0) + move $t0 $a1 + li $v0, 1 + move $a0 $t0 + syscall + move $v0 $t1 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 4 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_8: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -8 + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $ra, 0($sp) + lw $t0, 0($fp) + jal get_string + move $t0 $v0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_10 + move $t0 $v0 + addi $sp, $sp, 4 + move $v0 $t0 + lw $ra, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 8 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_9: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -8 + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $ra, 0($sp) + lw $t0, 0($fp) + li $v0, 5 + syscall + move $t0 $v0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + move $v0 $t0 + lw $ra, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 8 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_10: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -12 + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t7, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + addi $sp, $sp, -4 + sw $a2, 0($sp) + lw $t1, 0($fp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $t7, 0($sp) + li $t1, 2 + sll $t1 $t1 2 + la $t7, proto_table + addu $t7 $t7 $t1 + lw $t7, 0($t7) + lw $a0, 4($t7) + sll $a0 $a0 2 + jal malloc + move $a2 $a0 + move $a0 $t7 + move $a1 $v0 + jal copy + lw $t7, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + move $t0 $v0 + sw $t1, 12($t0) + move $a0 $t1 + jal len + move $t1 $v0 + addi $sp, $sp, -4 + sw $t1, 0($sp) + jal L_14 + move $t1 $v0 + addi $sp, $sp, 4 + sw $t1, 16($t0) + move $v0 $t0 + lw $a2, 0($sp) + addi $sp, $sp, 4 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $t7, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 12 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_11: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -4 + addi $sp, $sp, -4 + sw $a1, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + lw $t0, 0($fp) + lw $a1, 16($t0) + move $t0 $a1 + move $v0 $t0 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $a1, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 4 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_12: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -24 + addi $sp, $sp, -4 + sw $t3, 0($sp) + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t2, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + addi $sp, $sp, -4 + sw $a2, 0($sp) + lw $t0, 0($fp) + lw $t1, 4($fp) + lw $a1, 12($t1) + move $t3 $a1 + lw $a1, 12($t0) + move $t2 $a1 + lw $a1, 16($t1) + move $t1 $a1 + lw $a1, 16($t0) + move $t0 $a1 + lw $a1, 12($t1) + move $t1 $a1 + lw $a1, 12($t0) + move $t0 $a1 + add $t1 $t1 $t0 + move $a0 $t3 + move $a1 $t2 + move $a2 $t1 + jal concat + move $t0 $v0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_10 + move $t0 $v0 + addi $sp, $sp, 4 + move $v0 $t0 + lw $a2, 0($sp) + addi $sp, $sp, 4 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $t2, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + lw $t3, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 24 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_13: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -32 + addi $sp, $sp, -4 + sw $t2, 0($sp) + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $t3, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $t4, 0($sp) + addi $sp, $sp, -4 + sw $a2, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + lw $t0, 0($fp) + lw $t2, 4($fp) + lw $t1, 8($fp) + lw $a1, 12($t1) + move $t3 $a1 + lw $a1, 12($t2) + move $t4 $a1 + lw $a1, 12($t0) + move $t2 $a1 + lw $a1, 16($t1) + move $t0 $a1 + add $t1 $t2 $t4 + move $a0 $t0 + move $a1 $t1 + jal less + move $t0 $v0 + bne $t0 $zero L_29 + j L_30 + L_29: + li $v0, 4 + la $a0, data_10 + syscall + li $v0, 10 + syscall + L_30: + move $a0 $t3 + move $a1 $t4 + move $a2 $t2 + jal sub_string + move $t0 $v0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_10 + move $t0 $v0 + addi $sp, $sp, 4 + move $v0 $t0 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $a2, 0($sp) + addi $sp, $sp, 4 + lw $t4, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t3, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + lw $t2, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 32 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_14: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -4 + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t4, 0($sp) + addi $sp, $sp, -4 + sw $t8, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + addi $sp, $sp, -4 + sw $a2, 0($sp) + lw $t1, 0($fp) + addi $sp, $sp, -4 + sw $t8, 0($sp) + addi $sp, $sp, -4 + sw $t4, 0($sp) + li $t8, 3 + sll $t8 $t8 2 + la $t4, proto_table + addu $t4 $t4 $t8 + lw $t4, 0($t4) + lw $a0, 4($t4) + sll $a0 $a0 2 + jal malloc + move $a2 $a0 + move $a0 $t4 + move $a1 $v0 + jal copy + lw $t4, 0($sp) + addi $sp, $sp, 4 + lw $t8, 0($sp) + addi $sp, $sp, 4 + move $t0 $v0 + sw $t1, 12($t0) + move $v0 $t0 + lw $a2, 0($sp) + addi $sp, $sp, 4 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $t8, 0($sp) + addi $sp, $sp, 4 + lw $t4, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 4 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_15: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -4 + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $t5, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $t3, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + addi $sp, $sp, -4 + sw $a2, 0($sp) + lw $t1, 0($fp) + addi $sp, $sp, -4 + sw $t3, 0($sp) + addi $sp, $sp, -4 + sw $t5, 0($sp) + li $t3, 4 + sll $t3 $t3 2 + la $t5, proto_table + addu $t5 $t5 $t3 + lw $t5, 0($t5) + lw $a0, 4($t5) + sll $a0 $a0 2 + jal malloc + move $a2 $a0 + move $a0 $t5 + move $a1 $v0 + jal copy + lw $t5, 0($sp) + addi $sp, $sp, 4 + lw $t3, 0($sp) + addi $sp, $sp, 4 + move $t0 $v0 + sw $t1, 12($t0) + move $v0 $t0 + lw $a2, 0($sp) + addi $sp, $sp, 4 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $t3, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t5, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 4 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_16: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, 0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + lw $t1, 0($fp) + lw $t0, 4($fp) + sw $t1, 12($t0) + move $v0 $t0 + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 0 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_17: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -44 + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t2, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $t3, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + addi $sp, $sp, -4 + sw $a2, 0($sp) + lw $t1, 0($fp) + la $t0, data_9 + 0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_10 + move $t0 $v0 + addi $sp, $sp, 4 + move $t2 $t0 + lw $a1, 12($t1) + move $t0 $a1 + move $t0 $t0 + move $a0 $t0 + li $a1, 0 + jal eqs + move $t3 $v0 + bne $t3 $zero L_31 + j L_32 + L_31: + li $v0, 4 + la $a0, data_11 + syscall + li $v0, 10 + syscall + L_32: + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $t2, 0($sp) + lw $t0, 0($t0) + la $a1, proto_table + sll $a2 $t0 2 + addu $a1 $a1 $a2 + lw $a1, 0($a1) + lw $a1, 8($a1) + addiu $a1 $a1 16 + lw $a1, 0($a1) + jal $a1 + move $t0 $v0 + addi $sp, $sp, 8 + move $t0 $t0 + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + lw $t0, 0($t1) + la $a1, proto_table + sll $a2 $t0 2 + addu $a1 $a1 $a2 + lw $a1, 0($a1) + lw $a1, 8($a1) + addiu $a1 $a1 12 + lw $a1, 0($a1) + jal $a1 + move $t0 $v0 + addi $sp, $sp, 8 + move $v0 $t1 + lw $a2, 0($sp) + addi $sp, $sp, 4 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $t3, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $t2, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 44 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_18: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -20 + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + addi $sp, $sp, -4 + sw $a2, 0($sp) + lw $t0, 0($fp) + lw $a1, 12($t0) + move $t0 $a1 + move $t1 $t0 + move $a0 $t1 + li $a1, 0 + jal eqs + move $t0 $v0 + bne $t0 $zero L_33 + j L_34 + L_33: + li $v0, 4 + la $a0, data_12 + syscall + li $v0, 10 + syscall + L_34: + addi $sp, $sp, -4 + sw $t1, 0($sp) + lw $t0, 0($t1) + la $a1, proto_table + sll $a2 $t0 2 + addu $a1 $a1 $a2 + lw $a1, 0($a1) + lw $a1, 8($a1) + addiu $a1 $a1 12 + lw $a1, 0($a1) + jal $a1 + move $t0 $v0 + addi $sp, $sp, 4 + move $v0 $t0 + lw $a2, 0($sp) + addi $sp, $sp, 4 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 20 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_19: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -32 + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $t3, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $t2, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + addi $sp, $sp, -4 + sw $a2, 0($sp) + lw $t0, 0($fp) + lw $t1, 4($fp) + move $t3 $t0 + li $a0, 1 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + move $t2 $t0 + lw $a1, 12($t1) + move $t0 $a1 + move $t0 $t0 + move $a0 $t0 + li $a1, 0 + jal eqs + move $t1 $v0 + bne $t1 $zero L_35 + j L_36 + L_35: + li $v0, 4 + la $a0, data_13 + syscall + li $v0, 10 + syscall + L_36: + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $t3, 0($sp) + addi $sp, $sp, -4 + sw $t2, 0($sp) + lw $t0, 0($t0) + la $a1, proto_table + sll $a2 $t0 2 + addu $a1 $a1 $a2 + lw $a1, 0($a1) + lw $a1, 8($a1) + addiu $a1 $a1 20 + lw $a1, 0($a1) + jal $a1 + move $t0 $v0 + addi $sp, $sp, 12 + move $v0 $t0 + lw $a2, 0($sp) + addi $sp, $sp, 4 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $t2, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t3, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 32 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_20: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -120 + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t6, 0($sp) + addi $sp, $sp, -4 + sw $t5, 0($sp) + addi $sp, $sp, -4 + sw $t2, 0($sp) + addi $sp, $sp, -4 + sw $t4, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $t3, 0($sp) + addi $sp, $sp, -4 + sw $a2, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + lw $t1, 0($fp) + lw $t4, 4($fp) + li $a0, 0 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_14 + move $t5 $v0 + addi $sp, $sp, 4 + lw $a0, 0($t1) + sll $a0 $a0 2 + la $a1, type_name_table + addu $a0 $a0 $a1 + lw $a0, 0($a0) + move $t2 $a0 + la $t0, type_name_table + addiu $t0 $t0 12 + lw $t0, 0($t0) + la $t3, type_name_table + addiu $t3 $t3 16 + lw $t3, 0($t3) + la $t6, type_name_table + addiu $t6 $t6 8 + lw $t6, 0($t6) + move $a0 $t2 + move $a1 $t0 + jal eqs + move $t0 $v0 + bne $t0 $zero L_37 + move $a0 $t2 + move $a1 $t3 + jal eqs + move $t0 $v0 + bne $t0 $zero L_37 + move $a0 $t2 + move $a1 $t6 + jal eqs + move $t0 $v0 + bne $t0 $zero L_38 + j L_39 + L_37: + lw $a1, 12($t1) + move $t0 $a1 + lw $a1, 12($t5) + move $t2 $a1 + move $a0 $t0 + move $a1 $t2 + jal eqs + move $t0 $v0 + j L_40 + L_38: + lw $a1, 12($t1) + move $t0 $a1 + lw $a1, 12($t5) + move $t2 $a1 + move $a0 $t0 + move $a1 $t2 + jal eq_string + move $t0 $v0 + j L_40 + L_39: + move $a0 $t1 + move $a1 $t5 + jal eqs + move $t0 $v0 + L_40: + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_15 + move $t0 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t0) + move $t0 $a1 + bne $t0 $zero L_41 + j L_42 + L_41: + addi $sp, $sp, -4 + sw $t4, 0($sp) + lw $t0, 0($t4) + la $a1, proto_table + sll $a2 $t0 2 + addu $a1 $a1 $a2 + lw $a1, 0($a1) + lw $a1, 8($a1) + addiu $a1 $a1 36 + lw $a1, 0($a1) + jal $a1 + move $t0 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t0) + move $t1 $a1 + li $a0, 1 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t0) + move $t0 $a1 + sub $t0 $t1 $t0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + move $t0 $t0 + addi $sp, $sp, -4 + sw $t4, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + lw $t0, 0($t4) + la $a1, proto_table + sll $a2 $t0 2 + addu $a1 $a1 $a2 + lw $a1, 0($a1) + lw $a1, 8($a1) + addiu $a1 $a1 40 + lw $a1, 0($a1) + jal $a1 + move $t0 $v0 + addi $sp, $sp, 8 + move $t0 $t0 + j L_43 + L_42: + lw $a1, 12($t1) + move $t1 $a1 + li $a0, 1 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t0) + move $t0 $a1 + sub $t0 $t1 $t0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + move $t0 $t0 + addi $sp, $sp, -4 + sw $t4, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + lw $t0, 0($t4) + la $a1, proto_table + sll $a2 $t0 2 + addu $a1 $a1 $a2 + lw $a1, 0($a1) + lw $a1, 8($a1) + addiu $a1 $a1 40 + lw $a1, 0($a1) + jal $a1 + move $t0 $v0 + addi $sp, $sp, 8 + move $t0 $t0 + L_43: + move $v0 $t0 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $a2, 0($sp) + addi $sp, $sp, 4 + lw $t3, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t4, 0($sp) + addi $sp, $sp, 4 + lw $t2, 0($sp) + addi $sp, $sp, 4 + lw $t5, 0($sp) + addi $sp, $sp, 4 + lw $t6, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 120 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_21: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -120 + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t6, 0($sp) + addi $sp, $sp, -4 + sw $t5, 0($sp) + addi $sp, $sp, -4 + sw $t2, 0($sp) + addi $sp, $sp, -4 + sw $t4, 0($sp) + addi $sp, $sp, -4 + sw $t3, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $a2, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + lw $t0, 0($fp) + lw $t3, 4($fp) + addi $sp, $sp, -4 + sw $t3, 0($sp) + lw $t1, 0($t3) + la $a1, proto_table + sll $a2 $t1 2 + addu $a1 $a1 $a2 + lw $a1, 0($a1) + lw $a1, 8($a1) + addiu $a1 $a1 36 + lw $a1, 0($a1) + jal $a1 + move $t1 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t1) + move $t1 $a1 + li $a0, 1 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_14 + move $t2 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t2) + move $t2 $a1 + sub $t1 $t1 $t2 + addi $sp, $sp, -4 + sw $t1, 0($sp) + jal L_14 + move $t5 $v0 + addi $sp, $sp, 4 + lw $a0, 0($t0) + sll $a0 $a0 2 + la $a1, type_name_table + addu $a0 $a0 $a1 + lw $a0, 0($a0) + move $t2 $a0 + la $t4, type_name_table + addiu $t4 $t4 12 + lw $t4, 0($t4) + la $t6, type_name_table + addiu $t6 $t6 16 + lw $t6, 0($t6) + la $t1, type_name_table + addiu $t1 $t1 8 + lw $t1, 0($t1) + move $a0 $t2 + move $a1 $t4 + jal eqs + move $t4 $v0 + bne $t4 $zero L_44 + move $a0 $t2 + move $a1 $t6 + jal eqs + move $t4 $v0 + bne $t4 $zero L_44 + move $a0 $t2 + move $a1 $t1 + jal eqs + move $t4 $v0 + bne $t4 $zero L_45 + j L_46 + L_44: + lw $a1, 12($t0) + move $t1 $a1 + lw $a1, 12($t5) + move $t2 $a1 + move $a0 $t1 + move $a1 $t2 + jal eqs + move $t1 $v0 + j L_47 + L_45: + lw $a1, 12($t0) + move $t1 $a1 + lw $a1, 12($t5) + move $t2 $a1 + move $a0 $t1 + move $a1 $t2 + jal eq_string + move $t1 $v0 + j L_47 + L_46: + move $a0 $t0 + move $a1 $t5 + jal eqs + move $t1 $v0 + L_47: + addi $sp, $sp, -4 + sw $t1, 0($sp) + jal L_15 + move $t1 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t1) + move $t1 $a1 + bne $t1 $zero L_48 + j L_49 + L_48: + li $a0, 0 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + move $t0 $t0 + addi $sp, $sp, -4 + sw $t3, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + lw $t0, 0($t3) + la $a1, proto_table + sll $a2 $t0 2 + addu $a1 $a1 $a2 + lw $a1, 0($a1) + lw $a1, 8($a1) + addiu $a1 $a1 40 + lw $a1, 0($a1) + jal $a1 + move $t0 $v0 + addi $sp, $sp, 8 + move $t0 $t0 + j L_50 + L_49: + lw $a1, 12($t0) + move $t1 $a1 + li $a0, 1 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t0) + move $t0 $a1 + add $t0 $t1 $t0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + move $t0 $t0 + addi $sp, $sp, -4 + sw $t3, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + lw $t0, 0($t3) + la $a1, proto_table + sll $a2 $t0 2 + addu $a1 $a1 $a2 + lw $a1, 0($a1) + lw $a1, 8($a1) + addiu $a1 $a1 40 + lw $a1, 0($a1) + jal $a1 + move $t0 $v0 + addi $sp, $sp, 8 + move $t0 $t0 + L_50: + move $v0 $t0 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $a2, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t3, 0($sp) + addi $sp, $sp, 4 + lw $t4, 0($sp) + addi $sp, $sp, 4 + lw $t2, 0($sp) + addi $sp, $sp, 4 + lw $t5, 0($sp) + addi $sp, $sp, 4 + lw $t6, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 120 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_22: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -312 + addi $sp, $sp, -4 + sw $t4, 0($sp) + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $t3, 0($sp) + addi $sp, $sp, -4 + sw $t7, 0($sp) + addi $sp, $sp, -4 + sw $t5, 0($sp) + addi $sp, $sp, -4 + sw $a2, 0($sp) + addi $sp, $sp, -4 + sw $t2, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $t6, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $t8, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + lw $t3, 0($fp) + lw $t2, 4($fp) + move $t0 $t3 + addi $sp, $sp, -4 + sw $t2, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + lw $t0, 0($t2) + la $a1, proto_table + sll $a2 $t0 2 + addu $a1 $a1 $a2 + lw $a1, 0($a1) + lw $a1, 8($a1) + addiu $a1 $a1 40 + lw $a1, 0($a1) + jal $a1 + move $t7 $v0 + addi $sp, $sp, 8 + la $t0, data_14 + 0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_10 + move $t1 $v0 + addi $sp, $sp, 4 + lw $a0, 0($t7) + sll $a0 $a0 2 + la $a1, type_name_table + addu $a0 $a0 $a1 + lw $a0, 0($a0) + move $t0 $a0 + la $t5, type_name_table + addiu $t5 $t5 12 + lw $t5, 0($t5) + la $t6, type_name_table + addiu $t6 $t6 16 + lw $t6, 0($t6) + la $t4, type_name_table + addiu $t4 $t4 8 + lw $t4, 0($t4) + move $a0 $t0 + move $a1 $t5 + jal eqs + move $t5 $v0 + bne $t5 $zero L_51 + move $a0 $t0 + move $a1 $t6 + jal eqs + move $t5 $v0 + bne $t5 $zero L_51 + move $a0 $t0 + move $a1 $t4 + jal eqs + move $t5 $v0 + bne $t5 $zero L_52 + j L_53 + L_51: + lw $a1, 12($t7) + move $t4 $a1 + lw $a1, 12($t1) + move $t0 $a1 + move $a0 $t4 + move $a1 $t0 + jal eqs + move $t0 $v0 + j L_54 + L_52: + lw $a1, 12($t7) + move $t4 $a1 + lw $a1, 12($t1) + move $t0 $a1 + move $a0 $t4 + move $a1 $t0 + jal eq_string + move $t0 $v0 + j L_54 + L_53: + move $a0 $t7 + move $a1 $t1 + jal eqs + move $t0 $v0 + L_54: + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_15 + move $t0 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t0) + move $t0 $a1 + bne $t0 $zero L_55 + j L_56 + L_55: + li $a0, 1 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + move $t0 $t0 + j L_57 + L_56: + li $a0, 0 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + move $t0 $t0 + L_57: + lw $a1, 12($t0) + move $t1 $a1 + move $t0 $t3 + addi $sp, $sp, -4 + sw $t2, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + lw $t0, 0($t2) + la $a1, proto_table + sll $a2 $t0 2 + addu $a1 $a1 $a2 + lw $a1, 0($a1) + lw $a1, 8($a1) + addiu $a1 $a1 44 + lw $a1, 0($a1) + jal $a1 + move $t5 $v0 + addi $sp, $sp, 8 + la $t0, data_14 + 0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_10 + move $t7 $v0 + addi $sp, $sp, 4 + lw $a0, 0($t5) + sll $a0 $a0 2 + la $a1, type_name_table + addu $a0 $a0 $a1 + lw $a0, 0($a0) + move $t8 $a0 + la $t6, type_name_table + addiu $t6 $t6 12 + lw $t6, 0($t6) + la $t4, type_name_table + addiu $t4 $t4 16 + lw $t4, 0($t4) + la $t0, type_name_table + addiu $t0 $t0 8 + lw $t0, 0($t0) + move $a0 $t8 + move $a1 $t6 + jal eqs + move $t6 $v0 + bne $t6 $zero L_58 + move $a0 $t8 + move $a1 $t4 + jal eqs + move $t6 $v0 + bne $t6 $zero L_58 + move $a0 $t8 + move $a1 $t0 + jal eqs + move $t6 $v0 + bne $t6 $zero L_59 + j L_60 + L_58: + lw $a1, 12($t5) + move $t0 $a1 + lw $a1, 12($t7) + move $t4 $a1 + move $a0 $t0 + move $a1 $t4 + jal eqs + move $t0 $v0 + j L_61 + L_59: + lw $a1, 12($t5) + move $t0 $a1 + lw $a1, 12($t7) + move $t4 $a1 + move $a0 $t0 + move $a1 $t4 + jal eq_string + move $t0 $v0 + j L_61 + L_60: + move $a0 $t5 + move $a1 $t7 + jal eqs + move $t0 $v0 + L_61: + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_15 + move $t0 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t0) + move $t0 $a1 + bne $t0 $zero L_62 + j L_63 + L_62: + li $a0, 1 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + move $t0 $t0 + j L_64 + L_63: + li $a0, 0 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + move $t0 $t0 + L_64: + lw $a1, 12($t0) + move $t0 $a1 + add $t0 $t1 $t0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t0) + move $t1 $a1 + move $t0 $t3 + addi $sp, $sp, -4 + sw $t2, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + lw $t0, 0($t2) + la $a1, proto_table + sll $a2 $t0 2 + addu $a1 $a1 $a2 + lw $a1, 0($a1) + lw $a1, 8($a1) + addiu $a1 $a1 48 + lw $a1, 0($a1) + jal $a1 + move $t6 $v0 + addi $sp, $sp, 8 + la $t0, data_14 + 0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_10 + move $t3 $v0 + addi $sp, $sp, 4 + lw $a0, 0($t6) + sll $a0 $a0 2 + la $a1, type_name_table + addu $a0 $a0 $a1 + lw $a0, 0($a0) + move $t5 $a0 + la $t0, type_name_table + addiu $t0 $t0 12 + lw $t0, 0($t0) + la $t4, type_name_table + addiu $t4 $t4 16 + lw $t4, 0($t4) + la $t2, type_name_table + addiu $t2 $t2 8 + lw $t2, 0($t2) + move $a0 $t5 + move $a1 $t0 + jal eqs + move $t0 $v0 + bne $t0 $zero L_65 + move $a0 $t5 + move $a1 $t4 + jal eqs + move $t0 $v0 + bne $t0 $zero L_65 + move $a0 $t5 + move $a1 $t2 + jal eqs + move $t0 $v0 + bne $t0 $zero L_66 + j L_67 + L_65: + lw $a1, 12($t6) + move $t2 $a1 + lw $a1, 12($t3) + move $t0 $a1 + move $a0 $t2 + move $a1 $t0 + jal eqs + move $t0 $v0 + j L_68 + L_66: + lw $a1, 12($t6) + move $t2 $a1 + lw $a1, 12($t3) + move $t0 $a1 + move $a0 $t2 + move $a1 $t0 + jal eq_string + move $t0 $v0 + j L_68 + L_67: + move $a0 $t6 + move $a1 $t3 + jal eqs + move $t0 $v0 + L_68: + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_15 + move $t0 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t0) + move $t0 $a1 + bne $t0 $zero L_69 + j L_70 + L_69: + li $a0, 1 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + move $t0 $t0 + j L_71 + L_70: + li $a0, 0 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + move $t0 $t0 + L_71: + lw $a1, 12($t0) + move $t0 $a1 + add $t0 $t1 $t0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_14 + move $t3 $v0 + addi $sp, $sp, 4 + li $a0, 1 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_14 + move $t1 $v0 + addi $sp, $sp, 4 + lw $a0, 0($t3) + sll $a0 $a0 2 + la $a1, type_name_table + addu $a0 $a0 $a1 + lw $a0, 0($a0) + move $t0 $a0 + la $t4, type_name_table + addiu $t4 $t4 12 + lw $t4, 0($t4) + la $t2, type_name_table + addiu $t2 $t2 16 + lw $t2, 0($t2) + la $t5, type_name_table + addiu $t5 $t5 8 + lw $t5, 0($t5) + move $a0 $t0 + move $a1 $t4 + jal eqs + move $t4 $v0 + bne $t4 $zero L_72 + move $a0 $t0 + move $a1 $t2 + jal eqs + move $t4 $v0 + bne $t4 $zero L_72 + move $a0 $t0 + move $a1 $t5 + jal eqs + move $t4 $v0 + bne $t4 $zero L_73 + j L_74 + L_72: + lw $a1, 12($t3) + move $t0 $a1 + lw $a1, 12($t1) + move $t1 $a1 + move $a0 $t0 + move $a1 $t1 + jal eqs + move $t0 $v0 + j L_75 + L_73: + lw $a1, 12($t3) + move $t0 $a1 + lw $a1, 12($t1) + move $t1 $a1 + move $a0 $t0 + move $a1 $t1 + jal eq_string + move $t0 $v0 + j L_75 + L_74: + move $a0 $t3 + move $a1 $t1 + jal eqs + move $t0 $v0 + L_75: + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_15 + move $t0 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t0) + move $t0 $a1 + bne $t0 $zero L_76 + j L_77 + L_76: + la $t0, data_14 + 0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_10 + move $t0 $v0 + addi $sp, $sp, 4 + move $t0 $t0 + j L_78 + L_77: + la $t0, data_15 + 0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_10 + move $t0 $v0 + addi $sp, $sp, 4 + move $t0 $t0 + L_78: + move $v0 $t0 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $t8, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $t6, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t2, 0($sp) + addi $sp, $sp, 4 + lw $a2, 0($sp) + addi $sp, $sp, 4 + lw $t5, 0($sp) + addi $sp, $sp, 4 + lw $t7, 0($sp) + addi $sp, $sp, 4 + lw $t3, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + lw $t4, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 312 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_23: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -104 + addi $sp, $sp, -4 + sw $t9, 0($sp) + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t5, 0($sp) + addi $sp, $sp, -4 + sw $t7, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $t6, 0($sp) + addi $sp, $sp, -4 + sw $a2, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $t2, 0($sp) + addi $sp, $sp, -4 + sw $t3, 0($sp) + addi $sp, $sp, -4 + sw $t4, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + lw $t5, 0($fp) + addi $sp, $sp, -4 + sw $t7, 0($sp) + addi $sp, $sp, -4 + sw $t6, 0($sp) + li $t7, 3 + sll $t7 $t7 2 + la $t6, proto_table + addu $t6 $t6 $t7 + lw $t6, 0($t6) + lw $a0, 4($t6) + sll $a0 $a0 2 + jal malloc + move $a2 $a0 + move $a0 $t6 + move $a1 $v0 + jal copy + lw $t6, 0($sp) + addi $sp, $sp, 4 + lw $t7, 0($sp) + addi $sp, $sp, 4 + move $t4 $v0 + addi $sp, $sp, -4 + sw $t5, 0($sp) + lw $t0, 0($t5) + la $a1, proto_table + sll $a2 $t0 2 + addu $a1 $a1 $a2 + lw $a1, 0($a1) + lw $a1, 8($a1) + addiu $a1 $a1 36 + lw $a1, 0($a1) + jal $a1 + move $t0 $v0 + addi $sp, $sp, 4 + move $t2 $t0 + addi $sp, $sp, -4 + sw $t9, 0($sp) + addi $sp, $sp, -4 + sw $t4, 0($sp) + li $t9, 2 + sll $t9 $t9 2 + la $t4, proto_table + addu $t4 $t4 $t9 + lw $t4, 0($t4) + lw $a0, 4($t4) + sll $a0 $a0 2 + jal malloc + move $a2 $a0 + move $a0 $t4 + move $a1 $v0 + jal copy + lw $t4, 0($sp) + addi $sp, $sp, 4 + lw $t9, 0($sp) + addi $sp, $sp, 4 + move $t3 $v0 + L_79: + lw $a1, 12($t4) + move $t0 $a1 + lw $a1, 12($t2) + move $t1 $a1 + move $a0 $t0 + move $a1 $t1 + jal less + move $t0 $v0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_15 + move $t0 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t0) + move $t0 $a1 + bne $t0 $zero L_80 + j L_83 + L_80: + move $t0 $t4 + addi $sp, $sp, -4 + sw $t5, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + lw $t0, 0($t5) + la $a1, proto_table + sll $a2 $t0 2 + addu $a1 $a1 $a2 + lw $a1, 0($a1) + lw $a1, 8($a1) + addiu $a1 $a1 52 + lw $a1, 0($a1) + jal $a1 + move $t0 $v0 + addi $sp, $sp, 8 + move $t1 $t0 + move $t3 $t3 + move $a0 $t3 + li $a1, 0 + jal eqs + move $t0 $v0 + bne $t0 $zero L_81 + j L_82 + L_81: + li $v0, 4 + la $a0, data_16 + syscall + li $v0, 10 + syscall + L_82: + addi $sp, $sp, -4 + sw $t3, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + lw $t0, 0($t3) + la $a1, proto_table + sll $a2 $t0 2 + addu $a1 $a1 $a2 + lw $a1, 0($a1) + lw $a1, 8($a1) + addiu $a1 $a1 16 + lw $a1, 0($a1) + jal $a1 + move $t0 $v0 + addi $sp, $sp, 8 + move $t3 $t0 + lw $a1, 12($t4) + move $t1 $a1 + li $a0, 1 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t0) + move $t0 $a1 + add $t0 $t1 $t0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + move $t4 $t0 + j L_79 + L_83: + sw $t3, 12($t5) + move $t0 $t5 + move $t0 $t0 + move $t0 $t0 + move $v0 $t0 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $t4, 0($sp) + addi $sp, $sp, 4 + lw $t3, 0($sp) + addi $sp, $sp, 4 + lw $t2, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $a2, 0($sp) + addi $sp, $sp, 4 + lw $t6, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $t7, 0($sp) + addi $sp, $sp, 4 + lw $t5, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + lw $t9, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 104 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_24: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -8 + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + addi $sp, $sp, -4 + sw $a2, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + li $t1, 5 + sll $t1 $t1 2 + la $t0, proto_table + addu $t0 $t0 $t1 + lw $t0, 0($t0) + lw $a0, 4($t0) + sll $a0 $a0 2 + jal malloc + move $a2 $a0 + move $a0 $t0 + move $a1 $v0 + jal copy + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + move $t0 $v0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_25 + move $t1 $v0 + addi $sp, $sp, 4 + move $v0 $t0 + lw $a2, 0($sp) + addi $sp, $sp, 4 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 8 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_25: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -4 + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t3, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $t6, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $a2, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + lw $t1, 0($fp) + addi $sp, $sp, -4 + sw $t6, 0($sp) + addi $sp, $sp, -4 + sw $t3, 0($sp) + li $t6, 2 + sll $t6 $t6 2 + la $t3, proto_table + addu $t3 $t3 $t6 + lw $t3, 0($t3) + lw $a0, 4($t3) + sll $a0 $a0 2 + jal malloc + move $a2 $a0 + move $a0 $t3 + move $a1 $v0 + jal copy + lw $t3, 0($sp) + addi $sp, $sp, 4 + lw $t6, 0($sp) + addi $sp, $sp, 4 + move $t0 $v0 + sw $t0, 12($t1) + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $a2, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $t6, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t3, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 4 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_26: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -148 + addi $sp, $sp, -4 + sw $t3, 0($sp) + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $t2, 0($sp) + addi $sp, $sp, -4 + sw $a2, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + lw $t2, 0($fp) + la $t0, data_17 + 0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_10 + move $t0 $v0 + addi $sp, $sp, 4 + move $t1 $t0 + jal L_24 + move $t0 $v0 + move $t0 $t0 + move $a0 $t0 + li $a1, 0 + jal eqs + move $t3 $v0 + bne $t3 $zero L_84 + j L_85 + L_84: + li $v0, 4 + la $a0, data_18 + syscall + li $v0, 10 + syscall + L_85: + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + lw $t0, 0($t0) + la $a1, proto_table + sll $a2 $t0 2 + addu $a1 $a1 $a2 + lw $a1, 0($a1) + lw $a1, 8($a1) + addiu $a1 $a1 28 + lw $a1, 0($a1) + jal $a1 + move $t0 $v0 + addi $sp, $sp, 8 + sw $t0, 12($t2) + lw $a1, 12($t2) + move $t0 $a1 + move $t0 $t0 + move $a0 $t0 + li $a1, 0 + jal eqs + move $t1 $v0 + bne $t1 $zero L_86 + j L_87 + L_86: + li $v0, 4 + la $a0, data_19 + syscall + li $v0, 10 + syscall + L_87: + addi $sp, $sp, -4 + sw $t0, 0($sp) + lw $t0, 0($t0) + la $a1, proto_table + sll $a2 $t0 2 + addu $a1 $a1 $a2 + lw $a1, 0($a1) + lw $a1, 8($a1) + addiu $a1 $a1 32 + lw $a1, 0($a1) + jal $a1 + move $t0 $v0 + addi $sp, $sp, 4 + li $a0, 20 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + move $t3 $t0 + L_88: + li $a0, 0 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t0) + move $t0 $a1 + lw $a1, 12($t3) + move $t1 $a1 + move $a0 $t0 + move $a1 $t1 + jal less + move $t0 $v0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_15 + move $t0 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t0) + move $t0 $a1 + bne $t0 $zero L_89 + j L_94 + L_89: + lw $a1, 12($t2) + move $t0 $a1 + move $t0 $t0 + move $a0 $t0 + li $a1, 0 + jal eqs + move $t1 $v0 + bne $t1 $zero L_90 + j L_91 + L_90: + li $v0, 4 + la $a0, data_20 + syscall + li $v0, 10 + syscall + L_91: + addi $sp, $sp, -4 + sw $t0, 0($sp) + lw $t0, 0($t0) + la $a1, proto_table + sll $a2 $t0 2 + addu $a1 $a1 $a2 + lw $a1, 0($a1) + lw $a1, 8($a1) + addiu $a1 $a1 56 + lw $a1, 0($a1) + jal $a1 + move $t0 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t2) + move $t0 $a1 + move $t0 $t0 + move $a0 $t0 + li $a1, 0 + jal eqs + move $t1 $v0 + bne $t1 $zero L_92 + j L_93 + L_92: + li $v0, 4 + la $a0, data_21 + syscall + li $v0, 10 + syscall + L_93: + addi $sp, $sp, -4 + sw $t0, 0($sp) + lw $t0, 0($t0) + la $a1, proto_table + sll $a2 $t0 2 + addu $a1 $a1 $a2 + lw $a1, 0($a1) + lw $a1, 8($a1) + addiu $a1 $a1 32 + lw $a1, 0($a1) + jal $a1 + move $t0 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t3) + move $t0 $a1 + li $a0, 1 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_14 + move $t1 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t1) + move $t1 $a1 + sub $t0 $t0 $t1 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + move $t3 $t0 + j L_88 + L_94: + move $t0 $zero + move $v0 $t2 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $a2, 0($sp) + addi $sp, $sp, 4 + lw $t2, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + lw $t3, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 148 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_27: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -8 + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t8, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $t7, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $a2, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + addi $sp, $sp, -4 + sw $t7, 0($sp) + addi $sp, $sp, -4 + sw $t8, 0($sp) + li $t7, 6 + sll $t7 $t7 2 + la $t8, proto_table + addu $t8 $t8 $t7 + lw $t8, 0($t8) + lw $a0, 4($t8) + sll $a0 $a0 2 + jal malloc + move $a2 $a0 + move $a0 $t8 + move $a1 $v0 + jal copy + lw $t8, 0($sp) + addi $sp, $sp, 4 + lw $t7, 0($sp) + addi $sp, $sp, 4 + move $t1 $v0 + addi $sp, $sp, -4 + sw $t1, 0($sp) + jal L_28 + move $t0 $v0 + addi $sp, $sp, 4 + move $v0 $t1 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $a2, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $t7, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t8, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 8 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_28: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, 0 + addi $sp, $sp, 0 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra + + + + alloc_size = 2048 + free_list = 0 + header_size = 12 + header_size_slot = 0 + header_next_slot = 4 + header_reachable_slot = 8 + init_alloc_size = 28 + int_type = 0 + meta_data_obj_size = 4 + neg_header_size = -12 + new_line = 10 + obj_mark = -1 + obj_extended = -2 + reachable = 1 + state_size = 4 + stack_base = -4 + string_size_treshold = 1024 + string_type = 0 + total_alloc_size = 2060 + num_type = 0 + used_list = header_size + +verify_obj: + addiu $sp $sp -20 + sw $t0 0($sp) + sw $t1 4($sp) + sw $t2 8($sp) + sw $t3 12($sp) + sw $a0 16($sp) + + move $t0 $a0 + + li $v0 9 + move $a0 $zero + syscall + + addiu $t1 $v0 -4 + + + blt $t0 $gp verify_obj_not_obj + bgt $t0 $t1 verify_obj_not_obj + lw $t2 0($t0) + blt $t2 $zero verify_obj_not_obj + la $t3 num_type + lw $t3 0($t3) + bge $t2 $t3 verify_obj_not_obj + + addiu $t0 $t0 4 + blt $t0 $gp verify_obj_not_obj + bgt $t0 $t1 verify_obj_not_obj + lw $t2 0($t0) + + addiu $t0 $t0 8 + + + li $t3 meta_data_obj_size + sub $t2 $t2 $t3 + sll $t2 $t2 2 + addu $t0 $t0 $t2 + + + blt $t0 $gp verify_obj_not_obj + bgt $t0 $t1 verify_obj_not_obj + lw $t2 0($t0) + beq $t2 obj_mark verify_obj_is_obj + beq $t2 obj_extended verify_obj_is_obj + +verify_obj_not_obj: + li $v0 0 + j verify_obj_finish + +verify_obj_is_obj: + li $v0 1 + +verify_obj_finish: + lw $t0 0($sp) + lw $t1 4($sp) + lw $t2 8($sp) + lw $t3 12($sp) + lw $a0 16($sp) + addiu $sp $sp 20 + + jr $ra + +concat: + addiu $sp $sp -24 + sw $t0 0($sp) + sw $t1 4($sp) + sw $t2 8($sp) + sw $a0 12($sp) + sw $a1 16($sp) + sw $ra 20($sp) + + move $t0 $a0 + move $t1 $a1 + + + addiu $a0 $a2 1 + li $t2 4 + div $a0 $t2 + mfhi $a0 + bne $a0 $zero concat_allign_size + addiu $a0 $a2 1 + +concat_size_alligned: + jal malloc + move $t2 $v0 + j concat_copy_first_cycle + +concat_allign_size: + sub $t2 $t2 $a0 + add $a0 $a2 $t2 + addiu $a0 $a0 1 + j concat_size_alligned + +concat_copy_first_cycle: + lb $a0 0($t0) + beq $a0 $zero concat_copy_second_cycle + sb $a0 0($t2) + addiu $t0 $t0 1 + addiu $t2 $t2 1 + j concat_copy_first_cycle + +concat_copy_second_cycle: + lb $a0 0($t1) + beq $a0 $zero concat_finish + sb $a0 0($t2) + addiu $t1 $t1 1 + addiu $t2 $t2 1 + j concat_copy_second_cycle + +concat_finish: + sb $zero 0($t2) + lw $t0 0($sp) + lw $t1 4($sp) + lw $t2 8($sp) + lw $a0 12($sp) + lw $a1 16($sp) + lw $ra 20($sp) + addiu $sp $sp 24 + + jr $ra + +copy: + addiu $sp $sp -16 + sw $a0 0($sp) + sw $a1 4($sp) + sw $a2 8($sp) + sw $t0 12($sp) + +copy_cycle: + beq $a2 $zero copy_finish + lw $t0 0($a0) + sw $t0 0($a1) + addiu $a0 $a0 4 + addiu $a1 $a1 4 + addi $a2 $a2 -4 + j copy_cycle + +copy_finish: + lw $a0 0($sp) + lw $a1 4($sp) + lw $a2 8($sp) + lw $t0 12($sp) + addiu $sp $sp 16 + + jr $ra + +eqs: + beq $a0 $a1 eqs_eq + li $v0 0 + j eqs_finish + +eqs_eq: + li $v0 1 + +eqs_finish: + jr $ra + +eq_string: + addiu $sp $sp -16 + sw $t0 0($sp) + sw $t1 4($sp) + sw $t2 8($sp) + sw $t3 12($sp) + + move $t0 $a0 + move $t1 $a1 + +eq_string_cycle: + lb $t2 0($t0) + lb $t3 0($t1) + bne $t2 $t3 eq_string_not_eq + beq $t2 $zero eq_string_eq + + addiu $t0 $t0 1 + addiu $t1 $t1 1 + j eq_string_cycle + +eq_string_not_eq: + move $v0 $zero + j eq_string_finish + +eq_string_eq: + li $v0 1 + +eq_string_finish: + lw $t0 0($sp) + lw $t1 4($sp) + lw $t2 8($sp) + lw $t3 12($sp) + addiu $sp $sp 16 + + jr $ra + +extend_block: + addiu $sp $sp -16 + sw $t0 0($sp) + sw $t1 4($sp) + sw $t2 8($sp) + sw $t3 12($sp) + + + addiu $t0 $gp free_list + + beq $t0 $a0 extend_block_finish + move $t0 $a0 + + lw $t1 header_next_slot($t0) + lw $t2 header_size_slot($t0) + move $t3 $t2 + addiu $t2 $t2 header_size + addu $t2 $t2 $t0 + beq $t2 $t1 extend_block_extend + j extend_block_finish + +extend_block_extend: + lw $t2 header_size_slot($t1) + addi $t2 $t2 header_size + add $t2 $t2 $t3 + sw $t2 header_size_slot($t0) + lw $t1 header_next_slot($t1) + sw $t1 header_next_slot($t0) + +extend_block_finish: + lw $t0 0($sp) + lw $t1 4($sp) + lw $t2 8($sp) + lw $t3 12($sp) + addiu $sp $sp 16 + + jr $ra + +extend_heap: + addiu $sp $sp -12 + sw $a0 0($sp) + sw $a1 4($sp) + sw $t0 8($sp) + + + li $v0 9 + addiu $a0 $a1 header_size + syscall + + + move $t0 $a1 + sw $t0 header_size_slot($v0) + sw $zero header_next_slot($v0) + sw $zero header_reachable_slot($v0) + + + lw $t0, 0($sp) + sw $v0 header_next_slot($t0) + + move $a0 $t0 + lw $a1 4($sp) + lw $t0 8($sp) + addiu $sp $sp 12 + + jr $ra + +free_block: + addiu $sp $sp -28 + sw $t0 0($sp) + sw $t1 4($sp) + sw $t2 8($sp) + sw $a0 12($sp) + sw $ra 16($sp) + sw $t3 20($sp) + sw $t4 24($sp) + + move $t0 $a0 + + addiu $t1 $gp free_list + + addiu $t3 $gp used_list + +free_block_cycle_used_list: + lw $t4 header_next_slot($t3) + beq $t4 $t0 free_block_cycle_free_list + move $t3 $t4 + j free_block_cycle_used_list + +free_block_cycle_free_list: + lw $t2 header_next_slot($t1) + beq $t2 $zero free_block_founded_prev + bge $t2 $t0 free_block_founded_prev + move $t1 $t2 + j free_block_cycle_free_list + +free_block_founded_prev: + lw $t4 header_next_slot($t0) + sw $t4 header_next_slot($t3) + + + sw $t2 header_next_slot($t0) + sw $t0 header_next_slot($t1) + +free_block_finish: + + move $a0 $t0 + jal extend_block + move $a0 $t1 + jal extend_block + + lw $t0 0($sp) + lw $t1 4($sp) + lw $t2 8($sp) + lw $a0 12($sp) + lw $ra 16($sp) + lw $t3 20($sp) + lw $t4 24($sp) + addiu $sp $sp 28 + + jr $ra + +get_gc: + addiu $sp $sp -24 + sw $t0 0($sp) + sw $t1 4($sp) + sw $t2 8($sp) + sw $t3 12($sp) + sw $a0 16($sp) + sw $ra 20($sp) + + li $t3 reachable + addiu $t0 $sp 20 + lw $t1 stack_base($gp) + + li $t2 1 + +get_gc_cycle: + + addiu $t0 $t0 4 + beq $t0 $t1 get_gc_dfs + + lw $a0 0($t0) + jal verify_obj + + bne $v0 $t2 get_gc_cycle + + addiu $a0 $a0 neg_header_size + sw $t3 header_reachable_slot($a0) + + j get_gc_cycle + +get_gc_dfs: + addiu $t1 $gp used_list + +get_gc_outer_cycle: + lw $t1 header_next_slot($t1) + beq $t1 $zero get_gc_free + lw $t2 header_reachable_slot($t1) + beq $t2 reachable get_gc_extend + j get_gc_outer_cycle + +get_gc_extend: + addiu $a0 $t1 header_size + jal get_gc_rec_extend + j get_gc_outer_cycle + +get_gc_free: + addiu $t0 $gp used_list + lw $t0 header_next_slot($t0) + +get_gc_free_cycle: + beq $t0 $zero get_gc_finish + lw $t1 header_reachable_slot($t0) + bne $t1 reachable get_gc_free_cycle_free + sw $zero header_reachable_slot($t0) + move $a0 $t0 + jal verify_obj + beq $v0 $zero get_gc_free_cycle + li $t1 obj_mark + addiu $t2 $t0 header_size + lw $t3 4($t2) + sll $t3 $t3 2 + addu $t2 $t2 $t3 + sw $t1 -4($t2) + lw $t0 header_next_slot($t0) + j get_gc_free_cycle + +get_gc_free_cycle_free: + move $a0 $t0 + lw $t0 header_next_slot($t0) + jal free_block + j get_gc_free_cycle + +get_gc_finish: + lw $t0 0($sp) + lw $t1 4($sp) + lw $t2 8($sp) + lw $t3 12($sp) + lw $a0 16($sp) + lw $ra 20($sp) + addiu $sp $sp 24 + + jr $ra + +get_gc_rec_extend: + addiu $sp $sp -16 + sw $a0 0($sp) + sw $t0 4($sp) + sw $t1 8($sp) + sw $ra 12($sp) + + jal verify_obj + beq $v0 $zero get_gc_rec_extend_finish + + lw $t0 4($a0) + sll $t0 $t0 2 + addiu $t0 $t0 -4 + addu $t0 $a0 $t0 + lw $t1 0($t0) + beq $t1 obj_extended get_gc_rec_extend_finish + + + li $t1 reachable + addiu $a0 $a0 neg_header_size + sw $t1 header_reachable_slot($a0) + addiu $a0 $a0 header_size + + + li $t1 obj_extended + sw $t1 0($t0) + + lw $t0 0($a0) + + + la $t1 int_type + lw $t1 0($t1) + beq $t0 $t1 get_gc_rec_extend_finish + + la $t1 string_type + lw $t1 0($t1) + beq $t0 $t1 get_gc_rec_extend_string_obj + + lw $t0 4($a0) + li $t1 meta_data_obj_size + sub $t0 $t0 $t1 + + addiu $t1 $a0 12 + +get_gc_rec_extend_attr_cycle: + beq $t0 $zero get_gc_rec_extend_finish + lw $a0 0($t1) + jal get_gc_rec_extend + addiu $t1 $t1 4 + sub $t0 $t0 1 + j get_gc_rec_extend_attr_cycle + +get_gc_rec_extend_string_obj: + lw $t0 8($a0) + addiu $t0 $t0 neg_header_size + li $t1 reachable + sw $t1 header_reachable_slot($t0) + +get_gc_rec_extend_finish: + lw $a0 0($sp) + lw $t0 4($sp) + lw $t1 8($sp) + lw $ra 12($sp) + addiu $sp $sp 16 + + jr $ra + +less_eq: + ble $a0 $a1 less_eq_true + li $v0 0 + j less_eq_finish + +less_eq_true: + li $v0 1 + +less_eq_finish: + jr $ra + +less: + blt $a0 $a1 less_true + li $v0 0 + j less_finish + +less_true: + li $v0 1 + +less_finish: + jr $ra + +len: + addiu $sp $sp -8 + sw $t0 0($sp) + sw $t1 4($sp) + + move $t0 $a0 + move $v0 $zero + +len_cycle: + lb $t1 0($t0) + beq $t1 $zero len_finish + addi $v0 $v0 1 + addiu $t0 $t0 1 + j len_cycle + +len_finish: + lw $t0 0($sp) + lw $t1 4($sp) + addiu $sp $sp 8 + + jr $ra + +malloc: + move $v0 $zero + addiu $sp $sp -28 + sw $t1 0($sp) + sw $t0 4($sp) + sw $a0 8($sp) + sw $a1 12($sp) + sw $ra 16($sp) + sw $t2 20($sp) + sw $t3 24($sp) + + addiu $t0 $gp free_list + j malloc_cycle + +malloc_finish: + move $a0 $v0 + lw $a1 8($sp) + jal divide_block + + lw $t1 header_next_slot($v0) + sw $t1 header_next_slot($t3) + + addiu $t1 $gp used_list + lw $a0 header_next_slot($t1) + + sw $a0 header_next_slot($v0) + sw $v0 header_next_slot($t1) + + addiu $v0 $v0 header_size + + lw $t3 24($sp) + lw $t2 20($sp) + lw $ra 16($sp) + lw $a1 12($sp) + lw $a0 8($sp) + lw $t0 4($sp) + lw $t1 0($sp) + addiu $sp $sp 28 + + jr $ra + +malloc_cycle: + move $t2 $t0 + lw $t0 header_next_slot($t0) + beq $t0 $zero malloc_search_finish + j malloc_verify_valid_block + +malloc_search_finish: + beq $v0 $zero malloc_alloc_new_block + j malloc_finish + +malloc_alloc_new_block: + li $t1 alloc_size + move $t3 $t2 + move $a1 $a0 + move $a0 $t2 + bge $a1 $t1 malloc_big_block + li $a1 alloc_size + jal extend_heap + + j malloc_finish + +malloc_big_block: + jal extend_heap + j malloc_finish + +malloc_verify_valid_block: + lw $t1 header_size_slot($t0) + bge $t1 $a0 malloc_valid_block + j malloc_cycle + +malloc_valid_block: + beq $v0 $zero malloc_first_valid_block + bge $t1 $v1 malloc_cycle + move $v0 $t0 + move $v1 $t1 + move $t3 $t2 + j malloc_cycle + +malloc_first_valid_block: + move $v0 $t0 + move $v1 $t1 + move $t3 $t2 + j malloc_cycle + +mem_manager_init: + addiu $sp $sp -16 + sw $v0 0($sp) + sw $a0 4($sp) + sw $a1 8($sp) + sw $ra 12($sp) + li $v0 9 + li $a0 init_alloc_size + syscall + move $gp $v0 + addiu $gp $gp state_size + + sw $zero header_size_slot($gp) + sw $zero header_reachable_slot($gp) + + move $a0 $gp + li $a1 alloc_size + jal extend_heap + + addiu $a0 $a0 header_size + sw $zero header_size_slot($a0) + sw $zero header_next_slot($a0) + sw $zero header_reachable_slot($a0) + + + + lw $v0 0($sp) + lw $a0 4($sp) + lw $a1 8($sp) + lw $ra 12($sp) + addiu $sp $sp 16 + + sw $sp stack_base($gp) + + jr $ra + +get_string: + addiu $sp $sp -36 + sw $t0 0($sp) + sw $t1 4($sp) + sw $t2 8($sp) + sw $t3 12($sp) + sw $t4 16($sp) + sw $t5 20($sp) + sw $a0 24($sp) + sw $a1 28($sp) + sw $ra 32($sp) + + addiu $t0 $gp free_list + move $t1 $zero + move $t2 $t0 + +get_string_larger_block_cycle: + lw $t0 header_next_slot($t0) + beq $t0 $zero get_string_reading + lw $t3 header_size_slot($t0) + bge $t1 $t3 get_string_larger_block_cycle + move $t1 $t3 + move $t2 $t0 + j get_string_larger_block_cycle + +get_string_reading: + beq $t1 $zero get_string_new_block + move $a1 $t1 + li $v0 8 + addiu $a0 $t2 header_size + syscall + move $t0 $a0 + move $t1 $zero + +get_string_look_nl: + lb $t2 0($t0) + beq $t2 new_line get_string_nl_founded + beq $t2 $zero get_string_zero_founded + addi $t1 $t1 1 + addi $t0 $t0 1 + j get_string_look_nl + +get_string_zero_founded: + blt $t1 $t3 get_string_nl_founded + j get_string_no_nl + +get_string_nl_founded: + sb $zero 0($t0) + addi $t1 $t1 1 + li $t2 4 + div $t1 $t2 + mfhi $t3 + beq $t3 $zero get_string_nl_founded_alligned + sub $t2 $t2 $t3 + add $t1 $t1 $t2 + +get_string_nl_founded_alligned: + move $a1 $t1 + addiu $a0 $a0 neg_header_size + jal divide_block + jal use_block + + addiu $v0 $a0 header_size + j get_string_finish + +get_string_no_nl: + addi $t1 $t1 1 + blt $t1 string_size_treshold get_string_dup + addi $t1 $t1 alloc_size + j get_string_extend_heap + +get_string_dup: + sll $t1 $t1 1 + +get_string_extend_heap: + move $a1 $t1 + move $t0 $a0 + addiu $a0 $gp free_list + +get_string_last_block_cycle: + lw $t1 header_next_slot($a0) + beq $t1 $zero get_string_last_block_founded + lw $a0 header_next_slot($a0) + j get_string_last_block_cycle + +get_string_last_block_founded: + jal extend_heap + jal extend_block + lw $t1 header_next_slot($a0) + bne $t1 $zero get_string_copy_prev + move $t1 $a0 + +get_string_copy_prev: + lw $t3 header_size_slot($t1) + move $t2 $zero + move $t5 $t1 + addiu $t1 $t1 header_size + +get_string_copy_cycle: + lb $t4 0($t0) + beq $t4 $zero get_string_copy_finish + sb $t4 0($t1) + addi $t2 $t2 1 + addi $t0 $t0 1 + addi $t1 $t1 1 + j get_string_copy_cycle + +get_string_copy_finish: + sub $t3 $t3 $t2 + move $a0 $t1 + move $a1 $t3 + li $v0 8 + syscall + move $t0 $a0 + move $t1 $t2 + addiu $a0 $t5 header_size + j get_string_look_nl + +get_string_finish: + lw $t0 0($sp) + lw $t1 4($sp) + lw $t2 8($sp) + lw $t3 12($sp) + lw $t4 16($sp) + lw $t5 20($sp) + lw $a0 24($sp) + lw $a1 28($sp) + lw $ra 32($sp) + addiu $sp $sp 36 + + jr $ra + +get_string_new_block: + addiu $t0 $gp free_list + +get_string_new_block_search_last: + lw $t1 header_next_slot($t0) + beq $t1 $zero get_string_new_block_create + move $t0 $t1 + j get_string_new_block_search_last + +get_string_new_block_create: + move $a0 $t0 + li $a1 alloc_size + jal extend_heap + jal extend_block + lw $t2 header_next_slot($a0) + beq $t2 $zero get_string_new_block_extended + lw $t1 header_size_slot($t2) + j get_string_reading + +get_string_new_block_extended: + move $t2 $a0 + lw $t1 header_size_slot($a0) + j get_string_reading + +divide_block: + addiu $sp $sp -16 + sw $t0 0($sp) + sw $t1 4($sp) + sw $a0 8($sp) + sw $a1 12($sp) + + + lw $t0 header_size_slot($a0) + bgt $a1 $t0 divide_block_error_small + + + sub $t0 $t0 $a1 + li $t1 header_size + ble $t0 $t1 divide_block_same_size + + + addu $t0 $a0 $a1 + addiu $t0 $t0 header_size + + + lw $t1 header_next_slot($a0) + sw $t1 header_next_slot($t0) + sw $t0 header_next_slot($a0) + + lw $t1 header_size_slot($a0) + sub $t1 $t1 $a1 + + addi $t1 $t1 neg_header_size + sw $t1 header_size_slot($t0) + sw $a1 header_size_slot($a0) + move $v0 $a0 + j divide_block_finish + +divide_block_same_size: + move $v0 $a0 + j divide_block_finish + +divide_block_error_small: + j divide_block_finish + +divide_block_finish: + lw $t0 0($sp) + lw $t1 4($sp) + lw $a0 8($sp) + lw $a1 12($sp) + addiu $sp $sp 16 + + jr $ra + +sub_string: + addiu $sp $sp -24 + sw $t0 0($sp) + sw $t1 4($sp) + sw $t2 8($sp) + sw $t3 12($sp) + sw $a0 16($sp) + sw $ra 20($sp) + + move $t0 $a0 + li $t1 4 + addiu $t3 $a2 1 + div $t3 $t1 + + mfhi $t2 + bne $t2 $zero sub_string_allign_size + move $t1 $t3 + j sub_string_new_block + +sub_string_allign_size: + sub $t1 $t1 $t2 + add $t1 $t1 $t3 + +sub_string_new_block: + move $a0 $t1 + jal malloc + move $t3 $v0 + move $t1 $zero + addu $t0 $t0 $a1 + +sub_string_copy_cycle: + beq $t1 $a2 sub_string_finish + lb $t2 0($t0) + sb $t2 0($t3) + addiu $t0 $t0 1 + addiu $t3 $t3 1 + addiu $t1 $t1 1 + j sub_string_copy_cycle + +sub_string_finish: + sb $zero 0($t3) + lw $t0 0($sp) + lw $t1 4($sp) + lw $t2 8($sp) + lw $t3 12($sp) + lw $a0 16($sp) + lw $ra 20($sp) + addiu $sp $sp 24 + + jr $ra + +use_block: + addiu $sp $sp -12 + sw $t0 0($sp) + sw $t1 4($sp) + sw $t2 8($sp) + + addiu $t0 $gp free_list + +use_block_cycle: + move $t1 $t0 + lw $t0 header_next_slot($t0) + beq $t0 $zero use_block_finish + beq $t0 $a0 use_block_founded + j use_block_cycle + +use_block_founded: + lw $t2 header_next_slot($t0) + sw $t2 header_next_slot($t1) + + addiu $t1 $gp used_list + lw $t2 header_next_slot($t1) + sw $t0 header_next_slot($t1) + sw $t2 header_next_slot($t0) + +use_block_finish: + lw $t0 0($sp) + lw $t1 4($sp) + lw $t2 8($sp) + addiu $sp $sp 12 + + jr $ra + diff --git a/src/utils/code_generation/cil/Base_COOL_to_CIL.py b/src/utils/code_generation/cil/Base_COOL_to_CIL.py index 74a037557..5b96ca925 100644 --- a/src/utils/code_generation/cil/Base_COOL_to_CIL.py +++ b/src/utils/code_generation/cil/Base_COOL_to_CIL.py @@ -14,11 +14,11 @@ def __init__(self, context): self.context = context self.vself = VariableInfo('self', None) - + @property def params(self): return self.current_function.params - + @property def localvars(self): return self.current_function.localvars @@ -26,22 +26,22 @@ def localvars(self): @property def ids(self): return self.current_function.ids - + @property def instructions(self): return self.current_function.instructions - + def register_param(self, vinfo): param_node = nodes.ParamNode(vinfo.name) self.params.append(param_node) return vinfo.name - + def register_local(self, vinfo, id=False): if len(self.current_function.id) >= 8 and self.current_function.id[:8] == 'function': name = f'local_{self.current_function.id[9:]}_{vinfo.name}_{len(self.localvars)}' else: name = f'local_{self.current_function.id[5:]}_{vinfo.name}_{len(self.localvars)}' - + new_vinfo = VariableInfo(name, None) local_node = nodes.LocalNode(new_vinfo.name) @@ -58,7 +58,7 @@ def define_internal_local(self): def register_instruction(self, instruction): self.instructions.append(instruction) return instruction - + def to_function_name(self, method_name, type_name): return f'function_{method_name}_at_{type_name}' @@ -66,12 +66,12 @@ def init_name(self, type_name, attr=False): if attr: return f'init_attr_at_{type_name}' return f'init_at_{type_name}' - + def register_function(self, function_name): function_node = nodes.FunctionNode(function_name, [], [], []) self.dotcode.append(function_node) return function_node - + def register_type(self, name): type_node = nodes.TypeNode(name) self.dottypes.append(type_node) @@ -87,42 +87,42 @@ def register_label(self, label): lname = f'{label}_{self.current_function.labels_count}' self.current_function.labels_count += 1 return nodes.LabelNode(lname) - + def register_runtime_error(self, condition, msg): error_node = self.register_label('error_label') continue_node = self.register_label('continue_label') - self.register_instruction(nodes.IfGotoNode(condition, error_node.label)) + self.register_instruction( + nodes.IfGotoNode(condition, error_node.label)) self.register_instruction(nodes.GotoNode(continue_node.label)) self.register_instruction(error_node) data_node = self.register_data(msg) self.register_instruction(nodes.ErrorNode(data_node)) self.register_instruction(continue_node) - + def register_built_in(self): self.__register_Object() self.__register_IO() - self.__register_Int() self.__register_String() + self.__register_Int() self.__register_Bool() - - - - - # convirtiendo tipos y funciones integrados en COOL en CIL + def __register_Object(self): type_node = self.register_type('Object') - self.current_function = self.register_function(self.init_name('Object')) + self.current_function = self.register_function( + self.init_name('Object')) instance = self.define_internal_local() self.register_instruction(nodes.AllocateNode('Object', instance)) self.register_instruction(nodes.ReturnNode(instance)) - self.current_function = self.register_function(self.to_function_name('abort', 'Object')) + self.current_function = self.register_function( + self.to_function_name('abort', 'Object')) self.register_param(self.vself) vname = self.define_internal_local() - data_node = [dn for dn in self.dotdata if dn.value == 'Aborting... in class '][0] + data_node = [dn for dn in self.dotdata if dn.value == + 'Aborting... in class '][0] self.register_instruction(nodes.LoadNode(vname, data_node)) self.register_instruction(nodes.PrintStrNode(vname)) self.register_instruction(nodes.TypeNameNode(vname, self.vself.name)) @@ -132,24 +132,28 @@ def __register_Object(self): self.register_instruction(nodes.PrintStrNode(vname)) self.register_instruction(nodes.AbortNode()) - self.current_function = self.register_function(self.to_function_name('type_name', 'Object')) + self.current_function = self.register_function( + self.to_function_name('type_name', 'Object')) self.register_param(self.vself) result = self.define_internal_local() self.register_instruction(nodes.TypeNameNode(result, self.vself.name)) instance = self.define_internal_local() self.register_instruction(nodes.ArgNode(result)) - self.register_instruction(nodes.StaticCallNode(self.init_name('String'), instance)) + self.register_instruction(nodes.StaticCallNode( + self.init_name('String'), instance)) self.register_instruction(nodes.ReturnNode(instance)) - self.current_function = self.register_function(self.to_function_name('copy', 'Object')) + self.current_function = self.register_function( + self.to_function_name('copy', 'Object')) self.register_param(self.vself) result = self.define_internal_local() self.register_instruction(nodes.CopyNode(result, self.vself.name)) self.register_instruction(nodes.ReturnNode(result)) - type_node.methods = [(name, self.to_function_name(name, 'Object')) for name in ['abort', 'type_name', 'copy']] + type_node.methods = [(name, self.to_function_name(name, 'Object')) + for name in ['abort', 'type_name', 'copy']] type_node.methods += [('init', self.init_name('Object'))] - + def __register_IO(self): type_node = self.register_type('IO') @@ -158,44 +162,54 @@ def __register_IO(self): self.register_instruction(nodes.AllocateNode('IO', instance)) self.register_instruction(nodes.ReturnNode(instance)) - self.current_function = self.register_function(self.to_function_name('out_string', 'IO')) + self.current_function = self.register_function( + self.to_function_name('out_string', 'IO')) self.register_param(self.vself) self.register_param(VariableInfo('x', None)) vname = self.define_internal_local() - self.register_instruction(nodes.GetAttrNode(vname, 'x', 'value', 'String')) + self.register_instruction( + nodes.GetAttrNode(vname, 'x', 'value', 'String')) self.register_instruction(nodes.PrintStrNode(vname)) self.register_instruction(nodes.ReturnNode(self.vself.name)) - self.current_function = self.register_function(self.to_function_name('out_int', 'IO')) + self.current_function = self.register_function( + self.to_function_name('out_int', 'IO')) self.register_param(self.vself) self.register_param(VariableInfo('x', None)) vname = self.define_internal_local() - self.register_instruction(nodes.GetAttrNode(vname, 'x', 'value', 'Int')) + self.register_instruction( + nodes.GetAttrNode(vname, 'x', 'value', 'Int')) self.register_instruction(nodes.PrintIntNode(vname)) - self.register_instruction(nodes.ReturnNode(self.vself.name)) + self.register_instruction(nodes.ReturnNode(self.vself.name)) - self.current_function = self.register_function(self.to_function_name('in_string', 'IO')) + self.current_function = self.register_function( + self.to_function_name('in_string', 'IO')) self.register_param(self.vself) result = self.define_internal_local() self.register_instruction(nodes.ReadStrNode(result)) instance = self.define_internal_local() self.register_instruction(nodes.ArgNode(result)) - self.register_instruction(nodes.StaticCallNode(self.init_name('String'), instance)) + self.register_instruction(nodes.StaticCallNode( + self.init_name('String'), instance)) self.register_instruction(nodes.ReturnNode(instance)) - self.current_function = self.register_function(self.to_function_name('in_int', 'IO')) + self.current_function = self.register_function( + self.to_function_name('in_int', 'IO')) self.register_param(self.vself) result = self.define_internal_local() self.register_instruction(nodes.ReadIntNode(result)) instance = self.define_internal_local() self.register_instruction(nodes.ArgNode(result)) - self.register_instruction(nodes.StaticCallNode(self.init_name('Int'), instance)) - self.register_instruction(nodes.ReturnNode(instance)) + self.register_instruction(nodes.StaticCallNode( + self.init_name('Int'), instance)) + self.register_instruction(nodes.ReturnNode(instance)) - type_node.methods = [(method, self.to_function_name(method, 'Object')) for method in ['type_name','abort','copy']] - type_node.methods += [(name, self.to_function_name(name, 'IO')) for name in ['out_string', 'out_int', 'in_string', 'in_int']] + type_node.methods = [(method, self.to_function_name( + method, 'Object')) for method in ['type_name', 'abort', 'copy']] + type_node.methods += [(name, self.to_function_name(name, 'IO')) + for name in ['out_string', 'out_int', 'in_string', 'in_int']] type_node.methods += [('init', self.init_name('IO'))] - + def __register_Int(self): type_node = self.register_type('Int') type_node.attributes = ['value'] @@ -204,58 +218,76 @@ def __register_Int(self): self.register_param(VariableInfo('val', None)) instance = self.define_internal_local() self.register_instruction(nodes.AllocateNode('Int', instance)) - self.register_instruction(nodes.SetAttrNode(instance, 'value', 'val', 'Int')) + self.register_instruction(nodes.SetAttrNode( + instance, 'value', 'val', 'Int')) self.register_instruction(nodes.ReturnNode(instance)) - type_node.methods = [(method, self.to_function_name(method, 'Object')) for method in ['type_name','abort','copy']] + type_node.methods = [(method, self.to_function_name( + method, 'Object')) for method in ['type_name', 'abort', 'copy']] type_node.methods += [('init', self.init_name('Int'))] - + def __register_String(self): type_node = self.register_type('String') type_node.attributes = ['value', 'length'] - self.current_function = self.register_function(self.init_name('String')) + self.current_function = self.register_function( + self.init_name('String')) self.register_param(VariableInfo('val', None)) instance = self.define_internal_local() self.register_instruction(nodes.AllocateNode('String', instance)) - self.register_instruction(nodes.SetAttrNode(instance, 'value', 'val', 'String')) + self.register_instruction(nodes.SetAttrNode( + instance, 'value', 'val', 'String')) result = self.define_internal_local() self.register_instruction(nodes.LengthNode(result, 'val')) attr = self.define_internal_local() self.register_instruction(nodes.ArgNode(result)) - self.register_instruction(nodes.StaticCallNode(self.init_name('Int'), attr)) - self.register_instruction(nodes.SetAttrNode(instance, 'length', attr, 'String')) + self.register_instruction( + nodes.StaticCallNode(self.init_name('Int'), attr)) + self.register_instruction(nodes.SetAttrNode( + instance, 'length', attr, 'String')) self.register_instruction(nodes.ReturnNode(instance)) - self.current_function = self.register_function(self.to_function_name('length', 'String')) + self.current_function = self.register_function( + self.to_function_name('length', 'String')) self.register_param(self.vself) result = self.define_internal_local() - self.register_instruction(nodes.GetAttrNode(result, self.vself.name, 'length', 'String')) + self.register_instruction(nodes.GetAttrNode( + result, self.vself.name, 'length', 'String')) self.register_instruction(nodes.ReturnNode(result)) - self.current_function = self.register_function(self.to_function_name('concat', 'String')) + self.current_function = self.register_function( + self.to_function_name('concat', 'String')) self.register_param(self.vself) self.register_param(VariableInfo('s', None)) str_1 = self.define_internal_local() str_2 = self.define_internal_local() length_1 = self.define_internal_local() length_2 = self.define_internal_local() - self.register_instruction(nodes.GetAttrNode(str_1, self.vself.name, 'value', 'String')) - self.register_instruction(nodes.GetAttrNode(str_2, 's', 'value', 'String')) - self.register_instruction(nodes.GetAttrNode(length_1, self.vself.name, 'length', 'String')) - self.register_instruction(nodes.GetAttrNode(length_2, 's', 'length', 'String')) - self.register_instruction(nodes.GetAttrNode(length_1, length_1, 'value', 'Int')) - self.register_instruction(nodes.GetAttrNode(length_2, length_2, 'value', 'Int')) + self.register_instruction(nodes.GetAttrNode( + str_1, self.vself.name, 'value', 'String')) + self.register_instruction( + nodes.GetAttrNode(str_2, 's', 'value', 'String')) + self.register_instruction(nodes.GetAttrNode( + length_1, self.vself.name, 'length', 'String')) + self.register_instruction(nodes.GetAttrNode( + length_2, 's', 'length', 'String')) + self.register_instruction(nodes.GetAttrNode( + length_1, length_1, 'value', 'Int')) + self.register_instruction(nodes.GetAttrNode( + length_2, length_2, 'value', 'Int')) self.register_instruction(nodes.PlusNode(length_1, length_1, length_2)) result = self.define_internal_local() - self.register_instruction(nodes.ConcatNode(result, str_1, str_2, length_1)) + self.register_instruction( + nodes.ConcatNode(result, str_1, str_2, length_1)) instance = self.define_internal_local() self.register_instruction(nodes.ArgNode(result)) - self.register_instruction(nodes.StaticCallNode(self.init_name('String'), instance)) + self.register_instruction(nodes.StaticCallNode( + self.init_name('String'), instance)) self.register_instruction(nodes.ReturnNode(instance)) - self.current_function = self.register_function(self.to_function_name('substr', 'String')) + self.current_function = self.register_function( + self.to_function_name('substr', 'String')) self.register_param(self.vself) self.register_param(VariableInfo('i', None)) self.register_param(VariableInfo('l', None)) @@ -266,24 +298,34 @@ def __register_String(self): length_substr = self.define_internal_local() less_value = self.define_internal_local() str_value = self.define_internal_local() - self.register_instruction(nodes.GetAttrNode(str_value, self.vself.name, 'value', 'String')) - self.register_instruction(nodes.GetAttrNode(index_value, 'i', 'value', 'Int')) - self.register_instruction(nodes.GetAttrNode(length_value, 'l', 'value', 'Int')) - - self.register_instruction(nodes.GetAttrNode(length_attr, self.vself.name, 'length', 'String')) - self.register_instruction(nodes.PlusNode(length_substr, length_value, index_value)) - self.register_instruction(nodes.LessThanNode(less_value, length_attr, length_substr)) + self.register_instruction(nodes.GetAttrNode( + str_value, self.vself.name, 'value', 'String')) + self.register_instruction(nodes.GetAttrNode( + index_value, 'i', 'value', 'Int')) + self.register_instruction(nodes.GetAttrNode( + length_value, 'l', 'value', 'Int')) + + self.register_instruction(nodes.GetAttrNode( + length_attr, self.vself.name, 'length', 'String')) + self.register_instruction(nodes.PlusNode( + length_substr, length_value, index_value)) + self.register_instruction(nodes.LessThanNode( + less_value, length_attr, length_substr)) self.register_runtime_error(less_value, 'Substring out of range') - self.register_instruction(nodes.SubstringNode(result, str_value, index_value, length_value)) + self.register_instruction(nodes.SubstringNode( + result, str_value, index_value, length_value)) instance = self.define_internal_local() self.register_instruction(nodes.ArgNode(result)) - self.register_instruction(nodes.StaticCallNode(self.init_name('String'), instance)) + self.register_instruction(nodes.StaticCallNode( + self.init_name('String'), instance)) self.register_instruction(nodes.ReturnNode(instance)) - type_node.methods = [(method, self.to_function_name(method, 'Object')) for method in ['type_name','abort','copy']] - type_node.methods += [(name, self.to_function_name(name, 'String')) for name in ['length', 'concat', 'substr']] + type_node.methods = [(method, self.to_function_name( + method, 'Object')) for method in ['type_name', 'abort', 'copy']] + type_node.methods += [(name, self.to_function_name(name, 'String')) + for name in ['length', 'concat', 'substr']] type_node.methods += [('init', self.init_name('String'))] - + def __register_Bool(self): type_node = self.register_type('Bool') type_node.attributes = ['value'] @@ -292,8 +334,10 @@ def __register_Bool(self): self.register_param(VariableInfo('val', None)) instance = self.define_internal_local() self.register_instruction(nodes.AllocateNode('Bool', instance)) - self.register_instruction(nodes.SetAttrNode(instance, 'value', 'val', 'Bool')) + self.register_instruction(nodes.SetAttrNode( + instance, 'value', 'val', 'Bool')) self.register_instruction(nodes.ReturnNode(instance)) - type_node.methods = [(method, self.to_function_name(method, 'Object')) for method in ['type_name','abort','copy']] - type_node.methods += [('init', self.init_name('Bool'))] \ No newline at end of file + type_node.methods = [(method, self.to_function_name( + method, 'Object')) for method in ['type_name', 'abort', 'copy']] + type_node.methods += [('init', self.init_name('Bool'))] diff --git a/src/utils/code_generation/cil/COOL_to_CIL.py b/src/utils/code_generation/cil/COOL_to_CIL.py index 140146854..220bd2ba5 100644 --- a/src/utils/code_generation/cil/COOL_to_CIL.py +++ b/src/utils/code_generation/cil/COOL_to_CIL.py @@ -4,93 +4,101 @@ from utils.code_generation.cil.AST_CIL import cil_ast as nodes_cil from utils.code_generation.cil.Base_COOL_to_CIL import BaseCOOLToCIL + class COOLtoCIL(BaseCOOLToCIL): def __init__(self, context): BaseCOOLToCIL.__init__(self, context) - @visitor.on('node') def visit(self, node, scope): pass - @visitor.when(nodes.ProgramNode) def visit(self, node, scope=None): self.current_function = self.register_function('entry') result = self.define_internal_local() instance = self.register_local(VariableInfo('instance', None)) - self.register_instruction(nodes_cil.StaticCallNode(self.init_name('Main'), instance)) + self.register_instruction(nodes_cil.StaticCallNode( + self.init_name('Main'), instance)) self.register_instruction(nodes_cil.ArgNode(instance)) - self.register_instruction(nodes_cil.StaticCallNode(self.to_function_name('main', 'Main'), result)) + self.register_instruction(nodes_cil.StaticCallNode( + self.to_function_name('main', 'Main'), result)) self.register_instruction(nodes_cil.ReturnNode(0)) - + self.register_data('Aborting... in class ') self.register_built_in() self.current_function = None - + for declaration, child_scope in zip(node.declarations, scope.children): self.visit(declaration, child_scope) return nodes_cil.ProgramNode(self.dottypes, self.dotdata, self.dotcode) - @visitor.when(nodes.ClassDeclarationNode) def visit(self, node, scope): self.current_type = self.context.get_type(node.id) - + type_node = self.register_type(node.id) - type_node.attributes = [attr.name for attr, _ in self.current_type.all_attributes()] - type_node.methods = [(method.name, self.to_function_name(method.name, xtype.name)) for method, xtype in self.current_type.all_methods()] + type_node.attributes = [attr.name for attr, + _ in self.current_type.all_attributes()] + type_node.methods = [(method.name, self.to_function_name( + method.name, xtype.name)) for method, xtype in self.current_type.all_methods()] - func_declarations = (f for f in node.features if isinstance(f, nodes.MethDeclarationNode)) + func_declarations = (f for f in node.features if isinstance( + f, nodes.MethDeclarationNode)) for feature, child_scope in zip(func_declarations, scope.children): self.visit(feature, child_scope) self.current_function = self.register_function(self.init_name(node.id)) - + instance = self.register_local(VariableInfo('instance', None)) - self.register_instruction(nodes_cil.AllocateNode(node.id, instance)) + self.register_instruction(nodes_cil.AllocateNode(node.id, instance)) temp_f = self.current_function vtemp = self.define_internal_local() - self.current_function = self.register_function(self.init_name(node.id, attr=True)) + self.current_function = self.register_function( + self.init_name(node.id, attr=True)) self.register_param(self.vself) if node.parent != 'Object' and node.parent != 'IO': self.register_instruction(nodes_cil.ArgNode(self.vself.name)) - self.register_instruction(nodes_cil.StaticCallNode(self.init_name(node.parent, attr=True), vtemp)) - attr_declarations = (f for f in node.features if isinstance(f, nodes.AttrDeclarationNode)) + self.register_instruction(nodes_cil.StaticCallNode( + self.init_name(node.parent, attr=True), vtemp)) + attr_declarations = (f for f in node.features if isinstance( + f, nodes.AttrDeclarationNode)) for feature in attr_declarations: self.visit(feature, scope) - + self.current_function = temp_f self.register_instruction(nodes_cil.ArgNode(instance)) - self.register_instruction(nodes_cil.StaticCallNode(self.init_name(node.id, attr=True), vtemp)) + self.register_instruction(nodes_cil.StaticCallNode( + self.init_name(node.id, attr=True), vtemp)) self.register_instruction(nodes_cil.ReturnNode(instance)) self.current_function = None self.current_type = None - @visitor.when(nodes.AttrDeclarationNode) def visit(self, node, scope): if node.expr: self.visit(node.expr, scope) - self.register_instruction(nodes_cil.SetAttrNode(self.vself.name, node.id, scope._return, self.current_type)) + self.register_instruction(nodes_cil.SetAttrNode( + self.vself.name, node.id, scope._return, self.current_type)) elif node.type in ['String', 'Int', 'Bool']: vtemp = self.define_internal_local() self.register_instruction(nodes_cil.AllocateNode(node.type, vtemp)) - self.register_instruction(nodes_cil.SetAttrNode(self.vself.name, node.id, vtemp, self.current_type)) - + self.register_instruction(nodes_cil.SetAttrNode( + self.vself.name, node.id, vtemp, self.current_type)) @visitor.when(nodes.MethDeclarationNode) def visit(self, node, scope): self.current_method = self.current_type.get_method(node.id) - self.current_function = self.register_function(self.to_function_name(self.current_method.name, self.current_type.name)) - + self.current_function = self.register_function( + self.to_function_name(self.current_method.name, self.current_type.name)) + self.register_param(self.vself) for param_name, _ in node.params: self.register_param(VariableInfo(param_name, None)) - + scope._return = None self.visit(node.body, scope) @@ -100,9 +108,8 @@ def visit(self, node, scope): self.register_instruction(nodes_cil.ReturnNode(0)) else: self.register_instruction(nodes_cil.ReturnNode(scope._return)) - - self.current_method = None + self.current_method = None @visitor.when(nodes.AssignNode) def visit(self, node, scope): @@ -110,8 +117,9 @@ def visit(self, node, scope): try: self.current_type.get_attribute(node.id, None) - self.register_instruction(nodes_cil.SetAttrNode(self.vself.name, node.id, scope._return, self.current_type.name)) - + self.register_instruction(nodes_cil.SetAttrNode( + self.vself.name, node.id, scope._return, self.current_type.name)) + except SemanticError: vname = None param_names = [pn.id for pn in self.current_function.params] @@ -125,66 +133,81 @@ def visit(self, node, scope): if node.id in n.split("_"): vname = n break - self.register_instruction(nodes_cil.AssignNode(vname, scope._return)) - + self.register_instruction( + nodes_cil.AssignNode(vname, scope._return)) @visitor.when(nodes.CallNode) def visit(self, node, scope): if node.obj == None and node.type == None: args = [] for arg in node.args: - vname = self.register_local(VariableInfo(f'{node.id}_arg', None), id=True) + vname = self.register_local( + VariableInfo(f'{node.id}_arg', None), id=True) self.visit(arg, scope) - self.register_instruction(nodes_cil.AssignNode(vname, scope._return)) + self.register_instruction( + nodes_cil.AssignNode(vname, scope._return)) args.append(nodes_cil.ArgNode(vname)) - result = self.register_local(VariableInfo(f'return_value_of_{node.id}', None), id=True) + result = self.register_local(VariableInfo( + f'return_value_of_{node.id}', None), id=True) self.register_instruction(nodes_cil.ArgNode(self.vself.name)) for arg in args: self.register_instruction(arg) - - type_of_node = self.register_local(VariableInfo(f'{self.vself.name}_type', None)) - self.register_instruction(nodes_cil.TypeOfNode(self.vself.name, type_of_node)) - self.register_instruction(nodes_cil.DynamicCallNode(type_of_node, node.id, result, self.current_type.name)) + + type_of_node = self.register_local( + VariableInfo(f'{self.vself.name}_type', None)) + self.register_instruction( + nodes_cil.TypeOfNode(self.vself.name, type_of_node)) + self.register_instruction(nodes_cil.DynamicCallNode( + type_of_node, node.id, result, self.current_type.name)) scope._return = result else: args = [] for arg in node.args: - vname = self.register_local(VariableInfo(f'{node.id}_arg', None), id=True) + vname = self.register_local( + VariableInfo(f'{node.id}_arg', None), id=True) self.visit(arg, scope) - self.register_instruction(nodes_cil.AssignNode(vname, scope._return)) + self.register_instruction( + nodes_cil.AssignNode(vname, scope._return)) args.append(nodes_cil.ArgNode(vname)) - result = self.register_local(VariableInfo(f'return_value_of_{node.id}', None), id=True) - + result = self.register_local(VariableInfo( + f'return_value_of_{node.id}', None), id=True) + vobj = self.define_internal_local() self.visit(node.obj, scope) - self.register_instruction(nodes_cil.AssignNode(vobj, scope._return)) + self.register_instruction( + nodes_cil.AssignNode(vobj, scope._return)) void = nodes_cil.VoidNode() equal_result = self.define_internal_local() - self.register_instruction(nodes_cil.EqualNode(equal_result, vobj, void)) + self.register_instruction( + nodes_cil.EqualNode(equal_result, vobj, void)) + + self.register_runtime_error( + equal_result, f'({node.line},{node.column}) - RuntimeError: Dispatch on void\n') - self.register_runtime_error(equal_result, f'({node.line},{node.column}) - RuntimeError: Dispatch on void\n') - self.register_instruction(nodes_cil.ArgNode(vobj)) for arg in args: self.register_instruction(arg) if node.type: - self.register_instruction(nodes_cil.StaticCallNode(self.to_function_name(node.id, node.type), result)) + self.register_instruction(nodes_cil.StaticCallNode( + self.to_function_name(node.id, node.type), result)) else: - type_of_node = self.register_local(VariableInfo(f'{node.id}_type', None), id=True) - self.register_instruction(nodes_cil.TypeOfNode(vobj, type_of_node)) + type_of_node = self.register_local( + VariableInfo(f'{node.id}_type', None), id=True) + self.register_instruction( + nodes_cil.TypeOfNode(vobj, type_of_node)) typex = node.obj.computed_type if typex.name == 'SELF_TYPE': typex = self.current_type - self.register_instruction(nodes_cil.DynamicCallNode(type_of_node, node.id, result, typex.name)) + self.register_instruction(nodes_cil.DynamicCallNode( + type_of_node, node.id, result, typex.name)) scope._return = result - @visitor.when(nodes.IfThenElseNode) def visit(self, node, scope): vresult = self.register_local(VariableInfo('if_then_else_value', None)) @@ -195,16 +218,19 @@ def visit(self, node, scope): continue_label_node = self.register_label('continue_label') self.visit(node.if_expr, scope) - self.register_instruction(nodes_cil.GetAttrNode(vcondition, scope._return, 'value', 'Bool')) - self.register_instruction(nodes_cil.IfGotoNode(vcondition, then_label_node.label)) - + self.register_instruction(nodes_cil.GetAttrNode( + vcondition, scope._return, 'value', 'Bool')) + self.register_instruction(nodes_cil.IfGotoNode( + vcondition, then_label_node.label)) + self.register_instruction(nodes_cil.GotoNode(else_label_node.label)) - + self.register_instruction(then_label_node) self.visit(node.then_expr, scope) self.register_instruction(nodes_cil.AssignNode(vresult, scope._return)) - self.register_instruction(nodes_cil.GotoNode(continue_label_node.label)) - + self.register_instruction( + nodes_cil.GotoNode(continue_label_node.label)) + self.register_instruction(else_label_node) self.visit(node.else_expr, scope) self.register_instruction(nodes_cil.AssignNode(vresult, scope._return)) @@ -212,35 +238,34 @@ def visit(self, node, scope): self.register_instruction(continue_label_node) scope._return = vresult - @visitor.when(nodes.WhileNode) def visit(self, node, scope): vcondition = self.define_internal_local() while_label_node = self.register_label('while_label') loop_label_node = self.register_label('loop_label') pool_label_node = self.register_label('pool_label') - + self.register_instruction(while_label_node) self.visit(node.conditional_expr, scope) - self.register_instruction(nodes_cil.GetAttrNode(vcondition, scope._return, 'value', 'Bool')) - self.register_instruction(nodes_cil.IfGotoNode(vcondition, loop_label_node.label)) - + self.register_instruction(nodes_cil.GetAttrNode( + vcondition, scope._return, 'value', 'Bool')) + self.register_instruction(nodes_cil.IfGotoNode( + vcondition, loop_label_node.label)) + self.register_instruction(nodes_cil.GotoNode(pool_label_node.label)) self.register_instruction(loop_label_node) self.visit(node.loop_expr, scope) - + self.register_instruction(nodes_cil.GotoNode(while_label_node.label)) self.register_instruction(pool_label_node) scope._return = nodes_cil.VoidNode() - @visitor.when(nodes.BlockNode) def visit(self, node, scope): for expr in node.expr_list: self.visit(expr, scope) - @visitor.when(nodes.LetNode) def visit(self, node, scope): vresult = self.register_local(VariableInfo('let_in_value', None)) @@ -253,21 +278,22 @@ def visit(self, node, scope): if id_expr: self.visit(id_expr, scope) - self.register_instruction(nodes_cil.AssignNode(vname, scope._return)) - elif typex in ['String','Int','Bool']: + self.register_instruction( + nodes_cil.AssignNode(vname, scope._return)) + elif typex in ['String', 'Int', 'Bool']: self.register_instruction(nodes_cil.AllocateNode(typex, vname)) self.visit(node.in_expr, scope) self.register_instruction(nodes_cil.AssignNode(vresult, scope._return)) scope._return = vresult - @visitor.when(nodes.CaseNode) def visit(self, node, scope): - _condition = self.register_local(VariableInfo('equal_value', None)) - _type = self.register_local(VariableInfo('typeName_value', None)) - _expr = self.register_local(VariableInfo('case_expr_value', None)) - vresult = self.register_local(VariableInfo('case_value', None)) + _expr = self.register_local(VariableInfo('case_expr_value', None)) + _type = self.register_local(VariableInfo('typeName_value', None)) + _condition = self.register_local(VariableInfo('equal_value', None)) + + vresult = self.register_local(VariableInfo('case_value', None)) self.visit(node.predicate, scope) self.register_instruction(nodes_cil.AssignNode(_expr, scope._return)) @@ -275,21 +301,23 @@ def visit(self, node, scope): void = nodes_cil.VoidNode() equal_result = self.define_internal_local() - self.register_instruction(nodes_cil.EqualNode(equal_result, _expr, void)) + self.register_instruction( + nodes_cil.EqualNode(equal_result, _expr, void)) - self.register_runtime_error(equal_result, f'({node.line},{node.column}) - RuntimeError: Case on void\n') + self.register_runtime_error( + equal_result, f'({node.line},{node.column}) - RuntimeError: Case on void\n') end_label = self.register_label('end_label') labels = [] order = [] for branch in node.branches: - (_,typex,_) = branch + (_, typex, _) = branch count = 0 t1 = self.context.get_type(typex) for other_branch in node.branches: - (_,other_typex,_) = other_branch + (_, other_typex, _) = other_branch t2 = self.context.get_type(other_typex) count += t2.conforms_to(t1) @@ -297,21 +325,27 @@ def visit(self, node, scope): order.sort(key=lambda x: x[0]) for i, (_, branch) in enumerate(order): - (_,typex,_) = branch + (_, typex, _) = branch labels.append(self.register_label(f'{i}_label')) - h = {x.name for x in self.context.types.values() if x.conforms_to(self.context.get_type(typex))} if typex != 'Object' else None + h = {x.name for x in self.context.types.values() if x.conforms_to( + self.context.get_type(typex))} if typex != 'Object' else None if not h: self.register_instruction(nodes_cil.GotoNode(labels[-1].label)) break h.add(typex) for t in h: - vbranch_type_name = self.register_local(VariableInfo('branch_type_name', None)) - self.register_instruction(nodes_cil.NameNode(vbranch_type_name, t)) - self.register_instruction(nodes_cil.EqualNode(_condition, _type, vbranch_type_name)) - self.register_instruction(nodes_cil.IfGotoNode(_condition, labels[-1].label)) - - (line,column) = node.branchesPos[i] - data_node = self.register_data(f'({line},{column}) - RuntimeError: Execution of a case statement without a matching branch\n') + vbranch_type_name = self.register_local( + VariableInfo('branch_type_name', None)) + self.register_instruction( + nodes_cil.NameNode(vbranch_type_name, t)) + self.register_instruction(nodes_cil.EqualNode( + _condition, _type, vbranch_type_name)) + self.register_instruction( + nodes_cil.IfGotoNode(_condition, labels[-1].label)) + + (line, column) = node.branchesPos[i] + data_node = self.register_data( + f'({line},{column}) - RuntimeError: Execution of a case statement without a matching branch\n') self.register_instruction(nodes_cil.ErrorNode(data_node)) for i, l in enumerate(labels): @@ -322,13 +356,13 @@ def visit(self, node, scope): self.register_instruction(nodes_cil.AssignNode(vid, _expr)) self.visit(expr, scope) - self.register_instruction(nodes_cil.AssignNode(vresult, scope._return)) + self.register_instruction( + nodes_cil.AssignNode(vresult, scope._return)) self.register_instruction(nodes_cil.GotoNode(end_label.label)) scope._return = vresult self.register_instruction(end_label) - @visitor.when(nodes.NotNode) def visit(self, node, scope): vname = self.define_internal_local() @@ -336,22 +370,23 @@ def visit(self, node, scope): instance = self.define_internal_local() self.visit(node.expr, scope) - self.register_instruction(nodes_cil.GetAttrNode(value, scope._return, 'value', 'Bool')) + self.register_instruction(nodes_cil.GetAttrNode( + value, scope._return, 'value', 'Bool')) self.register_instruction(nodes_cil.MinusNode(vname, 1, value)) self.register_instruction(nodes_cil.ArgNode(vname)) - self.register_instruction(nodes_cil.StaticCallNode(self.init_name('Bool'), instance)) + self.register_instruction(nodes_cil.StaticCallNode( + self.init_name('Bool'), instance)) scope._return = instance - @visitor.when(nodes.ConstantNumNode) def visit(self, node, scope): instance = self.define_internal_local() self.register_instruction(nodes_cil.ArgNode(int(node.lex))) - self.register_instruction(nodes_cil.StaticCallNode(self.init_name('Int'), instance)) + self.register_instruction(nodes_cil.StaticCallNode( + self.init_name('Int'), instance)) scope._return = instance - @visitor.when(nodes.ConstantBoolNode) def visit(self, node, scope): if node.lex == 'true': @@ -362,10 +397,10 @@ def visit(self, node, scope): instance = self.define_internal_local() self.register_instruction(nodes_cil.ArgNode(value)) - self.register_instruction(nodes_cil.StaticCallNode(self.init_name('Bool'), instance)) + self.register_instruction(nodes_cil.StaticCallNode( + self.init_name('Bool'), instance)) scope._return = instance - @visitor.when(nodes.ConstantStringNode) def visit(self, node, scope): try: @@ -378,16 +413,17 @@ def visit(self, node, scope): self.register_instruction(nodes_cil.LoadNode(vmsg, data_node)) self.register_instruction(nodes_cil.ArgNode(vmsg)) - self.register_instruction(nodes_cil.StaticCallNode(self.init_name('String'), instance)) + self.register_instruction(nodes_cil.StaticCallNode( + self.init_name('String'), instance)) scope._return = instance - @visitor.when(nodes.VariableNode) def visit(self, node, scope): try: self.current_type.get_attribute(node.lex, None) attr = self.register_local(VariableInfo(node.lex, None), id=True) - self.register_instruction(nodes_cil.GetAttrNode(attr, self.vself.name, node.lex, self.current_type.name)) + self.register_instruction(nodes_cil.GetAttrNode( + attr, self.vself.name, node.lex, self.current_type.name)) scope._return = attr except SemanticError: @@ -400,14 +436,14 @@ def visit(self, node, scope): else: scope._return = self.ids[node.lex] - @visitor.when(nodes.InstantiateNode) def visit(self, node, scope): instance = self.define_internal_local() - + if node.lex == 'SELF_TYPE': vtype = self.define_internal_local() - self.register_instruction(nodes_cil.TypeOfNode(self.vself.name, vtype)) + self.register_instruction( + nodes_cil.TypeOfNode(self.vself.name, vtype)) self.register_instruction(nodes_cil.AllocateNode(vtype, instance)) elif node.lex == 'Int' or node.lex == 'Bool': @@ -419,10 +455,10 @@ def visit(self, node, scope): self.register_instruction(nodes_cil.LoadNode(vmsg, data_node)) self.register_instruction(nodes_cil.ArgNode(vmsg)) - self.register_instruction(nodes_cil.StaticCallNode(self.init_name(node.lex), instance)) + self.register_instruction(nodes_cil.StaticCallNode( + self.init_name(node.lex), instance)) scope._return = instance - @visitor.when(nodes.IsVoidNode) def visit(self, node, scope): void = nodes_cil.VoidNode() @@ -434,10 +470,10 @@ def visit(self, node, scope): self.register_instruction(nodes_cil.EqualNode(vresult, value, void)) self.register_instruction(nodes_cil.ArgNode(vresult)) - self.register_instruction(nodes_cil.StaticCallNode(self.init_name("Bool"), vresult)) + self.register_instruction(nodes_cil.StaticCallNode( + self.init_name("Bool"), vresult)) scope._return = vresult - @visitor.when(nodes.ComplementNode) def visit(self, node, scope): vname = self.define_internal_local() @@ -445,13 +481,14 @@ def visit(self, node, scope): instance = self.define_internal_local() self.visit(node.lex, scope) - self.register_instruction(nodes_cil.GetAttrNode(value, scope._return, 'value', 'Int')) + self.register_instruction(nodes_cil.GetAttrNode( + value, scope._return, 'value', 'Int')) self.register_instruction(nodes_cil.ComplementNode(vname, value)) self.register_instruction(nodes_cil.ArgNode(vname)) - self.register_instruction(nodes_cil.StaticCallNode(self.init_name('Int'), instance)) + self.register_instruction(nodes_cil.StaticCallNode( + self.init_name('Int'), instance)) scope._return = instance - @visitor.when(nodes.PlusNode) def visit(self, node, scope): vname = self.define_internal_local() @@ -459,17 +496,20 @@ def visit(self, node, scope): right_value = self.define_internal_local() self.visit(node.left, scope) - self.register_instruction(nodes_cil.GetAttrNode(left_value, scope._return, 'value', 'Int')) + self.register_instruction(nodes_cil.GetAttrNode( + left_value, scope._return, 'value', 'Int')) self.visit(node.right, scope) - self.register_instruction(nodes_cil.GetAttrNode(right_value, scope._return, 'value', 'Int')) + self.register_instruction(nodes_cil.GetAttrNode( + right_value, scope._return, 'value', 'Int')) - self.register_instruction(nodes_cil.PlusNode(vname, left_value, right_value)) + self.register_instruction( + nodes_cil.PlusNode(vname, left_value, right_value)) instance = self.define_internal_local() self.register_instruction(nodes_cil.ArgNode(vname)) - self.register_instruction(nodes_cil.StaticCallNode(self.init_name('Int'), instance)) + self.register_instruction(nodes_cil.StaticCallNode( + self.init_name('Int'), instance)) scope._return = instance - @visitor.when(nodes.MinusNode) def visit(self, node, scope): @@ -478,18 +518,21 @@ def visit(self, node, scope): right_value = self.define_internal_local() self.visit(node.left, scope) - self.register_instruction(nodes_cil.GetAttrNode(left_value, scope._return, 'value', 'Int')) + self.register_instruction(nodes_cil.GetAttrNode( + left_value, scope._return, 'value', 'Int')) self.visit(node.right, scope) - self.register_instruction(nodes_cil.GetAttrNode(right_value, scope._return, 'value', 'Int')) + self.register_instruction(nodes_cil.GetAttrNode( + right_value, scope._return, 'value', 'Int')) - self.register_instruction(nodes_cil.MinusNode(vname, left_value, right_value)) + self.register_instruction( + nodes_cil.MinusNode(vname, left_value, right_value)) instance = self.define_internal_local() self.register_instruction(nodes_cil.ArgNode(vname)) - self.register_instruction(nodes_cil.StaticCallNode(self.init_name('Int'), instance)) + self.register_instruction(nodes_cil.StaticCallNode( + self.init_name('Int'), instance)) scope._return = instance - @visitor.when(nodes.StarNode) def visit(self, node, scope): vname = self.define_internal_local() @@ -497,18 +540,21 @@ def visit(self, node, scope): right_value = self.define_internal_local() self.visit(node.left, scope) - self.register_instruction(nodes_cil.GetAttrNode(left_value, scope._return, 'value', 'Int')) + self.register_instruction(nodes_cil.GetAttrNode( + left_value, scope._return, 'value', 'Int')) self.visit(node.right, scope) - self.register_instruction(nodes_cil.GetAttrNode(right_value, scope._return, 'value', 'Int')) + self.register_instruction(nodes_cil.GetAttrNode( + right_value, scope._return, 'value', 'Int')) - self.register_instruction(nodes_cil.StarNode(vname, left_value, right_value)) + self.register_instruction( + nodes_cil.StarNode(vname, left_value, right_value)) instance = self.define_internal_local() self.register_instruction(nodes_cil.ArgNode(vname)) - self.register_instruction(nodes_cil.StaticCallNode(self.init_name('Int'), instance)) + self.register_instruction(nodes_cil.StaticCallNode( + self.init_name('Int'), instance)) scope._return = instance - @visitor.when(nodes.DivNode) def visit(self, node, scope): vname = self.define_internal_local() @@ -516,21 +562,25 @@ def visit(self, node, scope): right_value = self.define_internal_local() self.visit(node.left, scope) - self.register_instruction(nodes_cil.GetAttrNode(left_value, scope._return, 'value', 'Int')) + self.register_instruction(nodes_cil.GetAttrNode( + left_value, scope._return, 'value', 'Int')) self.visit(node.right, scope) - self.register_instruction(nodes_cil.GetAttrNode(right_value, scope._return, 'value', 'Int')) + self.register_instruction(nodes_cil.GetAttrNode( + right_value, scope._return, 'value', 'Int')) vresult = self.define_internal_local() self.register_instruction(nodes_cil.EqualNode(vresult, right_value, 0)) - self.register_runtime_error(vresult, f'({node.line},{node.column}) - RuntimeError: Division by zero\n') + self.register_runtime_error( + vresult, f'({node.line},{node.column}) - RuntimeError: Division by zero\n') - self.register_instruction(nodes_cil.DivNode(vname, left_value, right_value)) + self.register_instruction( + nodes_cil.DivNode(vname, left_value, right_value)) instance = self.define_internal_local() self.register_instruction(nodes_cil.ArgNode(vname)) - self.register_instruction(nodes_cil.StaticCallNode(self.init_name('Int'), instance)) + self.register_instruction(nodes_cil.StaticCallNode( + self.init_name('Int'), instance)) scope._return = instance - @visitor.when(nodes.LessThanNode) def visit(self, node, scope): @@ -545,15 +595,18 @@ def visit(self, node, scope): self.visit(node.right, scope) right = scope._return - self.register_instruction(nodes_cil.GetAttrNode(left_value, left, 'value', 'Bool')) - self.register_instruction(nodes_cil.GetAttrNode(right_value, right, 'value', 'Bool')) - self.register_instruction(nodes_cil.LessThanNode(vname, left_value, right_value)) + self.register_instruction(nodes_cil.GetAttrNode( + left_value, left, 'value', 'Bool')) + self.register_instruction(nodes_cil.GetAttrNode( + right_value, right, 'value', 'Bool')) + self.register_instruction( + nodes_cil.LessThanNode(vname, left_value, right_value)) self.register_instruction(nodes_cil.ArgNode(vname)) - self.register_instruction(nodes_cil.StaticCallNode(self.init_name('Bool'), instance)) + self.register_instruction(nodes_cil.StaticCallNode( + self.init_name('Bool'), instance)) scope._return = instance - @visitor.when(nodes.LessEqualNode) def visit(self, node, scope): vname = self.define_internal_local() @@ -567,14 +620,17 @@ def visit(self, node, scope): self.visit(node.right, scope) right = scope._return - self.register_instruction(nodes_cil.GetAttrNode(left_value, left, 'value', 'Bool')) - self.register_instruction(nodes_cil.GetAttrNode(right_value, right, 'value', 'Bool')) - self.register_instruction(nodes_cil.LessEqualNode(vname, left_value, right_value)) - + self.register_instruction(nodes_cil.GetAttrNode( + left_value, left, 'value', 'Bool')) + self.register_instruction(nodes_cil.GetAttrNode( + right_value, right, 'value', 'Bool')) + self.register_instruction( + nodes_cil.LessEqualNode(vname, left_value, right_value)) + self.register_instruction(nodes_cil.ArgNode(vname)) - self.register_instruction(nodes_cil.StaticCallNode(self.init_name('Bool'), instance)) + self.register_instruction(nodes_cil.StaticCallNode( + self.init_name('Bool'), instance)) scope._return = instance - @visitor.when(nodes.EqualNode) def visit(self, node, scope): @@ -604,24 +660,36 @@ def visit(self, node, scope): reference_node = self.register_label('reference_label') continue_node = self.register_label('continue_label') - self.register_instruction(nodes_cil.EqualNode(vresult, type_left, _int)) - self.register_instruction(nodes_cil.IfGotoNode(vresult, int_node.label)) - self.register_instruction(nodes_cil.EqualNode(vresult, type_left, _bool)) - self.register_instruction(nodes_cil.IfGotoNode(vresult, int_node.label)) - self.register_instruction(nodes_cil.EqualNode(vresult, type_left, _string)) - self.register_instruction(nodes_cil.IfGotoNode(vresult, string_node.label)) + self.register_instruction( + nodes_cil.EqualNode(vresult, type_left, _int)) + self.register_instruction( + nodes_cil.IfGotoNode(vresult, int_node.label)) + self.register_instruction( + nodes_cil.EqualNode(vresult, type_left, _bool)) + self.register_instruction( + nodes_cil.IfGotoNode(vresult, int_node.label)) + self.register_instruction( + nodes_cil.EqualNode(vresult, type_left, _string)) + self.register_instruction( + nodes_cil.IfGotoNode(vresult, string_node.label)) self.register_instruction(nodes_cil.GotoNode(reference_node.label)) self.register_instruction(int_node) - self.register_instruction(nodes_cil.GetAttrNode(left_value, left, 'value', 'Int')) - self.register_instruction(nodes_cil.GetAttrNode(right_value, right, 'value', 'Int')) - self.register_instruction(nodes_cil.EqualNode(vname, left_value, right_value)) + self.register_instruction(nodes_cil.GetAttrNode( + left_value, left, 'value', 'Int')) + self.register_instruction(nodes_cil.GetAttrNode( + right_value, right, 'value', 'Int')) + self.register_instruction( + nodes_cil.EqualNode(vname, left_value, right_value)) self.register_instruction(nodes_cil.GotoNode(continue_node.label)) self.register_instruction(string_node) - self.register_instruction(nodes_cil.GetAttrNode(left_value, left, 'value', 'String')) - self.register_instruction(nodes_cil.GetAttrNode(right_value, right, 'value', 'String')) - self.register_instruction(nodes_cil.EqualStrNode(vname, left_value, right_value)) + self.register_instruction(nodes_cil.GetAttrNode( + left_value, left, 'value', 'String')) + self.register_instruction(nodes_cil.GetAttrNode( + right_value, right, 'value', 'String')) + self.register_instruction( + nodes_cil.EqualStrNode(vname, left_value, right_value)) self.register_instruction(nodes_cil.GotoNode(continue_node.label)) self.register_instruction(reference_node) @@ -629,5 +697,6 @@ def visit(self, node, scope): self.register_instruction(continue_node) self.register_instruction(nodes_cil.ArgNode(vname)) - self.register_instruction(nodes_cil.StaticCallNode(self.init_name('Bool'), instance)) - scope._return = instance \ No newline at end of file + self.register_instruction(nodes_cil.StaticCallNode( + self.init_name('Bool'), instance)) + scope._return = instance From 1a04129e8747d9f7a2f8f5c0c3f3872930236ee5 Mon Sep 17 00:00:00 2001 From: darian10 Date: Fri, 25 Feb 2022 15:40:22 -0500 Subject: [PATCH 77/83] Change abort msg like tests --- src/main.py | 2 +- src/primes.mips | 2443 +++++++++++++++++ .../code_generation/cil/Base_COOL_to_CIL.py | 2 +- src/utils/code_generation/cil/COOL_to_CIL.py | 2 +- 4 files changed, 2446 insertions(+), 3 deletions(-) create mode 100644 src/primes.mips diff --git a/src/main.py b/src/main.py index 3b9bbd73b..b479553fe 100644 --- a/src/main.py +++ b/src/main.py @@ -16,7 +16,7 @@ if __name__ == "__main__": add = "codegen/" - _file = "cells.cl" + _file = "primes.cl" path: str = f"{Path.cwd()}/tests/{add}" if os.path.exists( f"{Path.cwd()}/tests/{add}") else f"{Path.cwd()}/../tests/{add}{_file}" diff --git a/src/primes.mips b/src/primes.mips new file mode 100644 index 000000000..e4e48967c --- /dev/null +++ b/src/primes.mips @@ -0,0 +1,2443 @@ + .data +default_str: .asciiz "" +data_1: .asciiz "Object" +data_2: .asciiz "IO" +data_3: .asciiz "String" +data_4: .asciiz "Int" +data_5: .asciiz "Bool" +data_6: .asciiz "Main" +data_7: .asciiz "Abort called from class " +data_8: .asciiz " +" +data_9: .asciiz "Substring out of range" +data_10: .asciiz "2 is trivially prime. +" +data_11: .asciiz "(55,39) - RuntimeError: Division by zero +" +data_12: .asciiz " is prime. +" +data_13: .asciiz "halt" +data_14: .asciiz "(75,11) - RuntimeError: Dispatch on void +" +data_15: .asciiz "continue" + +type_name_table: + .word data_1 + .word data_2 + .word data_3 + .word data_4 + .word data_5 + .word data_6 + +proto_table: + .word type_1_proto + .word type_2_proto + .word type_3_proto + .word type_4_proto + .word type_5_proto + .word type_6_proto + +type_1_dispatch: + .word L_2 + .word L_3 + .word L_4 + .word L_1 + +type_1_proto: + .word 0 + .word 4 + .word type_1_dispatch + .word -1 + +type_2_dispatch: + .word L_3 + .word L_2 + .word L_4 + .word L_6 + .word L_7 + .word L_8 + .word L_9 + .word L_5 + +type_2_proto: + .word 1 + .word 4 + .word type_2_dispatch + .word -1 + +type_3_dispatch: + .word L_3 + .word L_2 + .word L_4 + .word L_11 + .word L_12 + .word L_13 + .word L_10 + +type_3_proto: + .word 2 + .word 6 + .word type_3_dispatch + .word default_str + .word type_4_proto + .word -1 + +type_4_dispatch: + .word L_3 + .word L_2 + .word L_4 + .word L_14 + +type_4_proto: + .word 3 + .word 5 + .word type_4_dispatch + .word 0 + .word -1 + +type_5_dispatch: + .word L_3 + .word L_2 + .word L_4 + .word L_15 + +type_5_proto: + .word 4 + .word 5 + .word type_5_dispatch + .word 0 + .word -1 + +type_6_dispatch: + .word L_2 + .word L_3 + .word L_4 + .word L_6 + .word L_7 + .word L_8 + .word L_9 + .word L_16 + +type_6_proto: + .word 5 + .word 9 + .word type_6_dispatch + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word -1 + .text + .globl main +main: + jal mem_manager_init + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -8 + jal L_17 + move $t0 $v0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_16 + move $t0 $v0 + addi $sp, $sp, 4 + li $v0, 0 + addi $sp, $sp, 8 + lw $fp, 0($sp) + addi $sp, $sp, 4 + li $v0, 10 + syscall +L_1: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -4 + addi $sp, $sp, -4 + sw $a2, 0($sp) + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t2, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $t3, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + addi $sp, $sp, -4 + sw $t2, 0($sp) + addi $sp, $sp, -4 + sw $t3, 0($sp) + li $t2, 0 + sll $t2 $t2 2 + la $t3, proto_table + addu $t3 $t3 $t2 + lw $t3, 0($t3) + lw $a0, 4($t3) + sll $a0 $a0 2 + jal malloc + move $a2 $a0 + move $a0 $t3 + move $a1 $v0 + jal copy + lw $t3, 0($sp) + addi $sp, $sp, 4 + lw $t2, 0($sp) + addi $sp, $sp, 4 + move $t0 $v0 + move $v0 $t0 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t3, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $t2, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + lw $a2, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 4 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_2: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -4 + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + lw $t0, 0($fp) + la $t1, data_7 + 0 + li $v0, 4 + move $a0 $t1 + syscall + lw $a0, 0($t0) + sll $a0 $a0 2 + la $a1, type_name_table + addu $a0 $a0 $a1 + lw $a0, 0($a0) + move $t1 $a0 + li $v0, 4 + move $a0 $t1 + syscall + la $t1, data_8 + 0 + li $v0, 4 + move $a0 $t1 + syscall + li $v0, 10 + syscall + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 4 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_3: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -8 + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + lw $t0, 0($fp) + lw $a0, 0($t0) + sll $a0 $a0 2 + la $a1, type_name_table + addu $a0 $a0 $a1 + lw $a0, 0($a0) + move $t0 $a0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_10 + move $t0 $v0 + addi $sp, $sp, 4 + move $v0 $t0 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 8 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_4: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -4 + addi $sp, $sp, -4 + sw $a2, 0($sp) + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + lw $t0, 0($fp) + lw $a0, 4($t0) + sll $a0 $a0 2 + jal malloc + move $a2 $a0 + move $a0 $t0 + move $a1 $v0 + jal copy + move $t0 $v0 + move $v0 $t0 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + lw $a2, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 4 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_5: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -4 + addi $sp, $sp, -4 + sw $a2, 0($sp) + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t9, 0($sp) + addi $sp, $sp, -4 + sw $t5, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + addi $sp, $sp, -4 + sw $t9, 0($sp) + addi $sp, $sp, -4 + sw $t5, 0($sp) + li $t9, 1 + sll $t9 $t9 2 + la $t5, proto_table + addu $t5 $t5 $t9 + lw $t5, 0($t5) + lw $a0, 4($t5) + sll $a0 $a0 2 + jal malloc + move $a2 $a0 + move $a0 $t5 + move $a1 $v0 + jal copy + lw $t5, 0($sp) + addi $sp, $sp, 4 + lw $t9, 0($sp) + addi $sp, $sp, 4 + move $t0 $v0 + move $v0 $t0 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $t5, 0($sp) + addi $sp, $sp, 4 + lw $t9, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + lw $a2, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 4 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_6: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -4 + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + lw $t1, 0($fp) + lw $t0, 4($fp) + lw $a1, 12($t1) + move $t1 $a1 + li $v0, 4 + move $a0 $t1 + syscall + move $v0 $t0 + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 4 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_7: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -4 + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + lw $t1, 0($fp) + lw $t0, 4($fp) + lw $a1, 12($t1) + move $t1 $a1 + li $v0, 1 + move $a0 $t1 + syscall + move $v0 $t0 + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 4 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_8: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -8 + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + lw $t0, 0($fp) + jal get_string + move $t0 $v0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_10 + move $t0 $v0 + addi $sp, $sp, 4 + move $v0 $t0 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 8 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_9: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -8 + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + lw $t0, 0($fp) + li $v0, 5 + syscall + move $t0 $v0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + move $v0 $t0 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 8 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_10: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -12 + addi $sp, $sp, -4 + sw $a2, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $t5, 0($sp) + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $t3, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + lw $t1, 0($fp) + addi $sp, $sp, -4 + sw $t5, 0($sp) + addi $sp, $sp, -4 + sw $t3, 0($sp) + li $t5, 2 + sll $t5 $t5 2 + la $t3, proto_table + addu $t3 $t3 $t5 + lw $t3, 0($t3) + lw $a0, 4($t3) + sll $a0 $a0 2 + jal malloc + move $a2 $a0 + move $a0 $t3 + move $a1 $v0 + jal copy + lw $t3, 0($sp) + addi $sp, $sp, 4 + lw $t5, 0($sp) + addi $sp, $sp, 4 + move $t0 $v0 + sw $t1, 12($t0) + move $a0 $t1 + jal len + move $t1 $v0 + addi $sp, $sp, -4 + sw $t1, 0($sp) + jal L_14 + move $t1 $v0 + addi $sp, $sp, 4 + sw $t1, 16($t0) + move $v0 $t0 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t3, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + lw $t5, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $a2, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 12 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_11: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -4 + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + lw $t0, 0($fp) + lw $a1, 16($t0) + move $t0 $a1 + move $v0 $t0 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 4 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_12: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -24 + addi $sp, $sp, -4 + sw $a2, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + addi $sp, $sp, -4 + sw $t4, 0($sp) + addi $sp, $sp, -4 + sw $t2, 0($sp) + addi $sp, $sp, -4 + sw $t3, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + lw $t4, 0($fp) + lw $t0, 4($fp) + lw $a1, 12($t0) + move $t1 $a1 + lw $a1, 12($t4) + move $t3 $a1 + lw $a1, 16($t0) + move $t2 $a1 + lw $a1, 16($t4) + move $t0 $a1 + lw $a1, 12($t2) + move $t2 $a1 + lw $a1, 12($t0) + move $t0 $a1 + add $t2 $t2 $t0 + move $a0 $t1 + move $a1 $t3 + move $a2 $t2 + jal concat + move $t0 $v0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_10 + move $t0 $v0 + addi $sp, $sp, 4 + move $v0 $t0 + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t3, 0($sp) + addi $sp, $sp, 4 + lw $t2, 0($sp) + addi $sp, $sp, 4 + lw $t4, 0($sp) + addi $sp, $sp, 4 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $a2, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 24 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_13: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -32 + addi $sp, $sp, -4 + sw $a2, 0($sp) + addi $sp, $sp, -4 + sw $t4, 0($sp) + addi $sp, $sp, -4 + sw $t3, 0($sp) + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t2, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + lw $t3, 0($fp) + lw $t2, 4($fp) + lw $t1, 8($fp) + lw $a1, 12($t1) + move $t0 $a1 + lw $a1, 12($t2) + move $t4 $a1 + lw $a1, 12($t3) + move $t2 $a1 + lw $a1, 16($t1) + move $t1 $a1 + add $t3 $t2 $t4 + move $a0 $t1 + move $a1 $t3 + jal less + move $t1 $v0 + bne $t1 $zero L_19 + j L_20 + L_19: + li $v0, 4 + la $a0, data_9 + syscall + li $v0, 10 + syscall + L_20: + move $a0 $t0 + move $a1 $t4 + move $a2 $t2 + jal sub_string + move $t0 $v0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_10 + move $t0 $v0 + addi $sp, $sp, 4 + move $v0 $t0 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $t2, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + lw $t3, 0($sp) + addi $sp, $sp, 4 + lw $t4, 0($sp) + addi $sp, $sp, 4 + lw $a2, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 32 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_14: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -4 + addi $sp, $sp, -4 + sw $a2, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $t6, 0($sp) + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $t3, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + lw $t0, 0($fp) + addi $sp, $sp, -4 + sw $t6, 0($sp) + addi $sp, $sp, -4 + sw $t3, 0($sp) + li $t6, 3 + sll $t6 $t6 2 + la $t3, proto_table + addu $t3 $t3 $t6 + lw $t3, 0($t3) + lw $a0, 4($t3) + sll $a0 $a0 2 + jal malloc + move $a2 $a0 + move $a0 $t3 + move $a1 $v0 + jal copy + lw $t3, 0($sp) + addi $sp, $sp, 4 + lw $t6, 0($sp) + addi $sp, $sp, 4 + move $t1 $v0 + sw $t0, 12($t1) + move $v0 $t1 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $t3, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + lw $t6, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $a2, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 4 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_15: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -4 + addi $sp, $sp, -4 + sw $a2, 0($sp) + addi $sp, $sp, -4 + sw $t2, 0($sp) + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t3, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + lw $t0, 0($fp) + addi $sp, $sp, -4 + sw $t3, 0($sp) + addi $sp, $sp, -4 + sw $t2, 0($sp) + li $t3, 4 + sll $t3 $t3 2 + la $t2, proto_table + addu $t2 $t2 $t3 + lw $t2, 0($t2) + lw $a0, 4($t2) + sll $a0 $a0 2 + jal malloc + move $a2 $a0 + move $a0 $t2 + move $a1 $v0 + jal copy + lw $t2, 0($sp) + addi $sp, $sp, 4 + lw $t3, 0($sp) + addi $sp, $sp, 4 + move $t1 $v0 + sw $t0, 12($t1) + move $v0 $t1 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $t3, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + lw $t2, 0($sp) + addi $sp, $sp, 4 + lw $a2, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 4 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_16: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -4 + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + lw $t0, 0($fp) + li $a0, 0 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + move $v0 $t0 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 4 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_17: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -8 + addi $sp, $sp, -4 + sw $a2, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + addi $sp, $sp, -4 + sw $t1, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + li $t1, 5 + sll $t1 $t1 2 + la $t0, proto_table + addu $t0 $t0 $t1 + lw $t0, 0($t0) + lw $a0, 4($t0) + sll $a0 $a0 2 + jal malloc + move $a2 $a0 + move $a0 $t0 + move $a1 $v0 + jal copy + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + move $t1 $v0 + addi $sp, $sp, -4 + sw $t1, 0($sp) + jal L_18 + move $t0 $v0 + addi $sp, $sp, 4 + move $v0 $t1 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $t1, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $a2, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 8 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra +L_18: + addi $sp, $sp, -4 + sw $fp, 0($sp) + addi $fp, $sp, 4 + addi $sp, $sp, -440 + addi $sp, $sp, -4 + sw $a2, 0($sp) + addi $sp, $sp, -4 + sw $t5, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + addi $sp, $sp, -4 + sw $ra, 0($sp) + addi $sp, $sp, -4 + sw $t4, 0($sp) + addi $sp, $sp, -4 + sw $a1, 0($sp) + addi $sp, $sp, -4 + sw $t3, 0($sp) + addi $sp, $sp, -4 + sw $t2, 0($sp) + addi $sp, $sp, -4 + sw $a0, 0($sp) + addi $sp, $sp, -4 + sw $t7, 0($sp) + addi $sp, $sp, -4 + sw $t6, 0($sp) + lw $t2, 0($fp) + la $t0, data_10 + 0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_10 + move $t0 $v0 + addi $sp, $sp, 4 + move $t0 $t0 + addi $sp, $sp, -4 + sw $t2, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + lw $t0, 0($t2) + la $a1, proto_table + sll $a2 $t0 2 + addu $a1 $a1 $a2 + lw $a1, 0($a1) + lw $a1, 8($a1) + addiu $a1 $a1 12 + lw $a1, 0($a1) + jal $a1 + move $t0 $v0 + addi $sp, $sp, 8 + li $a0, 2 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + sw $t0, 12($t2) + lw $a1, 12($t2) + move $t0 $a1 + sw $t0, 16($t2) + addi $sp, $sp, -4 + sw $t3, 0($sp) + addi $sp, $sp, -4 + sw $t6, 0($sp) + li $t3, 3 + sll $t3 $t3 2 + la $t6, proto_table + addu $t6 $t6 $t3 + lw $t6, 0($t6) + lw $a0, 4($t6) + sll $a0 $a0 2 + jal malloc + move $a2 $a0 + move $a0 $t6 + move $a1 $v0 + jal copy + lw $t6, 0($sp) + addi $sp, $sp, 4 + lw $t3, 0($sp) + addi $sp, $sp, 4 + move $t0 $v0 + sw $t0, 20($t2) + li $a0, 500 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + sw $t0, 24($t2) + L_21: + li $a0, 1 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_15 + move $t0 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t0) + move $t0 $a1 + bne $t0 $zero L_22 + j L_46 + L_22: + lw $a1, 16($t2) + move $t0 $a1 + lw $a1, 12($t0) + move $t3 $a1 + li $a0, 1 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t0) + move $t0 $a1 + add $t0 $t3 $t0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + sw $t0, 16($t2) + li $a0, 2 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + sw $t0, 20($t2) + L_23: + lw $a1, 16($t2) + move $t4 $a1 + lw $a1, 20($t2) + move $t0 $a1 + lw $a1, 12($t0) + move $t0 $a1 + lw $a1, 20($t2) + move $t3 $a1 + lw $a1, 12($t3) + move $t3 $a1 + mul $t0 $t0 $t3 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t4) + move $t3 $a1 + lw $a1, 12($t0) + move $t0 $a1 + move $a0 $t3 + move $a1 $t0 + jal less + move $t0 $v0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_15 + move $t0 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t0) + move $t0 $a1 + bne $t0 $zero L_24 + j L_25 + L_24: + li $a0, 0 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_15 + move $t0 $v0 + addi $sp, $sp, 4 + move $t0 $t0 + j L_35 + L_25: + lw $a1, 16($t2) + move $t0 $a1 + lw $a1, 12($t0) + move $t3 $a1 + lw $a1, 20($t2) + move $t0 $a1 + lw $a1, 12($t0) + move $t4 $a1 + lw $a1, 16($t2) + move $t0 $a1 + lw $a1, 12($t0) + move $t6 $a1 + lw $a1, 20($t2) + move $t0 $a1 + lw $a1, 12($t0) + move $t0 $a1 + move $a0 $t0 + li $a1, 0 + jal eqs + move $t5 $v0 + bne $t5 $zero L_26 + j L_27 + L_26: + li $v0, 4 + la $a0, data_11 + syscall + li $v0, 10 + syscall + L_27: + div $t6 $t0 + mflo $t0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t0) + move $t0 $a1 + mul $t0 $t4 $t0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t0) + move $t0 $a1 + sub $t0 $t3 $t0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_14 + move $t3 $v0 + addi $sp, $sp, 4 + li $a0, 0 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_14 + move $t6 $v0 + addi $sp, $sp, 4 + lw $a0, 0($t3) + sll $a0 $a0 2 + la $a1, type_name_table + addu $a0 $a0 $a1 + lw $a0, 0($a0) + move $t7 $a0 + la $t0, type_name_table + addiu $t0 $t0 12 + lw $t0, 0($t0) + la $t5, type_name_table + addiu $t5 $t5 16 + lw $t5, 0($t5) + la $t4, type_name_table + addiu $t4 $t4 8 + lw $t4, 0($t4) + move $a0 $t7 + move $a1 $t0 + jal eqs + move $t0 $v0 + bne $t0 $zero L_28 + move $a0 $t7 + move $a1 $t5 + jal eqs + move $t0 $v0 + bne $t0 $zero L_28 + move $a0 $t7 + move $a1 $t4 + jal eqs + move $t0 $v0 + bne $t0 $zero L_29 + j L_30 + L_28: + lw $a1, 12($t3) + move $t0 $a1 + lw $a1, 12($t6) + move $t3 $a1 + move $a0 $t0 + move $a1 $t3 + jal eqs + move $t0 $v0 + j L_31 + L_29: + lw $a1, 12($t3) + move $t0 $a1 + lw $a1, 12($t6) + move $t3 $a1 + move $a0 $t0 + move $a1 $t3 + jal eq_string + move $t0 $v0 + j L_31 + L_30: + move $a0 $t3 + move $a1 $t6 + jal eqs + move $t0 $v0 + L_31: + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_15 + move $t0 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t0) + move $t0 $a1 + bne $t0 $zero L_32 + j L_33 + L_32: + li $a0, 0 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_15 + move $t0 $v0 + addi $sp, $sp, 4 + move $t0 $t0 + j L_34 + L_33: + li $a0, 1 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_15 + move $t0 $v0 + addi $sp, $sp, 4 + move $t0 $t0 + L_34: + move $t0 $t0 + L_35: + lw $a1, 12($t0) + move $t0 $a1 + bne $t0 $zero L_36 + j L_37 + L_36: + lw $a1, 20($t2) + move $t0 $a1 + lw $a1, 12($t0) + move $t3 $a1 + li $a0, 1 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t0) + move $t0 $a1 + add $t0 $t3 $t0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + sw $t0, 20($t2) + j L_23 + L_37: + lw $a1, 16($t2) + move $t4 $a1 + lw $a1, 20($t2) + move $t0 $a1 + lw $a1, 12($t0) + move $t3 $a1 + lw $a1, 20($t2) + move $t0 $a1 + lw $a1, 12($t0) + move $t0 $a1 + mul $t0 $t3 $t0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_14 + move $t3 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t4) + move $t0 $a1 + lw $a1, 12($t3) + move $t3 $a1 + move $a0 $t0 + move $a1 $t3 + jal less + move $t0 $v0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_15 + move $t0 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t0) + move $t0 $a1 + bne $t0 $zero L_38 + j L_39 + L_38: + lw $a1, 16($t2) + move $t0 $a1 + sw $t0, 12($t2) + lw $a1, 12($t2) + move $t0 $a1 + move $t0 $t0 + addi $sp, $sp, -4 + sw $t2, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + lw $t0, 0($t2) + la $a1, proto_table + sll $a2 $t0 2 + addu $a1 $a1 $a2 + lw $a1, 0($a1) + lw $a1, 8($a1) + addiu $a1 $a1 16 + lw $a1, 0($a1) + jal $a1 + move $t0 $v0 + addi $sp, $sp, 8 + la $t0, data_12 + 0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_10 + move $t0 $v0 + addi $sp, $sp, 4 + move $t0 $t0 + addi $sp, $sp, -4 + sw $t2, 0($sp) + addi $sp, $sp, -4 + sw $t0, 0($sp) + lw $t0, 0($t2) + la $a1, proto_table + sll $a2 $t0 2 + addu $a1 $a1 $a2 + lw $a1, 0($a1) + lw $a1, 8($a1) + addiu $a1 $a1 12 + lw $a1, 0($a1) + jal $a1 + move $t0 $v0 + addi $sp, $sp, 8 + move $t0 $t0 + j L_40 + L_39: + li $a0, 0 + addi $sp, $sp, -4 + sw $a0, 0($sp) + jal L_14 + move $t0 $v0 + addi $sp, $sp, 4 + move $t0 $t0 + L_40: + lw $a1, 24($t2) + move $t3 $a1 + lw $a1, 16($t2) + move $t0 $a1 + lw $a1, 12($t3) + move $t3 $a1 + lw $a1, 12($t0) + move $t0 $a1 + move $a0 $t3 + move $a1 $t0 + jal less_eq + move $t0 $v0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_15 + move $t0 $v0 + addi $sp, $sp, 4 + lw $a1, 12($t0) + move $t0 $a1 + bne $t0 $zero L_41 + j L_44 + L_41: + la $t0, data_13 + 0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_10 + move $t0 $v0 + addi $sp, $sp, 4 + move $t3 $t0 + move $a0 $t3 + li $a1, 0 + jal eqs + move $t0 $v0 + bne $t0 $zero L_42 + j L_43 + L_42: + li $v0, 4 + la $a0, data_14 + syscall + li $v0, 10 + syscall + L_43: + addi $sp, $sp, -4 + sw $t3, 0($sp) + lw $t0, 0($t3) + la $a1, proto_table + sll $a2 $t0 2 + addu $a1 $a1 $a2 + lw $a1, 0($a1) + lw $a1, 8($a1) + addiu $a1 $a1 4 + lw $a1, 0($a1) + jal $a1 + move $t0 $v0 + addi $sp, $sp, 4 + move $t0 $t0 + j L_45 + L_44: + la $t0, data_15 + 0 + addi $sp, $sp, -4 + sw $t0, 0($sp) + jal L_10 + move $t0 $v0 + addi $sp, $sp, 4 + move $t0 $t0 + L_45: + j L_21 + L_46: + sw $t1, 28($t2) + lw $t6, 0($sp) + addi $sp, $sp, 4 + lw $t7, 0($sp) + addi $sp, $sp, 4 + lw $a0, 0($sp) + addi $sp, $sp, 4 + lw $t2, 0($sp) + addi $sp, $sp, 4 + lw $t3, 0($sp) + addi $sp, $sp, 4 + lw $a1, 0($sp) + addi $sp, $sp, 4 + lw $t4, 0($sp) + addi $sp, $sp, 4 + lw $ra, 0($sp) + addi $sp, $sp, 4 + lw $t0, 0($sp) + addi $sp, $sp, 4 + lw $t5, 0($sp) + addi $sp, $sp, 4 + lw $a2, 0($sp) + addi $sp, $sp, 4 + addi $sp, $sp, 440 + lw $fp, 0($sp) + addi $sp, $sp, 4 + jr $ra + + + + alloc_size = 2048 + free_list = 0 + header_size = 12 + header_size_slot = 0 + header_next_slot = 4 + header_reachable_slot = 8 + init_alloc_size = 28 + int_type = 0 + meta_data_obj_size = 4 + neg_header_size = -12 + new_line = 10 + obj_mark = -1 + obj_extended = -2 + reachable = 1 + state_size = 4 + stack_base = -4 + string_size_treshold = 1024 + string_type = 0 + total_alloc_size = 2060 + num_type = 0 + used_list = header_size + +verify_obj: + addiu $sp $sp -20 + sw $t0 0($sp) + sw $t1 4($sp) + sw $t2 8($sp) + sw $t3 12($sp) + sw $a0 16($sp) + + move $t0 $a0 + + li $v0 9 + move $a0 $zero + syscall + + addiu $t1 $v0 -4 + + + blt $t0 $gp verify_obj_not_obj + bgt $t0 $t1 verify_obj_not_obj + lw $t2 0($t0) + blt $t2 $zero verify_obj_not_obj + la $t3 num_type + lw $t3 0($t3) + bge $t2 $t3 verify_obj_not_obj + + addiu $t0 $t0 4 + blt $t0 $gp verify_obj_not_obj + bgt $t0 $t1 verify_obj_not_obj + lw $t2 0($t0) + + addiu $t0 $t0 8 + + + li $t3 meta_data_obj_size + sub $t2 $t2 $t3 + sll $t2 $t2 2 + addu $t0 $t0 $t2 + + + blt $t0 $gp verify_obj_not_obj + bgt $t0 $t1 verify_obj_not_obj + lw $t2 0($t0) + beq $t2 obj_mark verify_obj_is_obj + beq $t2 obj_extended verify_obj_is_obj + +verify_obj_not_obj: + li $v0 0 + j verify_obj_finish + +verify_obj_is_obj: + li $v0 1 + +verify_obj_finish: + lw $t0 0($sp) + lw $t1 4($sp) + lw $t2 8($sp) + lw $t3 12($sp) + lw $a0 16($sp) + addiu $sp $sp 20 + + jr $ra + +concat: + addiu $sp $sp -24 + sw $t0 0($sp) + sw $t1 4($sp) + sw $t2 8($sp) + sw $a0 12($sp) + sw $a1 16($sp) + sw $ra 20($sp) + + move $t0 $a0 + move $t1 $a1 + + + addiu $a0 $a2 1 + li $t2 4 + div $a0 $t2 + mfhi $a0 + bne $a0 $zero concat_allign_size + addiu $a0 $a2 1 + +concat_size_alligned: + jal malloc + move $t2 $v0 + j concat_copy_first_cycle + +concat_allign_size: + sub $t2 $t2 $a0 + add $a0 $a2 $t2 + addiu $a0 $a0 1 + j concat_size_alligned + +concat_copy_first_cycle: + lb $a0 0($t0) + beq $a0 $zero concat_copy_second_cycle + sb $a0 0($t2) + addiu $t0 $t0 1 + addiu $t2 $t2 1 + j concat_copy_first_cycle + +concat_copy_second_cycle: + lb $a0 0($t1) + beq $a0 $zero concat_finish + sb $a0 0($t2) + addiu $t1 $t1 1 + addiu $t2 $t2 1 + j concat_copy_second_cycle + +concat_finish: + sb $zero 0($t2) + lw $t0 0($sp) + lw $t1 4($sp) + lw $t2 8($sp) + lw $a0 12($sp) + lw $a1 16($sp) + lw $ra 20($sp) + addiu $sp $sp 24 + + jr $ra + +copy: + addiu $sp $sp -16 + sw $a0 0($sp) + sw $a1 4($sp) + sw $a2 8($sp) + sw $t0 12($sp) + +copy_cycle: + beq $a2 $zero copy_finish + lw $t0 0($a0) + sw $t0 0($a1) + addiu $a0 $a0 4 + addiu $a1 $a1 4 + addi $a2 $a2 -4 + j copy_cycle + +copy_finish: + lw $a0 0($sp) + lw $a1 4($sp) + lw $a2 8($sp) + lw $t0 12($sp) + addiu $sp $sp 16 + + jr $ra + +eqs: + beq $a0 $a1 eqs_eq + li $v0 0 + j eqs_finish + +eqs_eq: + li $v0 1 + +eqs_finish: + jr $ra + +eq_string: + addiu $sp $sp -16 + sw $t0 0($sp) + sw $t1 4($sp) + sw $t2 8($sp) + sw $t3 12($sp) + + move $t0 $a0 + move $t1 $a1 + +eq_string_cycle: + lb $t2 0($t0) + lb $t3 0($t1) + bne $t2 $t3 eq_string_not_eq + beq $t2 $zero eq_string_eq + + addiu $t0 $t0 1 + addiu $t1 $t1 1 + j eq_string_cycle + +eq_string_not_eq: + move $v0 $zero + j eq_string_finish + +eq_string_eq: + li $v0 1 + +eq_string_finish: + lw $t0 0($sp) + lw $t1 4($sp) + lw $t2 8($sp) + lw $t3 12($sp) + addiu $sp $sp 16 + + jr $ra + +extend_block: + addiu $sp $sp -16 + sw $t0 0($sp) + sw $t1 4($sp) + sw $t2 8($sp) + sw $t3 12($sp) + + + addiu $t0 $gp free_list + + beq $t0 $a0 extend_block_finish + move $t0 $a0 + + lw $t1 header_next_slot($t0) + lw $t2 header_size_slot($t0) + move $t3 $t2 + addiu $t2 $t2 header_size + addu $t2 $t2 $t0 + beq $t2 $t1 extend_block_extend + j extend_block_finish + +extend_block_extend: + lw $t2 header_size_slot($t1) + addi $t2 $t2 header_size + add $t2 $t2 $t3 + sw $t2 header_size_slot($t0) + lw $t1 header_next_slot($t1) + sw $t1 header_next_slot($t0) + +extend_block_finish: + lw $t0 0($sp) + lw $t1 4($sp) + lw $t2 8($sp) + lw $t3 12($sp) + addiu $sp $sp 16 + + jr $ra + +extend_heap: + addiu $sp $sp -12 + sw $a0 0($sp) + sw $a1 4($sp) + sw $t0 8($sp) + + + li $v0 9 + addiu $a0 $a1 header_size + syscall + + + move $t0 $a1 + sw $t0 header_size_slot($v0) + sw $zero header_next_slot($v0) + sw $zero header_reachable_slot($v0) + + + lw $t0, 0($sp) + sw $v0 header_next_slot($t0) + + move $a0 $t0 + lw $a1 4($sp) + lw $t0 8($sp) + addiu $sp $sp 12 + + jr $ra + +free_block: + addiu $sp $sp -28 + sw $t0 0($sp) + sw $t1 4($sp) + sw $t2 8($sp) + sw $a0 12($sp) + sw $ra 16($sp) + sw $t3 20($sp) + sw $t4 24($sp) + + move $t0 $a0 + + addiu $t1 $gp free_list + + addiu $t3 $gp used_list + +free_block_cycle_used_list: + lw $t4 header_next_slot($t3) + beq $t4 $t0 free_block_cycle_free_list + move $t3 $t4 + j free_block_cycle_used_list + +free_block_cycle_free_list: + lw $t2 header_next_slot($t1) + beq $t2 $zero free_block_founded_prev + bge $t2 $t0 free_block_founded_prev + move $t1 $t2 + j free_block_cycle_free_list + +free_block_founded_prev: + lw $t4 header_next_slot($t0) + sw $t4 header_next_slot($t3) + + + sw $t2 header_next_slot($t0) + sw $t0 header_next_slot($t1) + +free_block_finish: + + move $a0 $t0 + jal extend_block + move $a0 $t1 + jal extend_block + + lw $t0 0($sp) + lw $t1 4($sp) + lw $t2 8($sp) + lw $a0 12($sp) + lw $ra 16($sp) + lw $t3 20($sp) + lw $t4 24($sp) + addiu $sp $sp 28 + + jr $ra + +get_gc: + addiu $sp $sp -24 + sw $t0 0($sp) + sw $t1 4($sp) + sw $t2 8($sp) + sw $t3 12($sp) + sw $a0 16($sp) + sw $ra 20($sp) + + li $t3 reachable + addiu $t0 $sp 20 + lw $t1 stack_base($gp) + + li $t2 1 + +get_gc_cycle: + + addiu $t0 $t0 4 + beq $t0 $t1 get_gc_dfs + + lw $a0 0($t0) + jal verify_obj + + bne $v0 $t2 get_gc_cycle + + addiu $a0 $a0 neg_header_size + sw $t3 header_reachable_slot($a0) + + j get_gc_cycle + +get_gc_dfs: + addiu $t1 $gp used_list + +get_gc_outer_cycle: + lw $t1 header_next_slot($t1) + beq $t1 $zero get_gc_free + lw $t2 header_reachable_slot($t1) + beq $t2 reachable get_gc_extend + j get_gc_outer_cycle + +get_gc_extend: + addiu $a0 $t1 header_size + jal get_gc_rec_extend + j get_gc_outer_cycle + +get_gc_free: + addiu $t0 $gp used_list + lw $t0 header_next_slot($t0) + +get_gc_free_cycle: + beq $t0 $zero get_gc_finish + lw $t1 header_reachable_slot($t0) + bne $t1 reachable get_gc_free_cycle_free + sw $zero header_reachable_slot($t0) + move $a0 $t0 + jal verify_obj + beq $v0 $zero get_gc_free_cycle + li $t1 obj_mark + addiu $t2 $t0 header_size + lw $t3 4($t2) + sll $t3 $t3 2 + addu $t2 $t2 $t3 + sw $t1 -4($t2) + lw $t0 header_next_slot($t0) + j get_gc_free_cycle + +get_gc_free_cycle_free: + move $a0 $t0 + lw $t0 header_next_slot($t0) + jal free_block + j get_gc_free_cycle + +get_gc_finish: + lw $t0 0($sp) + lw $t1 4($sp) + lw $t2 8($sp) + lw $t3 12($sp) + lw $a0 16($sp) + lw $ra 20($sp) + addiu $sp $sp 24 + + jr $ra + +get_gc_rec_extend: + addiu $sp $sp -16 + sw $a0 0($sp) + sw $t0 4($sp) + sw $t1 8($sp) + sw $ra 12($sp) + + jal verify_obj + beq $v0 $zero get_gc_rec_extend_finish + + lw $t0 4($a0) + sll $t0 $t0 2 + addiu $t0 $t0 -4 + addu $t0 $a0 $t0 + lw $t1 0($t0) + beq $t1 obj_extended get_gc_rec_extend_finish + + + li $t1 reachable + addiu $a0 $a0 neg_header_size + sw $t1 header_reachable_slot($a0) + addiu $a0 $a0 header_size + + + li $t1 obj_extended + sw $t1 0($t0) + + lw $t0 0($a0) + + + la $t1 int_type + lw $t1 0($t1) + beq $t0 $t1 get_gc_rec_extend_finish + + la $t1 string_type + lw $t1 0($t1) + beq $t0 $t1 get_gc_rec_extend_string_obj + + lw $t0 4($a0) + li $t1 meta_data_obj_size + sub $t0 $t0 $t1 + + addiu $t1 $a0 12 + +get_gc_rec_extend_attr_cycle: + beq $t0 $zero get_gc_rec_extend_finish + lw $a0 0($t1) + jal get_gc_rec_extend + addiu $t1 $t1 4 + sub $t0 $t0 1 + j get_gc_rec_extend_attr_cycle + +get_gc_rec_extend_string_obj: + lw $t0 8($a0) + addiu $t0 $t0 neg_header_size + li $t1 reachable + sw $t1 header_reachable_slot($t0) + +get_gc_rec_extend_finish: + lw $a0 0($sp) + lw $t0 4($sp) + lw $t1 8($sp) + lw $ra 12($sp) + addiu $sp $sp 16 + + jr $ra + +less_eq: + ble $a0 $a1 less_eq_true + li $v0 0 + j less_eq_finish + +less_eq_true: + li $v0 1 + +less_eq_finish: + jr $ra + +less: + blt $a0 $a1 less_true + li $v0 0 + j less_finish + +less_true: + li $v0 1 + +less_finish: + jr $ra + +len: + addiu $sp $sp -8 + sw $t0 0($sp) + sw $t1 4($sp) + + move $t0 $a0 + move $v0 $zero + +len_cycle: + lb $t1 0($t0) + beq $t1 $zero len_finish + addi $v0 $v0 1 + addiu $t0 $t0 1 + j len_cycle + +len_finish: + lw $t0 0($sp) + lw $t1 4($sp) + addiu $sp $sp 8 + + jr $ra + +malloc: + move $v0 $zero + addiu $sp $sp -28 + sw $t1 0($sp) + sw $t0 4($sp) + sw $a0 8($sp) + sw $a1 12($sp) + sw $ra 16($sp) + sw $t2 20($sp) + sw $t3 24($sp) + + addiu $t0 $gp free_list + j malloc_cycle + +malloc_finish: + move $a0 $v0 + lw $a1 8($sp) + jal divide_block + + lw $t1 header_next_slot($v0) + sw $t1 header_next_slot($t3) + + addiu $t1 $gp used_list + lw $a0 header_next_slot($t1) + + sw $a0 header_next_slot($v0) + sw $v0 header_next_slot($t1) + + addiu $v0 $v0 header_size + + lw $t3 24($sp) + lw $t2 20($sp) + lw $ra 16($sp) + lw $a1 12($sp) + lw $a0 8($sp) + lw $t0 4($sp) + lw $t1 0($sp) + addiu $sp $sp 28 + + jr $ra + +malloc_cycle: + move $t2 $t0 + lw $t0 header_next_slot($t0) + beq $t0 $zero malloc_search_finish + j malloc_verify_valid_block + +malloc_search_finish: + beq $v0 $zero malloc_alloc_new_block + j malloc_finish + +malloc_alloc_new_block: + li $t1 alloc_size + move $t3 $t2 + move $a1 $a0 + move $a0 $t2 + bge $a1 $t1 malloc_big_block + li $a1 alloc_size + jal extend_heap + + j malloc_finish + +malloc_big_block: + jal extend_heap + j malloc_finish + +malloc_verify_valid_block: + lw $t1 header_size_slot($t0) + bge $t1 $a0 malloc_valid_block + j malloc_cycle + +malloc_valid_block: + beq $v0 $zero malloc_first_valid_block + bge $t1 $v1 malloc_cycle + move $v0 $t0 + move $v1 $t1 + move $t3 $t2 + j malloc_cycle + +malloc_first_valid_block: + move $v0 $t0 + move $v1 $t1 + move $t3 $t2 + j malloc_cycle + +mem_manager_init: + addiu $sp $sp -16 + sw $v0 0($sp) + sw $a0 4($sp) + sw $a1 8($sp) + sw $ra 12($sp) + li $v0 9 + li $a0 init_alloc_size + syscall + move $gp $v0 + addiu $gp $gp state_size + + sw $zero header_size_slot($gp) + sw $zero header_reachable_slot($gp) + + move $a0 $gp + li $a1 alloc_size + jal extend_heap + + addiu $a0 $a0 header_size + sw $zero header_size_slot($a0) + sw $zero header_next_slot($a0) + sw $zero header_reachable_slot($a0) + + + + lw $v0 0($sp) + lw $a0 4($sp) + lw $a1 8($sp) + lw $ra 12($sp) + addiu $sp $sp 16 + + sw $sp stack_base($gp) + + jr $ra + +get_string: + addiu $sp $sp -36 + sw $t0 0($sp) + sw $t1 4($sp) + sw $t2 8($sp) + sw $t3 12($sp) + sw $t4 16($sp) + sw $t5 20($sp) + sw $a0 24($sp) + sw $a1 28($sp) + sw $ra 32($sp) + + addiu $t0 $gp free_list + move $t1 $zero + move $t2 $t0 + +get_string_larger_block_cycle: + lw $t0 header_next_slot($t0) + beq $t0 $zero get_string_reading + lw $t3 header_size_slot($t0) + bge $t1 $t3 get_string_larger_block_cycle + move $t1 $t3 + move $t2 $t0 + j get_string_larger_block_cycle + +get_string_reading: + beq $t1 $zero get_string_new_block + move $a1 $t1 + li $v0 8 + addiu $a0 $t2 header_size + syscall + move $t0 $a0 + move $t1 $zero + +get_string_look_nl: + lb $t2 0($t0) + beq $t2 new_line get_string_nl_founded + beq $t2 $zero get_string_zero_founded + addi $t1 $t1 1 + addi $t0 $t0 1 + j get_string_look_nl + +get_string_zero_founded: + blt $t1 $t3 get_string_nl_founded + j get_string_no_nl + +get_string_nl_founded: + sb $zero 0($t0) + addi $t1 $t1 1 + li $t2 4 + div $t1 $t2 + mfhi $t3 + beq $t3 $zero get_string_nl_founded_alligned + sub $t2 $t2 $t3 + add $t1 $t1 $t2 + +get_string_nl_founded_alligned: + move $a1 $t1 + addiu $a0 $a0 neg_header_size + jal divide_block + jal use_block + + addiu $v0 $a0 header_size + j get_string_finish + +get_string_no_nl: + addi $t1 $t1 1 + blt $t1 string_size_treshold get_string_dup + addi $t1 $t1 alloc_size + j get_string_extend_heap + +get_string_dup: + sll $t1 $t1 1 + +get_string_extend_heap: + move $a1 $t1 + move $t0 $a0 + addiu $a0 $gp free_list + +get_string_last_block_cycle: + lw $t1 header_next_slot($a0) + beq $t1 $zero get_string_last_block_founded + lw $a0 header_next_slot($a0) + j get_string_last_block_cycle + +get_string_last_block_founded: + jal extend_heap + jal extend_block + lw $t1 header_next_slot($a0) + bne $t1 $zero get_string_copy_prev + move $t1 $a0 + +get_string_copy_prev: + lw $t3 header_size_slot($t1) + move $t2 $zero + move $t5 $t1 + addiu $t1 $t1 header_size + +get_string_copy_cycle: + lb $t4 0($t0) + beq $t4 $zero get_string_copy_finish + sb $t4 0($t1) + addi $t2 $t2 1 + addi $t0 $t0 1 + addi $t1 $t1 1 + j get_string_copy_cycle + +get_string_copy_finish: + sub $t3 $t3 $t2 + move $a0 $t1 + move $a1 $t3 + li $v0 8 + syscall + move $t0 $a0 + move $t1 $t2 + addiu $a0 $t5 header_size + j get_string_look_nl + +get_string_finish: + lw $t0 0($sp) + lw $t1 4($sp) + lw $t2 8($sp) + lw $t3 12($sp) + lw $t4 16($sp) + lw $t5 20($sp) + lw $a0 24($sp) + lw $a1 28($sp) + lw $ra 32($sp) + addiu $sp $sp 36 + + jr $ra + +get_string_new_block: + addiu $t0 $gp free_list + +get_string_new_block_search_last: + lw $t1 header_next_slot($t0) + beq $t1 $zero get_string_new_block_create + move $t0 $t1 + j get_string_new_block_search_last + +get_string_new_block_create: + move $a0 $t0 + li $a1 alloc_size + jal extend_heap + jal extend_block + lw $t2 header_next_slot($a0) + beq $t2 $zero get_string_new_block_extended + lw $t1 header_size_slot($t2) + j get_string_reading + +get_string_new_block_extended: + move $t2 $a0 + lw $t1 header_size_slot($a0) + j get_string_reading + +divide_block: + addiu $sp $sp -16 + sw $t0 0($sp) + sw $t1 4($sp) + sw $a0 8($sp) + sw $a1 12($sp) + + + lw $t0 header_size_slot($a0) + bgt $a1 $t0 divide_block_error_small + + + sub $t0 $t0 $a1 + li $t1 header_size + ble $t0 $t1 divide_block_same_size + + + addu $t0 $a0 $a1 + addiu $t0 $t0 header_size + + + lw $t1 header_next_slot($a0) + sw $t1 header_next_slot($t0) + sw $t0 header_next_slot($a0) + + lw $t1 header_size_slot($a0) + sub $t1 $t1 $a1 + + addi $t1 $t1 neg_header_size + sw $t1 header_size_slot($t0) + sw $a1 header_size_slot($a0) + move $v0 $a0 + j divide_block_finish + +divide_block_same_size: + move $v0 $a0 + j divide_block_finish + +divide_block_error_small: + j divide_block_finish + +divide_block_finish: + lw $t0 0($sp) + lw $t1 4($sp) + lw $a0 8($sp) + lw $a1 12($sp) + addiu $sp $sp 16 + + jr $ra + +sub_string: + addiu $sp $sp -24 + sw $t0 0($sp) + sw $t1 4($sp) + sw $t2 8($sp) + sw $t3 12($sp) + sw $a0 16($sp) + sw $ra 20($sp) + + move $t0 $a0 + li $t1 4 + addiu $t3 $a2 1 + div $t3 $t1 + + mfhi $t2 + bne $t2 $zero sub_string_allign_size + move $t1 $t3 + j sub_string_new_block + +sub_string_allign_size: + sub $t1 $t1 $t2 + add $t1 $t1 $t3 + +sub_string_new_block: + move $a0 $t1 + jal malloc + move $t3 $v0 + move $t1 $zero + addu $t0 $t0 $a1 + +sub_string_copy_cycle: + beq $t1 $a2 sub_string_finish + lb $t2 0($t0) + sb $t2 0($t3) + addiu $t0 $t0 1 + addiu $t3 $t3 1 + addiu $t1 $t1 1 + j sub_string_copy_cycle + +sub_string_finish: + sb $zero 0($t3) + lw $t0 0($sp) + lw $t1 4($sp) + lw $t2 8($sp) + lw $t3 12($sp) + lw $a0 16($sp) + lw $ra 20($sp) + addiu $sp $sp 24 + + jr $ra + +use_block: + addiu $sp $sp -12 + sw $t0 0($sp) + sw $t1 4($sp) + sw $t2 8($sp) + + addiu $t0 $gp free_list + +use_block_cycle: + move $t1 $t0 + lw $t0 header_next_slot($t0) + beq $t0 $zero use_block_finish + beq $t0 $a0 use_block_founded + j use_block_cycle + +use_block_founded: + lw $t2 header_next_slot($t0) + sw $t2 header_next_slot($t1) + + addiu $t1 $gp used_list + lw $t2 header_next_slot($t1) + sw $t0 header_next_slot($t1) + sw $t2 header_next_slot($t0) + +use_block_finish: + lw $t0 0($sp) + lw $t1 4($sp) + lw $t2 8($sp) + addiu $sp $sp 12 + + jr $ra + diff --git a/src/utils/code_generation/cil/Base_COOL_to_CIL.py b/src/utils/code_generation/cil/Base_COOL_to_CIL.py index 5b96ca925..164c42ca6 100644 --- a/src/utils/code_generation/cil/Base_COOL_to_CIL.py +++ b/src/utils/code_generation/cil/Base_COOL_to_CIL.py @@ -122,7 +122,7 @@ def __register_Object(self): self.register_param(self.vself) vname = self.define_internal_local() data_node = [dn for dn in self.dotdata if dn.value == - 'Aborting... in class '][0] + 'Abort called from class '][0] self.register_instruction(nodes.LoadNode(vname, data_node)) self.register_instruction(nodes.PrintStrNode(vname)) self.register_instruction(nodes.TypeNameNode(vname, self.vself.name)) diff --git a/src/utils/code_generation/cil/COOL_to_CIL.py b/src/utils/code_generation/cil/COOL_to_CIL.py index 220bd2ba5..c62a7630f 100644 --- a/src/utils/code_generation/cil/COOL_to_CIL.py +++ b/src/utils/code_generation/cil/COOL_to_CIL.py @@ -25,7 +25,7 @@ def visit(self, node, scope=None): self.to_function_name('main', 'Main'), result)) self.register_instruction(nodes_cil.ReturnNode(0)) - self.register_data('Aborting... in class ') + self.register_data('Abort called from class ') self.register_built_in() self.current_function = None From 03cb1336f2540d394bcc8e6ce29b6d982ee857cb Mon Sep 17 00:00:00 2001 From: Alejandro Campos Matanzas <74170015+Alexx-4@users.noreply.github.com> Date: Fri, 25 Feb 2022 12:45:10 -0800 Subject: [PATCH 78/83] Update team.yml --- doc/team.yml | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/doc/team.yml b/doc/team.yml index c16162532..af017d6ba 100644 --- a/doc/team.yml +++ b/doc/team.yml @@ -1,10 +1,8 @@ members: - - name: Nombre Apellido1 Apellido2 - github: github_id - group: CXXX - - name: Nombre Apellido1 Apellido2 - github: github_id - group: CXXX - - name: Nombre Apellido1 Apellido2 - github: github_id - group: CXXX + - name: Alejandro Campos Matanzas + github: Alexx-4 + group: C-411 + + - name: Darian Dominguez Alayón + github: Darian10 + group: C-411 From 492ddec059685785a3a787828643e3390cdfa181 Mon Sep 17 00:00:00 2001 From: Alejandro Campos Matanzas <74170015+Alexx-4@users.noreply.github.com> Date: Fri, 25 Feb 2022 13:17:27 -0800 Subject: [PATCH 79/83] Delete cells.mips --- src/cells.mips | 3661 ------------------------------------------------ 1 file changed, 3661 deletions(-) delete mode 100644 src/cells.mips diff --git a/src/cells.mips b/src/cells.mips deleted file mode 100644 index bf951bd30..000000000 --- a/src/cells.mips +++ /dev/null @@ -1,3661 +0,0 @@ - .data -default_str: .asciiz "" -data_1: .asciiz "Object" -data_2: .asciiz "IO" -data_3: .asciiz "String" -data_4: .asciiz "Int" -data_5: .asciiz "Bool" -data_6: .asciiz "CellularAutomaton" -data_7: .asciiz "Main" -data_8: .asciiz "Aborting... in class " -data_9: .asciiz " -" -data_10: .asciiz "Substring out of range" -data_11: .asciiz "(17,24) - RuntimeError: Dispatch on void -" -data_12: .asciiz "(23,9) - RuntimeError: Dispatch on void -" -data_13: .asciiz "(27,9) - RuntimeError: Dispatch on void -" -data_14: .asciiz "X" -data_15: .asciiz "." -data_16: .asciiz "(67,33) - RuntimeError: Dispatch on void -" -data_17: .asciiz " X " -data_18: .asciiz "(83,27) - RuntimeError: Dispatch on void -" -data_19: .asciiz "(84,13) - RuntimeError: Dispatch on void -" -data_20: .asciiz "(88,25) - RuntimeError: Dispatch on void -" -data_21: .asciiz "(89,25) - RuntimeError: Dispatch on void -" - -type_name_table: - .word data_1 - .word data_2 - .word data_3 - .word data_4 - .word data_5 - .word data_6 - .word data_7 - -proto_table: - .word type_1_proto - .word type_2_proto - .word type_3_proto - .word type_4_proto - .word type_5_proto - .word type_6_proto - .word type_7_proto - -type_1_dispatch: - .word L_2 - .word L_3 - .word L_4 - .word L_1 - -type_1_proto: - .word 0 - .word 4 - .word type_1_dispatch - .word -1 - -type_2_dispatch: - .word L_3 - .word L_2 - .word L_4 - .word L_6 - .word L_7 - .word L_8 - .word L_9 - .word L_5 - -type_2_proto: - .word 1 - .word 4 - .word type_2_dispatch - .word -1 - -type_3_dispatch: - .word L_3 - .word L_2 - .word L_4 - .word L_11 - .word L_12 - .word L_13 - .word L_10 - -type_3_proto: - .word 2 - .word 6 - .word type_3_dispatch - .word default_str - .word type_4_proto - .word -1 - -type_4_dispatch: - .word L_3 - .word L_2 - .word L_4 - .word L_14 - -type_4_proto: - .word 3 - .word 5 - .word type_4_dispatch - .word 0 - .word -1 - -type_5_dispatch: - .word L_3 - .word L_2 - .word L_4 - .word L_15 - -type_5_proto: - .word 4 - .word 5 - .word type_5_dispatch - .word 0 - .word -1 - -type_6_dispatch: - .word L_2 - .word L_3 - .word L_4 - .word L_6 - .word L_7 - .word L_8 - .word L_9 - .word L_16 - .word L_17 - .word L_18 - .word L_19 - .word L_20 - .word L_21 - .word L_22 - .word L_23 - -type_6_proto: - .word 5 - .word 5 - .word type_6_dispatch - .word 0 - .word -1 - -type_7_dispatch: - .word L_2 - .word L_3 - .word L_4 - .word L_26 - -type_7_proto: - .word 6 - .word 5 - .word type_7_dispatch - .word 0 - .word -1 - .text - .globl main -main: - jal mem_manager_init - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -8 - jal L_27 - move $t0 $v0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_26 - move $t0 $v0 - addi $sp, $sp, 4 - li $v0, 0 - addi $sp, $sp, 8 - lw $fp, 0($sp) - addi $sp, $sp, 4 - li $v0, 10 - syscall -L_1: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -4 - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $t5, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $a2, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - addi $sp, $sp, -4 - sw $t5, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - li $t5, 0 - sll $t5 $t5 2 - la $t1, proto_table - addu $t1 $t1 $t5 - lw $t1, 0($t1) - lw $a0, 4($t1) - sll $a0 $a0 2 - jal malloc - move $a2 $a0 - move $a0 $t1 - move $a1 $v0 - jal copy - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $t5, 0($sp) - addi $sp, $sp, 4 - move $t0 $v0 - move $v0 $t0 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $a2, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t5, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 4 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_2: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -4 - addi $sp, $sp, -4 - sw $a1, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - lw $t1, 0($fp) - la $t0, data_8 + 0 - li $v0, 4 - move $a0 $t0 - syscall - lw $a0, 0($t1) - sll $a0 $a0 2 - la $a1, type_name_table - addu $a0 $a0 $a1 - lw $a0, 0($a0) - move $t0 $a0 - li $v0, 4 - move $a0 $t0 - syscall - la $t0, data_9 + 0 - li $v0, 4 - move $a0 $t0 - syscall - li $v0, 10 - syscall - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $a1, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 4 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_3: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -8 - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - lw $t0, 0($fp) - lw $a0, 0($t0) - sll $a0 $a0 2 - la $a1, type_name_table - addu $a0 $a0 $a1 - lw $a0, 0($a0) - move $t0 $a0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_10 - move $t0 $v0 - addi $sp, $sp, 4 - move $v0 $t0 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 8 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_4: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -4 - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - addi $sp, $sp, -4 - sw $a2, 0($sp) - lw $t0, 0($fp) - lw $a0, 4($t0) - sll $a0 $a0 2 - jal malloc - move $a2 $a0 - move $a0 $t0 - move $a1 $v0 - jal copy - move $t0 $v0 - move $v0 $t0 - lw $a2, 0($sp) - addi $sp, $sp, 4 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 4 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_5: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -4 - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $t5, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - addi $sp, $sp, -4 - sw $a2, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $t5, 0($sp) - li $t1, 1 - sll $t1 $t1 2 - la $t5, proto_table - addu $t5 $t5 $t1 - lw $t5, 0($t5) - lw $a0, 4($t5) - sll $a0 $a0 2 - jal malloc - move $a2 $a0 - move $a0 $t5 - move $a1 $v0 - jal copy - lw $t5, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - move $t0 $v0 - move $v0 $t0 - lw $a2, 0($sp) - addi $sp, $sp, 4 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $t5, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 4 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_6: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -4 - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - lw $t0, 0($fp) - lw $t1, 4($fp) - lw $a1, 12($t0) - move $t0 $a1 - li $v0, 4 - move $a0 $t0 - syscall - move $v0 $t1 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 4 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_7: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -4 - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - lw $t0, 0($fp) - lw $t1, 4($fp) - lw $a1, 12($t0) - move $t0 $a1 - li $v0, 1 - move $a0 $t0 - syscall - move $v0 $t1 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 4 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_8: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -8 - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $ra, 0($sp) - lw $t0, 0($fp) - jal get_string - move $t0 $v0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_10 - move $t0 $v0 - addi $sp, $sp, 4 - move $v0 $t0 - lw $ra, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 8 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_9: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -8 - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $ra, 0($sp) - lw $t0, 0($fp) - li $v0, 5 - syscall - move $t0 $v0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - move $v0 $t0 - lw $ra, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 8 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_10: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -12 - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t7, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - addi $sp, $sp, -4 - sw $a2, 0($sp) - lw $t1, 0($fp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $t7, 0($sp) - li $t1, 2 - sll $t1 $t1 2 - la $t7, proto_table - addu $t7 $t7 $t1 - lw $t7, 0($t7) - lw $a0, 4($t7) - sll $a0 $a0 2 - jal malloc - move $a2 $a0 - move $a0 $t7 - move $a1 $v0 - jal copy - lw $t7, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - move $t0 $v0 - sw $t1, 12($t0) - move $a0 $t1 - jal len - move $t1 $v0 - addi $sp, $sp, -4 - sw $t1, 0($sp) - jal L_14 - move $t1 $v0 - addi $sp, $sp, 4 - sw $t1, 16($t0) - move $v0 $t0 - lw $a2, 0($sp) - addi $sp, $sp, 4 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $t7, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 12 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_11: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -4 - addi $sp, $sp, -4 - sw $a1, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - lw $t0, 0($fp) - lw $a1, 16($t0) - move $t0 $a1 - move $v0 $t0 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $a1, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 4 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_12: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -24 - addi $sp, $sp, -4 - sw $t3, 0($sp) - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t2, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - addi $sp, $sp, -4 - sw $a2, 0($sp) - lw $t0, 0($fp) - lw $t1, 4($fp) - lw $a1, 12($t1) - move $t3 $a1 - lw $a1, 12($t0) - move $t2 $a1 - lw $a1, 16($t1) - move $t1 $a1 - lw $a1, 16($t0) - move $t0 $a1 - lw $a1, 12($t1) - move $t1 $a1 - lw $a1, 12($t0) - move $t0 $a1 - add $t1 $t1 $t0 - move $a0 $t3 - move $a1 $t2 - move $a2 $t1 - jal concat - move $t0 $v0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_10 - move $t0 $v0 - addi $sp, $sp, 4 - move $v0 $t0 - lw $a2, 0($sp) - addi $sp, $sp, 4 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $t2, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - lw $t3, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 24 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_13: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -32 - addi $sp, $sp, -4 - sw $t2, 0($sp) - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $t3, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $t4, 0($sp) - addi $sp, $sp, -4 - sw $a2, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - lw $t0, 0($fp) - lw $t2, 4($fp) - lw $t1, 8($fp) - lw $a1, 12($t1) - move $t3 $a1 - lw $a1, 12($t2) - move $t4 $a1 - lw $a1, 12($t0) - move $t2 $a1 - lw $a1, 16($t1) - move $t0 $a1 - add $t1 $t2 $t4 - move $a0 $t0 - move $a1 $t1 - jal less - move $t0 $v0 - bne $t0 $zero L_29 - j L_30 - L_29: - li $v0, 4 - la $a0, data_10 - syscall - li $v0, 10 - syscall - L_30: - move $a0 $t3 - move $a1 $t4 - move $a2 $t2 - jal sub_string - move $t0 $v0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_10 - move $t0 $v0 - addi $sp, $sp, 4 - move $v0 $t0 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $a2, 0($sp) - addi $sp, $sp, 4 - lw $t4, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t3, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - lw $t2, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 32 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_14: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -4 - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t4, 0($sp) - addi $sp, $sp, -4 - sw $t8, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - addi $sp, $sp, -4 - sw $a2, 0($sp) - lw $t1, 0($fp) - addi $sp, $sp, -4 - sw $t8, 0($sp) - addi $sp, $sp, -4 - sw $t4, 0($sp) - li $t8, 3 - sll $t8 $t8 2 - la $t4, proto_table - addu $t4 $t4 $t8 - lw $t4, 0($t4) - lw $a0, 4($t4) - sll $a0 $a0 2 - jal malloc - move $a2 $a0 - move $a0 $t4 - move $a1 $v0 - jal copy - lw $t4, 0($sp) - addi $sp, $sp, 4 - lw $t8, 0($sp) - addi $sp, $sp, 4 - move $t0 $v0 - sw $t1, 12($t0) - move $v0 $t0 - lw $a2, 0($sp) - addi $sp, $sp, 4 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $t8, 0($sp) - addi $sp, $sp, 4 - lw $t4, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 4 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_15: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -4 - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $t5, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $t3, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - addi $sp, $sp, -4 - sw $a2, 0($sp) - lw $t1, 0($fp) - addi $sp, $sp, -4 - sw $t3, 0($sp) - addi $sp, $sp, -4 - sw $t5, 0($sp) - li $t3, 4 - sll $t3 $t3 2 - la $t5, proto_table - addu $t5 $t5 $t3 - lw $t5, 0($t5) - lw $a0, 4($t5) - sll $a0 $a0 2 - jal malloc - move $a2 $a0 - move $a0 $t5 - move $a1 $v0 - jal copy - lw $t5, 0($sp) - addi $sp, $sp, 4 - lw $t3, 0($sp) - addi $sp, $sp, 4 - move $t0 $v0 - sw $t1, 12($t0) - move $v0 $t0 - lw $a2, 0($sp) - addi $sp, $sp, 4 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $t3, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t5, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 4 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_16: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, 0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - lw $t1, 0($fp) - lw $t0, 4($fp) - sw $t1, 12($t0) - move $v0 $t0 - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 0 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_17: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -44 - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t2, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $t3, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - addi $sp, $sp, -4 - sw $a2, 0($sp) - lw $t1, 0($fp) - la $t0, data_9 + 0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_10 - move $t0 $v0 - addi $sp, $sp, 4 - move $t2 $t0 - lw $a1, 12($t1) - move $t0 $a1 - move $t0 $t0 - move $a0 $t0 - li $a1, 0 - jal eqs - move $t3 $v0 - bne $t3 $zero L_31 - j L_32 - L_31: - li $v0, 4 - la $a0, data_11 - syscall - li $v0, 10 - syscall - L_32: - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $t2, 0($sp) - lw $t0, 0($t0) - la $a1, proto_table - sll $a2 $t0 2 - addu $a1 $a1 $a2 - lw $a1, 0($a1) - lw $a1, 8($a1) - addiu $a1 $a1 16 - lw $a1, 0($a1) - jal $a1 - move $t0 $v0 - addi $sp, $sp, 8 - move $t0 $t0 - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - lw $t0, 0($t1) - la $a1, proto_table - sll $a2 $t0 2 - addu $a1 $a1 $a2 - lw $a1, 0($a1) - lw $a1, 8($a1) - addiu $a1 $a1 12 - lw $a1, 0($a1) - jal $a1 - move $t0 $v0 - addi $sp, $sp, 8 - move $v0 $t1 - lw $a2, 0($sp) - addi $sp, $sp, 4 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $t3, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $t2, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 44 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_18: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -20 - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - addi $sp, $sp, -4 - sw $a2, 0($sp) - lw $t0, 0($fp) - lw $a1, 12($t0) - move $t0 $a1 - move $t1 $t0 - move $a0 $t1 - li $a1, 0 - jal eqs - move $t0 $v0 - bne $t0 $zero L_33 - j L_34 - L_33: - li $v0, 4 - la $a0, data_12 - syscall - li $v0, 10 - syscall - L_34: - addi $sp, $sp, -4 - sw $t1, 0($sp) - lw $t0, 0($t1) - la $a1, proto_table - sll $a2 $t0 2 - addu $a1 $a1 $a2 - lw $a1, 0($a1) - lw $a1, 8($a1) - addiu $a1 $a1 12 - lw $a1, 0($a1) - jal $a1 - move $t0 $v0 - addi $sp, $sp, 4 - move $v0 $t0 - lw $a2, 0($sp) - addi $sp, $sp, 4 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 20 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_19: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -32 - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $t3, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $t2, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - addi $sp, $sp, -4 - sw $a2, 0($sp) - lw $t0, 0($fp) - lw $t1, 4($fp) - move $t3 $t0 - li $a0, 1 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - move $t2 $t0 - lw $a1, 12($t1) - move $t0 $a1 - move $t0 $t0 - move $a0 $t0 - li $a1, 0 - jal eqs - move $t1 $v0 - bne $t1 $zero L_35 - j L_36 - L_35: - li $v0, 4 - la $a0, data_13 - syscall - li $v0, 10 - syscall - L_36: - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $t3, 0($sp) - addi $sp, $sp, -4 - sw $t2, 0($sp) - lw $t0, 0($t0) - la $a1, proto_table - sll $a2 $t0 2 - addu $a1 $a1 $a2 - lw $a1, 0($a1) - lw $a1, 8($a1) - addiu $a1 $a1 20 - lw $a1, 0($a1) - jal $a1 - move $t0 $v0 - addi $sp, $sp, 12 - move $v0 $t0 - lw $a2, 0($sp) - addi $sp, $sp, 4 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $t2, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t3, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 32 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_20: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -120 - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t6, 0($sp) - addi $sp, $sp, -4 - sw $t5, 0($sp) - addi $sp, $sp, -4 - sw $t2, 0($sp) - addi $sp, $sp, -4 - sw $t4, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $t3, 0($sp) - addi $sp, $sp, -4 - sw $a2, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - lw $t1, 0($fp) - lw $t4, 4($fp) - li $a0, 0 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_14 - move $t5 $v0 - addi $sp, $sp, 4 - lw $a0, 0($t1) - sll $a0 $a0 2 - la $a1, type_name_table - addu $a0 $a0 $a1 - lw $a0, 0($a0) - move $t2 $a0 - la $t0, type_name_table - addiu $t0 $t0 12 - lw $t0, 0($t0) - la $t3, type_name_table - addiu $t3 $t3 16 - lw $t3, 0($t3) - la $t6, type_name_table - addiu $t6 $t6 8 - lw $t6, 0($t6) - move $a0 $t2 - move $a1 $t0 - jal eqs - move $t0 $v0 - bne $t0 $zero L_37 - move $a0 $t2 - move $a1 $t3 - jal eqs - move $t0 $v0 - bne $t0 $zero L_37 - move $a0 $t2 - move $a1 $t6 - jal eqs - move $t0 $v0 - bne $t0 $zero L_38 - j L_39 - L_37: - lw $a1, 12($t1) - move $t0 $a1 - lw $a1, 12($t5) - move $t2 $a1 - move $a0 $t0 - move $a1 $t2 - jal eqs - move $t0 $v0 - j L_40 - L_38: - lw $a1, 12($t1) - move $t0 $a1 - lw $a1, 12($t5) - move $t2 $a1 - move $a0 $t0 - move $a1 $t2 - jal eq_string - move $t0 $v0 - j L_40 - L_39: - move $a0 $t1 - move $a1 $t5 - jal eqs - move $t0 $v0 - L_40: - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_15 - move $t0 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t0) - move $t0 $a1 - bne $t0 $zero L_41 - j L_42 - L_41: - addi $sp, $sp, -4 - sw $t4, 0($sp) - lw $t0, 0($t4) - la $a1, proto_table - sll $a2 $t0 2 - addu $a1 $a1 $a2 - lw $a1, 0($a1) - lw $a1, 8($a1) - addiu $a1 $a1 36 - lw $a1, 0($a1) - jal $a1 - move $t0 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t0) - move $t1 $a1 - li $a0, 1 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t0) - move $t0 $a1 - sub $t0 $t1 $t0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - move $t0 $t0 - addi $sp, $sp, -4 - sw $t4, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - lw $t0, 0($t4) - la $a1, proto_table - sll $a2 $t0 2 - addu $a1 $a1 $a2 - lw $a1, 0($a1) - lw $a1, 8($a1) - addiu $a1 $a1 40 - lw $a1, 0($a1) - jal $a1 - move $t0 $v0 - addi $sp, $sp, 8 - move $t0 $t0 - j L_43 - L_42: - lw $a1, 12($t1) - move $t1 $a1 - li $a0, 1 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t0) - move $t0 $a1 - sub $t0 $t1 $t0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - move $t0 $t0 - addi $sp, $sp, -4 - sw $t4, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - lw $t0, 0($t4) - la $a1, proto_table - sll $a2 $t0 2 - addu $a1 $a1 $a2 - lw $a1, 0($a1) - lw $a1, 8($a1) - addiu $a1 $a1 40 - lw $a1, 0($a1) - jal $a1 - move $t0 $v0 - addi $sp, $sp, 8 - move $t0 $t0 - L_43: - move $v0 $t0 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $a2, 0($sp) - addi $sp, $sp, 4 - lw $t3, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t4, 0($sp) - addi $sp, $sp, 4 - lw $t2, 0($sp) - addi $sp, $sp, 4 - lw $t5, 0($sp) - addi $sp, $sp, 4 - lw $t6, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 120 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_21: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -120 - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t6, 0($sp) - addi $sp, $sp, -4 - sw $t5, 0($sp) - addi $sp, $sp, -4 - sw $t2, 0($sp) - addi $sp, $sp, -4 - sw $t4, 0($sp) - addi $sp, $sp, -4 - sw $t3, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $a2, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - lw $t0, 0($fp) - lw $t3, 4($fp) - addi $sp, $sp, -4 - sw $t3, 0($sp) - lw $t1, 0($t3) - la $a1, proto_table - sll $a2 $t1 2 - addu $a1 $a1 $a2 - lw $a1, 0($a1) - lw $a1, 8($a1) - addiu $a1 $a1 36 - lw $a1, 0($a1) - jal $a1 - move $t1 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t1) - move $t1 $a1 - li $a0, 1 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_14 - move $t2 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t2) - move $t2 $a1 - sub $t1 $t1 $t2 - addi $sp, $sp, -4 - sw $t1, 0($sp) - jal L_14 - move $t5 $v0 - addi $sp, $sp, 4 - lw $a0, 0($t0) - sll $a0 $a0 2 - la $a1, type_name_table - addu $a0 $a0 $a1 - lw $a0, 0($a0) - move $t2 $a0 - la $t4, type_name_table - addiu $t4 $t4 12 - lw $t4, 0($t4) - la $t6, type_name_table - addiu $t6 $t6 16 - lw $t6, 0($t6) - la $t1, type_name_table - addiu $t1 $t1 8 - lw $t1, 0($t1) - move $a0 $t2 - move $a1 $t4 - jal eqs - move $t4 $v0 - bne $t4 $zero L_44 - move $a0 $t2 - move $a1 $t6 - jal eqs - move $t4 $v0 - bne $t4 $zero L_44 - move $a0 $t2 - move $a1 $t1 - jal eqs - move $t4 $v0 - bne $t4 $zero L_45 - j L_46 - L_44: - lw $a1, 12($t0) - move $t1 $a1 - lw $a1, 12($t5) - move $t2 $a1 - move $a0 $t1 - move $a1 $t2 - jal eqs - move $t1 $v0 - j L_47 - L_45: - lw $a1, 12($t0) - move $t1 $a1 - lw $a1, 12($t5) - move $t2 $a1 - move $a0 $t1 - move $a1 $t2 - jal eq_string - move $t1 $v0 - j L_47 - L_46: - move $a0 $t0 - move $a1 $t5 - jal eqs - move $t1 $v0 - L_47: - addi $sp, $sp, -4 - sw $t1, 0($sp) - jal L_15 - move $t1 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t1) - move $t1 $a1 - bne $t1 $zero L_48 - j L_49 - L_48: - li $a0, 0 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - move $t0 $t0 - addi $sp, $sp, -4 - sw $t3, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - lw $t0, 0($t3) - la $a1, proto_table - sll $a2 $t0 2 - addu $a1 $a1 $a2 - lw $a1, 0($a1) - lw $a1, 8($a1) - addiu $a1 $a1 40 - lw $a1, 0($a1) - jal $a1 - move $t0 $v0 - addi $sp, $sp, 8 - move $t0 $t0 - j L_50 - L_49: - lw $a1, 12($t0) - move $t1 $a1 - li $a0, 1 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t0) - move $t0 $a1 - add $t0 $t1 $t0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - move $t0 $t0 - addi $sp, $sp, -4 - sw $t3, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - lw $t0, 0($t3) - la $a1, proto_table - sll $a2 $t0 2 - addu $a1 $a1 $a2 - lw $a1, 0($a1) - lw $a1, 8($a1) - addiu $a1 $a1 40 - lw $a1, 0($a1) - jal $a1 - move $t0 $v0 - addi $sp, $sp, 8 - move $t0 $t0 - L_50: - move $v0 $t0 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $a2, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t3, 0($sp) - addi $sp, $sp, 4 - lw $t4, 0($sp) - addi $sp, $sp, 4 - lw $t2, 0($sp) - addi $sp, $sp, 4 - lw $t5, 0($sp) - addi $sp, $sp, 4 - lw $t6, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 120 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_22: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -312 - addi $sp, $sp, -4 - sw $t4, 0($sp) - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $t3, 0($sp) - addi $sp, $sp, -4 - sw $t7, 0($sp) - addi $sp, $sp, -4 - sw $t5, 0($sp) - addi $sp, $sp, -4 - sw $a2, 0($sp) - addi $sp, $sp, -4 - sw $t2, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $t6, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $t8, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - lw $t3, 0($fp) - lw $t2, 4($fp) - move $t0 $t3 - addi $sp, $sp, -4 - sw $t2, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - lw $t0, 0($t2) - la $a1, proto_table - sll $a2 $t0 2 - addu $a1 $a1 $a2 - lw $a1, 0($a1) - lw $a1, 8($a1) - addiu $a1 $a1 40 - lw $a1, 0($a1) - jal $a1 - move $t7 $v0 - addi $sp, $sp, 8 - la $t0, data_14 + 0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_10 - move $t1 $v0 - addi $sp, $sp, 4 - lw $a0, 0($t7) - sll $a0 $a0 2 - la $a1, type_name_table - addu $a0 $a0 $a1 - lw $a0, 0($a0) - move $t0 $a0 - la $t5, type_name_table - addiu $t5 $t5 12 - lw $t5, 0($t5) - la $t6, type_name_table - addiu $t6 $t6 16 - lw $t6, 0($t6) - la $t4, type_name_table - addiu $t4 $t4 8 - lw $t4, 0($t4) - move $a0 $t0 - move $a1 $t5 - jal eqs - move $t5 $v0 - bne $t5 $zero L_51 - move $a0 $t0 - move $a1 $t6 - jal eqs - move $t5 $v0 - bne $t5 $zero L_51 - move $a0 $t0 - move $a1 $t4 - jal eqs - move $t5 $v0 - bne $t5 $zero L_52 - j L_53 - L_51: - lw $a1, 12($t7) - move $t4 $a1 - lw $a1, 12($t1) - move $t0 $a1 - move $a0 $t4 - move $a1 $t0 - jal eqs - move $t0 $v0 - j L_54 - L_52: - lw $a1, 12($t7) - move $t4 $a1 - lw $a1, 12($t1) - move $t0 $a1 - move $a0 $t4 - move $a1 $t0 - jal eq_string - move $t0 $v0 - j L_54 - L_53: - move $a0 $t7 - move $a1 $t1 - jal eqs - move $t0 $v0 - L_54: - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_15 - move $t0 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t0) - move $t0 $a1 - bne $t0 $zero L_55 - j L_56 - L_55: - li $a0, 1 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - move $t0 $t0 - j L_57 - L_56: - li $a0, 0 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - move $t0 $t0 - L_57: - lw $a1, 12($t0) - move $t1 $a1 - move $t0 $t3 - addi $sp, $sp, -4 - sw $t2, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - lw $t0, 0($t2) - la $a1, proto_table - sll $a2 $t0 2 - addu $a1 $a1 $a2 - lw $a1, 0($a1) - lw $a1, 8($a1) - addiu $a1 $a1 44 - lw $a1, 0($a1) - jal $a1 - move $t5 $v0 - addi $sp, $sp, 8 - la $t0, data_14 + 0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_10 - move $t7 $v0 - addi $sp, $sp, 4 - lw $a0, 0($t5) - sll $a0 $a0 2 - la $a1, type_name_table - addu $a0 $a0 $a1 - lw $a0, 0($a0) - move $t8 $a0 - la $t6, type_name_table - addiu $t6 $t6 12 - lw $t6, 0($t6) - la $t4, type_name_table - addiu $t4 $t4 16 - lw $t4, 0($t4) - la $t0, type_name_table - addiu $t0 $t0 8 - lw $t0, 0($t0) - move $a0 $t8 - move $a1 $t6 - jal eqs - move $t6 $v0 - bne $t6 $zero L_58 - move $a0 $t8 - move $a1 $t4 - jal eqs - move $t6 $v0 - bne $t6 $zero L_58 - move $a0 $t8 - move $a1 $t0 - jal eqs - move $t6 $v0 - bne $t6 $zero L_59 - j L_60 - L_58: - lw $a1, 12($t5) - move $t0 $a1 - lw $a1, 12($t7) - move $t4 $a1 - move $a0 $t0 - move $a1 $t4 - jal eqs - move $t0 $v0 - j L_61 - L_59: - lw $a1, 12($t5) - move $t0 $a1 - lw $a1, 12($t7) - move $t4 $a1 - move $a0 $t0 - move $a1 $t4 - jal eq_string - move $t0 $v0 - j L_61 - L_60: - move $a0 $t5 - move $a1 $t7 - jal eqs - move $t0 $v0 - L_61: - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_15 - move $t0 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t0) - move $t0 $a1 - bne $t0 $zero L_62 - j L_63 - L_62: - li $a0, 1 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - move $t0 $t0 - j L_64 - L_63: - li $a0, 0 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - move $t0 $t0 - L_64: - lw $a1, 12($t0) - move $t0 $a1 - add $t0 $t1 $t0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t0) - move $t1 $a1 - move $t0 $t3 - addi $sp, $sp, -4 - sw $t2, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - lw $t0, 0($t2) - la $a1, proto_table - sll $a2 $t0 2 - addu $a1 $a1 $a2 - lw $a1, 0($a1) - lw $a1, 8($a1) - addiu $a1 $a1 48 - lw $a1, 0($a1) - jal $a1 - move $t6 $v0 - addi $sp, $sp, 8 - la $t0, data_14 + 0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_10 - move $t3 $v0 - addi $sp, $sp, 4 - lw $a0, 0($t6) - sll $a0 $a0 2 - la $a1, type_name_table - addu $a0 $a0 $a1 - lw $a0, 0($a0) - move $t5 $a0 - la $t0, type_name_table - addiu $t0 $t0 12 - lw $t0, 0($t0) - la $t4, type_name_table - addiu $t4 $t4 16 - lw $t4, 0($t4) - la $t2, type_name_table - addiu $t2 $t2 8 - lw $t2, 0($t2) - move $a0 $t5 - move $a1 $t0 - jal eqs - move $t0 $v0 - bne $t0 $zero L_65 - move $a0 $t5 - move $a1 $t4 - jal eqs - move $t0 $v0 - bne $t0 $zero L_65 - move $a0 $t5 - move $a1 $t2 - jal eqs - move $t0 $v0 - bne $t0 $zero L_66 - j L_67 - L_65: - lw $a1, 12($t6) - move $t2 $a1 - lw $a1, 12($t3) - move $t0 $a1 - move $a0 $t2 - move $a1 $t0 - jal eqs - move $t0 $v0 - j L_68 - L_66: - lw $a1, 12($t6) - move $t2 $a1 - lw $a1, 12($t3) - move $t0 $a1 - move $a0 $t2 - move $a1 $t0 - jal eq_string - move $t0 $v0 - j L_68 - L_67: - move $a0 $t6 - move $a1 $t3 - jal eqs - move $t0 $v0 - L_68: - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_15 - move $t0 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t0) - move $t0 $a1 - bne $t0 $zero L_69 - j L_70 - L_69: - li $a0, 1 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - move $t0 $t0 - j L_71 - L_70: - li $a0, 0 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - move $t0 $t0 - L_71: - lw $a1, 12($t0) - move $t0 $a1 - add $t0 $t1 $t0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_14 - move $t3 $v0 - addi $sp, $sp, 4 - li $a0, 1 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_14 - move $t1 $v0 - addi $sp, $sp, 4 - lw $a0, 0($t3) - sll $a0 $a0 2 - la $a1, type_name_table - addu $a0 $a0 $a1 - lw $a0, 0($a0) - move $t0 $a0 - la $t4, type_name_table - addiu $t4 $t4 12 - lw $t4, 0($t4) - la $t2, type_name_table - addiu $t2 $t2 16 - lw $t2, 0($t2) - la $t5, type_name_table - addiu $t5 $t5 8 - lw $t5, 0($t5) - move $a0 $t0 - move $a1 $t4 - jal eqs - move $t4 $v0 - bne $t4 $zero L_72 - move $a0 $t0 - move $a1 $t2 - jal eqs - move $t4 $v0 - bne $t4 $zero L_72 - move $a0 $t0 - move $a1 $t5 - jal eqs - move $t4 $v0 - bne $t4 $zero L_73 - j L_74 - L_72: - lw $a1, 12($t3) - move $t0 $a1 - lw $a1, 12($t1) - move $t1 $a1 - move $a0 $t0 - move $a1 $t1 - jal eqs - move $t0 $v0 - j L_75 - L_73: - lw $a1, 12($t3) - move $t0 $a1 - lw $a1, 12($t1) - move $t1 $a1 - move $a0 $t0 - move $a1 $t1 - jal eq_string - move $t0 $v0 - j L_75 - L_74: - move $a0 $t3 - move $a1 $t1 - jal eqs - move $t0 $v0 - L_75: - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_15 - move $t0 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t0) - move $t0 $a1 - bne $t0 $zero L_76 - j L_77 - L_76: - la $t0, data_14 + 0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_10 - move $t0 $v0 - addi $sp, $sp, 4 - move $t0 $t0 - j L_78 - L_77: - la $t0, data_15 + 0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_10 - move $t0 $v0 - addi $sp, $sp, 4 - move $t0 $t0 - L_78: - move $v0 $t0 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $t8, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $t6, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t2, 0($sp) - addi $sp, $sp, 4 - lw $a2, 0($sp) - addi $sp, $sp, 4 - lw $t5, 0($sp) - addi $sp, $sp, 4 - lw $t7, 0($sp) - addi $sp, $sp, 4 - lw $t3, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - lw $t4, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 312 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_23: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -104 - addi $sp, $sp, -4 - sw $t9, 0($sp) - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t5, 0($sp) - addi $sp, $sp, -4 - sw $t7, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $t6, 0($sp) - addi $sp, $sp, -4 - sw $a2, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $t2, 0($sp) - addi $sp, $sp, -4 - sw $t3, 0($sp) - addi $sp, $sp, -4 - sw $t4, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - lw $t5, 0($fp) - addi $sp, $sp, -4 - sw $t7, 0($sp) - addi $sp, $sp, -4 - sw $t6, 0($sp) - li $t7, 3 - sll $t7 $t7 2 - la $t6, proto_table - addu $t6 $t6 $t7 - lw $t6, 0($t6) - lw $a0, 4($t6) - sll $a0 $a0 2 - jal malloc - move $a2 $a0 - move $a0 $t6 - move $a1 $v0 - jal copy - lw $t6, 0($sp) - addi $sp, $sp, 4 - lw $t7, 0($sp) - addi $sp, $sp, 4 - move $t4 $v0 - addi $sp, $sp, -4 - sw $t5, 0($sp) - lw $t0, 0($t5) - la $a1, proto_table - sll $a2 $t0 2 - addu $a1 $a1 $a2 - lw $a1, 0($a1) - lw $a1, 8($a1) - addiu $a1 $a1 36 - lw $a1, 0($a1) - jal $a1 - move $t0 $v0 - addi $sp, $sp, 4 - move $t2 $t0 - addi $sp, $sp, -4 - sw $t9, 0($sp) - addi $sp, $sp, -4 - sw $t4, 0($sp) - li $t9, 2 - sll $t9 $t9 2 - la $t4, proto_table - addu $t4 $t4 $t9 - lw $t4, 0($t4) - lw $a0, 4($t4) - sll $a0 $a0 2 - jal malloc - move $a2 $a0 - move $a0 $t4 - move $a1 $v0 - jal copy - lw $t4, 0($sp) - addi $sp, $sp, 4 - lw $t9, 0($sp) - addi $sp, $sp, 4 - move $t3 $v0 - L_79: - lw $a1, 12($t4) - move $t0 $a1 - lw $a1, 12($t2) - move $t1 $a1 - move $a0 $t0 - move $a1 $t1 - jal less - move $t0 $v0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_15 - move $t0 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t0) - move $t0 $a1 - bne $t0 $zero L_80 - j L_83 - L_80: - move $t0 $t4 - addi $sp, $sp, -4 - sw $t5, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - lw $t0, 0($t5) - la $a1, proto_table - sll $a2 $t0 2 - addu $a1 $a1 $a2 - lw $a1, 0($a1) - lw $a1, 8($a1) - addiu $a1 $a1 52 - lw $a1, 0($a1) - jal $a1 - move $t0 $v0 - addi $sp, $sp, 8 - move $t1 $t0 - move $t3 $t3 - move $a0 $t3 - li $a1, 0 - jal eqs - move $t0 $v0 - bne $t0 $zero L_81 - j L_82 - L_81: - li $v0, 4 - la $a0, data_16 - syscall - li $v0, 10 - syscall - L_82: - addi $sp, $sp, -4 - sw $t3, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - lw $t0, 0($t3) - la $a1, proto_table - sll $a2 $t0 2 - addu $a1 $a1 $a2 - lw $a1, 0($a1) - lw $a1, 8($a1) - addiu $a1 $a1 16 - lw $a1, 0($a1) - jal $a1 - move $t0 $v0 - addi $sp, $sp, 8 - move $t3 $t0 - lw $a1, 12($t4) - move $t1 $a1 - li $a0, 1 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t0) - move $t0 $a1 - add $t0 $t1 $t0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - move $t4 $t0 - j L_79 - L_83: - sw $t3, 12($t5) - move $t0 $t5 - move $t0 $t0 - move $t0 $t0 - move $v0 $t0 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $t4, 0($sp) - addi $sp, $sp, 4 - lw $t3, 0($sp) - addi $sp, $sp, 4 - lw $t2, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $a2, 0($sp) - addi $sp, $sp, 4 - lw $t6, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $t7, 0($sp) - addi $sp, $sp, 4 - lw $t5, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - lw $t9, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 104 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_24: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -8 - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - addi $sp, $sp, -4 - sw $a2, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - li $t1, 5 - sll $t1 $t1 2 - la $t0, proto_table - addu $t0 $t0 $t1 - lw $t0, 0($t0) - lw $a0, 4($t0) - sll $a0 $a0 2 - jal malloc - move $a2 $a0 - move $a0 $t0 - move $a1 $v0 - jal copy - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - move $t0 $v0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_25 - move $t1 $v0 - addi $sp, $sp, 4 - move $v0 $t0 - lw $a2, 0($sp) - addi $sp, $sp, 4 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 8 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_25: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -4 - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t3, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $t6, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $a2, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - lw $t1, 0($fp) - addi $sp, $sp, -4 - sw $t6, 0($sp) - addi $sp, $sp, -4 - sw $t3, 0($sp) - li $t6, 2 - sll $t6 $t6 2 - la $t3, proto_table - addu $t3 $t3 $t6 - lw $t3, 0($t3) - lw $a0, 4($t3) - sll $a0 $a0 2 - jal malloc - move $a2 $a0 - move $a0 $t3 - move $a1 $v0 - jal copy - lw $t3, 0($sp) - addi $sp, $sp, 4 - lw $t6, 0($sp) - addi $sp, $sp, 4 - move $t0 $v0 - sw $t0, 12($t1) - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $a2, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $t6, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t3, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 4 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_26: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -148 - addi $sp, $sp, -4 - sw $t3, 0($sp) - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $t2, 0($sp) - addi $sp, $sp, -4 - sw $a2, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - lw $t2, 0($fp) - la $t0, data_17 + 0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_10 - move $t0 $v0 - addi $sp, $sp, 4 - move $t1 $t0 - jal L_24 - move $t0 $v0 - move $t0 $t0 - move $a0 $t0 - li $a1, 0 - jal eqs - move $t3 $v0 - bne $t3 $zero L_84 - j L_85 - L_84: - li $v0, 4 - la $a0, data_18 - syscall - li $v0, 10 - syscall - L_85: - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - lw $t0, 0($t0) - la $a1, proto_table - sll $a2 $t0 2 - addu $a1 $a1 $a2 - lw $a1, 0($a1) - lw $a1, 8($a1) - addiu $a1 $a1 28 - lw $a1, 0($a1) - jal $a1 - move $t0 $v0 - addi $sp, $sp, 8 - sw $t0, 12($t2) - lw $a1, 12($t2) - move $t0 $a1 - move $t0 $t0 - move $a0 $t0 - li $a1, 0 - jal eqs - move $t1 $v0 - bne $t1 $zero L_86 - j L_87 - L_86: - li $v0, 4 - la $a0, data_19 - syscall - li $v0, 10 - syscall - L_87: - addi $sp, $sp, -4 - sw $t0, 0($sp) - lw $t0, 0($t0) - la $a1, proto_table - sll $a2 $t0 2 - addu $a1 $a1 $a2 - lw $a1, 0($a1) - lw $a1, 8($a1) - addiu $a1 $a1 32 - lw $a1, 0($a1) - jal $a1 - move $t0 $v0 - addi $sp, $sp, 4 - li $a0, 20 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - move $t3 $t0 - L_88: - li $a0, 0 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t0) - move $t0 $a1 - lw $a1, 12($t3) - move $t1 $a1 - move $a0 $t0 - move $a1 $t1 - jal less - move $t0 $v0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_15 - move $t0 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t0) - move $t0 $a1 - bne $t0 $zero L_89 - j L_94 - L_89: - lw $a1, 12($t2) - move $t0 $a1 - move $t0 $t0 - move $a0 $t0 - li $a1, 0 - jal eqs - move $t1 $v0 - bne $t1 $zero L_90 - j L_91 - L_90: - li $v0, 4 - la $a0, data_20 - syscall - li $v0, 10 - syscall - L_91: - addi $sp, $sp, -4 - sw $t0, 0($sp) - lw $t0, 0($t0) - la $a1, proto_table - sll $a2 $t0 2 - addu $a1 $a1 $a2 - lw $a1, 0($a1) - lw $a1, 8($a1) - addiu $a1 $a1 56 - lw $a1, 0($a1) - jal $a1 - move $t0 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t2) - move $t0 $a1 - move $t0 $t0 - move $a0 $t0 - li $a1, 0 - jal eqs - move $t1 $v0 - bne $t1 $zero L_92 - j L_93 - L_92: - li $v0, 4 - la $a0, data_21 - syscall - li $v0, 10 - syscall - L_93: - addi $sp, $sp, -4 - sw $t0, 0($sp) - lw $t0, 0($t0) - la $a1, proto_table - sll $a2 $t0 2 - addu $a1 $a1 $a2 - lw $a1, 0($a1) - lw $a1, 8($a1) - addiu $a1 $a1 32 - lw $a1, 0($a1) - jal $a1 - move $t0 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t3) - move $t0 $a1 - li $a0, 1 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_14 - move $t1 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t1) - move $t1 $a1 - sub $t0 $t0 $t1 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - move $t3 $t0 - j L_88 - L_94: - move $t0 $zero - move $v0 $t2 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $a2, 0($sp) - addi $sp, $sp, 4 - lw $t2, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - lw $t3, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 148 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_27: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -8 - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t8, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $t7, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $a2, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - addi $sp, $sp, -4 - sw $t7, 0($sp) - addi $sp, $sp, -4 - sw $t8, 0($sp) - li $t7, 6 - sll $t7 $t7 2 - la $t8, proto_table - addu $t8 $t8 $t7 - lw $t8, 0($t8) - lw $a0, 4($t8) - sll $a0 $a0 2 - jal malloc - move $a2 $a0 - move $a0 $t8 - move $a1 $v0 - jal copy - lw $t8, 0($sp) - addi $sp, $sp, 4 - lw $t7, 0($sp) - addi $sp, $sp, 4 - move $t1 $v0 - addi $sp, $sp, -4 - sw $t1, 0($sp) - jal L_28 - move $t0 $v0 - addi $sp, $sp, 4 - move $v0 $t1 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $a2, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $t7, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t8, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 8 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_28: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, 0 - addi $sp, $sp, 0 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra - - - - alloc_size = 2048 - free_list = 0 - header_size = 12 - header_size_slot = 0 - header_next_slot = 4 - header_reachable_slot = 8 - init_alloc_size = 28 - int_type = 0 - meta_data_obj_size = 4 - neg_header_size = -12 - new_line = 10 - obj_mark = -1 - obj_extended = -2 - reachable = 1 - state_size = 4 - stack_base = -4 - string_size_treshold = 1024 - string_type = 0 - total_alloc_size = 2060 - num_type = 0 - used_list = header_size - -verify_obj: - addiu $sp $sp -20 - sw $t0 0($sp) - sw $t1 4($sp) - sw $t2 8($sp) - sw $t3 12($sp) - sw $a0 16($sp) - - move $t0 $a0 - - li $v0 9 - move $a0 $zero - syscall - - addiu $t1 $v0 -4 - - - blt $t0 $gp verify_obj_not_obj - bgt $t0 $t1 verify_obj_not_obj - lw $t2 0($t0) - blt $t2 $zero verify_obj_not_obj - la $t3 num_type - lw $t3 0($t3) - bge $t2 $t3 verify_obj_not_obj - - addiu $t0 $t0 4 - blt $t0 $gp verify_obj_not_obj - bgt $t0 $t1 verify_obj_not_obj - lw $t2 0($t0) - - addiu $t0 $t0 8 - - - li $t3 meta_data_obj_size - sub $t2 $t2 $t3 - sll $t2 $t2 2 - addu $t0 $t0 $t2 - - - blt $t0 $gp verify_obj_not_obj - bgt $t0 $t1 verify_obj_not_obj - lw $t2 0($t0) - beq $t2 obj_mark verify_obj_is_obj - beq $t2 obj_extended verify_obj_is_obj - -verify_obj_not_obj: - li $v0 0 - j verify_obj_finish - -verify_obj_is_obj: - li $v0 1 - -verify_obj_finish: - lw $t0 0($sp) - lw $t1 4($sp) - lw $t2 8($sp) - lw $t3 12($sp) - lw $a0 16($sp) - addiu $sp $sp 20 - - jr $ra - -concat: - addiu $sp $sp -24 - sw $t0 0($sp) - sw $t1 4($sp) - sw $t2 8($sp) - sw $a0 12($sp) - sw $a1 16($sp) - sw $ra 20($sp) - - move $t0 $a0 - move $t1 $a1 - - - addiu $a0 $a2 1 - li $t2 4 - div $a0 $t2 - mfhi $a0 - bne $a0 $zero concat_allign_size - addiu $a0 $a2 1 - -concat_size_alligned: - jal malloc - move $t2 $v0 - j concat_copy_first_cycle - -concat_allign_size: - sub $t2 $t2 $a0 - add $a0 $a2 $t2 - addiu $a0 $a0 1 - j concat_size_alligned - -concat_copy_first_cycle: - lb $a0 0($t0) - beq $a0 $zero concat_copy_second_cycle - sb $a0 0($t2) - addiu $t0 $t0 1 - addiu $t2 $t2 1 - j concat_copy_first_cycle - -concat_copy_second_cycle: - lb $a0 0($t1) - beq $a0 $zero concat_finish - sb $a0 0($t2) - addiu $t1 $t1 1 - addiu $t2 $t2 1 - j concat_copy_second_cycle - -concat_finish: - sb $zero 0($t2) - lw $t0 0($sp) - lw $t1 4($sp) - lw $t2 8($sp) - lw $a0 12($sp) - lw $a1 16($sp) - lw $ra 20($sp) - addiu $sp $sp 24 - - jr $ra - -copy: - addiu $sp $sp -16 - sw $a0 0($sp) - sw $a1 4($sp) - sw $a2 8($sp) - sw $t0 12($sp) - -copy_cycle: - beq $a2 $zero copy_finish - lw $t0 0($a0) - sw $t0 0($a1) - addiu $a0 $a0 4 - addiu $a1 $a1 4 - addi $a2 $a2 -4 - j copy_cycle - -copy_finish: - lw $a0 0($sp) - lw $a1 4($sp) - lw $a2 8($sp) - lw $t0 12($sp) - addiu $sp $sp 16 - - jr $ra - -eqs: - beq $a0 $a1 eqs_eq - li $v0 0 - j eqs_finish - -eqs_eq: - li $v0 1 - -eqs_finish: - jr $ra - -eq_string: - addiu $sp $sp -16 - sw $t0 0($sp) - sw $t1 4($sp) - sw $t2 8($sp) - sw $t3 12($sp) - - move $t0 $a0 - move $t1 $a1 - -eq_string_cycle: - lb $t2 0($t0) - lb $t3 0($t1) - bne $t2 $t3 eq_string_not_eq - beq $t2 $zero eq_string_eq - - addiu $t0 $t0 1 - addiu $t1 $t1 1 - j eq_string_cycle - -eq_string_not_eq: - move $v0 $zero - j eq_string_finish - -eq_string_eq: - li $v0 1 - -eq_string_finish: - lw $t0 0($sp) - lw $t1 4($sp) - lw $t2 8($sp) - lw $t3 12($sp) - addiu $sp $sp 16 - - jr $ra - -extend_block: - addiu $sp $sp -16 - sw $t0 0($sp) - sw $t1 4($sp) - sw $t2 8($sp) - sw $t3 12($sp) - - - addiu $t0 $gp free_list - - beq $t0 $a0 extend_block_finish - move $t0 $a0 - - lw $t1 header_next_slot($t0) - lw $t2 header_size_slot($t0) - move $t3 $t2 - addiu $t2 $t2 header_size - addu $t2 $t2 $t0 - beq $t2 $t1 extend_block_extend - j extend_block_finish - -extend_block_extend: - lw $t2 header_size_slot($t1) - addi $t2 $t2 header_size - add $t2 $t2 $t3 - sw $t2 header_size_slot($t0) - lw $t1 header_next_slot($t1) - sw $t1 header_next_slot($t0) - -extend_block_finish: - lw $t0 0($sp) - lw $t1 4($sp) - lw $t2 8($sp) - lw $t3 12($sp) - addiu $sp $sp 16 - - jr $ra - -extend_heap: - addiu $sp $sp -12 - sw $a0 0($sp) - sw $a1 4($sp) - sw $t0 8($sp) - - - li $v0 9 - addiu $a0 $a1 header_size - syscall - - - move $t0 $a1 - sw $t0 header_size_slot($v0) - sw $zero header_next_slot($v0) - sw $zero header_reachable_slot($v0) - - - lw $t0, 0($sp) - sw $v0 header_next_slot($t0) - - move $a0 $t0 - lw $a1 4($sp) - lw $t0 8($sp) - addiu $sp $sp 12 - - jr $ra - -free_block: - addiu $sp $sp -28 - sw $t0 0($sp) - sw $t1 4($sp) - sw $t2 8($sp) - sw $a0 12($sp) - sw $ra 16($sp) - sw $t3 20($sp) - sw $t4 24($sp) - - move $t0 $a0 - - addiu $t1 $gp free_list - - addiu $t3 $gp used_list - -free_block_cycle_used_list: - lw $t4 header_next_slot($t3) - beq $t4 $t0 free_block_cycle_free_list - move $t3 $t4 - j free_block_cycle_used_list - -free_block_cycle_free_list: - lw $t2 header_next_slot($t1) - beq $t2 $zero free_block_founded_prev - bge $t2 $t0 free_block_founded_prev - move $t1 $t2 - j free_block_cycle_free_list - -free_block_founded_prev: - lw $t4 header_next_slot($t0) - sw $t4 header_next_slot($t3) - - - sw $t2 header_next_slot($t0) - sw $t0 header_next_slot($t1) - -free_block_finish: - - move $a0 $t0 - jal extend_block - move $a0 $t1 - jal extend_block - - lw $t0 0($sp) - lw $t1 4($sp) - lw $t2 8($sp) - lw $a0 12($sp) - lw $ra 16($sp) - lw $t3 20($sp) - lw $t4 24($sp) - addiu $sp $sp 28 - - jr $ra - -get_gc: - addiu $sp $sp -24 - sw $t0 0($sp) - sw $t1 4($sp) - sw $t2 8($sp) - sw $t3 12($sp) - sw $a0 16($sp) - sw $ra 20($sp) - - li $t3 reachable - addiu $t0 $sp 20 - lw $t1 stack_base($gp) - - li $t2 1 - -get_gc_cycle: - - addiu $t0 $t0 4 - beq $t0 $t1 get_gc_dfs - - lw $a0 0($t0) - jal verify_obj - - bne $v0 $t2 get_gc_cycle - - addiu $a0 $a0 neg_header_size - sw $t3 header_reachable_slot($a0) - - j get_gc_cycle - -get_gc_dfs: - addiu $t1 $gp used_list - -get_gc_outer_cycle: - lw $t1 header_next_slot($t1) - beq $t1 $zero get_gc_free - lw $t2 header_reachable_slot($t1) - beq $t2 reachable get_gc_extend - j get_gc_outer_cycle - -get_gc_extend: - addiu $a0 $t1 header_size - jal get_gc_rec_extend - j get_gc_outer_cycle - -get_gc_free: - addiu $t0 $gp used_list - lw $t0 header_next_slot($t0) - -get_gc_free_cycle: - beq $t0 $zero get_gc_finish - lw $t1 header_reachable_slot($t0) - bne $t1 reachable get_gc_free_cycle_free - sw $zero header_reachable_slot($t0) - move $a0 $t0 - jal verify_obj - beq $v0 $zero get_gc_free_cycle - li $t1 obj_mark - addiu $t2 $t0 header_size - lw $t3 4($t2) - sll $t3 $t3 2 - addu $t2 $t2 $t3 - sw $t1 -4($t2) - lw $t0 header_next_slot($t0) - j get_gc_free_cycle - -get_gc_free_cycle_free: - move $a0 $t0 - lw $t0 header_next_slot($t0) - jal free_block - j get_gc_free_cycle - -get_gc_finish: - lw $t0 0($sp) - lw $t1 4($sp) - lw $t2 8($sp) - lw $t3 12($sp) - lw $a0 16($sp) - lw $ra 20($sp) - addiu $sp $sp 24 - - jr $ra - -get_gc_rec_extend: - addiu $sp $sp -16 - sw $a0 0($sp) - sw $t0 4($sp) - sw $t1 8($sp) - sw $ra 12($sp) - - jal verify_obj - beq $v0 $zero get_gc_rec_extend_finish - - lw $t0 4($a0) - sll $t0 $t0 2 - addiu $t0 $t0 -4 - addu $t0 $a0 $t0 - lw $t1 0($t0) - beq $t1 obj_extended get_gc_rec_extend_finish - - - li $t1 reachable - addiu $a0 $a0 neg_header_size - sw $t1 header_reachable_slot($a0) - addiu $a0 $a0 header_size - - - li $t1 obj_extended - sw $t1 0($t0) - - lw $t0 0($a0) - - - la $t1 int_type - lw $t1 0($t1) - beq $t0 $t1 get_gc_rec_extend_finish - - la $t1 string_type - lw $t1 0($t1) - beq $t0 $t1 get_gc_rec_extend_string_obj - - lw $t0 4($a0) - li $t1 meta_data_obj_size - sub $t0 $t0 $t1 - - addiu $t1 $a0 12 - -get_gc_rec_extend_attr_cycle: - beq $t0 $zero get_gc_rec_extend_finish - lw $a0 0($t1) - jal get_gc_rec_extend - addiu $t1 $t1 4 - sub $t0 $t0 1 - j get_gc_rec_extend_attr_cycle - -get_gc_rec_extend_string_obj: - lw $t0 8($a0) - addiu $t0 $t0 neg_header_size - li $t1 reachable - sw $t1 header_reachable_slot($t0) - -get_gc_rec_extend_finish: - lw $a0 0($sp) - lw $t0 4($sp) - lw $t1 8($sp) - lw $ra 12($sp) - addiu $sp $sp 16 - - jr $ra - -less_eq: - ble $a0 $a1 less_eq_true - li $v0 0 - j less_eq_finish - -less_eq_true: - li $v0 1 - -less_eq_finish: - jr $ra - -less: - blt $a0 $a1 less_true - li $v0 0 - j less_finish - -less_true: - li $v0 1 - -less_finish: - jr $ra - -len: - addiu $sp $sp -8 - sw $t0 0($sp) - sw $t1 4($sp) - - move $t0 $a0 - move $v0 $zero - -len_cycle: - lb $t1 0($t0) - beq $t1 $zero len_finish - addi $v0 $v0 1 - addiu $t0 $t0 1 - j len_cycle - -len_finish: - lw $t0 0($sp) - lw $t1 4($sp) - addiu $sp $sp 8 - - jr $ra - -malloc: - move $v0 $zero - addiu $sp $sp -28 - sw $t1 0($sp) - sw $t0 4($sp) - sw $a0 8($sp) - sw $a1 12($sp) - sw $ra 16($sp) - sw $t2 20($sp) - sw $t3 24($sp) - - addiu $t0 $gp free_list - j malloc_cycle - -malloc_finish: - move $a0 $v0 - lw $a1 8($sp) - jal divide_block - - lw $t1 header_next_slot($v0) - sw $t1 header_next_slot($t3) - - addiu $t1 $gp used_list - lw $a0 header_next_slot($t1) - - sw $a0 header_next_slot($v0) - sw $v0 header_next_slot($t1) - - addiu $v0 $v0 header_size - - lw $t3 24($sp) - lw $t2 20($sp) - lw $ra 16($sp) - lw $a1 12($sp) - lw $a0 8($sp) - lw $t0 4($sp) - lw $t1 0($sp) - addiu $sp $sp 28 - - jr $ra - -malloc_cycle: - move $t2 $t0 - lw $t0 header_next_slot($t0) - beq $t0 $zero malloc_search_finish - j malloc_verify_valid_block - -malloc_search_finish: - beq $v0 $zero malloc_alloc_new_block - j malloc_finish - -malloc_alloc_new_block: - li $t1 alloc_size - move $t3 $t2 - move $a1 $a0 - move $a0 $t2 - bge $a1 $t1 malloc_big_block - li $a1 alloc_size - jal extend_heap - - j malloc_finish - -malloc_big_block: - jal extend_heap - j malloc_finish - -malloc_verify_valid_block: - lw $t1 header_size_slot($t0) - bge $t1 $a0 malloc_valid_block - j malloc_cycle - -malloc_valid_block: - beq $v0 $zero malloc_first_valid_block - bge $t1 $v1 malloc_cycle - move $v0 $t0 - move $v1 $t1 - move $t3 $t2 - j malloc_cycle - -malloc_first_valid_block: - move $v0 $t0 - move $v1 $t1 - move $t3 $t2 - j malloc_cycle - -mem_manager_init: - addiu $sp $sp -16 - sw $v0 0($sp) - sw $a0 4($sp) - sw $a1 8($sp) - sw $ra 12($sp) - li $v0 9 - li $a0 init_alloc_size - syscall - move $gp $v0 - addiu $gp $gp state_size - - sw $zero header_size_slot($gp) - sw $zero header_reachable_slot($gp) - - move $a0 $gp - li $a1 alloc_size - jal extend_heap - - addiu $a0 $a0 header_size - sw $zero header_size_slot($a0) - sw $zero header_next_slot($a0) - sw $zero header_reachable_slot($a0) - - - - lw $v0 0($sp) - lw $a0 4($sp) - lw $a1 8($sp) - lw $ra 12($sp) - addiu $sp $sp 16 - - sw $sp stack_base($gp) - - jr $ra - -get_string: - addiu $sp $sp -36 - sw $t0 0($sp) - sw $t1 4($sp) - sw $t2 8($sp) - sw $t3 12($sp) - sw $t4 16($sp) - sw $t5 20($sp) - sw $a0 24($sp) - sw $a1 28($sp) - sw $ra 32($sp) - - addiu $t0 $gp free_list - move $t1 $zero - move $t2 $t0 - -get_string_larger_block_cycle: - lw $t0 header_next_slot($t0) - beq $t0 $zero get_string_reading - lw $t3 header_size_slot($t0) - bge $t1 $t3 get_string_larger_block_cycle - move $t1 $t3 - move $t2 $t0 - j get_string_larger_block_cycle - -get_string_reading: - beq $t1 $zero get_string_new_block - move $a1 $t1 - li $v0 8 - addiu $a0 $t2 header_size - syscall - move $t0 $a0 - move $t1 $zero - -get_string_look_nl: - lb $t2 0($t0) - beq $t2 new_line get_string_nl_founded - beq $t2 $zero get_string_zero_founded - addi $t1 $t1 1 - addi $t0 $t0 1 - j get_string_look_nl - -get_string_zero_founded: - blt $t1 $t3 get_string_nl_founded - j get_string_no_nl - -get_string_nl_founded: - sb $zero 0($t0) - addi $t1 $t1 1 - li $t2 4 - div $t1 $t2 - mfhi $t3 - beq $t3 $zero get_string_nl_founded_alligned - sub $t2 $t2 $t3 - add $t1 $t1 $t2 - -get_string_nl_founded_alligned: - move $a1 $t1 - addiu $a0 $a0 neg_header_size - jal divide_block - jal use_block - - addiu $v0 $a0 header_size - j get_string_finish - -get_string_no_nl: - addi $t1 $t1 1 - blt $t1 string_size_treshold get_string_dup - addi $t1 $t1 alloc_size - j get_string_extend_heap - -get_string_dup: - sll $t1 $t1 1 - -get_string_extend_heap: - move $a1 $t1 - move $t0 $a0 - addiu $a0 $gp free_list - -get_string_last_block_cycle: - lw $t1 header_next_slot($a0) - beq $t1 $zero get_string_last_block_founded - lw $a0 header_next_slot($a0) - j get_string_last_block_cycle - -get_string_last_block_founded: - jal extend_heap - jal extend_block - lw $t1 header_next_slot($a0) - bne $t1 $zero get_string_copy_prev - move $t1 $a0 - -get_string_copy_prev: - lw $t3 header_size_slot($t1) - move $t2 $zero - move $t5 $t1 - addiu $t1 $t1 header_size - -get_string_copy_cycle: - lb $t4 0($t0) - beq $t4 $zero get_string_copy_finish - sb $t4 0($t1) - addi $t2 $t2 1 - addi $t0 $t0 1 - addi $t1 $t1 1 - j get_string_copy_cycle - -get_string_copy_finish: - sub $t3 $t3 $t2 - move $a0 $t1 - move $a1 $t3 - li $v0 8 - syscall - move $t0 $a0 - move $t1 $t2 - addiu $a0 $t5 header_size - j get_string_look_nl - -get_string_finish: - lw $t0 0($sp) - lw $t1 4($sp) - lw $t2 8($sp) - lw $t3 12($sp) - lw $t4 16($sp) - lw $t5 20($sp) - lw $a0 24($sp) - lw $a1 28($sp) - lw $ra 32($sp) - addiu $sp $sp 36 - - jr $ra - -get_string_new_block: - addiu $t0 $gp free_list - -get_string_new_block_search_last: - lw $t1 header_next_slot($t0) - beq $t1 $zero get_string_new_block_create - move $t0 $t1 - j get_string_new_block_search_last - -get_string_new_block_create: - move $a0 $t0 - li $a1 alloc_size - jal extend_heap - jal extend_block - lw $t2 header_next_slot($a0) - beq $t2 $zero get_string_new_block_extended - lw $t1 header_size_slot($t2) - j get_string_reading - -get_string_new_block_extended: - move $t2 $a0 - lw $t1 header_size_slot($a0) - j get_string_reading - -divide_block: - addiu $sp $sp -16 - sw $t0 0($sp) - sw $t1 4($sp) - sw $a0 8($sp) - sw $a1 12($sp) - - - lw $t0 header_size_slot($a0) - bgt $a1 $t0 divide_block_error_small - - - sub $t0 $t0 $a1 - li $t1 header_size - ble $t0 $t1 divide_block_same_size - - - addu $t0 $a0 $a1 - addiu $t0 $t0 header_size - - - lw $t1 header_next_slot($a0) - sw $t1 header_next_slot($t0) - sw $t0 header_next_slot($a0) - - lw $t1 header_size_slot($a0) - sub $t1 $t1 $a1 - - addi $t1 $t1 neg_header_size - sw $t1 header_size_slot($t0) - sw $a1 header_size_slot($a0) - move $v0 $a0 - j divide_block_finish - -divide_block_same_size: - move $v0 $a0 - j divide_block_finish - -divide_block_error_small: - j divide_block_finish - -divide_block_finish: - lw $t0 0($sp) - lw $t1 4($sp) - lw $a0 8($sp) - lw $a1 12($sp) - addiu $sp $sp 16 - - jr $ra - -sub_string: - addiu $sp $sp -24 - sw $t0 0($sp) - sw $t1 4($sp) - sw $t2 8($sp) - sw $t3 12($sp) - sw $a0 16($sp) - sw $ra 20($sp) - - move $t0 $a0 - li $t1 4 - addiu $t3 $a2 1 - div $t3 $t1 - - mfhi $t2 - bne $t2 $zero sub_string_allign_size - move $t1 $t3 - j sub_string_new_block - -sub_string_allign_size: - sub $t1 $t1 $t2 - add $t1 $t1 $t3 - -sub_string_new_block: - move $a0 $t1 - jal malloc - move $t3 $v0 - move $t1 $zero - addu $t0 $t0 $a1 - -sub_string_copy_cycle: - beq $t1 $a2 sub_string_finish - lb $t2 0($t0) - sb $t2 0($t3) - addiu $t0 $t0 1 - addiu $t3 $t3 1 - addiu $t1 $t1 1 - j sub_string_copy_cycle - -sub_string_finish: - sb $zero 0($t3) - lw $t0 0($sp) - lw $t1 4($sp) - lw $t2 8($sp) - lw $t3 12($sp) - lw $a0 16($sp) - lw $ra 20($sp) - addiu $sp $sp 24 - - jr $ra - -use_block: - addiu $sp $sp -12 - sw $t0 0($sp) - sw $t1 4($sp) - sw $t2 8($sp) - - addiu $t0 $gp free_list - -use_block_cycle: - move $t1 $t0 - lw $t0 header_next_slot($t0) - beq $t0 $zero use_block_finish - beq $t0 $a0 use_block_founded - j use_block_cycle - -use_block_founded: - lw $t2 header_next_slot($t0) - sw $t2 header_next_slot($t1) - - addiu $t1 $gp used_list - lw $t2 header_next_slot($t1) - sw $t0 header_next_slot($t1) - sw $t2 header_next_slot($t0) - -use_block_finish: - lw $t0 0($sp) - lw $t1 4($sp) - lw $t2 8($sp) - addiu $sp $sp 12 - - jr $ra - From 2551b3a4626239ca5ffe9aa3aa245c9a3bbd684e Mon Sep 17 00:00:00 2001 From: Alejandro Campos Matanzas <74170015+Alexx-4@users.noreply.github.com> Date: Fri, 25 Feb 2022 13:17:36 -0800 Subject: [PATCH 80/83] Delete primes.mips --- src/primes.mips | 2443 ----------------------------------------------- 1 file changed, 2443 deletions(-) delete mode 100644 src/primes.mips diff --git a/src/primes.mips b/src/primes.mips deleted file mode 100644 index e4e48967c..000000000 --- a/src/primes.mips +++ /dev/null @@ -1,2443 +0,0 @@ - .data -default_str: .asciiz "" -data_1: .asciiz "Object" -data_2: .asciiz "IO" -data_3: .asciiz "String" -data_4: .asciiz "Int" -data_5: .asciiz "Bool" -data_6: .asciiz "Main" -data_7: .asciiz "Abort called from class " -data_8: .asciiz " -" -data_9: .asciiz "Substring out of range" -data_10: .asciiz "2 is trivially prime. -" -data_11: .asciiz "(55,39) - RuntimeError: Division by zero -" -data_12: .asciiz " is prime. -" -data_13: .asciiz "halt" -data_14: .asciiz "(75,11) - RuntimeError: Dispatch on void -" -data_15: .asciiz "continue" - -type_name_table: - .word data_1 - .word data_2 - .word data_3 - .word data_4 - .word data_5 - .word data_6 - -proto_table: - .word type_1_proto - .word type_2_proto - .word type_3_proto - .word type_4_proto - .word type_5_proto - .word type_6_proto - -type_1_dispatch: - .word L_2 - .word L_3 - .word L_4 - .word L_1 - -type_1_proto: - .word 0 - .word 4 - .word type_1_dispatch - .word -1 - -type_2_dispatch: - .word L_3 - .word L_2 - .word L_4 - .word L_6 - .word L_7 - .word L_8 - .word L_9 - .word L_5 - -type_2_proto: - .word 1 - .word 4 - .word type_2_dispatch - .word -1 - -type_3_dispatch: - .word L_3 - .word L_2 - .word L_4 - .word L_11 - .word L_12 - .word L_13 - .word L_10 - -type_3_proto: - .word 2 - .word 6 - .word type_3_dispatch - .word default_str - .word type_4_proto - .word -1 - -type_4_dispatch: - .word L_3 - .word L_2 - .word L_4 - .word L_14 - -type_4_proto: - .word 3 - .word 5 - .word type_4_dispatch - .word 0 - .word -1 - -type_5_dispatch: - .word L_3 - .word L_2 - .word L_4 - .word L_15 - -type_5_proto: - .word 4 - .word 5 - .word type_5_dispatch - .word 0 - .word -1 - -type_6_dispatch: - .word L_2 - .word L_3 - .word L_4 - .word L_6 - .word L_7 - .word L_8 - .word L_9 - .word L_16 - -type_6_proto: - .word 5 - .word 9 - .word type_6_dispatch - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word -1 - .text - .globl main -main: - jal mem_manager_init - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -8 - jal L_17 - move $t0 $v0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_16 - move $t0 $v0 - addi $sp, $sp, 4 - li $v0, 0 - addi $sp, $sp, 8 - lw $fp, 0($sp) - addi $sp, $sp, 4 - li $v0, 10 - syscall -L_1: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -4 - addi $sp, $sp, -4 - sw $a2, 0($sp) - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t2, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $t3, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - addi $sp, $sp, -4 - sw $t2, 0($sp) - addi $sp, $sp, -4 - sw $t3, 0($sp) - li $t2, 0 - sll $t2 $t2 2 - la $t3, proto_table - addu $t3 $t3 $t2 - lw $t3, 0($t3) - lw $a0, 4($t3) - sll $a0 $a0 2 - jal malloc - move $a2 $a0 - move $a0 $t3 - move $a1 $v0 - jal copy - lw $t3, 0($sp) - addi $sp, $sp, 4 - lw $t2, 0($sp) - addi $sp, $sp, 4 - move $t0 $v0 - move $v0 $t0 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t3, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $t2, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - lw $a2, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 4 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_2: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -4 - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - lw $t0, 0($fp) - la $t1, data_7 + 0 - li $v0, 4 - move $a0 $t1 - syscall - lw $a0, 0($t0) - sll $a0 $a0 2 - la $a1, type_name_table - addu $a0 $a0 $a1 - lw $a0, 0($a0) - move $t1 $a0 - li $v0, 4 - move $a0 $t1 - syscall - la $t1, data_8 + 0 - li $v0, 4 - move $a0 $t1 - syscall - li $v0, 10 - syscall - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 4 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_3: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -8 - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - lw $t0, 0($fp) - lw $a0, 0($t0) - sll $a0 $a0 2 - la $a1, type_name_table - addu $a0 $a0 $a1 - lw $a0, 0($a0) - move $t0 $a0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_10 - move $t0 $v0 - addi $sp, $sp, 4 - move $v0 $t0 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 8 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_4: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -4 - addi $sp, $sp, -4 - sw $a2, 0($sp) - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - lw $t0, 0($fp) - lw $a0, 4($t0) - sll $a0 $a0 2 - jal malloc - move $a2 $a0 - move $a0 $t0 - move $a1 $v0 - jal copy - move $t0 $v0 - move $v0 $t0 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - lw $a2, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 4 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_5: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -4 - addi $sp, $sp, -4 - sw $a2, 0($sp) - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t9, 0($sp) - addi $sp, $sp, -4 - sw $t5, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - addi $sp, $sp, -4 - sw $t9, 0($sp) - addi $sp, $sp, -4 - sw $t5, 0($sp) - li $t9, 1 - sll $t9 $t9 2 - la $t5, proto_table - addu $t5 $t5 $t9 - lw $t5, 0($t5) - lw $a0, 4($t5) - sll $a0 $a0 2 - jal malloc - move $a2 $a0 - move $a0 $t5 - move $a1 $v0 - jal copy - lw $t5, 0($sp) - addi $sp, $sp, 4 - lw $t9, 0($sp) - addi $sp, $sp, 4 - move $t0 $v0 - move $v0 $t0 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $t5, 0($sp) - addi $sp, $sp, 4 - lw $t9, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - lw $a2, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 4 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_6: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -4 - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - lw $t1, 0($fp) - lw $t0, 4($fp) - lw $a1, 12($t1) - move $t1 $a1 - li $v0, 4 - move $a0 $t1 - syscall - move $v0 $t0 - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 4 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_7: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -4 - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - lw $t1, 0($fp) - lw $t0, 4($fp) - lw $a1, 12($t1) - move $t1 $a1 - li $v0, 1 - move $a0 $t1 - syscall - move $v0 $t0 - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 4 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_8: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -8 - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - lw $t0, 0($fp) - jal get_string - move $t0 $v0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_10 - move $t0 $v0 - addi $sp, $sp, 4 - move $v0 $t0 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 8 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_9: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -8 - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - lw $t0, 0($fp) - li $v0, 5 - syscall - move $t0 $v0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - move $v0 $t0 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 8 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_10: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -12 - addi $sp, $sp, -4 - sw $a2, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $t5, 0($sp) - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $t3, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - lw $t1, 0($fp) - addi $sp, $sp, -4 - sw $t5, 0($sp) - addi $sp, $sp, -4 - sw $t3, 0($sp) - li $t5, 2 - sll $t5 $t5 2 - la $t3, proto_table - addu $t3 $t3 $t5 - lw $t3, 0($t3) - lw $a0, 4($t3) - sll $a0 $a0 2 - jal malloc - move $a2 $a0 - move $a0 $t3 - move $a1 $v0 - jal copy - lw $t3, 0($sp) - addi $sp, $sp, 4 - lw $t5, 0($sp) - addi $sp, $sp, 4 - move $t0 $v0 - sw $t1, 12($t0) - move $a0 $t1 - jal len - move $t1 $v0 - addi $sp, $sp, -4 - sw $t1, 0($sp) - jal L_14 - move $t1 $v0 - addi $sp, $sp, 4 - sw $t1, 16($t0) - move $v0 $t0 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t3, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - lw $t5, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $a2, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 12 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_11: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -4 - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - lw $t0, 0($fp) - lw $a1, 16($t0) - move $t0 $a1 - move $v0 $t0 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 4 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_12: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -24 - addi $sp, $sp, -4 - sw $a2, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - addi $sp, $sp, -4 - sw $t4, 0($sp) - addi $sp, $sp, -4 - sw $t2, 0($sp) - addi $sp, $sp, -4 - sw $t3, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - lw $t4, 0($fp) - lw $t0, 4($fp) - lw $a1, 12($t0) - move $t1 $a1 - lw $a1, 12($t4) - move $t3 $a1 - lw $a1, 16($t0) - move $t2 $a1 - lw $a1, 16($t4) - move $t0 $a1 - lw $a1, 12($t2) - move $t2 $a1 - lw $a1, 12($t0) - move $t0 $a1 - add $t2 $t2 $t0 - move $a0 $t1 - move $a1 $t3 - move $a2 $t2 - jal concat - move $t0 $v0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_10 - move $t0 $v0 - addi $sp, $sp, 4 - move $v0 $t0 - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t3, 0($sp) - addi $sp, $sp, 4 - lw $t2, 0($sp) - addi $sp, $sp, 4 - lw $t4, 0($sp) - addi $sp, $sp, 4 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $a2, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 24 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_13: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -32 - addi $sp, $sp, -4 - sw $a2, 0($sp) - addi $sp, $sp, -4 - sw $t4, 0($sp) - addi $sp, $sp, -4 - sw $t3, 0($sp) - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t2, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - lw $t3, 0($fp) - lw $t2, 4($fp) - lw $t1, 8($fp) - lw $a1, 12($t1) - move $t0 $a1 - lw $a1, 12($t2) - move $t4 $a1 - lw $a1, 12($t3) - move $t2 $a1 - lw $a1, 16($t1) - move $t1 $a1 - add $t3 $t2 $t4 - move $a0 $t1 - move $a1 $t3 - jal less - move $t1 $v0 - bne $t1 $zero L_19 - j L_20 - L_19: - li $v0, 4 - la $a0, data_9 - syscall - li $v0, 10 - syscall - L_20: - move $a0 $t0 - move $a1 $t4 - move $a2 $t2 - jal sub_string - move $t0 $v0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_10 - move $t0 $v0 - addi $sp, $sp, 4 - move $v0 $t0 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $t2, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - lw $t3, 0($sp) - addi $sp, $sp, 4 - lw $t4, 0($sp) - addi $sp, $sp, 4 - lw $a2, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 32 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_14: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -4 - addi $sp, $sp, -4 - sw $a2, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $t6, 0($sp) - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $t3, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - lw $t0, 0($fp) - addi $sp, $sp, -4 - sw $t6, 0($sp) - addi $sp, $sp, -4 - sw $t3, 0($sp) - li $t6, 3 - sll $t6 $t6 2 - la $t3, proto_table - addu $t3 $t3 $t6 - lw $t3, 0($t3) - lw $a0, 4($t3) - sll $a0 $a0 2 - jal malloc - move $a2 $a0 - move $a0 $t3 - move $a1 $v0 - jal copy - lw $t3, 0($sp) - addi $sp, $sp, 4 - lw $t6, 0($sp) - addi $sp, $sp, 4 - move $t1 $v0 - sw $t0, 12($t1) - move $v0 $t1 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $t3, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - lw $t6, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $a2, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 4 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_15: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -4 - addi $sp, $sp, -4 - sw $a2, 0($sp) - addi $sp, $sp, -4 - sw $t2, 0($sp) - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t3, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - lw $t0, 0($fp) - addi $sp, $sp, -4 - sw $t3, 0($sp) - addi $sp, $sp, -4 - sw $t2, 0($sp) - li $t3, 4 - sll $t3 $t3 2 - la $t2, proto_table - addu $t2 $t2 $t3 - lw $t2, 0($t2) - lw $a0, 4($t2) - sll $a0 $a0 2 - jal malloc - move $a2 $a0 - move $a0 $t2 - move $a1 $v0 - jal copy - lw $t2, 0($sp) - addi $sp, $sp, 4 - lw $t3, 0($sp) - addi $sp, $sp, 4 - move $t1 $v0 - sw $t0, 12($t1) - move $v0 $t1 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $t3, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - lw $t2, 0($sp) - addi $sp, $sp, 4 - lw $a2, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 4 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_16: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -4 - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - lw $t0, 0($fp) - li $a0, 0 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - move $v0 $t0 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 4 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_17: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -8 - addi $sp, $sp, -4 - sw $a2, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - addi $sp, $sp, -4 - sw $t1, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - li $t1, 5 - sll $t1 $t1 2 - la $t0, proto_table - addu $t0 $t0 $t1 - lw $t0, 0($t0) - lw $a0, 4($t0) - sll $a0 $a0 2 - jal malloc - move $a2 $a0 - move $a0 $t0 - move $a1 $v0 - jal copy - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - move $t1 $v0 - addi $sp, $sp, -4 - sw $t1, 0($sp) - jal L_18 - move $t0 $v0 - addi $sp, $sp, 4 - move $v0 $t1 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $t1, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $a2, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 8 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra -L_18: - addi $sp, $sp, -4 - sw $fp, 0($sp) - addi $fp, $sp, 4 - addi $sp, $sp, -440 - addi $sp, $sp, -4 - sw $a2, 0($sp) - addi $sp, $sp, -4 - sw $t5, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - addi $sp, $sp, -4 - sw $ra, 0($sp) - addi $sp, $sp, -4 - sw $t4, 0($sp) - addi $sp, $sp, -4 - sw $a1, 0($sp) - addi $sp, $sp, -4 - sw $t3, 0($sp) - addi $sp, $sp, -4 - sw $t2, 0($sp) - addi $sp, $sp, -4 - sw $a0, 0($sp) - addi $sp, $sp, -4 - sw $t7, 0($sp) - addi $sp, $sp, -4 - sw $t6, 0($sp) - lw $t2, 0($fp) - la $t0, data_10 + 0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_10 - move $t0 $v0 - addi $sp, $sp, 4 - move $t0 $t0 - addi $sp, $sp, -4 - sw $t2, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - lw $t0, 0($t2) - la $a1, proto_table - sll $a2 $t0 2 - addu $a1 $a1 $a2 - lw $a1, 0($a1) - lw $a1, 8($a1) - addiu $a1 $a1 12 - lw $a1, 0($a1) - jal $a1 - move $t0 $v0 - addi $sp, $sp, 8 - li $a0, 2 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - sw $t0, 12($t2) - lw $a1, 12($t2) - move $t0 $a1 - sw $t0, 16($t2) - addi $sp, $sp, -4 - sw $t3, 0($sp) - addi $sp, $sp, -4 - sw $t6, 0($sp) - li $t3, 3 - sll $t3 $t3 2 - la $t6, proto_table - addu $t6 $t6 $t3 - lw $t6, 0($t6) - lw $a0, 4($t6) - sll $a0 $a0 2 - jal malloc - move $a2 $a0 - move $a0 $t6 - move $a1 $v0 - jal copy - lw $t6, 0($sp) - addi $sp, $sp, 4 - lw $t3, 0($sp) - addi $sp, $sp, 4 - move $t0 $v0 - sw $t0, 20($t2) - li $a0, 500 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - sw $t0, 24($t2) - L_21: - li $a0, 1 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_15 - move $t0 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t0) - move $t0 $a1 - bne $t0 $zero L_22 - j L_46 - L_22: - lw $a1, 16($t2) - move $t0 $a1 - lw $a1, 12($t0) - move $t3 $a1 - li $a0, 1 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t0) - move $t0 $a1 - add $t0 $t3 $t0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - sw $t0, 16($t2) - li $a0, 2 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - sw $t0, 20($t2) - L_23: - lw $a1, 16($t2) - move $t4 $a1 - lw $a1, 20($t2) - move $t0 $a1 - lw $a1, 12($t0) - move $t0 $a1 - lw $a1, 20($t2) - move $t3 $a1 - lw $a1, 12($t3) - move $t3 $a1 - mul $t0 $t0 $t3 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t4) - move $t3 $a1 - lw $a1, 12($t0) - move $t0 $a1 - move $a0 $t3 - move $a1 $t0 - jal less - move $t0 $v0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_15 - move $t0 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t0) - move $t0 $a1 - bne $t0 $zero L_24 - j L_25 - L_24: - li $a0, 0 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_15 - move $t0 $v0 - addi $sp, $sp, 4 - move $t0 $t0 - j L_35 - L_25: - lw $a1, 16($t2) - move $t0 $a1 - lw $a1, 12($t0) - move $t3 $a1 - lw $a1, 20($t2) - move $t0 $a1 - lw $a1, 12($t0) - move $t4 $a1 - lw $a1, 16($t2) - move $t0 $a1 - lw $a1, 12($t0) - move $t6 $a1 - lw $a1, 20($t2) - move $t0 $a1 - lw $a1, 12($t0) - move $t0 $a1 - move $a0 $t0 - li $a1, 0 - jal eqs - move $t5 $v0 - bne $t5 $zero L_26 - j L_27 - L_26: - li $v0, 4 - la $a0, data_11 - syscall - li $v0, 10 - syscall - L_27: - div $t6 $t0 - mflo $t0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t0) - move $t0 $a1 - mul $t0 $t4 $t0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t0) - move $t0 $a1 - sub $t0 $t3 $t0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_14 - move $t3 $v0 - addi $sp, $sp, 4 - li $a0, 0 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_14 - move $t6 $v0 - addi $sp, $sp, 4 - lw $a0, 0($t3) - sll $a0 $a0 2 - la $a1, type_name_table - addu $a0 $a0 $a1 - lw $a0, 0($a0) - move $t7 $a0 - la $t0, type_name_table - addiu $t0 $t0 12 - lw $t0, 0($t0) - la $t5, type_name_table - addiu $t5 $t5 16 - lw $t5, 0($t5) - la $t4, type_name_table - addiu $t4 $t4 8 - lw $t4, 0($t4) - move $a0 $t7 - move $a1 $t0 - jal eqs - move $t0 $v0 - bne $t0 $zero L_28 - move $a0 $t7 - move $a1 $t5 - jal eqs - move $t0 $v0 - bne $t0 $zero L_28 - move $a0 $t7 - move $a1 $t4 - jal eqs - move $t0 $v0 - bne $t0 $zero L_29 - j L_30 - L_28: - lw $a1, 12($t3) - move $t0 $a1 - lw $a1, 12($t6) - move $t3 $a1 - move $a0 $t0 - move $a1 $t3 - jal eqs - move $t0 $v0 - j L_31 - L_29: - lw $a1, 12($t3) - move $t0 $a1 - lw $a1, 12($t6) - move $t3 $a1 - move $a0 $t0 - move $a1 $t3 - jal eq_string - move $t0 $v0 - j L_31 - L_30: - move $a0 $t3 - move $a1 $t6 - jal eqs - move $t0 $v0 - L_31: - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_15 - move $t0 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t0) - move $t0 $a1 - bne $t0 $zero L_32 - j L_33 - L_32: - li $a0, 0 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_15 - move $t0 $v0 - addi $sp, $sp, 4 - move $t0 $t0 - j L_34 - L_33: - li $a0, 1 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_15 - move $t0 $v0 - addi $sp, $sp, 4 - move $t0 $t0 - L_34: - move $t0 $t0 - L_35: - lw $a1, 12($t0) - move $t0 $a1 - bne $t0 $zero L_36 - j L_37 - L_36: - lw $a1, 20($t2) - move $t0 $a1 - lw $a1, 12($t0) - move $t3 $a1 - li $a0, 1 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t0) - move $t0 $a1 - add $t0 $t3 $t0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - sw $t0, 20($t2) - j L_23 - L_37: - lw $a1, 16($t2) - move $t4 $a1 - lw $a1, 20($t2) - move $t0 $a1 - lw $a1, 12($t0) - move $t3 $a1 - lw $a1, 20($t2) - move $t0 $a1 - lw $a1, 12($t0) - move $t0 $a1 - mul $t0 $t3 $t0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_14 - move $t3 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t4) - move $t0 $a1 - lw $a1, 12($t3) - move $t3 $a1 - move $a0 $t0 - move $a1 $t3 - jal less - move $t0 $v0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_15 - move $t0 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t0) - move $t0 $a1 - bne $t0 $zero L_38 - j L_39 - L_38: - lw $a1, 16($t2) - move $t0 $a1 - sw $t0, 12($t2) - lw $a1, 12($t2) - move $t0 $a1 - move $t0 $t0 - addi $sp, $sp, -4 - sw $t2, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - lw $t0, 0($t2) - la $a1, proto_table - sll $a2 $t0 2 - addu $a1 $a1 $a2 - lw $a1, 0($a1) - lw $a1, 8($a1) - addiu $a1 $a1 16 - lw $a1, 0($a1) - jal $a1 - move $t0 $v0 - addi $sp, $sp, 8 - la $t0, data_12 + 0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_10 - move $t0 $v0 - addi $sp, $sp, 4 - move $t0 $t0 - addi $sp, $sp, -4 - sw $t2, 0($sp) - addi $sp, $sp, -4 - sw $t0, 0($sp) - lw $t0, 0($t2) - la $a1, proto_table - sll $a2 $t0 2 - addu $a1 $a1 $a2 - lw $a1, 0($a1) - lw $a1, 8($a1) - addiu $a1 $a1 12 - lw $a1, 0($a1) - jal $a1 - move $t0 $v0 - addi $sp, $sp, 8 - move $t0 $t0 - j L_40 - L_39: - li $a0, 0 - addi $sp, $sp, -4 - sw $a0, 0($sp) - jal L_14 - move $t0 $v0 - addi $sp, $sp, 4 - move $t0 $t0 - L_40: - lw $a1, 24($t2) - move $t3 $a1 - lw $a1, 16($t2) - move $t0 $a1 - lw $a1, 12($t3) - move $t3 $a1 - lw $a1, 12($t0) - move $t0 $a1 - move $a0 $t3 - move $a1 $t0 - jal less_eq - move $t0 $v0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_15 - move $t0 $v0 - addi $sp, $sp, 4 - lw $a1, 12($t0) - move $t0 $a1 - bne $t0 $zero L_41 - j L_44 - L_41: - la $t0, data_13 + 0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_10 - move $t0 $v0 - addi $sp, $sp, 4 - move $t3 $t0 - move $a0 $t3 - li $a1, 0 - jal eqs - move $t0 $v0 - bne $t0 $zero L_42 - j L_43 - L_42: - li $v0, 4 - la $a0, data_14 - syscall - li $v0, 10 - syscall - L_43: - addi $sp, $sp, -4 - sw $t3, 0($sp) - lw $t0, 0($t3) - la $a1, proto_table - sll $a2 $t0 2 - addu $a1 $a1 $a2 - lw $a1, 0($a1) - lw $a1, 8($a1) - addiu $a1 $a1 4 - lw $a1, 0($a1) - jal $a1 - move $t0 $v0 - addi $sp, $sp, 4 - move $t0 $t0 - j L_45 - L_44: - la $t0, data_15 + 0 - addi $sp, $sp, -4 - sw $t0, 0($sp) - jal L_10 - move $t0 $v0 - addi $sp, $sp, 4 - move $t0 $t0 - L_45: - j L_21 - L_46: - sw $t1, 28($t2) - lw $t6, 0($sp) - addi $sp, $sp, 4 - lw $t7, 0($sp) - addi $sp, $sp, 4 - lw $a0, 0($sp) - addi $sp, $sp, 4 - lw $t2, 0($sp) - addi $sp, $sp, 4 - lw $t3, 0($sp) - addi $sp, $sp, 4 - lw $a1, 0($sp) - addi $sp, $sp, 4 - lw $t4, 0($sp) - addi $sp, $sp, 4 - lw $ra, 0($sp) - addi $sp, $sp, 4 - lw $t0, 0($sp) - addi $sp, $sp, 4 - lw $t5, 0($sp) - addi $sp, $sp, 4 - lw $a2, 0($sp) - addi $sp, $sp, 4 - addi $sp, $sp, 440 - lw $fp, 0($sp) - addi $sp, $sp, 4 - jr $ra - - - - alloc_size = 2048 - free_list = 0 - header_size = 12 - header_size_slot = 0 - header_next_slot = 4 - header_reachable_slot = 8 - init_alloc_size = 28 - int_type = 0 - meta_data_obj_size = 4 - neg_header_size = -12 - new_line = 10 - obj_mark = -1 - obj_extended = -2 - reachable = 1 - state_size = 4 - stack_base = -4 - string_size_treshold = 1024 - string_type = 0 - total_alloc_size = 2060 - num_type = 0 - used_list = header_size - -verify_obj: - addiu $sp $sp -20 - sw $t0 0($sp) - sw $t1 4($sp) - sw $t2 8($sp) - sw $t3 12($sp) - sw $a0 16($sp) - - move $t0 $a0 - - li $v0 9 - move $a0 $zero - syscall - - addiu $t1 $v0 -4 - - - blt $t0 $gp verify_obj_not_obj - bgt $t0 $t1 verify_obj_not_obj - lw $t2 0($t0) - blt $t2 $zero verify_obj_not_obj - la $t3 num_type - lw $t3 0($t3) - bge $t2 $t3 verify_obj_not_obj - - addiu $t0 $t0 4 - blt $t0 $gp verify_obj_not_obj - bgt $t0 $t1 verify_obj_not_obj - lw $t2 0($t0) - - addiu $t0 $t0 8 - - - li $t3 meta_data_obj_size - sub $t2 $t2 $t3 - sll $t2 $t2 2 - addu $t0 $t0 $t2 - - - blt $t0 $gp verify_obj_not_obj - bgt $t0 $t1 verify_obj_not_obj - lw $t2 0($t0) - beq $t2 obj_mark verify_obj_is_obj - beq $t2 obj_extended verify_obj_is_obj - -verify_obj_not_obj: - li $v0 0 - j verify_obj_finish - -verify_obj_is_obj: - li $v0 1 - -verify_obj_finish: - lw $t0 0($sp) - lw $t1 4($sp) - lw $t2 8($sp) - lw $t3 12($sp) - lw $a0 16($sp) - addiu $sp $sp 20 - - jr $ra - -concat: - addiu $sp $sp -24 - sw $t0 0($sp) - sw $t1 4($sp) - sw $t2 8($sp) - sw $a0 12($sp) - sw $a1 16($sp) - sw $ra 20($sp) - - move $t0 $a0 - move $t1 $a1 - - - addiu $a0 $a2 1 - li $t2 4 - div $a0 $t2 - mfhi $a0 - bne $a0 $zero concat_allign_size - addiu $a0 $a2 1 - -concat_size_alligned: - jal malloc - move $t2 $v0 - j concat_copy_first_cycle - -concat_allign_size: - sub $t2 $t2 $a0 - add $a0 $a2 $t2 - addiu $a0 $a0 1 - j concat_size_alligned - -concat_copy_first_cycle: - lb $a0 0($t0) - beq $a0 $zero concat_copy_second_cycle - sb $a0 0($t2) - addiu $t0 $t0 1 - addiu $t2 $t2 1 - j concat_copy_first_cycle - -concat_copy_second_cycle: - lb $a0 0($t1) - beq $a0 $zero concat_finish - sb $a0 0($t2) - addiu $t1 $t1 1 - addiu $t2 $t2 1 - j concat_copy_second_cycle - -concat_finish: - sb $zero 0($t2) - lw $t0 0($sp) - lw $t1 4($sp) - lw $t2 8($sp) - lw $a0 12($sp) - lw $a1 16($sp) - lw $ra 20($sp) - addiu $sp $sp 24 - - jr $ra - -copy: - addiu $sp $sp -16 - sw $a0 0($sp) - sw $a1 4($sp) - sw $a2 8($sp) - sw $t0 12($sp) - -copy_cycle: - beq $a2 $zero copy_finish - lw $t0 0($a0) - sw $t0 0($a1) - addiu $a0 $a0 4 - addiu $a1 $a1 4 - addi $a2 $a2 -4 - j copy_cycle - -copy_finish: - lw $a0 0($sp) - lw $a1 4($sp) - lw $a2 8($sp) - lw $t0 12($sp) - addiu $sp $sp 16 - - jr $ra - -eqs: - beq $a0 $a1 eqs_eq - li $v0 0 - j eqs_finish - -eqs_eq: - li $v0 1 - -eqs_finish: - jr $ra - -eq_string: - addiu $sp $sp -16 - sw $t0 0($sp) - sw $t1 4($sp) - sw $t2 8($sp) - sw $t3 12($sp) - - move $t0 $a0 - move $t1 $a1 - -eq_string_cycle: - lb $t2 0($t0) - lb $t3 0($t1) - bne $t2 $t3 eq_string_not_eq - beq $t2 $zero eq_string_eq - - addiu $t0 $t0 1 - addiu $t1 $t1 1 - j eq_string_cycle - -eq_string_not_eq: - move $v0 $zero - j eq_string_finish - -eq_string_eq: - li $v0 1 - -eq_string_finish: - lw $t0 0($sp) - lw $t1 4($sp) - lw $t2 8($sp) - lw $t3 12($sp) - addiu $sp $sp 16 - - jr $ra - -extend_block: - addiu $sp $sp -16 - sw $t0 0($sp) - sw $t1 4($sp) - sw $t2 8($sp) - sw $t3 12($sp) - - - addiu $t0 $gp free_list - - beq $t0 $a0 extend_block_finish - move $t0 $a0 - - lw $t1 header_next_slot($t0) - lw $t2 header_size_slot($t0) - move $t3 $t2 - addiu $t2 $t2 header_size - addu $t2 $t2 $t0 - beq $t2 $t1 extend_block_extend - j extend_block_finish - -extend_block_extend: - lw $t2 header_size_slot($t1) - addi $t2 $t2 header_size - add $t2 $t2 $t3 - sw $t2 header_size_slot($t0) - lw $t1 header_next_slot($t1) - sw $t1 header_next_slot($t0) - -extend_block_finish: - lw $t0 0($sp) - lw $t1 4($sp) - lw $t2 8($sp) - lw $t3 12($sp) - addiu $sp $sp 16 - - jr $ra - -extend_heap: - addiu $sp $sp -12 - sw $a0 0($sp) - sw $a1 4($sp) - sw $t0 8($sp) - - - li $v0 9 - addiu $a0 $a1 header_size - syscall - - - move $t0 $a1 - sw $t0 header_size_slot($v0) - sw $zero header_next_slot($v0) - sw $zero header_reachable_slot($v0) - - - lw $t0, 0($sp) - sw $v0 header_next_slot($t0) - - move $a0 $t0 - lw $a1 4($sp) - lw $t0 8($sp) - addiu $sp $sp 12 - - jr $ra - -free_block: - addiu $sp $sp -28 - sw $t0 0($sp) - sw $t1 4($sp) - sw $t2 8($sp) - sw $a0 12($sp) - sw $ra 16($sp) - sw $t3 20($sp) - sw $t4 24($sp) - - move $t0 $a0 - - addiu $t1 $gp free_list - - addiu $t3 $gp used_list - -free_block_cycle_used_list: - lw $t4 header_next_slot($t3) - beq $t4 $t0 free_block_cycle_free_list - move $t3 $t4 - j free_block_cycle_used_list - -free_block_cycle_free_list: - lw $t2 header_next_slot($t1) - beq $t2 $zero free_block_founded_prev - bge $t2 $t0 free_block_founded_prev - move $t1 $t2 - j free_block_cycle_free_list - -free_block_founded_prev: - lw $t4 header_next_slot($t0) - sw $t4 header_next_slot($t3) - - - sw $t2 header_next_slot($t0) - sw $t0 header_next_slot($t1) - -free_block_finish: - - move $a0 $t0 - jal extend_block - move $a0 $t1 - jal extend_block - - lw $t0 0($sp) - lw $t1 4($sp) - lw $t2 8($sp) - lw $a0 12($sp) - lw $ra 16($sp) - lw $t3 20($sp) - lw $t4 24($sp) - addiu $sp $sp 28 - - jr $ra - -get_gc: - addiu $sp $sp -24 - sw $t0 0($sp) - sw $t1 4($sp) - sw $t2 8($sp) - sw $t3 12($sp) - sw $a0 16($sp) - sw $ra 20($sp) - - li $t3 reachable - addiu $t0 $sp 20 - lw $t1 stack_base($gp) - - li $t2 1 - -get_gc_cycle: - - addiu $t0 $t0 4 - beq $t0 $t1 get_gc_dfs - - lw $a0 0($t0) - jal verify_obj - - bne $v0 $t2 get_gc_cycle - - addiu $a0 $a0 neg_header_size - sw $t3 header_reachable_slot($a0) - - j get_gc_cycle - -get_gc_dfs: - addiu $t1 $gp used_list - -get_gc_outer_cycle: - lw $t1 header_next_slot($t1) - beq $t1 $zero get_gc_free - lw $t2 header_reachable_slot($t1) - beq $t2 reachable get_gc_extend - j get_gc_outer_cycle - -get_gc_extend: - addiu $a0 $t1 header_size - jal get_gc_rec_extend - j get_gc_outer_cycle - -get_gc_free: - addiu $t0 $gp used_list - lw $t0 header_next_slot($t0) - -get_gc_free_cycle: - beq $t0 $zero get_gc_finish - lw $t1 header_reachable_slot($t0) - bne $t1 reachable get_gc_free_cycle_free - sw $zero header_reachable_slot($t0) - move $a0 $t0 - jal verify_obj - beq $v0 $zero get_gc_free_cycle - li $t1 obj_mark - addiu $t2 $t0 header_size - lw $t3 4($t2) - sll $t3 $t3 2 - addu $t2 $t2 $t3 - sw $t1 -4($t2) - lw $t0 header_next_slot($t0) - j get_gc_free_cycle - -get_gc_free_cycle_free: - move $a0 $t0 - lw $t0 header_next_slot($t0) - jal free_block - j get_gc_free_cycle - -get_gc_finish: - lw $t0 0($sp) - lw $t1 4($sp) - lw $t2 8($sp) - lw $t3 12($sp) - lw $a0 16($sp) - lw $ra 20($sp) - addiu $sp $sp 24 - - jr $ra - -get_gc_rec_extend: - addiu $sp $sp -16 - sw $a0 0($sp) - sw $t0 4($sp) - sw $t1 8($sp) - sw $ra 12($sp) - - jal verify_obj - beq $v0 $zero get_gc_rec_extend_finish - - lw $t0 4($a0) - sll $t0 $t0 2 - addiu $t0 $t0 -4 - addu $t0 $a0 $t0 - lw $t1 0($t0) - beq $t1 obj_extended get_gc_rec_extend_finish - - - li $t1 reachable - addiu $a0 $a0 neg_header_size - sw $t1 header_reachable_slot($a0) - addiu $a0 $a0 header_size - - - li $t1 obj_extended - sw $t1 0($t0) - - lw $t0 0($a0) - - - la $t1 int_type - lw $t1 0($t1) - beq $t0 $t1 get_gc_rec_extend_finish - - la $t1 string_type - lw $t1 0($t1) - beq $t0 $t1 get_gc_rec_extend_string_obj - - lw $t0 4($a0) - li $t1 meta_data_obj_size - sub $t0 $t0 $t1 - - addiu $t1 $a0 12 - -get_gc_rec_extend_attr_cycle: - beq $t0 $zero get_gc_rec_extend_finish - lw $a0 0($t1) - jal get_gc_rec_extend - addiu $t1 $t1 4 - sub $t0 $t0 1 - j get_gc_rec_extend_attr_cycle - -get_gc_rec_extend_string_obj: - lw $t0 8($a0) - addiu $t0 $t0 neg_header_size - li $t1 reachable - sw $t1 header_reachable_slot($t0) - -get_gc_rec_extend_finish: - lw $a0 0($sp) - lw $t0 4($sp) - lw $t1 8($sp) - lw $ra 12($sp) - addiu $sp $sp 16 - - jr $ra - -less_eq: - ble $a0 $a1 less_eq_true - li $v0 0 - j less_eq_finish - -less_eq_true: - li $v0 1 - -less_eq_finish: - jr $ra - -less: - blt $a0 $a1 less_true - li $v0 0 - j less_finish - -less_true: - li $v0 1 - -less_finish: - jr $ra - -len: - addiu $sp $sp -8 - sw $t0 0($sp) - sw $t1 4($sp) - - move $t0 $a0 - move $v0 $zero - -len_cycle: - lb $t1 0($t0) - beq $t1 $zero len_finish - addi $v0 $v0 1 - addiu $t0 $t0 1 - j len_cycle - -len_finish: - lw $t0 0($sp) - lw $t1 4($sp) - addiu $sp $sp 8 - - jr $ra - -malloc: - move $v0 $zero - addiu $sp $sp -28 - sw $t1 0($sp) - sw $t0 4($sp) - sw $a0 8($sp) - sw $a1 12($sp) - sw $ra 16($sp) - sw $t2 20($sp) - sw $t3 24($sp) - - addiu $t0 $gp free_list - j malloc_cycle - -malloc_finish: - move $a0 $v0 - lw $a1 8($sp) - jal divide_block - - lw $t1 header_next_slot($v0) - sw $t1 header_next_slot($t3) - - addiu $t1 $gp used_list - lw $a0 header_next_slot($t1) - - sw $a0 header_next_slot($v0) - sw $v0 header_next_slot($t1) - - addiu $v0 $v0 header_size - - lw $t3 24($sp) - lw $t2 20($sp) - lw $ra 16($sp) - lw $a1 12($sp) - lw $a0 8($sp) - lw $t0 4($sp) - lw $t1 0($sp) - addiu $sp $sp 28 - - jr $ra - -malloc_cycle: - move $t2 $t0 - lw $t0 header_next_slot($t0) - beq $t0 $zero malloc_search_finish - j malloc_verify_valid_block - -malloc_search_finish: - beq $v0 $zero malloc_alloc_new_block - j malloc_finish - -malloc_alloc_new_block: - li $t1 alloc_size - move $t3 $t2 - move $a1 $a0 - move $a0 $t2 - bge $a1 $t1 malloc_big_block - li $a1 alloc_size - jal extend_heap - - j malloc_finish - -malloc_big_block: - jal extend_heap - j malloc_finish - -malloc_verify_valid_block: - lw $t1 header_size_slot($t0) - bge $t1 $a0 malloc_valid_block - j malloc_cycle - -malloc_valid_block: - beq $v0 $zero malloc_first_valid_block - bge $t1 $v1 malloc_cycle - move $v0 $t0 - move $v1 $t1 - move $t3 $t2 - j malloc_cycle - -malloc_first_valid_block: - move $v0 $t0 - move $v1 $t1 - move $t3 $t2 - j malloc_cycle - -mem_manager_init: - addiu $sp $sp -16 - sw $v0 0($sp) - sw $a0 4($sp) - sw $a1 8($sp) - sw $ra 12($sp) - li $v0 9 - li $a0 init_alloc_size - syscall - move $gp $v0 - addiu $gp $gp state_size - - sw $zero header_size_slot($gp) - sw $zero header_reachable_slot($gp) - - move $a0 $gp - li $a1 alloc_size - jal extend_heap - - addiu $a0 $a0 header_size - sw $zero header_size_slot($a0) - sw $zero header_next_slot($a0) - sw $zero header_reachable_slot($a0) - - - - lw $v0 0($sp) - lw $a0 4($sp) - lw $a1 8($sp) - lw $ra 12($sp) - addiu $sp $sp 16 - - sw $sp stack_base($gp) - - jr $ra - -get_string: - addiu $sp $sp -36 - sw $t0 0($sp) - sw $t1 4($sp) - sw $t2 8($sp) - sw $t3 12($sp) - sw $t4 16($sp) - sw $t5 20($sp) - sw $a0 24($sp) - sw $a1 28($sp) - sw $ra 32($sp) - - addiu $t0 $gp free_list - move $t1 $zero - move $t2 $t0 - -get_string_larger_block_cycle: - lw $t0 header_next_slot($t0) - beq $t0 $zero get_string_reading - lw $t3 header_size_slot($t0) - bge $t1 $t3 get_string_larger_block_cycle - move $t1 $t3 - move $t2 $t0 - j get_string_larger_block_cycle - -get_string_reading: - beq $t1 $zero get_string_new_block - move $a1 $t1 - li $v0 8 - addiu $a0 $t2 header_size - syscall - move $t0 $a0 - move $t1 $zero - -get_string_look_nl: - lb $t2 0($t0) - beq $t2 new_line get_string_nl_founded - beq $t2 $zero get_string_zero_founded - addi $t1 $t1 1 - addi $t0 $t0 1 - j get_string_look_nl - -get_string_zero_founded: - blt $t1 $t3 get_string_nl_founded - j get_string_no_nl - -get_string_nl_founded: - sb $zero 0($t0) - addi $t1 $t1 1 - li $t2 4 - div $t1 $t2 - mfhi $t3 - beq $t3 $zero get_string_nl_founded_alligned - sub $t2 $t2 $t3 - add $t1 $t1 $t2 - -get_string_nl_founded_alligned: - move $a1 $t1 - addiu $a0 $a0 neg_header_size - jal divide_block - jal use_block - - addiu $v0 $a0 header_size - j get_string_finish - -get_string_no_nl: - addi $t1 $t1 1 - blt $t1 string_size_treshold get_string_dup - addi $t1 $t1 alloc_size - j get_string_extend_heap - -get_string_dup: - sll $t1 $t1 1 - -get_string_extend_heap: - move $a1 $t1 - move $t0 $a0 - addiu $a0 $gp free_list - -get_string_last_block_cycle: - lw $t1 header_next_slot($a0) - beq $t1 $zero get_string_last_block_founded - lw $a0 header_next_slot($a0) - j get_string_last_block_cycle - -get_string_last_block_founded: - jal extend_heap - jal extend_block - lw $t1 header_next_slot($a0) - bne $t1 $zero get_string_copy_prev - move $t1 $a0 - -get_string_copy_prev: - lw $t3 header_size_slot($t1) - move $t2 $zero - move $t5 $t1 - addiu $t1 $t1 header_size - -get_string_copy_cycle: - lb $t4 0($t0) - beq $t4 $zero get_string_copy_finish - sb $t4 0($t1) - addi $t2 $t2 1 - addi $t0 $t0 1 - addi $t1 $t1 1 - j get_string_copy_cycle - -get_string_copy_finish: - sub $t3 $t3 $t2 - move $a0 $t1 - move $a1 $t3 - li $v0 8 - syscall - move $t0 $a0 - move $t1 $t2 - addiu $a0 $t5 header_size - j get_string_look_nl - -get_string_finish: - lw $t0 0($sp) - lw $t1 4($sp) - lw $t2 8($sp) - lw $t3 12($sp) - lw $t4 16($sp) - lw $t5 20($sp) - lw $a0 24($sp) - lw $a1 28($sp) - lw $ra 32($sp) - addiu $sp $sp 36 - - jr $ra - -get_string_new_block: - addiu $t0 $gp free_list - -get_string_new_block_search_last: - lw $t1 header_next_slot($t0) - beq $t1 $zero get_string_new_block_create - move $t0 $t1 - j get_string_new_block_search_last - -get_string_new_block_create: - move $a0 $t0 - li $a1 alloc_size - jal extend_heap - jal extend_block - lw $t2 header_next_slot($a0) - beq $t2 $zero get_string_new_block_extended - lw $t1 header_size_slot($t2) - j get_string_reading - -get_string_new_block_extended: - move $t2 $a0 - lw $t1 header_size_slot($a0) - j get_string_reading - -divide_block: - addiu $sp $sp -16 - sw $t0 0($sp) - sw $t1 4($sp) - sw $a0 8($sp) - sw $a1 12($sp) - - - lw $t0 header_size_slot($a0) - bgt $a1 $t0 divide_block_error_small - - - sub $t0 $t0 $a1 - li $t1 header_size - ble $t0 $t1 divide_block_same_size - - - addu $t0 $a0 $a1 - addiu $t0 $t0 header_size - - - lw $t1 header_next_slot($a0) - sw $t1 header_next_slot($t0) - sw $t0 header_next_slot($a0) - - lw $t1 header_size_slot($a0) - sub $t1 $t1 $a1 - - addi $t1 $t1 neg_header_size - sw $t1 header_size_slot($t0) - sw $a1 header_size_slot($a0) - move $v0 $a0 - j divide_block_finish - -divide_block_same_size: - move $v0 $a0 - j divide_block_finish - -divide_block_error_small: - j divide_block_finish - -divide_block_finish: - lw $t0 0($sp) - lw $t1 4($sp) - lw $a0 8($sp) - lw $a1 12($sp) - addiu $sp $sp 16 - - jr $ra - -sub_string: - addiu $sp $sp -24 - sw $t0 0($sp) - sw $t1 4($sp) - sw $t2 8($sp) - sw $t3 12($sp) - sw $a0 16($sp) - sw $ra 20($sp) - - move $t0 $a0 - li $t1 4 - addiu $t3 $a2 1 - div $t3 $t1 - - mfhi $t2 - bne $t2 $zero sub_string_allign_size - move $t1 $t3 - j sub_string_new_block - -sub_string_allign_size: - sub $t1 $t1 $t2 - add $t1 $t1 $t3 - -sub_string_new_block: - move $a0 $t1 - jal malloc - move $t3 $v0 - move $t1 $zero - addu $t0 $t0 $a1 - -sub_string_copy_cycle: - beq $t1 $a2 sub_string_finish - lb $t2 0($t0) - sb $t2 0($t3) - addiu $t0 $t0 1 - addiu $t3 $t3 1 - addiu $t1 $t1 1 - j sub_string_copy_cycle - -sub_string_finish: - sb $zero 0($t3) - lw $t0 0($sp) - lw $t1 4($sp) - lw $t2 8($sp) - lw $t3 12($sp) - lw $a0 16($sp) - lw $ra 20($sp) - addiu $sp $sp 24 - - jr $ra - -use_block: - addiu $sp $sp -12 - sw $t0 0($sp) - sw $t1 4($sp) - sw $t2 8($sp) - - addiu $t0 $gp free_list - -use_block_cycle: - move $t1 $t0 - lw $t0 header_next_slot($t0) - beq $t0 $zero use_block_finish - beq $t0 $a0 use_block_founded - j use_block_cycle - -use_block_founded: - lw $t2 header_next_slot($t0) - sw $t2 header_next_slot($t1) - - addiu $t1 $gp used_list - lw $t2 header_next_slot($t1) - sw $t0 header_next_slot($t1) - sw $t2 header_next_slot($t0) - -use_block_finish: - lw $t0 0($sp) - lw $t1 4($sp) - lw $t2 8($sp) - addiu $sp $sp 12 - - jr $ra - From acbe11eee528a50b1eb98a51f8c1b4bf25d51261 Mon Sep 17 00:00:00 2001 From: Ale Date: Fri, 25 Feb 2022 21:00:05 -0800 Subject: [PATCH 81/83] rename to report --- doc/{Informe => Report}/files/SPIM_Manual.pdf | Bin doc/{Informe => Report}/files/compilers.pdf | Bin doc/{Informe => Report}/files/cool-manual.pdf | Bin .../files/github-git-cheat-sheet.pdf | Bin 4 files changed, 0 insertions(+), 0 deletions(-) rename doc/{Informe => Report}/files/SPIM_Manual.pdf (100%) rename doc/{Informe => Report}/files/compilers.pdf (100%) rename doc/{Informe => Report}/files/cool-manual.pdf (100%) rename doc/{Informe => Report}/files/github-git-cheat-sheet.pdf (100%) diff --git a/doc/Informe/files/SPIM_Manual.pdf b/doc/Report/files/SPIM_Manual.pdf similarity index 100% rename from doc/Informe/files/SPIM_Manual.pdf rename to doc/Report/files/SPIM_Manual.pdf diff --git a/doc/Informe/files/compilers.pdf b/doc/Report/files/compilers.pdf similarity index 100% rename from doc/Informe/files/compilers.pdf rename to doc/Report/files/compilers.pdf diff --git a/doc/Informe/files/cool-manual.pdf b/doc/Report/files/cool-manual.pdf similarity index 100% rename from doc/Informe/files/cool-manual.pdf rename to doc/Report/files/cool-manual.pdf diff --git a/doc/Informe/files/github-git-cheat-sheet.pdf b/doc/Report/files/github-git-cheat-sheet.pdf similarity index 100% rename from doc/Informe/files/github-git-cheat-sheet.pdf rename to doc/Report/files/github-git-cheat-sheet.pdf From 66e4e4a78dd692cd1fd27003fe65c605464eb9e2 Mon Sep 17 00:00:00 2001 From: Ale Date: Fri, 25 Feb 2022 22:21:32 -0800 Subject: [PATCH 82/83] report --- doc/Report/report.pdf | Bin 0 -> 138498 bytes doc/Report/report.tex | 215 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 215 insertions(+) create mode 100644 doc/Report/report.pdf create mode 100644 doc/Report/report.tex diff --git a/doc/Report/report.pdf b/doc/Report/report.pdf new file mode 100644 index 0000000000000000000000000000000000000000..0d4b4907b1a3e1d442e60e4f142ef6642225cc61 GIT binary patch literal 138498 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

SzHy5Zm;)CIy~7R^(gxnDn->iceDnv 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 Date: Sat, 26 Feb 2022 22:38:19 -0800 Subject: [PATCH 83/83] update report --- doc/Report/report.pdf | Bin 138498 -> 138493 bytes doc/Report/report.tex | 14 +++++++------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/Report/report.pdf b/doc/Report/report.pdf index 0d4b4907b1a3e1d442e60e4f142ef6642225cc61..ec0da7e3ec699247ce15c3a524aa36ee56526474 100644 GIT binary patch delta 11425 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 B`fLCI diff --git a/doc/Report/report.tex b/doc/Report/report.tex index 46fe42451..43af13d3e 100644 --- a/doc/Report/report.tex +++ b/doc/Report/report.tex @@ -62,14 +62,14 @@ \begin{center} \textbf{Resumen} \end{center} -\noindent \textit{Este reporte contiene las principales ideas seguidas en la implementaci\'on de un compilador completamente funcional para el lenguaje COOL. El cual es un peque\~no lenguaje que mantiene muchas de las caracter\'isticas de los lenguajes de programaci\'on modernos, incluyendo orientaci\'on a objetos, tipado est\'atico y manejo autom\'atico de memoria. A lo largo de este informe se explicar\'an, adem\'as, cada una de las etapas o fases seguidas en la implementaci\'on del compilador. Por \'ultimo, daremos, a groso modo, una peque\~na ojeada al c\'odigo con el objetivo de que el lector entienda el funcionamiento de los m\'etodos que consideramos fundamentales para el desarrollo del compilador.}\\[0.5cm] +\noindent \textit{Este reporte contiene las principales ideas seguidas en la implementaci\'on de un compilador completamente funcional para el lenguaje COOL, el cual es un peque\~no lenguaje que mantiene muchas de las caracter\'isticas de los lenguajes de programaci\'on modernos, incluyendo orientaci\'on a objetos, tipado est\'atico y manejo autom\'atico de memoria. A lo largo de este informe se explicar\'an, adem\'as, cada una de las etapas o fases seguidas en la implementaci\'on del compilador. Por \'ultimo, daremos, a groso modo, una peque\~na ojeada al c\'odigo con el objetivo de que el lector entienda el funcionamiento de los m\'etodos que consideramos fundamentales para el desarrollo del compilador.}\\[0.5cm] \section{Introducci\'on} Un compilador es un programa que traduce c\'odigo escrito en un lenguaje de programaci\'on, llamado fuente, a otro lenguaje. En este tipo de traductor, el lenguaje fuente es generalmente un lenguaje de alto nivel, y el otro, un lenguaje de bajo nivel. Un compilador es uno de los pilares de la programaci\'on y de c\'omo entender la comunicaci\'on entre un lenguaje de alto nivel y una m\'aquina. Al poder conocer el funcionamiento de este paso intermedio nos permitir\'a desarrollar y programar de una forma m\'as precisa en los lenguajes de alto nivel. El proceso de compilaci\'on es aquel por el cual se traducen las instrucciones escritas en un determinado lenguaje de programaci\'on a lenguaje de m\'aquina, es decir, a algo que la computadora entiende. En nuestro caso, el lenguaje fuente es COOL. Un programa en COOL son conjuntos de clases. Una clase encapsula las variables y procedimientos de un tipo de datos. Las instancias de una clase son objetos. En COOL se identifican clases y tipos; es decir, cada clase define un tipo. Las clases permiten a los programadores definir nuevos tipos y procedimientos asociados (o m\'etodos) espec\'ificos para esos tipos. La herencia permite que los nuevos tipos ampl\'ien el comportamiento de los tipos existentes. COOL es un lenguaje de expresi\'on. La mayor\'ia de las construcciones son expresiones, y cada expresi\'on tiene un valor y un tipo. Este lenguaje es type safe, es decir, se garantiza que los procedimientos se aplicar\'an a los datos del tipo correcto. Si bien el tipeo est\'atico impone una fuerte disciplina en la programaci\'on, garantiza que no puedan surgir errores de tipo en la ejecuci\'on de los programas en COOL. -Una vez se tiene una idea acerca del funcionamiento de un compilador y del lenguaje COOL, podemos decir que el objetivo de este informe es presentar la soluci\'on al proceso de compilaci\'on del lenguaje COOL a lenguaje ensamblador, implementado en el lenguaje de pogramaci\'on python. Cuyo c\'odigo se encuentra en este \href{https://github.com/BeginnerCompilers/cool-compiler-2021}{\textcolor{red}{\underline{repositorio}}} de Github.\\\\ +Una vez se tiene una idea acerca del funcionamiento de un compilador y del lenguaje COOL, podemos decir que el objetivo de este informe es presentar la soluci\'on al proceso de compilaci\'on del lenguaje COOL a lenguaje ensamblador, implementado en el lenguaje de pogramaci\'on python, cuyo c\'odigo se encuentra en este \href{https://github.com/BeginnerCompilers/cool-compiler-2021}{\textcolor{red}{\underline{repositorio}}} de Github.\\\\ \section{Gram\'atica y AST de COOL} La gram\'atica de este lenguaje responde al manual de COOL \cite{cool}. Se encuentra definida en \texttt{src/utils/COOL\_Grammar.py} y su estructura se presenta a continuaci\'on:\\ @@ -139,7 +139,7 @@ \section{Gram\'atica y AST de COOL} &\rightarrow \textit{expr , non-empty-arg-list}\\ \end{align*} -El \'arbol de sint\'axis abstracta de COOL se encuentra definido en \texttt{src/utils/ast/AST\_Nodes.py}. Se defini\'o teniendo en cuenta la gram\'atica que definimos anteriormente. Esta gram\'atica es atributada y cada producci\'on contiene como computar cada uno de los atributos que la conforman que, en la mayor\'ia de los casos son argumentos que se pasan como par\'ametros para la creaci\'on de los nodos del ast de nuestro lenguaje.\\\\ +El \'arbol de sint\'axis abstracta de COOL se encuentra definido en \texttt{src/utils/ast/AST\_Nodes.py}. Se defini\'o teniendo en cuenta la gram\'atica que mostramos anteriormente. Esta gram\'atica es atributada y cada producci\'on contiene como computar cada uno de los atributos que la conforman que, en la mayor\'ia de los casos, son argumentos que se pasan como par\'ametros para la creaci\'on de los nodos del ast de nuestro lenguaje.\\\\ \section{An\'alisis lexicogr\'afico.} @@ -171,16 +171,16 @@ \section{An\'alisis Sem\'antico} \section{Generaci\'on de c\'odigo} -Para la generaci\'on de c\'odigo intermedio de COOL a MIPS vamos a dise\~nar un lenguaje de m\'aquina con capacidades orientadas a objeto. Este lenguaje nos va a permitir generar c\'odigo de MIPS de forma m\'as sencilla, ya que el salto directamente desde COOL a MIPS es demasiado complejo. Este lenguaje se denomina CIL, 3-address object-oriented. +Para la generaci\'on de c\'odigo intermedio de COOL a MIPS vamos a dise\~nar un lenguaje de m\'aquina con capacidades orientadas a objetos. Este lenguaje nos va a permitir generar c\'odigo de MIPS de forma m\'as sencilla, ya que el salto directamente desde COOL a MIPS es demasiado complejo. Este lenguaje se denomina CIL, 3-address object-oriented. En esta fase no hay incosistencia de tipos, es decir el c\'odigo de COOL est\'a lexicogr\'afica, sint\'actica y sem\'anticamente correcto, listo para la ejecuci\'on. Esta fase se encuentra implementada en \texttt{src/utils/code\_generation} \subsection{CIL} -Como ya se dijo, primeramente, pasaremos de COOL para un lenguaje intermedio, CIL. El ast de este lenguaje se implement\'o seg\'un la definici\'on brindada en \cite{compilers} Cap\'itulo 7. Donde, adem\'as de las funciones que ah\'i se describen, se a\~naden otras para realizar la ejecuci\'on de las funciones predefinidas en COOL, y que son necesarias para el retorno de valores de m\'etodos de este lenguaje. +Como ya se dijo, primeramente, pasaremos de COOL para un lenguaje intermedio, CIL. El ast de este lenguaje se implement\'o seg\'un la definici\'on brindada en \cite{compilers} Cap\'itulo 7, donde, adem\'as de las funciones que ah\'i se describen, se a\~naden otras para realizar la ejecuci\'on de las funciones predefinidas en COOL, y que son necesarias para el retorno de valores de m\'etodos de este lenguaje. -Con ayuda del patr\'on visitor se recorre el ast de COOL y, primeramente se a\~naden todas las funciones y tipos built-in, es decir, que est\'an definidas por defecto en COOL. Posteriormente, por cada nodo del ast de COOL se crean las instrucciones correspondientes en CIL de acuerdo a su definici\'on. +Con ayuda del patr\'on visitor se recorre el ast de COOL y, primeramente, se a\~naden todas las funciones y tipos built-in, es decir, que est\'an definidas por defecto en COOL. Posteriormente, por cada nodo del ast de COOL se crean las instrucciones correspondientes en CIL de acuerdo a su definici\'on. -Contamos con una clase auxiliar, \texttt{BaseCOOLToCIL}, que contiene funciones \'utiles para el registro de par\'ametros, funciones, instrucciones, variables locales y otras declaraciones en CIL. Esta clase contiene, adem\'as, la definici\'on de los me\'etodos built-in de COOL.\\ +Contamos con una clase auxiliar, \texttt{BaseCOOLToCIL}, que contiene funciones \'utiles para el registro de par\'ametros, funciones, instrucciones, variables locales y otras declaraciones en CIL. Esta clase contiene, adem\'as, la definici\'on de los m\'etodos built-in de COOL.\\ \subsection{MIPS} Despu\'es de tener el ast de CIL, el siguiente paso es, finalmente, generar el c\'odigo ensamblador correspondiente a la entrada de COOL. Para ello, primeramente definimos el ast de MIPS, con ayuda de \cite{mips}, en el cual cada nodo representa una instrucci\'on v\'alida en MIPS. Siguiendo la misma idea de generaci\'on de c\'odigo anterior, se recorre cada nodo del ast de CIL y se va creando el correspondiente ast v\'alido en MIPS. Una vez m\'as, los recorridos de cada ast se realizan con ayuda del patr\'on visitor, mediante el cual tambi\'en, se genera el c\'odigo ensamblador en la clase \texttt{PrintMIPS}, que tranforma cada nodo del ast en el c\'odigo de MIPS correspondiente.