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 term(caller_node):
	ice9_parser_global.logger.debug("Entering term")
	
	# Set pre child to caller node
	term_node = ice9_node.expr_node()
	term_node.pre_child = caller_node

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

	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 _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 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
def mathexp(caller_node):
	ice9_parser_global.logger.debug("Entering mathexp")
	
	math_node = ice9_node.expr_node()
	math_node.pre_child = caller_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 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
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
예제 #9
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