Example #1
0
 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)
Example #2
0
	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)
Example #4
0
 def __init__(self):
     self.global_scope = Scope("GLOBAL")
     self.global_scope.build_global([
         BuiltInTypeSymbol("STRING"),
         BuiltInTypeSymbol("INT"),
         BuiltInTypeSymbol("BOOL"),
         BuiltInTypeSymbol("NULL"),
     ])
Example #5
0
	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)
Example #6
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
Example #7
0
	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()
Example #8
0
    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()
Example #9
0
 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}
Example #10
0
 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
Example #11
0
    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"))
Example #12
0
	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)
Example #13
0
 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']
     }
Example #14
0
    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()
Example #15
0
	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'
Example #16
0
    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)
Example #17
0
 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']
     }
Example #18
0
 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']
     }
Example #19
0
 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)
Example #20
0
 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
     }
Example #21
0
 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 = []
Example #22
0
    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)])
Example #23
0
 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)
Example #24
0
    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)
Example #25
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)
Example #26
0
    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
Example #27
0
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*"'
Example #28
0
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()
Example #29
0
	def testBasic(self):
		scope = Scope()
		self.loop.play(scope)

		self.assertEqual(scope.lookup('x'), 10)
		self.assertEqual(scope.lookup('y'), 10)
Example #30
0
	def eval(self, scope = None):
		if scope == None:
			scope = Scope()
		return scope.eval(self.script)
Example #31
0
 def execute_here(self, child, scope=None):
     assert isinstance(child, Playable)
     if scope == None:
         scope = Scope()
     child.play(scope)
Example #32
0
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
Example #33
0
 def __init__(self, enclosing_scope):
     Symbol.__init__(self)
     scope_name = self.make_name(enclosing_scope.scope_name)
     Scope.__init__(self, scope_name, enclosing_scope)
Example #34
0
## 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
Example #35
0
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)
Example #36
0
## 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
Example #37
0
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)])
Example #38
0
 def play(self, basescope=None):
     if basescope == None:
         basescope = Scope()
     self.before(basescope)
     self.playmain(basescope)
     self.after(basescope)
Example #39
0
 def execute(self, scope=None):
     if scope == None:
         scope = Scope()
     scope.execute(self.script)
Example #40
0
 def execute_child(self, child, base=None):
     assert isinstance(child, Playable)
     if base == None:
         base = Scope()
     child.play(Scope(base))
Example #41
0
 def __init__(self, scope = None):
     self.scope = Scope() if scope is None else scope
Example #42
0
 def __init__(self):
     self.scope = Scope()
Example #43
0
    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()
Example #44
0
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
Example #45
0
	def execute(self, scope = None):
		if scope == None:
			scope = Scope()
		scope.execute(self.script)
Example #46
0
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()
Example #47
0
 def test_scope_insert(self):
     s = Scope(None)
     i = Integer()
     s.insert("Integer", i)
     self.assertEqual(i, s.find("Integer"))
Example #48
0
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()
Example #49
0
 def eval(self, scope=None):
     if scope == None:
         scope = Scope()
     return scope.eval(self.script)
Example #50
0
 def execute_script(self, script, base=None):
     assert isinstance(script, Script)
     if base == None:
         base = Scope()
     script.execute(base)