def play(self, scope=None): scope = Scope(scope) scope['_USER_INDEX_'] = self.user_index assert self.scripts == [] and self.children == [] global_reporter = scope.lookup('global_reporter') if global_reporter: reporter = global_reporter.get_reporter() scope['reporter'] = reporter else: reporter = None try: if self.iteration_factory: self.before(scope) for i in range(self.iteration_count): # TODO: put _ITERATION_INDEX_ in iteration scope instead of user scope scope['_ITERATION_INDEX_'] = i iteration = self.iteration_factory.create() iteration.player = self.player Player.execute_here(self, iteration, scope) self.after(scope) else: try: for i in range(self.iteration_count): scope['_ITERATION_INDEX_'] = i self.children.append(self.player) Player.play(self, scope) finally: self.children = [] except Errors.TerminateUser, e: log.exception('User terminated because of %s' % e)
def play(self, scope = None): scope = Scope(scope) scope['_USER_INDEX_'] = self.user_index assert self.scripts == [] and self.children == [] global_reporter = scope.lookup('global_reporter') if global_reporter: reporter = global_reporter.get_reporter() scope['reporter'] = reporter else: reporter = None try: if self.iteration_factory: self.before(scope) for i in range(self.iteration_count): # TODO: put _ITERATION_INDEX_ in iteration scope instead of user scope scope['_ITERATION_INDEX_'] = i iteration = self.iteration_factory.create() iteration.player = self.player Player.execute_here(self, iteration, scope) self.after(scope) else: try: for i in range(self.iteration_count): scope['_ITERATION_INDEX_'] = i self.children.append(self.player) Player.play(self, scope) finally: self.children = [] except Errors.TerminateUser, e: log.exception('User terminated because of %s' % e)
def test_variable(self): var_expr = Name(id='x') env = Scope([]) new_env = env.extend('x',(Num(3), env)) k = Done() val = step(var_expr, new_env, k) self.assertEqual(val[0].n, 3)
def __init__(self): self.global_scope = Scope("GLOBAL") self.global_scope.build_global([ BuiltInTypeSymbol("STRING"), BuiltInTypeSymbol("INT"), BuiltInTypeSymbol("BOOL"), BuiltInTypeSymbol("NULL"), ])
def testGlobalVariables(self): scope = Scope() scope['i'] = 1 self.If = If('i') self.If.add_child(Script('j = i')) self.If.add_child(Script('i = 0')) self.If.afterscript = Script('assert i == 0') self.If.play(Scope(scope)) self.assertEquals(scope['i'], 0)
def add_module(self, module, buffer_size=2**11): if module not in self.modules: s = Scope(buffer_size) s.set_title(module.__class__.__name__) module.set_scope(s) self.modules.append(module) self.partition() return True return False
def playmain(self, basescope): for script in self.scripts: script.execute(basescope) for child in self.children: #child.play(Scope(basescope)) # this has memory leak, use below... new_scope = Scope(basescope) child.play(new_scope) # XXX: fix memory leak -- why I need this? new_scope.clear()
def program_f(self, args): scope = Scope('global') children_scopes = get_scopes_of_children(args) set_parent_of_children_scope(scope, children_scopes) set_children_of_parent_scope(scope, children_scopes) decls = [args[0]] for decl in args[1]['decls']: decls.append(decl) for decl in decls: scope.decls[decl['id']] = decl return {'scopes': [scope], 'decls': decls}
def __init__(self, observer = Observer(), token_list=[], print_symbol_table = 0, visitor = Visitor()): self.current = 0 # current position in token list self.token_list = token_list # token list received from scanner self.kind_map = Token.kind_map # dictionary of token kinds self.observer = observer # output class determined by cmd line arguments self.total_error_flag = 0 # detects if an error occurs anywhere in the program self.universe = Scope(None) # universe scope self.universe.insert("INTEGER", integerInstance) # universe scope only holds integer self.program_scope = Scope(self.universe) # program scope to hold program names self.current_scope = self.program_scope # current scope for switching between scopes self.print_symbol_table = print_symbol_table # determines whether to print cst or st self.visitor = visitor
def test_scope_local(self): u = Scope(None) i = Integer() u.insert("Integer", i) p = Scope(u) c = Constant(i, 5) p.insert("const", c) self.assertTrue(u.local("Integer")) self.assertTrue(p.local("const")) self.assertEqual(None, u.find("const")) self.assertEqual(i, p.find("Integer"))
def testBreak(self): import Globals g = Globals.copy_globals() g['Break'] = Break scope = Scope() scope.variables = g self.loop.add_script(Script('if y == 3: raise Break()')) self.loop.afterscript = Script('assert x == 3; assert y == 3') self.loop.play(scope) self.assertEqual(scope.lookup('x'), 3) self.assertEqual(scope.lookup('y'), 3)
def interface_decl_f(self, args): scope = Scope('interface') children_scopes = get_scopes_of_children(args) set_parent_of_children_scope(scope, children_scopes) set_children_of_parent_scope(scope, children_scopes) for prototype in args[1]['prototypes']: # TODO is it an error? (it seems it is) if scope.does_decl_id_exist(prototype['id']): raise SemErr(f'duplicate id for prototypes') scope.decls[prototype['id']] = prototype return { 'scopes': [scope], 'id': args[0]['value'], 'prototypes': args[1]['prototypes'] }
def parse(self): """Method called by sc to parse the code.""" # Create the universe scope. self.universe_scope = Scope(None) self.record_scope = None self.integer_type = Integer() self.universe_scope.insert("INTEGER", self.integer_type) # Start by getting the first token. self.next() # Start parsing by matching the grammar of program. self.stack.append("Program") tree = self.program() # Display the output only if no error has occured. if self.display: if self.parser_type == "-t": # Set the program scope if printing symbol table. self.output_object.program_scope = self.program_scope elif self.parser_type == "-a": # Set the program scope and instruction tree for AST output. self.output_object.program_scope = self.program_scope self.output_object.tree = tree elif self.parser_type == "-i": # Set the environment and instruction tree for interpreter. visitor = SymbolTableVisitor() self.output_object.env = self.current_scope.accept(visitor) self.output_object.tree = tree self.output_object.display()
def setUp(self): self.it_factory = IterationFactory() self.player = Script() self.scope = Scope() self.it_factory.beforescript.script = 'i = i + 1' self.user = User(self.player, 2, self.it_factory) self.user.beforescript.script = 'i = 0' self.user.afterscript.script = 'assert i == 2'
def __init__(self, parent, scope: Scope = None): self.definitions = [] self.alterations = [] if scope is None: scope = Scope(parent.scope.scope_handler) self.scope = scope super().__init__(parent, scope)
def class_decl_f(self, args): scope = Scope('class') children_scopes = get_scopes_of_children(args) set_parent_of_children_scope(scope, children_scopes) set_children_of_parent_scope(scope, children_scopes) fields = args[3]['fields'] for field in fields: decl = field['declaration'] decl['access_mode'] = field_access_mode if decl['decl_type'] == 'function': scope.decls[decl['id']] = decl decl['scope'].parent = scope decl['parent'] = args[0][ 'value'] # set parent of field function to class id for variable in decl['formals']: variable['fp_offset'] += 4 this_type = { 'scopes': [None], 'dim': 0, 'type': 'Object', 'class': args[0]['value'] } this_variable = { 'scopes': [None], 'fp_offset': 4, 'decl_type': 'variable', 'type': this_type } decl['formals'].insert(0, this_variable) elif decl['decl_type'] == 'variable': if scope.does_decl_id_exist(decl['id']): raise SemErr( f'duplicate id \'{decl["id"]}\' in class \'{args[0]["value"]}\'' ) scope.decls[decl['id']] = decl else: assert 1 == 2 # decl_type must be 'function' or 'variable', but it wasn't return { 'scopes': [scope], 'id': args[0]['value'], 'parent_class': args[1]['parent_class'], 'interfaces': args[2]['interfaces'], 'fields': args[3]['fields'] }
def stmt_block_f(self, args): scope = Scope('stmt_block') children_scopes = get_scopes_of_children(args) set_parent_of_children_scope(scope, children_scopes) set_children_of_parent_scope(scope, children_scopes) for variable_decl in args[0]['variable_decls']: if scope.does_decl_id_exist(variable_decl['id']): raise SemErr( f'duplicate id \'{variable_decl["id"]}\' declared many times as a variable' ) scope.decls[variable_decl['id']] = variable_decl variable_decl_count = len(args[0]['variable_decls']) # for stmt in args[1]['stmts']: # stmt['base_fp_offset'] = variable_decl_count * 4 return { 'scopes': [scope], 'variable_decls': args[0]['variable_decls'], 'stmts': args[1]['stmts'] }
def enterWhile_stmt(self, ctx: TinyParser.While_stmtContext): self.blockCt += 1 self.scope = Scope("BLOCK %d" % self.blockCt, self.scope) self.symbolTables.append(self.scope) # Labels for control statements out = "out%d" % self.blockCt repeat = "block%d" % self.blockCt self.assembly_code.append(["label %s" % (repeat)]) self.labelStack.append(repeat) self.labelStack.append(out)
def function_decl_f(self, args): scope = Scope('function') children_scopes = get_scopes_of_children(args) set_parent_of_children_scope(scope, children_scopes) set_children_of_parent_scope(scope, children_scopes) type_ = None id_ = None formal_variables = None stmt_block = None # if declared function returns type if len(args) == 4: type_ = args[0] id_ = args[1]['value'] formal_variables = args[2]['variables'] stmt_block = args[3] # if declared function returns void else: type_ = {'dim': 0, 'class': 'primitive', 'type': 'void'} id_ = args[0]['value'] formal_variables = args[1]['variables'] stmt_block = args[2] fp_offset = 4 for variable in formal_variables: variable['decl_type'] = 'variable' variable['fp_offset'] = fp_offset fp_offset += 4 if scope.does_decl_id_exist(variable['id']): raise SemErr( f'duplicate id \'{variable["id"]}\' in formals of function \'{args[1]["value"]}\'' ) scope.decls[variable['id']] = variable # stmt_block['base_fp_offset'] = -8 return { 'parent': 'GLOBAL', 'scopes': [scope], 'decl_type': 'function', 'type': type_, 'id': id_, 'formals': formal_variables, 'stmt_block': stmt_block }
def __init__(self): self.scope = Scope("GLOBAL") self.symbolTables = [self.scope] self.blockCt = 0 self.currVarType = None self.writeVar = True self.writeFlag = False self.readFlag = False self.registers = [] self.register_counter = 0 self.labelStack = [] self.assembly_code = []
def enterElse_part(self, ctx: TinyParser.Else_partContext): self.scope = self.scope.parent #self.assembly_code.append() if len(ctx.getText()) > 0: parent = self.scope.parent self.blockCt += 1 self.scope = Scope("BLOCK %d" % self.blockCt, parent) self.symbolTables.append(self.scope) # Labels for control statements label = self.labelStack.pop() self.assembly_code.append(["jmp %s" % (self.labelStack[-1])]) self.assembly_code.append(["label %s" % (label)])
def enterIf_stmt(self, ctx: TinyParser.If_stmtContext): self.blockCt += 1 self.scope = Scope("BLOCK %d" % self.blockCt, self.scope) self.symbolTables.append(self.scope) # Labels for control statements if len(ctx.else_part().getText()) > 0: elselbl = "else%d" % self.blockCt outlbl = "out%d" % (self.blockCt) self.labelStack.append(outlbl) self.labelStack.append(elselbl) else: outlbl = "out%d" % (self.blockCt) self.labelStack.append(outlbl)
def test_get(self): defs = Scope(()).extend('g', 2).extend('f', 1).extend('x', 2).extend('x', 3) defs2 = defs.extend('x', 3) defs3 = defs.extend('f', 3) assert defs2.get('x') == 3 assert defs2.get('x') == 3 assert defs3.get('f') == 3 assert defs.get('x') == 3 defs_a = Scope(()) defs_b = defs_a.extend('x',0) assert(defs_b.get('x') == 0) assert(defs_b.get('x') == 0)
def play_in_single_thread(self, scope=None): g = self.global_factory.create() users = [] scope = Scope(scope) scope['_USER_COUNT_'] = self.user_count scope['_ITERATION_COUNT_'] = self.iteration_count scope['_PLAYER_'] = self.player if self.reporter: scope['global_reporter'] = self.reporter g.before(scope) for i in range(self.user_count): user = self.user_factory.create() user.player = self.player user.iteration_count = self.iteration_count user.iteration_factory = self.iteration_factory user.user_index = i users.append(user) user.play(scope) g.after(scope)
def __init__(self): self.trees = [] self.smallest_error = 9999999999999999999999999999999999999999999999999999 for i in range(0, 10): scope = Scope(ScopeHandler()) scope.add_var(Variable("arg1", Type.INT)) scope.add_var(Variable("arg2", Type.INT)) scope.add_var(Variable("boolvar", Type.BOOL)) # add initial variables to scope. tree = Block(None, scope) self.trees.append(tree) self.best_tree = None
class HCS(object): def __init__(self, scope = None): self.scope = Scope() if scope is None else scope def parse(self, source): grammar = '\n'.join(v.__doc__ for k, v in vars(self.__class__).items() if '__' not in k and hasattr(v, '__doc__') and v.__doc__) return parsimonious.Grammar(grammar)['program'].parse(source) def evaluate(self, source): node = self.parse(source.replace("\n", " ")) if isinstance(source, str) else source method = getattr(self, node.expr_name, lambda node, children: children) if node.expr_name in ['formal_parameters_and_body', 'ifelse']: return method(node) return method(node, [self.evaluate(n) for n in node]) #################################### RULES #################################### def add_op(self, node, children): 'add_op = ~"[+-]"' add_operator = {"+": operator.add, "-": operator.sub} return add_operator[node.text] def anonymous_function(self, node, children): 'anonymous_function = "def" _ formal_parameters_and_body' _, _, formal_params_and_body = children return formal_params_and_body def anonymous_function_assignment(self, node, children): 'anonymous_function_assignment = identifier_name _ "=" _ anonymous_function' func_name, _, _, _, anonymous_func_result = children params, stmts, anonymous_func = anonymous_func_result self.scope.add_function(func_name, params, stmts, anonymous_func) return anonymous_func def anonymous_function_call(self, node, children): 'anonymous_function_call = "(" _ anonymous_function _ ")" _ "(" _ arguments _ ")"' _, _, anonymous_func_result, _, _, _, _, _, args, _, _ = children params, stmts, anonymous_func = anonymous_func_result return self.scope.direct_function_call(params, stmts, anonymous_func, args) def arguments(self, node, children): 'arguments = expression ( _ "," _ expression _ )*' expr, expr_list = children exprs = [expr] for _, _, _, expr, _ in expr_list: exprs.append(expr) return exprs def assignment(self, node, children): 'assignment = anonymous_function_assignment / variable_assignment' return children[0] def expression(self, node, children): 'expression = anonymous_function_call / function_call / assignment / prefix_expression / simple_expression' return children[0] def factor(self, node, children): 'factor = number / postfix_expression / identifier_value / parenthesized_expression / string' return children[0] def formal_parameters_and_body(self, node): 'formal_parameters_and_body = "(" _ parameters _ ")" _ "{" _ statements _ "}"' _, _, params, _, _, _, _, _, stmts, _, _ = node params = list(map(lambda x: x.strip(), ''.join([param.text.strip() for param in params]).split(','))) def anonymous_func(function_metadata, *args): function_metadata.scope.add_variable_list(dict(zip(function_metadata.formal_params, args))) return HCS(function_metadata.scope).evaluate(function_metadata.statements) return (params, stmts, anonymous_func) def function_call(self, node, children): 'function_call = identifier_name _ "(" _ arguments _ ")"' name, _, _, _, args, _, _ = children return self.scope.call(name, args) def identifier_name(self, node, children): 'identifier_name = ~"[a-z_][a-z_0-9]*"i _' return node.text.strip() def identifier_value(self, node, children): 'identifier_value = ~"[a-z_][a-z_0-9]*"i _' name = node.text.strip() return self.scope.get_variable_value(name) def statement_block(self, node, children): 'statement_block = "{" _ statements _ "}"' _, _, stmt, _, _ = children return stmt def ifelse(self, node): 'ifelse = "if" _ parenthesized_expression _ statement_block _ ( "else" _ statement_block )?' _, _, condition, _, if_true, _, if_false = node if self.evaluate(condition): return self.evaluate(if_true) elif len(if_false.children) > 0: return self.evaluate(if_false) def mul_op(self, node, children): 'mul_op = "*" / "//" / "/" / "%"' mul_operator = {"*": operator.mul, "/": operator.truediv, "//": operator.floordiv, "%": operator.mod} return mul_operator[node.text] def named_function(self, node, children): 'named_function = "def" ws identifier_name _ formal_parameters_and_body' _, _, func_name, _, func_result = children params, stmts, func = func_result self.scope.add_function(func_name, params, stmts, func) return func def number(self, node, children): 'number = ~"[+-]?\s*(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?"' try: return int(node.text) except ValueError: return float(node.text) def optional_semicolon(self, node, children): 'optional_semicolon = _ ";"? _' def parameters(self, node, children): 'parameters = identifier_name ( _ "," _ identifier_name)*' first_id, id_list = children ids = [first_id] for _, _, _, cur_id in id_list: ids.append(cur_id) return ids def parenthesized_expression(self, node, children): 'parenthesized_expression = "(" _ expression _ ")"' return children[2] def postfix_expression(self, node, children): 'postfix_expression = identifier_name pre_posfix_op' var_name, op = children current_value = self.scope.get_variable_value(var_name) self.scope.add_or_update_variable(var_name, op(current_value)) return current_value def prefix_expression(self, node, children): 'prefix_expression = pre_posfix_op identifier_name' op, var_name = children self.scope.add_or_update_variable(var_name, op(self.scope.get_variable_value(var_name))) return self.scope.get_variable_value(var_name) def pre_op(self, node, children): 'pre_op = ~"[+-]"' pre_operator = {"+": lambda x: x, "-": operator.neg} return pre_operator[node.text] def pre_posfix_op(self, node, children): 'pre_posfix_op = "++" / "--"' pre_posfix = {"++": lambda x: x + 1, "--": lambda x: x - 1,} return pre_posfix[node.text] def program(self, node, children): 'program = statements*' return children[0] def simple_expression(self, node, children): 'simple_expression = pre_op? _ term ( _ add_op _ term )*' p_op, _, term, term_list = children if len(p_op) > 0: result = p_op[0](term) else: result = term for _, a_op, _, term in term_list: result = a_op(result, term) return result def statement(self, node, children): 'statement = ifelse / named_function / expression' return children[0] def statements(self, node, children): 'statements = _ statement ( optional_semicolon statement )* optional_semicolon ' _, stmt, stmt_list, _, = children result = stmt for _, stmt in stmt_list: result = stmt return stmt def string(self, node, children): 'string = ~"\\".*?\\""' return node.text def term(self, node, children): 'term = factor ( _ mul_op _ factor )*' factor, factor_list = children result = factor for _, m_op, _, factor in factor_list: result = m_op(result, factor) return result def variable_assignment(self, node, children): 'variable_assignment = identifier_name _ "=" _ expression' var_name, _, _, _, expr = children self.scope.add_or_update_variable(var_name, expr) return expr def ws(self, node, children): 'ws = ~"\s+"' def _(self, node, children): '_ = ~"\s*"'
class Parser: """Takes a list of tokens and performs semantic analysis to check if input adheres to grammar. Outputs to stdout a textual representation of the CST via the call stack. Parser is also capable of outputting graphical output """ # initializes Parser instance and parses a list of tokens # cmd line arguments determine output type def __init__(self, observer = Observer(), token_list=[], print_symbol_table = 0, visitor = Visitor()): self.current = 0 # current position in token list self.token_list = token_list # token list received from scanner self.kind_map = Token.kind_map # dictionary of token kinds self.observer = observer # output class determined by cmd line arguments self.total_error_flag = 0 # detects if an error occurs anywhere in the program self.universe = Scope(None) # universe scope self.universe.insert("INTEGER", Integer()) # universe scope only holds integer self.program_scope = Scope(self.universe) # program scope to hold program names self.current_scope = self.program_scope # current scope for switching between scopes self.print_symbol_table = print_symbol_table # determines whether to print cst or st self.visitor = visitor # parse the token list def parse(self): self._program() # do not print any output if error occurs if self.total_error_flag == 0: if self.print_symbol_table == 0: self.observer.print_output() elif self.print_symbol_table == 1: self.visitor.visitScope(self.program_scope) self.visitor.end() # check if the currently parsed token is a token we are # expecting to find # kind = expected kind of token def match(self, kind): if self.token_list[self.current].kind == self.kind_map[kind]: self.observer.print_token(self.token_list[self.current]) self.current += 1 ### for returning identifier names return self.token_list[self.current-1].get_token_name() else: self.total_error_flag = 1 sys.stderr.write("error: expected token kind \'{0}\', " "received unexpected token \'{1}\'" " @({2}, {3})".format(kind, self.token_list[self.current], self.token_list[self.current].start_position, self.token_list[self.current].end_position) + '\n') # set expectation of creating a program # by following the program production def _program(self): # print "Program" self.observer.begin_program() self.match("PROGRAM") name = self.match("IDENTIFIER") self.match(";") self._declarations() if self.token_list[self.current].kind == self.kind_map["BEGIN"]: self.match("BEGIN") self._instructions() self.match("END") end_name = self.match("IDENTIFIER") self.match(".") self.observer.end_program() if not name == end_name: self.total_error_flag = 1 sys.stderr.write("error: program identifier does not match end identifier\n") if not self.token_list[self.current].kind == self.kind_map["EOF"]: self.total_error_flag = 1 sys.stderr.write("error: trash detected after program end:\n" "Token \'{0}\'".format(self.token_list[self.current]) + '\n') # set expectation of creating a declaration # by following the declaration production def _declarations(self): self.observer.begin_declarations() while (self.token_list[self.current].kind == self.kind_map["CONST"]) or \ (self.token_list[self.current].kind == self.kind_map["TYPE"]) or \ (self.token_list[self.current].kind == self.kind_map["VAR"]): if self.token_list[self.current].kind == self.kind_map["CONST"]: self._constdecl() elif self.token_list[self.current].kind == self.kind_map["TYPE"]: self._typedecl() elif self.token_list[self.current].kind == self.kind_map["VAR"]: self._vardecl() else: pass self.observer.end_declarations() # set expectation of creating a ConstDecl # by following the ConstDecl production def _constdecl(self): # print "ConstDecl" self.observer.begin_constdecl() self.match("CONST") while self.token_list[self.current].kind == self.kind_map["IDENTIFIER"]: name = self.match("IDENTIFIER") # check if const name in local scope if self.program_scope.local(name): self.total_error_flag = 1 sys.stderr.write("error: attempted to redefine identifier\n") self.match("=") e = self._expression() self.match(";") # add it we formed a constant if isinstance(e, Constant): # is it constant object or constant name self.program_scope.insert(name, e) else: self.total_error_flag = 1 sys.stderr.write("error: attempted to define const with nonconst object\n") self.observer.end_constdecl() # set expectation of creating a TypeDecl # by following the TypeDecl production def _typedecl(self): # print "TypeDecl" self.observer.begin_typedecl() self.match("TYPE") while self.token_list[self.current].kind == self.kind_map["IDENTIFIER"]: name = self.match("IDENTIFIER") self.match("=") # type of current Type return_type = self._type() self.match(";") if return_type is None: self.total_error_flag = 1 sys.stderr.write("error: type not found\n") return None if not self.current_scope.local(name): self.current_scope.insert(name, return_type) else: self.total_error_flag = 1 sys.stderr.write("error: attempting to redefine variable\n") self.observer.end_typedecl() # set expectation of creating a VarDecl # by following the VarDecl production def _vardecl(self): # print "VarDecl" self.observer.begin_vardecl() self.match("VAR") id_list = [] return_type = None while self.token_list[self.current].kind == self.kind_map["IDENTIFIER"]: id_list = self._identifier_list() self.match(":") return_type = self._type() # type of current identifier if return_type is None: self.total_error_flag = 1 sys.stderr.write("error: type not found\n") return None self.match(";") for name in id_list: if not self.current_scope.local(name): self.current_scope.insert(name, Variable(return_type)) else: self.total_error_flag = 1 sys.stderr.write("error: attempting to redefine var\n") self.observer.end_vardecl() # set expectation of creating a Type # by following the Type production def _type(self): # print "Type" self.observer.begin_type() return_type = None if self.token_list[self.current].kind == self.kind_map["IDENTIFIER"]: name = self.match("IDENTIFIER") # get the name of an identifier return_type = self.current_scope.find(name) if return_type is None: self.total_error_flag = 1 sys.stderr.write("error: indentifier not found. attempting to assign " "uncreated type\n") self.observer.end_type() return None if isinstance(return_type, Type): self.observer.end_type() return return_type else: self.total_error_flag = 1 sys.stderr.write("error: found not Type object\n") return None elif self.token_list[self.current].kind == self.kind_map["ARRAY"]: self.match("ARRAY") length = None e = self._expression() # get length of array if isinstance(e, Constant): length = e else: self.total_error_flag = 1 sys.stderr.write("error: not a valid type for array length\n") self.match("OF") array_type = self._type() # check if array_type is already defined if array_type is None: self.total_error_flag = 1 sys.stderr.write("error: array type not found\n") return None return_type = Array(length, array_type) self.observer.end_type() return return_type elif self.token_list[self.current].kind == self.kind_map["RECORD"]: self.match("RECORD") id_list = [] outer_scope = self.current_scope self.current_scope = Scope(outer_scope) while self.token_list[self.current].kind == self.kind_map["IDENTIFIER"]: id_list = self._identifier_list() self.match(":") # type of current identifier(s) record_field_type = self._type() if record_field_type is None: self.total_error_flag = 1 sys.stderr.write("error: record field type nonexistent\n") self.match(";") for name in id_list: if not self.current_scope.local(name): self.current_scope.insert(name, Variable(record_field_type)) else: self.total_error_flag = 1 sys.stderr.write("error: attempting to redefine field\n") return None self.match("END") return_type = Record(self.current_scope) outer_scope = self.current_scope.outer_scope self.current_scope.outer_scope = None self.current_scope = outer_scope self.observer.end_type() return return_type else: self.total_error_flag = 1 sys.stderr.out("error: expecting Identifier, ARRAY, or RECORD\n") self.observer.end_type() # set expectation of creating a Expression # by following the Expression production def _expression(self): self.observer.begin_expression() if self.token_list[self.current].kind == self.kind_map["+"]: self.match("+") elif self.token_list[self.current].kind == self.kind_map["-"]: self.match("-") self._term() while (self.token_list[self.current].kind == self.kind_map["+"]) or \ (self.token_list[self.current].kind == self.kind_map["-"]): if self.token_list[self.current].kind == self.kind_map["+"]: self.match("+") elif self.token_list[self.current].kind == self.kind_map["-"]: self.match("-") else: self.total_error_flag = 1 sys.stderr.write("error: expecting \'+\' or \'-\'\n") self._term() self.observer.end_expression() e = Constant(self.universe.find("INTEGER"), 5) return e # set expectation of creating a Term # by following the Term production def _term(self): self.observer.begin_term() self._factor() while (self.token_list[self.current].kind == self.kind_map["*"])or \ (self.token_list[self.current].kind == self.kind_map["DIV"]) or \ (self.token_list[self.current].kind == self.kind_map["MOD"]): if self.token_list[self.current].kind == self.kind_map["*"]: self.match("*") elif self.token_list[self.current].kind == self.kind_map["DIV"]: self.match("DIV") elif self.token_list[self.current].kind == self.kind_map["MOD"]: self.match("MOD") else: self.total_error_flag = 1 sys.stderr.out("error: expecting \'*\', \'DIV\', or \'MOD\'\n") self._factor() self.observer.end_term() # set expectation of creating a Factor # by following the Factor production def _factor(self): self.observer.begin_factor() if self.token_list[self.current].kind == self.kind_map["INTEGER"]: self.match("INTEGER") elif self.token_list[self.current].kind == self.kind_map["IDENTIFIER"]: self._designator() elif self.token_list[self.current].kind == self.kind_map["("]: self.match("(") self._expression() self.match(")") else: self.total_error_flag = 1 sys.stdout.error("error: expecting integer, identifier or \'(\'\n") self.observer.end_factor() # set expectation of creating a Instructions # by following the Instructions production def _instructions(self): self.observer.begin_instructions() self._instruction() while self.token_list[self.current].kind == self.kind_map[";"]: self.match(";") self._instruction() self.observer.end_instructions() # set expectation of creating a Instruction # by following the Instruction production def _instruction(self): # print "Instruction" self.observer.begin_instruction() if self.token_list[self.current].kind == self.kind_map["IDENTIFIER"]: self._assign() elif self.token_list[self.current].kind == self.kind_map["IF"]: self._if() elif self.token_list[self.current].kind == self.kind_map["REPEAT"]: self._repeat() elif self.token_list[self.current].kind == self.kind_map["WHILE"]: self._while() elif self.token_list[self.current].kind == self.kind_map["READ"]: self._read() elif self.token_list[self.current].kind == self.kind_map["WRITE"]: self._write() else: self.total_error_flag = 1 sys.stderr.write("error: not a valid instruction\n" "@({0}, {1})".format(self.token_list[self.current].start_position, self.token_list[self.current].end_position)) self.observer.end_instruction() # set expectation of creating a Assign # by following the Assign production def _assign(self): # print "Assign" self.observer.begin_assign() self._designator() self.match(":=") self._expression() self.observer.end_assign() # set expectation of creating a If # by following the If production def _if(self): # print "If" self.observer.begin_if() self.match("IF") self._condition() self.match("THEN") self._instructions() if self.token_list[self.current].kind == self.kind_map["ELSE"]: self.match("ELSE") self._instructions() self.match("END") self.observer.end_if() # set expectation of creating a Repeat # by following the Repeat production def _repeat(self): self.observer.begin_repeat() self.match("REPEAT") self._instructions() self.match("UNTIL") self._condition() self.match("END") self.observer.end_repeat() # set expectation of creating a While # by following the While production def _while(self): self.observer.begin_while() self.match("WHILE") self._condition() self.match("DO") self._instructions() self.match("END") self.observer.end_while() # set expectation of creating a Condition # by following the Condition production def _condition(self): self.observer.begin_condition() self._expression() if self.token_list[self.current].kind == self.kind_map["="]: self.match("=") elif self.token_list[self.current].kind == self.kind_map["#"]: self.match("#") elif self.token_list[self.current].kind == self.kind_map["<"]: self.match("<") elif self.token_list[self.current].kind == self.kind_map[">"]: self.match(">") elif self.token_list[self.current].kind == self.kind_map["<="]: self.match("<=") elif self.token_list[self.current].kind == self.kind_map[">="]: self.match(">=") else: self.total_error_flag = 1 sys.stderr.write("error: not a valid condition\n" "@({0}, {1})".format(self.token_list[self.current].start_position, self.token_list[self.current].end_position)) self._expression() self.observer.end_condition() # set expectation of creating a Write # by following the Write production def _write(self): self.observer.begin_write() self.match("WRITE") self._expression() self.observer.end_write() # set expectation of creating a Read # by following the Read production def _read(self): self.observer.begin_read() self.match("READ") self._designator() self.observer.end_read() # set expectation of creating a Designator # by following the Designator production def _designator(self): self.observer.begin_designator() self.match("IDENTIFIER") self._selector() self.observer.end_designator() # set expectation of creating a Selector # by following the Selector production def _selector(self): self.observer.begin_selector() while (self.token_list[self.current].kind == self.kind_map["["]) \ or (self.token_list[self.current].kind == self.kind_map["."]): if self.token_list[self.current].kind == self.kind_map["["]: self.match("[") self._expression_list() self.match("]") elif self.token_list[self.current].kind == self.kind_map["."]: self.match(".") self.match("IDENTIFIER") else: self.total_error_flag = 1 sys.stderr.write("error: not a valid selector\n" "@({0}, {1})".format(self.token_list[self.current].start_position, self.token_list[self.current].end_position)) self.observer.end_selector() # set expectation of creating a IdentifierList # by following the IdentifierList production def _identifier_list(self): self.observer.begin_identifier_list() name = self.match("IDENTIFIER") id_list = [] id_list.append(name) while self.token_list[self.current].kind == self.kind_map[","]: self.match(",") name = self.match("IDENTIFIER") id_list.append(name) self.observer.end_identifier_list() return id_list # set expectation of creating a ExpressionList # by following the ExpressionList production def _expression_list(self): self.observer.begin_expression_list() self._expression() while self.token_list[self.current].kind == self.kind_map[","]: self.match(",") self._expression() self.observer.end_expression_list()
def testBasic(self): scope = Scope() self.loop.play(scope) self.assertEqual(scope.lookup('x'), 10) self.assertEqual(scope.lookup('y'), 10)
def eval(self, scope = None): if scope == None: scope = Scope() return scope.eval(self.script)
def execute_here(self, child, scope=None): assert isinstance(child, Playable) if scope == None: scope = Scope() child.play(scope)
class Parser: """Takes a list of tokens and performs semantic analysis to check if input adheres to grammar. Outputs to stdout a textual representation of the CST via the call stack. Parser is also capable of outputting graphical output """ # initializes Parser instance and parses a list of tokens # cmd line arguments determine output type def __init__(self, observer = Observer(), token_list=[], print_symbol_table = 0, visitor = Visitor()): self.current = 0 # current position in token list self.token_list = token_list # token list received from scanner self.kind_map = Token.kind_map # dictionary of token kinds self.observer = observer # output class determined by cmd line arguments self.total_error_flag = 0 # detects if an error occurs anywhere in the program self.universe = Scope(None) # universe scope self.universe.insert("INTEGER", integerInstance) # universe scope only holds integer self.program_scope = Scope(self.universe) # program scope to hold program names self.current_scope = self.program_scope # current scope for switching between scopes self.print_symbol_table = print_symbol_table # determines whether to print cst or st self.visitor = visitor # parse the token list def parse(self): instructions = self._program() # do not print any output if error occurs if self.total_error_flag == 0: if self.print_symbol_table == 0: self.observer.print_output() elif self.print_symbol_table == 1: self.visitor.visitScope(self.program_scope) self.visitor.end() elif self.print_symbol_table == 2: currinstruction = instructions self.visitor.start() # while(currinstruction is not None): currinstruction.visit(self.visitor) # currinstruction = currinstruction._next elif self.print_symbol_table == 3: # build environment pass def build_environment(self): pass # check if the currently parsed token is a token we are # expecting to find # kind = expected kind of token def match(self, kind): if self.token_list[self.current].kind == self.kind_map[kind]: self.observer.print_token(self.token_list[self.current]) self.current += 1 ### for returning identifier names return self.token_list[self.current-1].get_token_name() else: self.total_error_flag = 1 sys.stderr.write("error: expected token kind \'{0}\', " "received unexpected token \'{1}\'" " @({2}, {3})".format(kind, self.token_list[self.current], self.token_list[self.current].start_position, self.token_list[self.current].end_position) + '\n') # set expectation of creating a program # by following the program production def _program(self): # print "Program" self.observer.begin_program() self.match("PROGRAM") name = self.match("IDENTIFIER") self.match(";") self._declarations() instructions = None if self.token_list[self.current].kind == self.kind_map["BEGIN"]: self.match("BEGIN") instructions = self._instructions() self.match("END") end_name = self.match("IDENTIFIER") self.match(".") self.observer.end_program() if not name == end_name: self.total_error_flag = 1 sys.stderr.write("error: program identifier does not match end identifier\n") if not self.token_list[self.current].kind == self.kind_map["EOF"]: self.total_error_flag = 1 sys.stderr.write("error: trash detected after program end:\n" "Token \'{0}\'".format(self.token_list[self.current]) + '\n') return instructions # set expectation of creating a declaration # by following the declaration production def _declarations(self): self.observer.begin_declarations() while (self.token_list[self.current].kind == self.kind_map["CONST"]) or \ (self.token_list[self.current].kind == self.kind_map["TYPE"]) or \ (self.token_list[self.current].kind == self.kind_map["VAR"]): if self.token_list[self.current].kind == self.kind_map["CONST"]: self._constdecl() elif self.token_list[self.current].kind == self.kind_map["TYPE"]: self._typedecl() elif self.token_list[self.current].kind == self.kind_map["VAR"]: self._vardecl() else: pass self.observer.end_declarations() # set expectation of creating a ConstDecl # by following the ConstDecl production def _constdecl(self): # print "ConstDecl" self.observer.begin_constdecl() self.match("CONST") # return_obj = None while self.token_list[self.current].kind == self.kind_map["IDENTIFIER"]: name = self.match("IDENTIFIER") # check if const name in local scope if self.program_scope.local(name): self.total_error_flag = 1 sys.stderr.write("error: attempted to redefine identifier\n") self.match("=") e = self._expression() if not isinstance(e, NumberNode): self.total_error_flag = 1 sys.stderr.write("error: constdecl received nonconst exp\n") # exit(1) self.match(";") #return_obj = e # add it we formed a constant if isinstance(e.constant, Constant): # is it constant object or constant name self.program_scope.insert(name, e.constant) else: self.total_error_flag = 1 sys.stderr.write("error: attempted to define const with nonconst object\n") self.observer.end_constdecl() # return return_obj # set expectation of creating a TypeDecl # by following the TypeDecl production def _typedecl(self): # print "TypeDecl" self.observer.begin_typedecl() self.match("TYPE") #return_type = None while self.token_list[self.current].kind == self.kind_map["IDENTIFIER"]: name = self.match("IDENTIFIER") self.match("=") # type of current Type return_type = self._type() self.match(";") if return_type is None: self.total_error_flag = 1 sys.stderr.write("error: type not found\n") return None if not self.current_scope.local(name): self.current_scope.insert(name, return_type) else: self.total_error_flag = 1 sys.stderr.write("error: attempting to redefine variable\n") self.observer.end_typedecl() # return return_type # set expectation of creating a VarDecl # by following the VarDecl production def _vardecl(self): # print "VarDecl" self.observer.begin_vardecl() self.match("VAR") id_list = [] return_type = None while self.token_list[self.current].kind == self.kind_map["IDENTIFIER"]: id_list = self._identifier_list() self.match(":") return_type = self._type() # type of current identifier if return_type is None: self.total_error_flag = 1 sys.stderr.write("error: type not found\n") return None self.match(";") for name in id_list: if not self.current_scope.local(name): self.current_scope.insert(name, Variable(return_type)) else: self.total_error_flag = 1 sys.stderr.write("error: attempting to redefine var\n") self.observer.end_vardecl() return return_type # set expectation of creating a Type # by following the Type production def _type(self): # print "Type" self.observer.begin_type() return_type = None if self.token_list[self.current].kind == self.kind_map["IDENTIFIER"]: name = self.match("IDENTIFIER") # get the name of an identifier return_type = self.current_scope.find(name) if return_type is None: self.total_error_flag = 1 sys.stderr.write("error: indentifier not found. attempting to assign " "uncreated type\n") self.observer.end_type() return None if isinstance(return_type, Type): self.observer.end_type() return return_type else: self.total_error_flag = 1 sys.stderr.write("error: found not Type object\n") return None elif self.token_list[self.current].kind == self.kind_map["ARRAY"]: self.match("ARRAY") length = None e = self._expression() if isinstance(e, NumberNode): length = e.constant.value else: self.total_error_flag = 1 sys.stderr.write("error: not a valid type for array length\n") self.match("OF") array_type = self._type() if array_type is None: self.total_error_flag = 1 sys.stderr.write("error: array type not found\n") return None return_type = Array(length, array_type) self.observer.end_type() return return_type elif self.token_list[self.current].kind == self.kind_map["RECORD"]: self.match("RECORD") id_list = [] outer_scope = self.current_scope self.current_scope = Scope(outer_scope) while self.token_list[self.current].kind == self.kind_map["IDENTIFIER"]: id_list = self._identifier_list() self.match(":") record_field_type = self._type() if record_field_type is None: self.total_error_flag = 1 sys.stderr.write("error: record field type nonexistent\n") self.match(";") for name in id_list: if not self.current_scope.local(name): self.current_scope.insert(name, Variable(record_field_type)) else: self.total_error_flag = 1 sys.stderr.write("error: attempting to redefine field\n") return None self.match("END") return_type = Record(self.current_scope) outer_scope = self.current_scope.outer_scope self.current_scope.outer_scope = None self.current_scope = outer_scope self.observer.end_type() return return_type else: self.total_error_flag = 1 sys.stderr.out("error: expecting Identifier, ARRAY, or RECORD\n") self.observer.end_type() # set expectation of creating a Expression # by following the Expression production def _expression(self): self.observer.begin_expression() node = self.nexpression() self.observer.end_expression() return node def nexpression(self): outer_operation = -1 if self.token_list[self.current].kind == self.kind_map["+"]: outer_operation = self.match("+") elif self.token_list[self.current].kind == self.kind_map["-"]: outer_operation = self.match("-") subtree = self._term() node = subtree if (self.token_list[self.current].kind == self.kind_map["+"]) or \ (self.token_list[self.current].kind == self.kind_map["-"]): inner_operation = "" if self.token_list[self.current].kind == self.kind_map["+"]: inner_operation = self.match("+") elif self.token_list[self.current].kind == self.kind_map["-"]: inner_operation = self.match("-") else: self.total_error_flag = 1 sys.stderr.write("error: expecting \'+\' or \'-\'\n") subtree_right = self._term() if isinstance(subtree, NumberNode) and isinstance(subtree_right, NumberNode): result = 0 if inner_operation == "+": result = int(subtree.type.value) + int(subtree_right.type.value) elif inner_operation == "-": result = int(subtree.type.value) + int(subtree_right.type.value) else: pass c = Constant(integerInstance, result) num_node = NumberNode(c) node = num_node else: bn = BinaryNode(inner_operation, subtree, subtree_right) node = bn else: node = subtree if outer_operation == "-": # how to do negative numbers? if isinstance(node, BinaryNode): if isinstance(node.exp_left, NumberNode) and isinstance(node.exp_right, NumberNode): op = node.operator left_value = node.exp_left.value right_value = node.exp_right.value op_result = 0 if op == "+": op_result = left_value + right_value elif op == "-": op_result = left_value - right_value elif op == "*": op_result = left_value * right_value elif op == "DIV": op_result = left_value / right_value elif op == "MOD": op_result = left_value % right_value else: sys.stderr.write("error: invalid op") result = -1*op_result c = Constant(integerInstance, result) num_node = NumberNode(c) node = num_node elif isinstance(node, NumberNode): c = Constant(integerInstance, 0 - node.constant.value) num_node = NumberNode(c) node = num_node return node # set expectation of creating a Term # by following the Term production def _term(self): self.observer.begin_term() node = self.nterm() #return singular factor or binary node self.observer.end_term() return node def nterm(self): sub_left = self._factor() node = sub_left operation = 0 if (self.token_list[self.current].kind == self.kind_map["*"])or \ (self.token_list[self.current].kind == self.kind_map["DIV"]) or \ (self.token_list[self.current].kind == self.kind_map["MOD"]): if self.token_list[self.current].kind == self.kind_map["*"]: operation = self.match("*") elif self.token_list[self.current].kind == self.kind_map["DIV"]: operation = self.match("DIV") elif self.token_list[self.current].kind == self.kind_map["MOD"]: operation = self.match("MOD") else: self.total_error_flag = 1 sys.stderr.out("error: expecting \'*\', \'DIV\', or \'MOD\'\n") sub_right = self.nterm() if isinstance(sub_left, NumberNode) and isinstance(sub_right, NumberNode): result = 0 if operation == "*": result = int(sub_left.constant.value) * int(sub_right.constant.value) elif operation == "DIV": result = int(sub_left.constant.value) / int(sub_right.constant.value) elif operation == "MOD": result = int(sub_left.constant.value) % int(sub_right.constant.value) c = Constant(integerInstance, result) num_node = NumberNode(c) return num_node else: bn = BinaryNode(operation, sub_left, sub_right) return bn else: return sub_left # set expectation of creating a Factor # by following the Factor production def _factor(self): self.observer.begin_factor() node = None if self.token_list[self.current].kind == self.kind_map["INTEGER"]: int_value = self.match("INTEGER") c = Constant(integerInstance, int_value) node = NumberNode(c) # make a number node of out of the constant # return number node elif self.token_list[self.current].kind == self.kind_map["IDENTIFIER"]: sub_tree = self._designator() node = sub_tree elif self.token_list[self.current].kind == self.kind_map["("]: self.match("(") sub_tree = self._expression() self.match(")") node = sub_tree else: self.total_error_flag = 1 sys.stdout.error("error: expecting integer, identifier or \'(\'\n") self.observer.end_factor() return node # set expectation of creating a Instructions # by following the Instructions production def _instructions(self): self.observer.begin_instructions() head = self._instruction() curr = head while self.token_list[self.current].kind == self.kind_map[";"]: self.match(";") temp = self._instruction() curr._next = temp curr = temp self.observer.end_instructions() return head # set expectation of creating a Instruction # by following the Instruction production def _instruction(self): # print "Instruction" self.observer.begin_instruction() node = None if self.token_list[self.current].kind == self.kind_map["IDENTIFIER"]: node = self._assign() elif self.token_list[self.current].kind == self.kind_map["IF"]: node = self._if() elif self.token_list[self.current].kind == self.kind_map["REPEAT"]: node = self._repeat() elif self.token_list[self.current].kind == self.kind_map["WHILE"]: node = self._while() elif self.token_list[self.current].kind == self.kind_map["READ"]: node = self._read() elif self.token_list[self.current].kind == self.kind_map["WRITE"]: node = self._write() else: self.total_error_flag = 1 sys.stderr.write("error: not a valid instruction\n" "@({0}, {1})".format(self.token_list[self.current].start_position, self.token_list[self.current].end_position)) self.observer.end_instruction() return node # set expectation of creating a Assign # by following the Assign production def _assign(self): # print "Assign" self.observer.begin_assign() subtree_left = self._designator() if not (isinstance(subtree_left, VariableNode) or isinstance(subtree_left, FieldNode) or isinstance(subtree_left, IndexNode)): print type(subtree_left) sys.stderr.write("error: assign") stl_type = subtree_left.type self.match(":=") subtree_right = self._expression() str_type = subtree_right.type if not type(stl_type) == type(str_type): sys.stderr.write("error: assigning things that don't have the same type\n") assign_node = AssignNode(None, subtree_left, subtree_right) self.observer.end_assign() return assign_node # set expectation of creating a If # by following the If production def _if(self): # print "If" self.observer.begin_if() self.match("IF") condition = self._condition() self.match("THEN") instructions_true = self._instructions() instructions_false = None if self.token_list[self.current].kind == self.kind_map["ELSE"]: self.match("ELSE") instructions_false = self._instructions() self.match("END") self.observer.end_if() if_node = IfNode(None, condition, instructions_true, instructions_false) return if_node # set expectation of creating a Repeat # by following the Repeat production def _repeat(self): self.observer.begin_repeat() self.match("REPEAT") instructions = self._instructions() self.match("UNTIL") condition = self._condition() self.match("END") self.observer.end_repeat() repeat_node = RepeatNode(None, condition, instructions) return repeat_node # set expectation of creating a While # by following the While production def _while(self): self.observer.begin_while() self.match("WHILE") condition = self._condition() self.match("DO") instructions = self._instructions() self.match("END") self.observer.end_while() negation_condition_node = self.get_negation(condition) repeat_node = RepeatNode(None, negation_condition_node, instructions) if_node = IfNode(None, condition, repeat_node, None) return if_node def get_negation(self, condition_node): relation_negation = {"=":"#", "#":"=", "<":">", ">":"<", "<=":">=", ">=":"<="} negation_condition_node = ConditionNode(condition_node.exp_left, condition_node.exp_right, relation_negation[condition_node.relation]) return negation_condition_node # set expectation of creating a Condition # by following the Condition production def _condition(self): self.observer.begin_condition() left = self._expression() relation = "" if self.token_list[self.current].kind == self.kind_map["="]: # self.match("=") relation = self.match("=") elif self.token_list[self.current].kind == self.kind_map["#"]: # self.match("#") relation = self.match("#") elif self.token_list[self.current].kind == self.kind_map["<"]: # self.match("<") relation = self.match("<") elif self.token_list[self.current].kind == self.kind_map[">"]: # self.match(">") relation = self.match(">") elif self.token_list[self.current].kind == self.kind_map["<="]: # self.match("<=") relation = self.match("<=") elif self.token_list[self.current].kind == self.kind_map[">="]: # self.match(">=") relation = self.match(">=") else: self.total_error_flag = 1 sys.stderr.write("error: not a valid condition\n" "@({0}, {1})".format(self.token_list[self.current].start_position, self.token_list[self.current].end_position)) right = self._expression() self.observer.end_condition() condition_subtree = ConditionNode(left, right, relation) return condition_subtree # set expectation of creating a Write # by following the Write production def _write(self): self.observer.begin_write() self.match("WRITE") expression = self._expression() if not isinstance(expression.type, Integer): self.total_error_flag = 1 sys.stderr.write("error: expression in write not of type integer") exit(1) self.observer.end_write() write_node = WriteNode(None, expression) return write_node # set expectation of creating a Read # by following the Read production def _read(self): self.observer.begin_read() self.match("READ") designator = self._designator() if not isinstance(designator.type, Integer): self.total_error_flag = 1 sys.stderr.write("error: designator in read not an integer") exit(1) self.observer.end_read() read_node = ReadNode(None, designator) return read_node # set expectation of creating a Designator # by following the Designator production def _designator(self): self.observer.begin_designator() var_name = self.match("IDENTIFIER") ret_obj = self.program_scope.find(var_name) pass_obj = None if isinstance(ret_obj, Variable): pass_obj = VariableNode(ret_obj._type, ret_obj, var_name) elif isinstance(ret_obj, Constant): pass_obj = NumberNode(ret_obj) else: self.total_error_flag = 1 sys.stderr.write("error: variable name not pointing var or const\n") exit(1) subtree = self._selector(pass_obj) self.observer.end_designator() return subtree # set expectation of creating a Selector # by following the Selector production def _selector(self, variable_node): self.observer.begin_selector() return_object = variable_node while (self.token_list[self.current].kind == self.kind_map["["]) \ or (self.token_list[self.current].kind == self.kind_map["."]): if self.token_list[self.current].kind == self.kind_map["["]: if not isinstance(return_object.type, Array): sys.stderr.write("error: not an array") self.match("[") exp_list = self._expression_list() self.match("]") node = return_object for e in exp_list: if not isinstance(e.type, Integer): sys.stderr.write("error: noninteger found in selector\n") index_type = return_object.type._type # print "it", type(index_type) # print "index type: ", type(index_type) index_node = IndexNode(index_type, node, exp_list[0]) for i in range(1, len(exp_list)): node = index_node index_type = node.type._type index_node = IndexNode(index_type, node, exp_list[i]) return_object = index_node elif self.token_list[self.current].kind == self.kind_map["."]: self.match(".") field_var_name = self.match("IDENTIFIER") if not isinstance(return_object.type, Record): sys.stderr.write("error: attempting to select field from non-record type\n") if(return_object.type.scope.local(field_var_name)): field_var_obj = return_object.type.scope.find(field_var_name) field_type = field_var_obj._type field_right_var_obj = VariableNode(field_type, field_var_obj, field_var_name) node = FieldNode(field_type, return_object, field_right_var_obj) return_object = node else: self.total_error_flag = 1 sys.stderr.write("error: not a valid selector\n" "@({0}, {1})".format(self.token_list[self.current].start_position, self.token_list[self.current].end_position)) self.observer.end_selector() return return_object # set expectation of creating a IdentifierList # by following the IdentifierList production def _identifier_list(self): self.observer.begin_identifier_list() name = self.match("IDENTIFIER") id_list = [] id_list.append(name) while self.token_list[self.current].kind == self.kind_map[","]: self.match(",") name = self.match("IDENTIFIER") id_list.append(name) self.observer.end_identifier_list() return id_list # set expectation of creating a ExpressionList # by following the ExpressionList production def _expression_list(self): # return list of expressions - added return in assignment 5 self.observer.begin_expression_list() exp_list = [] name = self._expression() exp_list.append(name) while self.token_list[self.current].kind == self.kind_map[","]: self.match(",") name = self._expression() exp_list.append(name) self.observer.end_expression_list() return exp_list
def __init__(self, enclosing_scope): Symbol.__init__(self) scope_name = self.make_name(enclosing_scope.scope_name) Scope.__init__(self, scope_name, enclosing_scope)
## start with python -i scope_ex1.py from Scope import Scope ## Create a scope object with the channel you are using s = Scope(2) s.setup() ## Apply the signal and then adjust vertical scale so that signal ## just fills scope display. ## ## Keep horizontal timebase so that sampling rate is 500 MSa/s ## Read capture data ## Sometimes this locks up and you have to do ctrl-c and try again ## cd = s.read() ## You can turn off the signal source once the scope is in the stop state ## Save capture data to file ## cd.save("filename") ## repeat for various measurments ## ctrl-d to exit
class Analyze(object): def __init__(self): self.scope = Scope() def analyze(self, tree): def simplifyObject(objectString): if isinstance(objectString, basestring): objectString = "'{}'".format(objectString) objLex = Lexitize().lexitize(str(objectString))[0] tree = Treeitize().treeitize(objLex)[0] return tree def getTopObjectAndParameter(objectVariable): return (objectVariable.popleft()["value"], objectVariable.popleft()["value"]) def analyzeObject(objectVariable): topValue, parVal = getTopObjectAndParameter(objectVariable) if topValue in ["number", "boolean", "string", None]: return parVal elif topValue == "list": newList = [] while parVal: newList.append(self.analyze(parVal.popLeftObject())) return newList def analyzeVariable(objectVariable): variable, variableValue = getTopObjectAndParameter(objectVariable) if variableValue == None: variableTree = self.scope.get(variable) return self.analyze(variableTree) else: simplifiedVariable = simplifyObject(self.analyze(variableValue)) self.scope.add(variable, simplifiedVariable) def analyzeOpComp(objectVariable): operator, values = getTopObjectAndParameter(objectVariable) val1 = self.analyze(values.popLeftObject()) val2 = self.analyze(values.popLeftObject()) if isinstance(val1, basestring): val1 = "'{}'".format(val1) if isinstance(val2, basestring): val2 = "'{}'".format(val2) return eval(str(val1) + operator + str(val2)) def analyzeConditional(objectVariable): # conditional currently unused, but needed if eventually diff cond types conditional, parVal = getTopObjectAndParameter(objectVariable) values = parVal.pop() ifValueTree = values.popleft() elseValueTree = values.popleft() comparisonValue = analyzeOpComp(parVal) if comparisonValue: executeConditionStructure(ifValueTree) # return executeConditionStructure(ifValueTree) elif elseValueTree: executeConditionStructure(elseValueTree) # return executeConditionStructure(elseValueTree) else: return def analyzeLoop(objectVariable): loop, parVal = getTopObjectAndParameter(objectVariable) if loop == "while": analyzeWhileLoop(parVal) elif loop == "for": analyzeForLoop(parVal) # ***PRINTING HERE INSTEAD OF THNAKE def analyzeWhileLoop(parVal): loopCondition = parVal.popLeftObject() while self.analyze(copy.deepcopy(loopCondition)): executeConditionStructure(parVal) def analyzeForLoop(parVal): loopVar = parVal.popLeftObject().popleft()["value"] loopList = parVal.popLeftObject() loopList = self.analyze(loopList) loopList = simplifyObject(loopList).pop()["value"] variableExists = False if self.scope.get(loopVar): variableExists = True while loopList: currentVarIteration = loopList.popLeftObject() self.scope.add(loopVar, currentVarIteration) executeConditionStructure(parVal) if not variableExists: self.scope.pop(loopVar) def executeConditionStructure(parVal): parVal = copy.deepcopy(parVal) while parVal: result = self.analyze(parVal.popLeftObject()) if result is not None: print result return result def analyzeAttribFunc(objectVariable): attribFunc, parVal = getTopObjectAndParameter(objectVariable) functionParameterTree = parVal.popleft() functionObjectTree = parVal.pop() functionParameter = self.analyze(functionParameterTree) functionObject = self.analyze(functionObjectTree) return eval(str(functionObject) + "[" + str(functionParameter) + "]") typeAnalysis = { "arithmetic": analyzeOpComp, "comparison": analyzeOpComp, "object": analyzeObject, "variable": analyzeVariable, "conditional": analyzeConditional, "loop": analyzeLoop, "attribFunc": analyzeAttribFunc, } result = None currentObject = tree.popLeftObject() currentType = currentObject[0]["type"] if currentType in typeAnalysis: return typeAnalysis[currentType](currentObject)
class Constants: varx = Variable('x') vary = Variable('y') varz = Variable('z') varo = Variable('o') emptyList = [] list123 = [Num(1), Num(2), Num(3)] listadd123 = [FuncApplication(Variable('+'), list123), Num(-3)] list12True = [Num(1), Num(2), Boolean(True)] listaddsubtract123 = [ FuncApplication(Variable('-'), list123), FuncApplication('+', list123) ] listmultiply123 = [FuncApplication(Variable('*'), list123)] list84 = [Num(8), Num(4)] listdivide84 = [FuncApplication(Variable('/'), list84)] listx23 = [varx, Num(2), Num(3)] listy3 = [vary, Num(3)] list43 = [Num(4), Num(3)] list403 = [Num(4), Num(0), Num(3)] expradd1 = FuncApplication(Variable('+'), [Num(1)]) expradd123 = FuncApplication(Variable('+'), list123) expradd43 = FuncApplication(Variable('+'), list43) expradderror = FuncApplication(Variable('+'), list12True) exprsub1 = FuncApplication(Variable('-'), [Num(1)]) exprsub123 = FuncApplication(Variable('-'), list123) exprsub_add123_add123 = FuncApplication(Variable('-'), [expradd123, expradd43]) exprdiv1 = FuncApplication(Variable('/'), [Num(1)]) exprdiv84 = FuncApplication(Variable('/'), list84) exprdiv403 = FuncApplication(Variable('/'), list403) exprmul1 = FuncApplication(Variable('*'), [Num(1)]) exprmul84 = FuncApplication(Variable('*'), list84) expradd_expradd123_exprdiv84 = FuncApplication(Variable('+'), [expradd123, exprdiv84]) expraddx23 = FuncApplication(Variable('+'), listx23) expraddy3 = FuncApplication(Variable('+'), listy3) expsub_expraddx23_expradd3 = FuncApplication(Variable('-'), [expraddx23, expraddy3]) #functions func_def_varx = FuncDef("f", LambdaExpr(["x"], Variable("x"))) func_app_varx = FuncApplication(Variable('f'), [Num(4)]) list_func_app_varx = [func_app_varx, Num(2)] expradd_func_app_varx = FuncApplication(Variable('+'), list_func_app_varx) funcDef2 = FuncDef('g', LambdaExpr([], expradd_func_app_varx)) func_app_emptylist = FuncApplication(Variable('g'), []) ############### expradd_varx_vary = FuncApplication(Variable('+'), [varx, vary]) func_def_add_varx_vary = FuncDef('z', LambdaExpr(['x', 'y'], expradd_varx_vary)) func_app_varx_vary = FuncApplication(Variable('z'), [Num(7), Num(7)]) func_app_error_777 = FuncApplication( Variable('z'), [Num(7), Num(7), Num(7)]) func_app_100 = FuncApplication(Variable('d'), [Num(100)]) defs1 = Scope(()).add_definitions() defs1 = defs1.extend('x', Num(1)).extend('y', Num(4)) #set the scope by mutating to second arg of the tuple defs1 = func_def_varx.eval(defs1)[1] defs1 = funcDef2.eval(defs1)[1] defs1 = func_def_add_varx_vary.eval(defs1)[1] #structs posn_def = StructDef('posn', ['x', 'y']) defs1 = posn_def.update(defs1) zeina_def = StructDef('zeina', ['x', 'y']) defs1 = zeina_def.update(defs1) make_zeina = FuncApplication(Variable('make-posn'), [Num(10), Num(20)]) select_zeina_x = FuncApplication(Variable('zeina-x'), [make_zeina]) make_posn = FuncApplication(Variable('make-posn'), [Num(1), Num(2)]) make_posn_comp = FuncApplication(Variable('make-posn'), [make_posn, Num(2)]) is_posn = FuncApplication(Variable('posn?'), [make_posn]) is_not_posn = FuncApplication(Variable('posn?'), [Num(3)]) select_posn_x = FuncApplication(Variable('posn-x'), [make_posn]) select_posn_y = FuncApplication(Variable('posn-y'), [make_posn]) select_posn_x_comp = FuncApplication(Variable('posn-x'), [make_posn_comp]) select_posn_y_comp = FuncApplication(Variable('posn-y'), [make_posn_comp]) value_posn = Structure('posn', [('x', Num(1)), ('y', Num(2))]) value_posn_comp = Structure('posn', [('x', value_posn), ('y', Num(2))]) #functions using struct make_posn_func = FuncApplication(Variable('make-posn'), [func_app_varx, Num(1)]) func_app_varx_1 = FuncApplication(Variable('f'), [make_posn_func]) value_posn_func = Structure('posn', [('x', Num(4)), ('y', Num(1))]) posn_x_func_app_varx_1 = FuncApplication(Variable('posn-x'), [func_app_varx_1]) select_posn_x_error = FuncApplication(Variable('posn-x'), [Num(3)]) ex1 = '(ex*' ex_abc = 'abc' ex_1 = '1' exx1 = ')' exx2 = ex_abc + exx1 #And and1 = And([Boolean(True), Boolean(False)]) and2 = And( [Boolean(False), FuncApplication(Variable('/'), [Num(1), Num(0)])]) and3 = And( [Boolean(True), FuncApplication(Variable('/'), [Num(1), Num(1)])]) #equals equals34 = FuncApplication(Variable('='), [Num(3), Num(4)]) equals33 = FuncApplication(Variable('='), [Num(3), Num(3)]) equals_3_true = FuncApplication(Variable('='), [Num(3), Boolean(False)]) #bigger and less than biggerthan34 = FuncApplication(Variable('>'), [Num(3), Num(4)]) lessthan34 = FuncApplication(Variable('<'), [Num(3), Num(4)]) lessthan_error = FuncApplication(Variable('>'), [Variable('xyz'), Num(4)]) #if. if_1 = If([equals34, Num(3), Num(4)]) if_2 = If([equals33, Num(3), Num(4)])
def play(self, basescope=None): if basescope == None: basescope = Scope() self.before(basescope) self.playmain(basescope) self.after(basescope)
def execute(self, scope=None): if scope == None: scope = Scope() scope.execute(self.script)
def execute_child(self, child, base=None): assert isinstance(child, Playable) if base == None: base = Scope() child.play(Scope(base))
def __init__(self, scope = None): self.scope = Scope() if scope is None else scope
def __init__(self): self.scope = Scope()
def _type(self): # print "Type" self.observer.begin_type() return_type = None if self.token_list[self.current].kind == self.kind_map["IDENTIFIER"]: name = self.match("IDENTIFIER") # get the name of an identifier return_type = self.current_scope.find(name) if return_type is None: self.total_error_flag = 1 sys.stderr.write("error: indentifier not found. attempting to assign " "uncreated type\n") self.observer.end_type() return None if isinstance(return_type, Type): self.observer.end_type() return return_type else: self.total_error_flag = 1 sys.stderr.write("error: found not Type object\n") return None elif self.token_list[self.current].kind == self.kind_map["ARRAY"]: self.match("ARRAY") length = None e = self._expression() if isinstance(e, NumberNode): length = e.constant.value else: self.total_error_flag = 1 sys.stderr.write("error: not a valid type for array length\n") self.match("OF") array_type = self._type() if array_type is None: self.total_error_flag = 1 sys.stderr.write("error: array type not found\n") return None return_type = Array(length, array_type) self.observer.end_type() return return_type elif self.token_list[self.current].kind == self.kind_map["RECORD"]: self.match("RECORD") id_list = [] outer_scope = self.current_scope self.current_scope = Scope(outer_scope) while self.token_list[self.current].kind == self.kind_map["IDENTIFIER"]: id_list = self._identifier_list() self.match(":") record_field_type = self._type() if record_field_type is None: self.total_error_flag = 1 sys.stderr.write("error: record field type nonexistent\n") self.match(";") for name in id_list: if not self.current_scope.local(name): self.current_scope.insert(name, Variable(record_field_type)) else: self.total_error_flag = 1 sys.stderr.write("error: attempting to redefine field\n") return None self.match("END") return_type = Record(self.current_scope) outer_scope = self.current_scope.outer_scope self.current_scope.outer_scope = None self.current_scope = outer_scope self.observer.end_type() return return_type else: self.total_error_flag = 1 sys.stderr.out("error: expecting Identifier, ARRAY, or RECORD\n") self.observer.end_type()
def interpreter(input_path="exampleInput.c",debugging=False): ### STEP 0:declaration of (global) variables and preprocessing ### # Declarate variables global func_table,main_flow,current_scope,flow_stack,jump_to_new_func, ret_val,current_scope, memory, isError, debug program_end = False # Set debugging mode if debugging: debug=True # Make AST with open(input_path,'r') as outfile: result=cparse().parse( input=outfile.read(), lexer=clex(), tracking=True ) if debug: print(result) # in case of Syntax error -> end program if result==None: isError=True return # Make function table for i in range(len(result)): if result[i][0] == "func": ast = result[i] if len(ast[3]) == 1 and ast[3][0] == "void": func_table[ast[2]] = {'ret_type':ast[1], 'param_num': 0, 'param_list': [], 'flow_graph': None} else: func_table[ast[2]] = {'name':ast[2], 'ret_type':ast[1], 'param_num': len(ast[3]), 'param_list': ast[3], 'flow_graph':None} # make symbol table # sub 1: Convert scope list to Scope objects Scope_list=list(map(lambda x: Scope(x),scope_list_ext(input_path=input_path))) # sub 2: Find parent scope for each scopes # note: Scope_list[0] is always global scope(see scope_list_ext) for i in range(1,len(Scope_list)): for j in range(i): if (Scope_list[j].start_line <= Scope_list[i].start_line and Scope_list[j].end_line >= Scope_list[i].end_line): Scope_list[i].parent_scope = Scope_list[j] current_scope = Scope_list[0] scope_start_line = [] scope_end_line = [] for output in Scope_list: scope_start_line.append(output.start_line) scope_end_line.append(output.end_line) scope_start_line.reverse() scope_end_line.reverse() Scope_list.reverse() # Print Scope (for debugging) if debug: print("** SCOPE LIST **") for output in Scope_list: print(output) print(scope_start_line) print("** FUNCTION TABLE: dictionary of dictionaries **") print(func_table) # make flow graph for each functions for i in range(len(result)): if result[i][0] == 'func': ast = result[i] ast_scope = ast[5] statement_list = ast[4] func_flow = make_flow(ast, ast_scope, statement_list) if ast[2] in func_table.keys(): func_table[ast[2]]['flow_graph'] = func_flow if ast[2] == 'main': main_flow = func_flow # Make memory structure compute_static_allocation(result) memory = Memory() ### STEP 1:main loop ### syntax=re.compile(r"(\Anext( (0|[1-9]\d*))?\Z)|(\Aprint [A-Za-z_]\w*(\[\d*\])?\Z)|(\Atrace [A-Za-z_]\w*\Z)|(\Aquit\Z)|(\Amem\Z)") while True: global current_address cmd = input(">> ").strip() #Catch incorrect syntax if syntax.match(cmd) is None: if (cmd[0:4] == "next"): print("Incorrect command usage: try 'next [lines]'") elif (cmd[0:5] == "print") or (cmd[0:5] == "trace"): print("Invalid typing of the variable name") else: print("Wrong expression!!\n <code syntax>\n") print((" next\n" " next <integer>\n" " print <ID>\n" " trace <ID>\n" " quit\n")) continue #instruction handler if (cmd[0:4] == "next"): if (len(cmd) == 4): line_num = 1 else: line_num = int(cmd[5:]) for i in range(line_num): if program_end: break if debug: print("line", main_flow.lineno, main_flow.statement) try: if (main_flow.statement is None): prev_scope = None if main_flow.lineno in scope_start_line: scope_copy = copy.deepcopy(Scope_list[scope_start_line.index(main_flow.lineno)]) prev_scope = current_scope current_scope = scope_copy if debug: print("Change scope to", current_scope) if jump_to_new_func: # save parameter to new symbol_table params = func_table[new_func]['param_list'] for k in range(func_table[new_func]['param_num']): if type(params[k][1]) is tuple: current_scope.symbol_table[params[k][1][1]] = {'address': current_address, 'type': params[k][0]+"arr", 'value':[param_pass[k]], 'history':[(main_flow.lineno, param_pass_addr.pop(0))]} current_address += 4 else: current_scope.symbol_table[params[k][1]] = {'address': current_address, 'type':params[k][0] , 'value':[param_pass[k]], 'history':[(main_flow.lineno, param_pass[k])]} current_address += 4 if debug: current_scope.print_symboltable() jump_to_new_func = False else: current_scope.parent_scope = prev_scope elif main_flow.lineno in scope_end_line: prev_scope = current_scope current_scope = current_scope.parent_scope if debug: print("Change scope to", current_scope) main_flow = main_flow.next_node if (main_flow is None): current_scope = prev_scope print("End of program") program_end = True elif main_flow.statement[0] == 'declare': for j in range(len(main_flow.statement[2])): if type(main_flow.statement[2][j]) is tuple: if (main_flow.statement[2][j][0] == 'TIMES'): # declaration of pointer current_scope.symbol_table[main_flow.statement[2][j][1]] = {"address": current_address, "type":main_flow.statement[1]+"ptr", "value":['N/A'], "size":0, "history": [(main_flow.statement[-1], 'N/A')]} current_address += 4 else: # declaration of array current_scope.symbol_table[main_flow.statement[2][j][0]] = {"address": current_address, "type":main_flow.statement[1]+"arr", "size":int(main_flow.statement[2][j][1]), "value":[['N/A' for k in range(int(main_flow.statement[2][j][1]))]], "history": [(main_flow.statement[-1], current_address)]} current_address += 4 * int(main_flow.statement[2][j][1]) else: current_scope.symbol_table[main_flow.statement[2][j]] = {"address": current_address, "type":main_flow.statement[1], "value":['N/A'], "history": [(main_flow.statement[-1], 'N/A')]} current_address += 4 if debug: current_scope.print_symboltable() main_flow = main_flow.next_node elif main_flow.statement[0] == 'assign': assign_value(main_flow.statement[1], main_flow.statement[3], current_scope, main_flow.statement[-1]) if debug: current_scope.print_symboltable() current_scope.parent_scope.print_symboltable() if jump_to_new_func == False: main_flow = main_flow.next_node elif main_flow.statement[0] == 'FOR': if main_flow.visited: if main_flow.statement[4][0] in current_scope.symbol_table.keys(): if main_flow.statement[4][1] == '++': assign_value(main_flow.statement[4][0], get_value(main_flow.statement[4][0],current_scope)+1, current_scope, main_flow.statement[4][2]) elif main_flow.statement[4][1] == '--': assign_value(main_flow.statement[4][0], get_value(main_flow.statement[4][0],current_scope)-1, current_scope, main_flow.statement[4][2]) if (get_value(main_flow.statement[3][0], current_scope) < get_value(main_flow.statement[3][2],current_scope)): main_flow = main_flow.next_node_branch else: main_flow.visited = False main_flow = main_flow.next_node else: assign_value(main_flow.statement[2][1], main_flow.statement[2][3], current_scope, main_flow.statement[2][-1]) main_flow.visited = True if (calc_value(main_flow.statement[3], current_scope)): main_flow = main_flow.next_node_branch else: main_flow = main_flow.next_node if debug: current_scope.print_symboltable() elif main_flow.statement[0] == 'IF': if main_flow.visited: main_flow.visited = False main_flow = main_flow.next_node else: main_flow.visited = True if calc_value(main_flow.statement[2], current_scope): main_flow = main_flow.next_node_branch else: if main_flow.next_node_branch2 is not None: main_flow = main_flow.next_node_branch2 else: main_flow.visited = False main_flow = main_flow.next_node elif main_flow.statement[0] == 'WHILE': if calc_value(main_flow.statement[2], current_scope): main_flow = main_flow.next_node_branch else: main_flow = main_flow.next_node elif main_flow.statement[0] == 'RETURN': if len(main_flow.statement) > 2: # if there is a return value ret_val = calc_value(main_flow.statement[1], current_scope) if debug: print("Return value: ", ret_val) if len(flow_stack) != 0: ret_addr = flow_stack.pop() main_flow = ret_addr[0] current_scope = ret_addr[1] else: print("End of program") program_end = True elif main_flow.statement[0] == 'printf': print_string = None if "%f" in main_flow.statement[1][0]: print_string = main_flow.statement[1][0][1:-1].replace('%f', str(calc_value(main_flow.statement[1][1], current_scope))) elif "%d" in main_flow.statement[1][0]: print_string = main_flow.statement[1][0][1:-1].replace('%d', str(calc_value(main_flow.statement[1][1], current_scope))) else: # printf(const char*) print_string = main_flow.statement[1][0][1:-1] print(print_string.replace(r'\n', '\n'), end="") main_flow = main_flow.next_node elif main_flow.statement[0] == 'free': target_scope = memory.free(int(current_scope.symbol_table[main_flow.statement[1][0]]['history'][-1][1])) target_scope.symbol_table[main_flow.statement[1][0]]['history'].append((main_flow.lineno, 'N/A')) main_flow = main_flow.next_node elif main_flow.statement[0] in current_scope.symbol_table.keys(): if main_flow.statement[1] == '++': assign_value(main_flow.statement[0], get_value(main_flow.statement[0],current_scope)+1, current_scope, main_flow.statement[2]) elif main_flow.statement[1] == '--': assign_value(main_flow.statement[0], get_value(main_flow.statement[0],current_scope)-1, current_scope, main_flow.statement[2]) main_flow = main_flow.next_node except: print("Run-time error: line", main_flow.lineno) isError=True break if isError: break elif (cmd[0:5] == "trace"): if len(cmd) == 5: # No parameter pass else: print_trace(cmd[6:], current_scope) elif (cmd[0:5] == "print"): if len(cmd) == 5: # No parameter pass else: print_value(cmd[6:], current_scope) elif (cmd[0:4] == "quit"): break elif (cmd[0:3] == "mem"): print("Dynamic allocation : {}, {}".format(memory.num_used_fragment, memory.total_memory - memory.free_memory)) else: print("Exception!") if isError: break
def execute(self, scope = None): if scope == None: scope = Scope() scope.execute(self.script)
def play_project(project, reporter = None, project_path = 'unkown', variables = None): assert isinstance(project, Project) if project.current_special == None: raise RuntimeError('No special to start!') user_count = project.user_count iteration_count = project.iteration_count special = project.current_special user_factory = project.user_factory iteration_factory = project.iteration_factory global_factory = project.global_factory if reporter != None: from Report import Report if type(reporter) in (str, unicode): reporter = Report(reporter) assert isinstance(reporter, Report) import datetime start_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') info = { 'Start Time': start_time, 'User Count': user_count, 'Iteration Count': iteration_count, 'Special': special.label, 'Project Path': project_path, } import ReportManager ReportManager.start_report(reporter = reporter, project = project, info = info) import PlayPolicy policy = PlayPolicy.IterationBasedPlayPolicy( player = special, user_count = user_count, iteration_count = iteration_count, user_factory = user_factory, iteration_factory = iteration_factory, global_factory = global_factory, reporter = reporter ) import sys sys.path.append(os.path.join(sys.path[0], 'runtime')) sys.path.append(os.path.join(sys.path[0], 'plugin')) if variables: from Scope import Scope scope = Scope() scope.variables = variables policy.play(scope) else: policy.play() if len(sys.path) >= 2 and sys.path[-2:] == ['runtime', 'plugin']: sys.path.pop() sys.path.pop() if reporter: reporter.finish()
def test_scope_insert(self): s = Scope(None) i = Integer() s.insert("Integer", i) self.assertEqual(i, s.find("Integer"))
class Parser: def __init__(self, scanner, output_object, parser_type, style): """Initializes the parser with a scanner and output style (text or graph). """ self.scanner = scanner self.last = None self.current = None self.style = style self.parser_type = parser_type self.output_object = output_object # The stack is used to store non-terminals for output. The # ParserObserver uses it to determine indentation and construct # edges for the graph. self.stack = [] # Used as IDs for non-terminals in the graph. self.graph_index = 0 # Number of tokens skipped after an error has occured. self.num_tokens_skipped = 0 # Whether to supress error messages. self.supress = False # Whether to display output (will be false when an error occurs). self.display = True # The last token mismatched. Used to make sure mismatched tokens do not # increment supression counters more than once. self.last_mismatch = None self.weak_tokens = {";", ":", ",", ")", "]", "END"} def next(self): """Get the next token. From Peter's lecture.""" self.last = self.current self.current = self.scanner.next() while self.current.kind == "INVALID": self.current = self.scanner.next() def invalid_token(self, e): """Handles an invalid token. Will print an error message if not supressed. """ if not self.supress: self.supress = True self.num_tokens_skipped = 0 self.display = False sys.stderr.write(e.message + "\n") self.last_mismatch = self.current def increment_skip(self): """If errors are being supressed, increment tokens skipped.""" # Do not increment the counter if the token has already been # mismatched before. if self.supress and (self.last_mismatch == None or self.last_mismatch != self.current): self.num_tokens_skipped += 1 if self.num_tokens_skipped > 7: self.supress = False self.num_tokens_skipped = 0 @ParserObserver.terminal def match(self, kind): """Match a token to kind(s). Parts from Peter's lecture. Return the token matched. """ try: self.increment_skip() # Match token with a set of kinds. if type(kind) is set: # Token matched. if self.current.kind in kind: self.next() return self.last # Token mismatch. Throw an exception. else: raise ParserInvalidKindError(kind, self.current) # Match token with a single kind else: # Token matched. if self.current.kind == kind: self.next() return self.last # Token mismatch. Throw an exception else: raise ParserInvalidKindError(kind, self.current) except ParserInvalidKindError as e: # Handle the exception. self.invalid_token(e) def sync(self, kinds, terminals): """Resync the parser when there is a mismatch of non-weak symbols. The function will skip tokens until reaching a strong token in kinds or a symbol that terminates the program. """ # Skip until finding a strong symbol in kinds. while self.current.kind not in kinds: # Raise an exception due to mismatch try: raise ParserInvalidKindError("Type", self.current) except ParserInvalidKindError as e: self.invalid_token(e) # The program ended before the parser is able to sync. end the loop. if self.current.kind in terminals: return False # Skip the current token. self.next() # Sucessfully re-synced the parser. return True def insert(self, name, value): """Insert an entry into the symbol table.""" try: if self.current_scope.local(name.value): raise DuplicateDeclarationError(name) self.current_scope.insert(name.value, value) except DuplicateDeclarationError as e: self.invalid_token(e) def find(self, name): """Find an identifier in the symbol table.""" try: entry = self.current_scope.find(name) if entry == None: raise EntryNotFoundInSymbolTable(self.last) return entry except EntryNotFoundInSymbolTable as e: self.invalid_token(e) def set_record_scope(self, entry): """Set the current scope to be a record's scope.""" if isinstance(entry, Variable) or isinstance(entry, Field): # Record can be either in variable or field. if isinstance(entry.type, Array) and isinstance(entry.type.element_type, Record): # An array of record. self.record_scope = entry.type.element_type.scope elif isinstance(entry.type, Record): # a record variable. self.record_scope = entry.type.scope else: self.record_scope = None else: self.record_scope = None def negate_relation(self, relation): """Negate the relation in a condition.""" negation_map = {"=": "#", "#": "=", ">": "<=", "<": ">=", ">=": "<", "<=": ">"} return negation_map[relation] @ParserObserver.selector def selector(self, location): """Match the grammar of a selector.""" ret = None # 0 to many patterns. while True: if self.current.kind == "[": self.match("[") self.stack.append("ExpressionList") expressions = self.expression_list() self.match("]") for expression in expressions: if not isinstance(location, Location) or not isinstance(location.type, Array): # Not an array variable. try: raise InvalidArray(location.type, self.last) except InvalidArray as e: self.invalid_token(e) cur = Index(location, expression) cur.token = self.last ret = cur location = cur elif self.current.kind == ".": self.match(".") name = self.match("identifier") if name == None: continue if self.record_scope == None: # Not a record variable. try: raise InvalidRecord(location.type, self.last) except InvalidRecord as e: self.invalid_token(e) break # Access the record's scope and find the variable with name. self.current_scope = self.record_scope entry = self.find(name.value) var = VariableAST(name.value, entry) self.set_record_scope(entry) cur = FieldAST(location, var) ret = cur location = cur else: # Pattern ended. break self.current_scope = self.program_scope return ret @ParserObserver.non_terminal def designator(self): """Match the grammar for a designator.""" name = self.match("identifier") if name == None: return None entry = self.find(name.value) if isinstance(entry, Constant): var = Number(entry) elif isinstance(entry, Variable): var = VariableAST(name.value, entry) else: # Identifier in designator cannot be a type. try: raise InvalidDesignator(entry, self.last) except InvalidDesignator as e: self.invalid_token(e) return VariableAST("INVALID", Variable(Invalid())) self.set_record_scope(entry) self.stack.append("Selector") ret = self.selector(var) if ret == None: ret = var if not isinstance(ret, Location) and not isinstance(ret, Number): try: raise InvalidDesignator(ret.type, self.last) except InvalidDesignator as e: self.invalid_token(e) return VariableAST("INVALID", Variable(Invalid())) return ret @ParserObserver.non_terminal def identifier_list(self): """Match the grammar for a identifier list.""" id_list = [] identifier = self.match("identifier") id_list.append(identifier) # 0 to many patterns. while True: if self.current.kind == ",": self.match(",") identifier = self.match("identifier") id_list.append(identifier) else: # Pattern ended. break return id_list @ParserObserver.non_terminal def expression_list(self): """Match the grammar for a expression list.""" exp_list = [] self.stack.append("Expression") exp_list.append(self.expression()) # 0 to many patterns. while True: if self.current.kind == ",": self.match(",") self.stack.append("Expression") expression = self.expression() exp_list.append(expression) else: # Pattern ended. break return exp_list @ParserObserver.non_terminal def read(self): """Match the grammar for a read.""" self.match("READ") self.stack.append("Designator") location = self.designator() if not isinstance(location, Location) or location.type != self.integer_type: # Not an integer variable. try: raise InvalidRead(location.type, self.last) except InvalidRead as e: self.invalid_token(e) r = Read(location) r.token = self.last return r @ParserObserver.non_terminal def write(self): """Match the grammar for a write.""" self.match("WRITE") self.stack.append("Expression") expression = self.expression() if expression.type != self.integer_type: # Not an integer. try: raise InvalidWrite(expression.type, self.last) except InvalidWrite as e: self.invalid_token(e) return Write(expression) @ParserObserver.non_terminal def condition(self): """Match the grammar for a condition.""" self.stack.append("Expression") left = self.expression() # Match a token with a set of kinds. kinds = {"=", "#", "<", ">", "<=", ">="} relation = self.match(kinds) self.stack.append("Expression") right = self.expression() if left.type != self.integer_type or right.type != self.integer_type: # Either is not of Constant or Variable of type integer. try: raise InvalidCondition(left.type, right.type, self.last) except InvalidCondition as e: self.invalid_token(e) return Condition(left, right, relation.kind) @ParserObserver.non_terminal def while_instruction(self): """Match the grammar for a while.""" self.match("WHILE") self.stack.append("Condition") condition = self.condition() self.match("DO") self.stack.append("Instructions") instructions = self.instructions() self.match("END") # Replaces while with repeat in AST left = condition.left right = condition.right inverse = self.negate_relation(condition.relation) inverse_left = copy.deepcopy(left) inverse_right = copy.deepcopy(right) inverse_condition = Condition(inverse_left, inverse_right, inverse) repeat = Repeat(inverse_condition, instructions) repeat.next = None return If(condition, repeat, None) @ParserObserver.non_terminal def repeat(self): """Match the grammar for a repeat.""" self.match("REPEAT") self.stack.append("Instructions") instructions = self.instructions() self.match("UNTIL") self.stack.append("Condition") condition = self.condition() self.match("END") return Repeat(condition, instructions) @ParserObserver.non_terminal def if_instruction(self): """Match the grammar for an if.""" self.match("IF") self.stack.append("Condition") condition = self.condition() self.match("THEN") self.stack.append("Instructions") instructions_true = self.instructions() instructions_false = None # Optional match. if self.current.kind == "ELSE": self.match("ELSE") self.stack.append("Instructions") instructions_false = self.instructions() self.match("END") return If(condition, instructions_true, instructions_false) @ParserObserver.non_terminal def assign(self): """Match the grammar for an assign.""" self.stack.append("Designator") location = self.designator() self.match(":=") self.stack.append("Expression") expression = self.expression() if not isinstance(location, Location) or location.type != expression.type: # Left side is not variable, or right side is a type, or types of # both sides do not match up. try: raise InvalidAssignment(location.type, expression.type, self.last) except InvalidAssignment as e: self.invalid_token(e) return Assign(location, expression) @ParserObserver.non_terminal def instruction(self): """Match the grammar for an instruction.""" # The set of kinds to be matched. kinds = {"identifier", "IF", "REPEAT", "WHILE", "READ", "WRITE"} # The symbols that signal end of an instruction. In this case, # . and eof singal the end of the program, which must be the # end of an instruction. terminals = {"END", ".", "eof"} if self.current.kind == "identifier": self.stack.append("Assign") return self.assign() elif self.current.kind == "IF": self.stack.append("If") return self.if_instruction() elif self.current.kind == "REPEAT": self.stack.append("Repeat") return self.repeat() elif self.current.kind == "WHILE": self.stack.append("While") return self.while_instruction() elif self.current.kind == "READ": self.stack.append("Read") return self.read() elif self.current.kind == "WRITE": self.stack.append("Write") return self.write() elif self.current.kind == "END": # END signifies the end of instructions. return None else: # No match is made and no END of ending instructions. An error has # occured and the symbol missing is not weak. The parser must resync # with the code. if not self.sync(kinds, terminals): return None @ParserObserver.non_terminal def instructions(self): """Match the grammar for instructions.""" self.stack.append("Instruction") head = instruction = self.instruction() # 0 or more patterns. while True: # These symbols preceed or end instructions. End the loop. if self.current.kind in {"THEN", "ELSE", "REPEAT", "DO", "END", "UNTIL", ".", "eof"}: break # A normal or a mismatch. If necessary resync will happen in # instruction. else: self.match(";") self.stack.append("Instruction") next_instruction = self.instruction() if next_instruction == None: continue instruction.next = next_instruction instruction = instruction.next if instruction != None: instruction.next = None return head @ParserObserver.non_terminal def factor(self): """Match the grammar for a factor.""" ret = None if self.current.kind == "integer": num = self.match("integer") const = Constant(self.integer_type, num.value) ret = Number(const) elif self.current.kind == "identifier": self.stack.append("Designator") ret = self.designator() elif self.current.kind == "(": self.match("(") self.stack.append("Expression") ret = self.expression() self.match(")") else: # An error has occured. Raise and catch it so we can handle the # error without crashing the program. try: self.increment_skip() raise ParserInvalidKindError("Factor", self.current) except ParserInvalidKindError as e: self.invalid_token(e) return ret @ParserObserver.non_terminal def term(self): """Match the grammar for a term.""" self.stack.append("Factor") operator_map = {"*": "*", "DIV": "/", "MOD": "%"} cur = self.factor() # 0 or more patterns. while True: if self.current.kind == "*" or self.current.kind == "DIV" or self.current.kind == "MOD": if self.current.kind == "*": operator = self.match("*") elif self.current.kind == "DIV": operator = self.match("DIV") else: operator = self.match("MOD") self.stack.append("Factor") var = self.factor() if isinstance(cur, Number) and isinstance(var, Number): # Constant folding. try: val = int(eval(str(cur.entry.value) + str(operator_map[operator.kind]) + str(var.entry.value))) except ZeroDivisionError: # Divide by 0 error. self.invalid_token(DivideByZero(self.last)) break const = Constant(self.integer_type, val) cur = Number(const) else: if isinstance(cur, VariableAST) and ( isinstance(cur.variable, Array) or isinstance(cur.variable, Record) ): # Trying to perform an operation on non-integers. try: raise InvalidArithmeticOperation(cur, self.last) except InvalidArithmeticOperation as e: self.invalid_token(e) else: cur = Binary(operator.kind, cur, var, self.integer_type) # Remember the token for node in case of run time errors. cur.token = self.last else: # Pattern ended. break return cur @ParserObserver.non_terminal def expression(self): """Match the grammar of an expression.""" operator = None if self.current.kind == "+": operator = self.match("+") elif self.current.kind == "-": operator = self.match("-") self.stack.append("Term") cur = self.term() if operator != None and operator.kind == "-": # Negate the expression if needed. if isinstance(cur, Number): # Constant folding. cur = Number(Constant(self.integer_type, eval(str(operator.kind) + str(cur.entry.value)))) else: if isinstance(cur, VariableAST) and ( isinstance(cur.variable, Array) or isinstance(cur.variable, Record) ): # Trying to perform an operation on non-integers. try: raise InvalidArithmeticOperation(cur, self.last) except InvalidArithmeticOperation as e: self.invalid_token(e) else: cur = Binary(operator.kind, Number(Constant(self.integer_type, 0)), cur, self.integer_type) # Remember the token for node in case of run time errors. cur.token = self.last # 0 or more patterns. while True: if self.current.kind in {"+", "-"}: if self.current.kind == "+": operator = self.match("+") else: operator = self.match("-") self.stack.append("Term") var = self.term() if isinstance(cur, Number) and isinstance(var, Number): # Constant folding. cur = Number( Constant( self.integer_type, eval(str(cur.entry.value) + str(operator.kind) + str(var.entry.value)) ) ) else: if isinstance(cur, VariableAST) and ( isinstance(cur.variable, Array) or isinstance(cur.variable, Record) ): # Trying to perform an operation on non-integers. try: raise InvalidArithmeticOperation(cur, self.last) except InvalidArithmeticOperation as e: self.invalid_token(e) else: cur = Binary(operator.kind, cur, var, self.integer_type) # Remember token for node in case of run time errors. cur.token = self.last else: # Pattern ended. break if cur == None: # Return an invalid variable node in case of parsing errors. cur = VariableAST("INVALID", Variable(Invalid())) return cur @ParserObserver.non_terminal def type(self): """Match the grammar of a type.""" type_obj = None if self.current.kind == "identifier": name = self.match("identifier") # Return the type object found in current scope try: type_obj = self.current_scope.find(name.value) if type_obj == None: raise IdentifierUsedBeforeDeclared(name) elif not isinstance(type_obj, Type): raise IdentifierDoesNotDenoteType(name, type_obj) except (IdentifierUsedBeforeDeclared, IdentifierDoesNotDenoteType) as e: type_obj = Invalid() self.invalid_token(e) elif self.current.kind == "ARRAY": self.match("ARRAY") self.stack.append("Expression") size = self.expression() try: if not isinstance(size, Number) or (isinstance(size, Number) and size.entry.value <= 0): # Arrays need to have size greater than 0. raise InvalidArraySize(size, self.last) except InvalidArraySize as e: type_obj = Invalid() self.invalid_token(e) return type_obj self.match("OF") self.stack.append("Type") t = self.type() # Create an Array type object. type_obj = Array(t, size.entry.value) elif self.current.kind == "RECORD": self.match("RECORD") # Create a new scope for the record and set the current scope # to the record scope. record_scope = Scope(self.current_scope) self.current_scope = record_scope # 0 or more patterns. while True: if self.current.kind == "identifier": self.stack.append("IdentifierList") id_list = self.identifier_list() self.match(":") self.stack.append("Type") t = self.type() self.match(";") # Insert the type objects into the current scope. field = Field(t) for name in id_list: self.insert(name, field) else: # pattern ended. break self.match("END") # Create a Record object with the current scope. Also set the # current scope to the outer scope and remove the outer pointer. type_obj = Record(self.current_scope) outer = self.current_scope.outer self.current_scope.outer = None self.current_scope = outer else: # An error has occured. Raise and catch it so we can handle the # error without crashing the program. try: self.increment_skip() raise ParserInvalidKindError("Type", self.current) except ParserInvalidKindError as e: self.invalid_token(e) return type_obj @ParserObserver.non_terminal def const_decl(self): """Match the grammar of a const declaration.""" self.match("CONST") # 0 or more patterns. while True: if self.current.kind == "identifier": name = self.match("identifier") self.match("=") self.stack.append("Expression") value = self.expression() self.match(";") try: if isinstance(value, Number): # Create Constant object and insert into symbol table. const = Constant(self.integer_type, value.entry.value) self.insert(name, const) else: self.insert(name, Variable(Invalid())) raise InvalidConstantValue(value, self.last) except InvalidConstantValue as e: self.invalid_token(e) else: # Pattern ended. break @ParserObserver.non_terminal def type_decl(self): """Match the grammar of a type declaration.""" self.match("TYPE") # 0 or more patterns. while True: if self.current.kind == "identifier": name = self.match("identifier") self.match("=") self.stack.append("Type") t = self.type() self.match(";") self.insert(name, t) else: # Pattern ended. break @ParserObserver.non_terminal def var_decl(self): """Match the grammar of a var declaration.""" self.match("VAR") # 0 or more patterns. while True: if self.current.kind == "identifier": self.stack.append("IdentifierList") id_list = self.identifier_list() self.match(":") self.stack.append("Type") var_type = self.type() self.match(";") # Create Variable object(s) and insert them into symbol table. for name in id_list: var = Variable(var_type) self.insert(name, var) else: # Pattern ended. break @ParserObserver.non_terminal def declarations(self): """Match the grammar of declarations.""" # Strong symbols for resync kinds = {"CONST", "TYPE", "VAR"} # Signify end of declaration. terminals = {".", "eof", "BEGIN"} # 0 or more patterns. while True: if self.current.kind == "CONST": self.stack.append("ConstDecl") self.const_decl() elif self.current.kind == "TYPE": self.stack.append("TypeDecl") self.type_decl() elif self.current.kind == "VAR": self.stack.append("VarDecl") self.var_decl() # A normal end of declaration. elif self.current.kind in {"BEGIN", "END"}: break # A strong symbol mismatch. Need to resync the parser. else: if not self.sync(kinds, terminals): return @ParserObserver.non_terminal def program(self): """Match the grammar of the program.""" # Create the program scope self.program_scope = Scope(self.universe_scope) self.current_scope = self.program_scope self.match("PROGRAM") begin_name = self.match("identifier") self.match(";") self.stack.append("Declarations") self.declarations() # AST instruction tree. tree = None # Optional begin symbol. if self.current.kind == "BEGIN": self.match("BEGIN") self.stack.append("Instructions") tree = self.instructions() self.match("END") end_name = self.match("identifier") # Throw an exception if there is a program name mismatch if ( begin_name == None or end_name == None or begin_name.value == None or end_name.value == None or begin_name.value != end_name.value ): try: raise ProgramNameMismatch(begin_name, end_name) except ProgramNameMismatch as e: self.invalid_token(e) self.match(".") self.match("eof") return tree def parse(self): """Method called by sc to parse the code.""" # Create the universe scope. self.universe_scope = Scope(None) self.record_scope = None self.integer_type = Integer() self.universe_scope.insert("INTEGER", self.integer_type) # Start by getting the first token. self.next() # Start parsing by matching the grammar of program. self.stack.append("Program") tree = self.program() # Display the output only if no error has occured. if self.display: if self.parser_type == "-t": # Set the program scope if printing symbol table. self.output_object.program_scope = self.program_scope elif self.parser_type == "-a": # Set the program scope and instruction tree for AST output. self.output_object.program_scope = self.program_scope self.output_object.tree = tree elif self.parser_type == "-i": # Set the environment and instruction tree for interpreter. visitor = SymbolTableVisitor() self.output_object.env = self.current_scope.accept(visitor) self.output_object.tree = tree self.output_object.display()
def eval(self, scope=None): if scope == None: scope = Scope() return scope.eval(self.script)
def execute_script(self, script, base=None): assert isinstance(script, Script) if base == None: base = Scope() script.execute(base)