def _mathexp(caller_node):
	ice9_parser_global.logger.debug("Entering _mathexp")
	
	math_node = ice9_node.expr_node()
	math_node.operation = ice9_parser_global.tok.type
	ice9_parser_global.consume()
	ice9_parser_global.logger.debug(ice9_parser_global.tok)

	# Set pre child to caller node
	math_node.pre_child = caller_node

	# Set post child to term node
	math_node.post_child = term(None)

	if caller_node:
		validate_mathexp(math_node)
		result_node = math_node
	else:
		result_node = math_node.post_child

	if ice9_parser_global.tok.type in ['PLUS', 'MINUS']:
		result_node = _mathexp(result_node)

	ice9_parser_global.logger.debug("Exiting _mathexp")
	return result_node
def _term(caller_node):	
	ice9_parser_global.logger.debug("Entering _term")

	term_node = ice9_node.expr_node()
	term_node.operation = ice9_parser_global.tok.type
	ice9_parser_global.consume()
	ice9_parser_global.logger.debug(ice9_parser_global.tok)

	# Set pre child to caller node
	term_node.pre_child = caller_node

	# Set post child to factor node
	if in_first_of_factor() == True:
		factor_node = factor()
		term_node.post_child = factor_node
	else:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting a factor"
		sys.exit()

	# If caller_node was None, return the same value obtained in lower depth
	if caller_node:
		result_node = term_node
		validate_term(result_node)
	else:
		result_node = term_node.post_child

	if ice9_parser_global.tok.type in ['STAR', 'SLASH', 'MOD']:
		result_node = _term(result_node)

	ice9_parser_global.logger.debug("Exiting _term")
	return result_node
def dectype(parameters):
	ice9_parser_global.logger.debug("Entering dectype")

	paramter_identifier_list = ice9_parser_var.idlist()	
	
	if ice9_parser_global.tok.type == 'COLON':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
	else:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting ':'"
		sys.exit()

	if ice9_parser_global.tok.type == 'ID':
		paramter_identifier_type = ice9_parser_global.tok.value

		if paramter_identifier_type not in ice9_st_type.st_type:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value \
				 + " type", paramter_identifier_type, "not defined"
			sys.exit()
	
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
	else:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting id"
		sys.exit()

	for param in paramter_identifier_list:
		id_node = ice9_node.id_node(str(param), paramter_identifier_type, 0)
		parameters.append(id_node)

	ice9_parser_global.logger.debug("Exiting dectype")
def typeid():
    global dimension_length

    # Reset global variable dimension_length
    dimension_length = None
    dimension_length = list()

    ice9_parser_global.logger.debug("Entering typeid")

    data_type = ice9_parser_global.tok.value
    ice9_parser_global.consume()
    ice9_parser_global.logger.debug(ice9_parser_global.tok)

    # Dimension of the type
    dimension = 0

    # If array variable, store the dimension
    if ice9_parser_global.tok.type == "LBRACK":
        dimension = const_array_index()

        # Create a type node
    type_node = ice9_node.type_node(data_type, dimension, dimension_length)

    # Reset global variable dimension_length
    dimension_length = None
    dimension_length = list()

    ice9_parser_global.logger.debug("Exiting typeid")
    return type_node
def returntype():
	ice9_parser_global.logger.debug("Entering returntype")
	
	if ice9_parser_global.tok.type == 'ID':
		foundation_return_type = ice9_parser_global.tok.value
		return_type = ice9_st_type.get_basic_data_type(foundation_return_type)
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
	else:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting id"
		sys.exit()

   # Check if return type defined
	if not return_type:
		print "Line", ice9_parser_global.tok.lineno, ": on token '" + \
			ice9_parser_global.tok.value + "' return type '" + foundation_return_type + \
			"' not defined in scope 'GLOBAL'"
		sys.exit()
		
	if return_type not in ice9_st_type.st_type:
		print "Line", ice9_parser_global.tok.lineno, ": on token '" + \
			ice9_parser_global.tok.value + "' return type '" + return_type + \
			"' not defined in scope 'GLOBAL'"
		sys.exit()

	# Check if foundation_data_type is not an array
	if ice9_st_type.st_type[foundation_return_type][-1].dimension != 0:
		print "Line", ice9_parser_global.tok.lineno, ": on token '" + \
			ice9_parser_global.tok.value + "'procedure return type '" + foundation_return_type + \
			"' cannot be an array"
		sys.exit()
		
	ice9_parser_global.logger.debug("Exiting returntype")
	return return_type
def arrayindex():
	ice9_parser_global.logger.debug("Entering arrayindex")

	# Create a expression list where each node is an array dimension
	expr_list = list()
	expr_list.append(expr(None))

	# Array index must be of type int
	if expr_list[-1].return_data_type != 'int':
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
			"array index must be an 'int' operand"
		sys.exit()

	# Array index must have dimension 0
	if expr_list[-1].dimension != 0:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
			"array index cannot be an array reference"
		sys.exit()

	if ice9_parser_global.tok.type == 'RBRACK':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
	else:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting ']'"
		sys.exit()
		
	# Attach any remaining dimensions
	if ice9_parser_global.tok.type == 'LBRACK':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
		expr_list += arrayindex()

	ice9_parser_global.logger.debug("Exiting arrayindex")
	return expr_list
Пример #7
0
def main():
	ice9_parser_global.setup()
	ice9_parser_global.consume()
	ice9_parser_global.logger.debug(ice9_parser_global.tok)
	ice9_parser_global.create_instructions_op_file()
	ice9_parser_global.create_string_op_file()
	parse()
	ice9_parser_global.fix_forward_declarations()
	ice9_parser_global.generate_output_file()
	check_undefined_proc()
def _declist(parameters):
	ice9_parser_global.logger.debug("Entering _declist")

	dectype(parameters)

	if ice9_parser_global.tok.type == 'COMMA':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
		_declist(parameters)

	ice9_parser_global.logger.debug("Exiting declist")
def handle_var():
    ice9_parser_global.logger.debug("Entering var")

    var_list_node = varlist()

    if ice9_parser_global.tok.type == "SEMI":
        ice9_parser_global.consume()
        ice9_parser_global.logger.debug(ice9_parser_global.tok)
    else:
        print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting ';'"
        sys.exit()

    ice9_parser_global.logger.debug("Exiting var")
Пример #10
0
def _varlist():
    ice9_parser_global.logger.debug("Entering _varlist")

    var_node_list = list()
    var_node_list.append(vartype())

    if ice9_parser_global.tok.type == "COMMA":
        ice9_parser_global.consume()
        ice9_parser_global.logger.debug(ice9_parser_global.tok)
        var_node_list += _varlist()

    ice9_parser_global.logger.debug("Exiting _varlist")
    return var_node_list
def handle_forward():
	ice9_parser_global.logger.debug("Entering forward")
    
	if ice9_parser_global.tok.type == 'ID':
		proc_identifier = ice9_parser_global.tok.value
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
	else:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting id"
		sys.exit()

	if ice9_parser_global.tok.type == 'LPAREN':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
	else:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting '('"
		sys.exit()
	
	parameters = list()

	if ice9_parser_global.tok.type == 'ID':
		declist(parameters)
	
	if ice9_parser_global.tok.type == 'RPAREN':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
	else:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting ')'"
		sys.exit()

	return_type = None

	if ice9_parser_global.tok.type == 'COLON':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
		return_type = returntype()

	parameter_list = list()
	
	for param in parameters:
		parameter_list.append(param.foundation_data_type)

	st_proc_entry = ice9_st_proc.st_proc_entry(len(parameters), parameters, return_type, False)
	ice9_st_proc.add_entry_to_st_proc(proc_identifier, st_proc_entry)

	if ice9_parser_global.tok.type == 'SEMI':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
	else:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting ';'"
		sys.exit()
Пример #12
0
def parse():
	ice9_parser_global.logger.debug("Entering parse")
	
	in_head = False
	in_body = False

	# Case for no input
	if not ice9_parser_global.tok:
		return

	type = ice9_parser_global.tok.type
	stmt_node_list = list()

	ice9_parser_global.setup_code_generation()
	while type != 'EOF':
		
		in_head = False

		if in_body == False:
			if type == 'VAR':
				in_head = True
				ice9_parser_global.consume()
				ice9_parser_global.logger.debug(ice9_parser_global.tok)
				ice9_parser_var.handle_var()

			elif type == 'TYPE':
				in_head = True
				ice9_parser_global.consume()
				ice9_parser_global.logger.debug(ice9_parser_global.tok)
				ice9_parser_type.handle_type()

			elif type == 'FORWARD':
				in_head = True
				ice9_parser_global.consume()
				ice9_parser_global.logger.debug(ice9_parser_global.tok)
				ice9_parser_forward.handle_forward()
	
			elif type =='PROC':
				in_head = True
				ice9_parser_global.consume()
				ice9_parser_global.logger.debug(ice9_parser_global.tok)
				ice9_parser_proc.handle_proc()

		if in_head == False:
			ice9_parser_global.setup_stmt_section(ice9_parser_global.lno)
			if ice9_parser_statements.in_first_of_statement() == True:
				in_body = True
				stmt_node_list += ice9_parser_statements.statements()
			else:
				print "Line", ice9_parser_global.tok.lineno, ": unexpected token -", ice9_parser_global.tok.value
				sys.exit()

		type = ice9_parser_global.tok.type

		# Generate Code
		for stmt in stmt_node_list:
			stmt.generate_code()

	ice9_parser_global.logger.debug("Exiting parse")
	return
def exprlist():
	ice9_parser_global.logger.debug("Entering exprlist")

	expr_list = list()	

	if ice9_parser_global.tok.type in ['SLIT', 'MINUS', 'READ', 'QUEST', 'ID', 'TRUE', 'INT', 'LPAREN', 'FALSE']:
		expr_list.append(expr(None))

		if ice9_parser_global.tok.type == 'COMMA':
			ice9_parser_global.consume()
			ice9_parser_global.logger.debug(ice9_parser_global.tok)
			expr_list += _exprlist()
	
	ice9_parser_global.logger.debug("Exiting exprlist")
	return expr_list
Пример #14
0
def vartype():
    ice9_parser_global.logger.debug("Entering vartype")

    var_node_list = list()

    if ice9_parser_global.tok.type == "ID":
        identifier_list = idlist()
    else:
        print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting id"
        sys.exit()

    if ice9_parser_global.tok.type == "COLON":
        ice9_parser_global.consume()
        ice9_parser_global.logger.debug(ice9_parser_global.tok)
    else:
        print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting ':'"
        sys.exit()

    if ice9_parser_global.tok.type == "ID":
        type_node = typeid()
    else:
        print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting id"
        sys.exit()

    for identifier in identifier_list:
        # Depending on the scope, calculate location for variable
        # If scope is GLOBAL, then location is in GLOBAL section
        # If scope is a procedure, then location is on stack, relative to FP
        if ice9_parser_global.scope[-1] == "GLOBAL":
            address = ice9_parser_global.get_next_global_address()
            ice9_parser_global.global_pointer += type_node.length - 1
        else:
            address = ice9_st_proc.st_proc[ice9_parser_global.scope[-1]].local_variable_line
            ice9_st_proc.st_proc[ice9_parser_global.scope[-1]].local_variable_line -= type_node.length

            # Add entry to symbol table
        identifier_entry = ice9_st_var.st_var_entry(
            type_node.data_type, type_node.dimension, address, type_node.dimension_length
        )
        ice9_st_var.add_entry_to_st_var(str(identifier), identifier_entry)
        id_node = ice9_node.id_node(str(identifier), type_node.data_type, type_node.dimension)
        id_node.set_basic_data_type()
        var_node_list.append(id_node)

    var_node = ice9_node.var_node(var_node_list, type_node)
    ice9_parser_global.logger.debug("Exiting vartype")
    return var_node
def _exprlist():
	ice9_parser_global.logger.debug("Entering _exprlist")

	expr_list = list()	

	if ice9_parser_global.tok.type in ['SLIT', 'MINUS', 'READ', 'QUEST', 'ID', 'TRUE', 'INT', 'LPAREN', 'FALSE']:
		expr_list.append(expr(None))
	
		if ice9_parser_global.tok.type == 'COMMA':
			ice9_parser_global.consume()
			ice9_parser_global.logger.debug(ice9_parser_global.tok)
			expr_list += _exprlist()
	else:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting an expression"
		sys.exit()
	
	ice9_parser_global.logger.debug("Exiting _exprlist")
	return expr_list
def logicexp(caller_node):
	ice9_parser_global.logger.debug("Entering logicexp")

	logic_node = ice9_node.expr_node()
	logic_node.operation = ice9_parser_global.tok.type
	ice9_parser_global.consume()
	ice9_parser_global.logger.debug(ice9_parser_global.tok)

	logic_node.pre_child = caller_node
	logic_node.post_child = mathexp(None)

	if caller_node:
		result_node = logic_node
		validate_logicexp(logic_node)
	else:
		result_node = logic_node.post_child

	ice9_parser_global.logger.debug("Exiting logicexp")
	return result_node
Пример #17
0
def _idlist():
    ice9_parser_global.logger.debug("Entering _idlist")

    identifier_list = list()

    if ice9_parser_global.tok.type == "ID":
        identifier_list.append(ice9_parser_global.tok.value)
        ice9_parser_global.consume()
        ice9_parser_global.logger.debug(ice9_parser_global.tok)
    else:
        print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting id"
        sys.exit()

    if ice9_parser_global.tok.type == "COMMA":
        ice9_parser_global.consume()
        ice9_parser_global.logger.debug(ice9_parser_global.tok)
        identifier_list += _idlist()

    ice9_parser_global.logger.debug("Exiting _idlist")
    return identifier_list
Пример #18
0
def const_array_index():
    global dimension_length
    ice9_parser_global.logger.debug("Entering const_array_index")

    ice9_parser_global.consume()
    ice9_parser_global.logger.debug(ice9_parser_global.tok)

    if ice9_parser_global.tok.type == "INT":
        dimension_length.append(ice9_parser_global.tok.value)
        ice9_parser_global.consume()
        ice9_parser_global.logger.debug(ice9_parser_global.tok)
    else:
        print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting a integer"
        sys.exit()

    if ice9_parser_global.tok.type == "RBRACK":
        ice9_parser_global.consume()
        ice9_parser_global.logger.debug(ice9_parser_global.tok)
    else:
        print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting ']'"
        sys.exit()

    dimension = 1

    if ice9_parser_global.tok.type == "LBRACK":
        dimension += const_array_index()

    ice9_parser_global.logger.debug("Exiting const_array_index")
    return dimension
def optsuffix():
	ice9_parser_global.logger.debug("Entering optsuffix")
	
	expr_node = None	
	
	if ice9_parser_global.tok.type == 'LBRACK':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
	
		expr_node = arrayindex()
		
	elif ice9_parser_global.tok.type == 'LPAREN':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)

		expr_node = exprlist()

		if ice9_parser_global.tok.type == 'RPAREN':
			ice9_parser_global.consume()
			ice9_parser_global.logger.debug(ice9_parser_global.tok)
		else:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting ')'"
			sys.exit()

	ice9_parser_global.logger.debug("Exiting optsuffix")
	return expr_node
def handle_type():
	ice9_parser_global.logger.debug("Entering type")
	
	if ice9_parser_global.tok.type == 'ID':
		derived_data_type = ice9_parser_global.tok.value
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
	else:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting id"
		sys.exit()

	if ice9_parser_global.tok.type == 'EQ':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
	else:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting '='"
		sys.exit()

	if ice9_parser_global.tok.type == 'ID':
		type_node = ice9_parser_var.typeid()
		type_node.derived_data_type = derived_data_type
	else:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting id"
		sys.exit()
	
	if ice9_parser_global.tok.type == 'SEMI':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
	else:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting ';'"
		sys.exit()

	data_type_entry = ice9_st_type.st_type_entry(str(type_node.data_type), type_node.dimension)
	ice9_st_type.add_entry_to_st_type(str(type_node.derived_data_type), data_type_entry)
	ice9_parser_global.logger.debug("Exiting type")
def do():
	ice9_parser_global.logger.debug("Entering do")
	
	ice9_parser_global.loop_depth += 1

	stmt_node = ice9_node.stmt_node()
	stmt_node.rule = 'DO'
	stmt_node.condition = ice9_parser_expressions.expr(None)

	if stmt_node.condition.return_data_type != 'bool':
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
			"if condition must return a 'bool'"
		sys.exit()

	if stmt_node.condition.dimension != 0:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
			"if condition cannot be a array variable, must return a 'bool'"
		sys.exit()

	if ice9_parser_global.tok.type == 'ARROW':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
	else:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting '->'"
		sys.exit()

	stmt_node.pre_child = ice9_parser_statements.statements()

	if ice9_parser_global.tok.type == 'OD':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
	else:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting od"
		sys.exit()
	
	ice9_parser_global.loop_depth -= 1

	ice9_parser_global.logger.debug("Exiting do")
	return stmt_node
def half_expr_or_assign(id_node):	
	ice9_parser_global.logger.debug("Entering half_expr_or_assign")

	half_expr_or_assign_node = ice9_node.expr_node()
	
	if ice9_parser_global.tok.type == 'LBRACK':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
		id_node.expr_list.append(expr(None))
		
		# Array index must be of type int
		if id_node.expr_list[-1].return_data_type != 'int':
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
				"array index must be an 'int' operand"
			sys.exit()

		# Array index must have dimension 0
		if id_node.expr_list[-1].dimension != 0:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
				"array index cannot be an array reference"
			sys.exit()
	
		if ice9_parser_global.tok.type == 'RBRACK':
			ice9_parser_global.consume()
			ice9_parser_global.logger.debug(ice9_parser_global.tok)
		else:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting ']'"
			sys.exit()

		id_node.return_data_type = ice9_st_var.st_var[id_node.value][-1].basic_data_type
		id_node.dimension = ice9_st_var.st_var[id_node.value][-1].dimension - len(id_node.expr_list)

		if id_node.dimension < 0:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
				"array dimension for variable '" + id_node.value + "'exceeded"
			sys.exit()

		half_expr_or_assign_node = half_expr_or_assign(id_node)
		
	elif ice9_parser_global.tok.type == 'ASSIGN':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)

		half_expr_or_assign_node.operation = 'ASSIGN'
		half_expr_or_assign_node.pre_child = id_node
		half_expr_or_assign_node.post_child = expr(None)

		half_expr_or_assign_node = validate_assign(half_expr_or_assign_node)

	else:
		half_expr_or_assign_node = half_expr(id_node)

	ice9_parser_global.logger.debug("Exiting half_expr_or_assign")
	return half_expr_or_assign_node
Пример #23
0
def handle_if():
	ice9_parser_global.logger.debug("Entering handle_if")

	stmt_node = ice9_node.stmt_node()
	stmt_node.rule = 'IF'

	# The condition expression
	expr_node = ice9_parser_expressions.expr(None)

	if expr_node.return_data_type != 'bool':
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
			"if condition must return a 'bool'"
		sys.exit()
	if expr_node.dimension != 0:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
			"if condition cannot be a array variable, must return a 'bool'"
		sys.exit()

	stmt_node.condition = expr_node

	if ice9_parser_global.tok.type == 'ARROW':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
	else:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting '->'"
		sys.exit()

	if ice9_parser_statements.in_first_of_statement():
		stmt_node.pre_child = ice9_parser_statements.statements()
	else:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting a statement"
		sys.exit()

	if ice9_parser_global.tok.type == 'BOX':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
		stmt_node.post_child = elseif_or_else()
	
	if ice9_parser_global.tok.type == 'FI':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
	else:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting fi"
		sys.exit()

	ice9_parser_global.logger.debug("Exiting handle_if")
	return stmt_node
def statements():
	ice9_parser_global.logger.debug("Entering statements")

	stmt_node = ice9_node.stmt_node()
	stmt_node_list = list()

	# CODE-GENERATED
	if ice9_parser_global.tok.type == 'IF':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
		stmt_node = ice9_parser_if.handle_if()

	# CODE-GENERATED
	elif ice9_parser_global.tok.type == 'DO':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
		stmt_node = ice9_parser_loops.do()

	# CODE-GENERATED
	elif ice9_parser_global.tok.type == 'FA':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
		stmt_node = ice9_parser_loops.fa()

	# CODE-GENERATED
	elif ice9_parser_global.tok.type == 'EXIT':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
		stmt_node.rule = 'EXIT'

	# CODE-GENERATED
	elif ice9_parser_global.tok.type == 'BREAK':
		stmt_node.rule =  ice9_parser_global.tok.type
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
	
		if stmt_node.rule == 'BREAK' and ice9_parser_global.loop_depth < 1:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
				"break statement permitted only inside loops"
			sys.exit()
			
		if ice9_parser_global.tok.type == 'SEMI':
			ice9_parser_global.consume()
			ice9_parser_global.logger.debug(ice9_parser_global.tok)
		else:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting ';'"
			sys.exit()

	# CODE-GENERATED
	elif ice9_parser_global.tok.type == 'SEMI':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)

	# CODE-GENERATED
	elif ice9_parser_global.tok.type == 'MINUS':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)

		expr_node = ice9_node.expr_node()
		expr_node.pre_child = ice9_parser_expressions.expr(None)
		expr_node.operation = 'UN_MINUS'
		expr_node.operand_data_type = expr_node.pre_child.return_data_type
		expr_node.dimension = expr_node.pre_child.dimension

		# Check if the operand are either bool or int
		if expr_node.operand_data_type not in ['bool', 'int']:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
				"unary minus operator expects a 'bool' or 'int' operand"
			sys.exit()

		# Check if the operands have dimension 0
 		if expr_node.dimension != 0:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
				"unary minus operator does not expect array datatypes"
			sys.exit()

		expr_node.return_data_type = expr_node.operand_data_type
		
		stmt_node.pre_child = expr_node
		stmt_node.rule =  'UN_MINUS'
			
		if ice9_parser_global.tok.type == 'SEMI':
			ice9_parser_global.consume()
			ice9_parser_global.logger.debug(ice9_parser_global.tok)
		else:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting ';'"
			sys.exit()

	# CODE-GENERATED
	elif ice9_parser_global.tok.type == 'QUEST':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)

		expr_node = ice9_node.expr_node()
		expr_node.pre_child = ice9_parser_expressions.expr(None)
		expr_node.operation = 'QUEST'
		expr_node.operand_data_type = expr_node.pre_child.return_data_type
		expr_node.dimension = expr_node.pre_child.dimension

		# Check if the operand is bool
		if expr_node.operand_data_type != 'bool':
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
				"unary ? operator expects a 'bool' operand"
			sys.exit()

		# Check if the operands have dimension 0
		if expr_node.dimension != 0:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
				"unary ? operator does not expect array datatypes"
			sys.exit()

		expr_node.return_data_type = 'int'

		stmt_node.pre_child = expr_node
		stmt_node.rule = 'QUEST'
	
		if ice9_parser_global.tok.type == 'SEMI':
			ice9_parser_global.consume()
			ice9_parser_global.logger.debug(ice9_parser_global.tok)
		else:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting ';'"
			sys.exit()

	# CODE-GENERATED
	elif ice9_parser_global.tok.type in ['WRITE', 'WRITES']:
		stmt_node.rule = ice9_parser_global.tok.type
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
		stmt_node.pre_child = ice9_parser_expressions.expr(None)

		# Check if the operands have dimension 0
 		if stmt_node.pre_child.dimension != 0:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
				"write(s) operator does not expect array datatypes"
			sys.exit()

		if ice9_parser_global.tok.type == 'SEMI':
			ice9_parser_global.consume()
			ice9_parser_global.logger.debug(ice9_parser_global.tok)
		else:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting ';'"
			sys.exit()

	# CODE-GENERATED
	elif ice9_parser_global.tok.type == 'ID':
		id_node = ice9_node.expr_node()
		id_node.value = ice9_parser_global.tok.value
		id_node.operation = 'ID'
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)

		#Look ahead and determine if operation was proc_call, then set id_node properties from st_proc
		if ice9_parser_global.tok.type == 'LPAREN':
			if id_node.value not in ice9_st_proc.st_proc:
				print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
					"procedure '" + id_node.value + "' not defined"
				sys.exit()

			id_node.return_data_type = ice9_st_proc.st_proc[id_node.value].return_type
			id_node.dimension = 0

		#If not, set id_node properties from st_var
		else:
			if id_node.value not in ice9_st_var.st_var:
				print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
					"variable '" + id_node.value + "' not defined"
				sys.exit()

			id_node.return_data_type = ice9_st_var.st_var[id_node.value][-1].basic_data_type
			id_node.dimension = ice9_st_var.st_var[id_node.value][-1].dimension

		result_node = ice9_parser_expressions.assign_or_expr(id_node)

		stmt_node = ice9_node.stmt_node()
		stmt_node.pre_child = result_node
		stmt_node.rule = 'EXPR'

		if ice9_parser_global.tok.type == 'SEMI':
			ice9_parser_global.consume()
			ice9_parser_global.logger.debug(ice9_parser_global.tok)
		else:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting ';'"
			sys.exit()
		
	# CODE-GENERATED
	elif ice9_parser_global.tok.type == 'LPAREN':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)

		expr_node = ice9_parser_expressions.expr()

		if ice9_parser_global.tok.type == 'RPAREN':
			ice9_parser_global.consume()
			ice9_parser_global.logger.debug(ice9_parser_global.tok)
		else:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting ')'"
			sys.exit()
	
		result_node = ice9_parser_expressions.half_expr(expr_node)

		if ice9_parser_global.tok.type == 'SEMI':
			ice9_parser_global.consume()
			ice9_parser_global.logger.debug(ice9_parser_global.tok)
		else:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting ';'"
		
		stmt_node.pre_child = expr_node
		stmt_node.rule = 'EXPR'
		
	# CODE-GENERATED
	elif ice9_parser_global.tok.type in ['INT', 'FALSE', 'TRUE']:
		stmt_node.rule = ice9_parser_global.tok.type

		# Create node for the first entity
		expr_node = ice9_node.expr_node()
		expr_nodedimension = 0
		expr_node.value = ice9_parser_global.tok.value
		expr_node.operation = ice9_parser_global.tok.type;
		if ice9_parser_global.tok.type == 'INT':
			expr_node.return_data_type = 'int'
		else:
			expr_node.return_data_type = 'bool'
		
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
		
		# Get the entire expression tree from half_expr
		result_node = ice9_parser_expressions.half_expr(expr_node)

		# Attach expression tree to stmt_node	
		stmt_node.pre_child = result_node

	# CODE-GENERATED
	elif ice9_parser_global.tok.type == 'SLIT':
		stmt_node.rule = 'EXPR'

		stmt_node.pre_child = ice9_node.expr_node()
		stmt_node.pre_child.operation = 'SLIT'
		stmt_node.pre_child.return_data_type = 'string'
		stmt_node.pre_child.operand_data_type = 'string'
		stmt_node.pre_child.value = str(ice9_parser_global.tok.value)
		stmt_node.pre_child.dimension = 0
		stmt_node.pre_child.length = len(stmt_node.pre_child.value) - 2

		if ice9_parser_global.tok.value not in ice9_parser_global.string_location_dict:
			ice9_parser_global.string_location_dict[ice9_parser_global.tok.value] = ice9_parser_global.string_location_pointer
			ice9_parser_global.string_location_pointer += stmt_node.pre_child.length
			ice9_parser_global.string_location_pointer += 1
		
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)

	# CODE-GENERATED
	elif ice9_parser_global.tok.type == 'READ':
		stmt_node.rule = 'READ'
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
		
		# Handle post-child
		stmt_node.pre_child = ice9_parser_expressions.expr(None)

		if stmt_node.pre_child.operation not in ['ID', 'ARRAY_REF']:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
				"read can be performed only on variables, not expressions"
			sys.exit()

		if ice9_parser_global.tok.type == 'SEMI':
			ice9_parser_global.consume()
			ice9_parser_global.logger.debug(ice9_parser_global.tok)
		else:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting ';'"
			sys.exit()

	stmt_node_list.append(stmt_node)

	if in_first_of_statement():
		stmt_node_list += statements()

	ice9_parser_global.logger.debug("Exiting statements")
	return stmt_node_list
def fa():
	ice9_parser_global.logger.debug("Entering fa")

	stmt_node = ice9_node.stmt_node()
	stmt_node.rule = 'FA'
	
	ice9_parser_global.loop_depth += 1
	
	if ice9_parser_global.tok.type == 'ID':
		fa_loop_id = ice9_parser_global.tok.value
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
	else:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting id"
		sys.exit()

	loop_id_node = ice9_node.expr_node()
	loop_id_node.operation = 'LOOP_ID'
	loop_id_node.value = fa_loop_id

	if ice9_parser_global.tok.type == 'ASSIGN':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
	else:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting ':='"
		sys.exit()

	loop_id_node.pre_child = ice9_parser_expressions.expr(None)	

	if loop_id_node.pre_child.return_data_type != 'int':
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
			"fa loop variable must be a 'int'"
		sys.exit()

	if loop_id_node.pre_child.dimension != 0:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
			"fa loop variable cannot be a array, must be a 'int'"
		sys.exit()

	if ice9_parser_global.tok.type == 'TO':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
	else:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting to"
		sys.exit()

	loop_id_node.post_child = ice9_parser_expressions.expr(None)
	
	if loop_id_node.post_child.return_data_type != 'int':
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
			"fa loop variable must be a 'int'"
		sys.exit()

	if loop_id_node.post_child.dimension != 0:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
			"fa loop expression cannot be a array , must be a 'int'"
		sys.exit()

	ice9_parser_global.fa_loop_variable.append(fa_loop_id)

	'''
	Might be un-necessary
	# Obtain the location to store the fa loop variable
	if ice9_parser_global.scope[-1] == 'GLOBAL':
		address = ice9_parser_global.get_next_global_address()
	else:
		address = ice9_st_proc.st_proc[ice9_parser_global.scope[-1]].parameter_count + 2 + \
			ice9_st_proc.st_proc[ice9_parser_global.scope[-1]].local_variable_count
	
	st_var_entry = ice9_st_var.st_var_entry('int', 0, address)
	'''

	st_var_entry = ice9_st_var.st_var_entry('int', 0, 1, 1)
	st_var_entry.basic_data_type = 'int'

	# Bypass the checks in st_var.add_entry_to_st_var
	# If variable not previously used, make an entry for it
	if fa_loop_id not in ice9_st_var.st_var:
		fa_loop_id_stack = list()
		ice9_st_var.st_var[fa_loop_id] = fa_loop_id_stack

	ice9_st_var.st_var[fa_loop_id].append(st_var_entry)
	
	if ice9_parser_global.tok.type == 'ARROW':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
	else:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting '->'"
		sys.exit()

	stmt_node.pre_child = loop_id_node
	stmt_node.post_child = ice9_parser_statements.statements()

	if ice9_parser_global.tok.type == 'AF':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
	else:
		print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting af"
		sys.exit()

	# Clean up
	ice9_parser_global.fa_loop_variable.pop()

	ice9_parser_global.loop_depth -= 1
	ice9_st_var.st_var[fa_loop_id].pop()
	
	if len(ice9_st_var.st_var[fa_loop_id]) == 0:
		del ice9_st_var.st_var[fa_loop_id]

	ice9_parser_global.logger.debug("Exiting fa")
	return stmt_node
Пример #26
0
def elseif_or_else():
	ice9_parser_global.logger.debug("Entering elseif_or_else")
	
	stmt_node = ice9_node.stmt_node()
	stmt_node.rule = 'IF'

	if ice9_parser_global.tok.type == 'ELSE':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)

		# Create dummy expression that always evaluates to true
		expr_node = ice9_node.expr_node()
		expr_node.operation = 'TRUE'
		expr_node.return_data_type = 'bool'
		
		stmt_node.condition = expr_node
	
		if ice9_parser_global.tok.type == 'ARROW':
			ice9_parser_global.consume()
			ice9_parser_global.logger.debug(ice9_parser_global.tok)
		else:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting '->'"
			sys.exit()

		if ice9_parser_statements.in_first_of_statement():
			stmt_node.pre_child = ice9_parser_statements.statements()
		else:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting a statement"
			sys.exit()
			
	else:
			
		# Condition expression
		expr_node = ice9_parser_expressions.expr(None)

		if expr_node.return_data_type != 'bool':
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
				"if condition must return a 'bool'"
			sys.exit()

		if expr_node.dimension != 0:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
				"if condition cannot be a array variable, must return a 'bool'"
			sys.exit()

		stmt_node.condition = expr_node		

		if ice9_parser_global.tok.type == 'ARROW':
			ice9_parser_global.consume()
			ice9_parser_global.logger.debug(ice9_parser_global.tok)
		else:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting ';'"
			sys.exit()
	
		if ice9_parser_statements.in_first_of_statement():
			stmt_node.pre_child = ice9_parser_statements.statements()
		else:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting a statement"
			sys.exit()			
	
		if ice9_parser_global.tok.type == 'BOX':
			ice9_parser_global.consume()
			ice9_parser_global.logger.debug(ice9_parser_global.tok)
			stmt_node.post_child = elseif_or_else()

	ice9_parser_global.logger.debug("Exiting elseif_or_else")
	return stmt_node
def factor():
	ice9_parser_global.logger.debug("Entering factor")

	expr_node = ice9_node.expr_node()

	if ice9_parser_global.tok.type == 'MINUS':
		expr_node.operation = 'UN_MINUS'
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
		
		if in_first_of_factor() == True:
			expr_node.pre_child = factor()
			expr_node.operand_data_type = expr_node.pre_child.return_data_type
			expr_node.dimension = expr_node.pre_child.dimension
		
			# Check if the operand are either bool or int
			if expr_node.operand_data_type not in ['bool', 'int']:
				print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
					"unary minus operator expects a 'bool' or 'int' operand"
				sys.exit()

			# Check if the operands have dimension 0
			if expr_node.dimension != 0:
				print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
					"unary minus operator does not expect array datatypes"
				sys.exit()

			# If the operand data type is boolean, then it indicates a NOT operation		
			if expr_node.operand_data_type == 'bool':
				expr_node.operation = 'NOT'

			expr_node.return_data_type = expr_node.operand_data_type

		else:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting a factor"
			sys.exit()
			
	elif ice9_parser_global.tok.type == 'QUEST':
		expr_node.operation = 'QUEST'
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
		
		if in_first_of_factor() == True:
			expr_node.pre_child = factor()
			expr_node.operand_data_type = expr_node.pre_child.return_data_type
			expr_node.dimension = expr_node.pre_child.dimension
			
			# Check if the operand is bool
			if expr_node.operand_data_type != 'bool':
				print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
					"unary minus operator expects a 'bool' or 'int' operand"
				sys.exit()

			# Check if the operands have dimension 0
			if expr_node.dimension != 0:
				print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
					"unary minus operator does not expect array datatypes"
				sys.exit()

			expr_node.return_data_type = 'int'

		else:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting a factor"
			sys.exit()

	elif ice9_parser_global.tok.type == 'LPAREN':
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)

		expr_node = expr(None)

		if ice9_parser_global.tok.type == 'RPAREN':
			ice9_parser_global.consume()
			ice9_parser_global.logger.debug(ice9_parser_global.tok)
		else:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting ')'"
			sys.exit()

	elif ice9_parser_global.tok.type == 'INT':
		expr_node.operation = 'INT'
		expr_node.operand_data_type = 'int'
		expr_node.return_data_type = 'int'
		expr_node.dimension = 0
		expr_node.value = ice9_parser_global.tok.value
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)

	elif ice9_parser_global.tok.type == 'SLIT':
		expr_node.operation = 'SLIT'
		expr_node.operand_data_type = 'string'
		expr_node.return_data_type = 'string'
		expr_node.value = str(ice9_parser_global.tok.value)
		expr_node.dimension = 0
		expr_node.length = len(expr_node.value) - 2

		if ice9_parser_global.tok.value not in ice9_parser_global.string_location_dict:
			ice9_parser_global.string_location_dict[ice9_parser_global.tok.value] = ice9_parser_global.string_location_pointer
			ice9_parser_global.string_location_pointer += expr_node.length
			ice9_parser_global.string_location_pointer += 1

		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)

	elif ice9_parser_global.tok.type == 'TRUE':
		expr_node.operation = 'TRUE'
		expr_node.operand_data_type = 'bool'
		expr_node.return_data_type = 'bool'
		expr_node.dimension = 0
		expr_node.value = 1
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)
	
	elif ice9_parser_global.tok.type == 'FALSE':
		expr_node.operation = 'FALSE'
		expr_node.operand_data_type = 'bool'
		expr_node.return_data_type = 'bool'
		expr_node.dimension = 0
		expr_node.value = 0
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)

	elif ice9_parser_global.tok.type == 'READ':
		expr_node.operation = 'READ'
		expr_node.operand_data_type = 'int'
		expr_node.return_data_type = 'int'
		expr_node.dimension = 0
		expr_node.value = 0
		ice9_parser_global.consume()
		ice9_parser_global.logger.debug(ice9_parser_global.tok)

	else:
		if ice9_parser_global.tok.type == 'ID':
			expr_node.value = ice9_parser_global.tok.value
			ice9_parser_global.consume()
			ice9_parser_global.logger.debug(ice9_parser_global.tok)
		else:
			print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, "expecting id"
			sys.exit()
		
		# Procedure call
		if ice9_parser_global.tok.type == 'LPAREN':
			expr_node.operation = 'PROC_CALL'
			expr_node.expr_list = optsuffix()
			validate_proc_call(expr_node)

		# Array variable
		elif ice9_parser_global.tok.type == 'LBRACK':
			expr_node.operation = 'ARRAY_REF'
			expr_node.expr_list = optsuffix()
			expr_node = validate_array_ref(expr_node)

		# Regular variable
		else:
			expr_node.operation = 'ID'
			# Check if variable has been declared
			if expr_node.value not in ice9_st_var.st_var:
				print "Line", ice9_parser_global.tok.lineno, ": on token", ice9_parser_global.tok.value, \
					"variable '" + expr_node.value + "' not defined"
				sys.exit()

			expr_node.return_data_type = ice9_st_var.st_var[expr_node.value][-1].basic_data_type
			expr_node.dimension = ice9_st_var.st_var[expr_node.value][-1].dimension
		
	ice9_parser_global.logger.debug("Exiting factor")
	return expr_node