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 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 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
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