Esempio n. 1
0
 void Visit(const Waypoint &wp) {
   if (compare_type(wp, type_index) &&
       (filter_data.distance_index == 0 || compare_name(wp, name)) &&
       compare_direction(wp, direction_index, location, heading))
     vector.push_back(wp, location);
 }
Esempio n. 2
0
int check_expression(struct tree_node * exp) {
	assert(exp -> unit_name == NODE_EXP);
	
	if (exp -> flags == FLAG_EXP_ID) {					// terminal
		const char * id_name = exp -> children[0] -> id_extra -> name;
		struct var_entry * ve = search_var_entry(id_name);
		if (ve == NULL) {
			semerrorpos(ERROR_VARIABLE_UNDEFINED, exp -> children[0] -> line);
			printf("identifier \'%s\' not exist\n", id_name);
		} else {
			// check the ve's type and its flags
			exp -> exp_type_flag = ve -> type_flag;
			exp -> exp_type = ve -> t;
			exp -> exp_is_lvalue = 1;
		}
	} else if (exp -> flags == FLAG_EXP_INT) {			// terminal
		assert(exp -> children[0] -> unit_name == TOKEN_INTEGER);
		exp -> exp_type_flag = TYPE_BASIC;
		exp -> exp_type.basic_type = TYPE_INT;
		exp -> exp_is_lvalue = 0;
	} else if (exp -> flags == FLAG_EXP_FLOAT) {		// terminal
	    assert(exp -> children[0] -> unit_name == TOKEN_FLOAT);
	    exp -> exp_type_flag = TYPE_BASIC;
		exp -> exp_type.basic_type = TYPE_FLOAT;
		exp -> exp_is_lvalue = 0;
	} else if (exp -> flags == FLAG_EXP_ASSIGN) {		// NON-terminal
		// TODO: check left-value, then check type confliction
		check_expression(exp -> children[0]);
		check_expression(exp -> children[2]);
		if (exp -> children[0] -> exp_is_lvalue == 0) {
			semerrorpos(ERROR_ASSIGN_NONLEFT, exp -> children[0] -> line);
			printf("expression on the left side is not left-value\n");
		}
		exp -> exp_is_lvalue = exp -> children[2] -> exp_is_lvalue;
		// whether or not the left side is left-value or not, better to check type first.
		int c = compare_type(
			exp -> children[0] -> exp_type_flag, &(exp -> children[0] -> exp_type),
			exp -> children[2] -> exp_type_flag, &(exp -> children[2] -> exp_type));
		if (c != COMPARE_GOOD) {
			semerrorpos(ERROR_ASSIGN_MISMATCH, exp -> children[1] -> line);
			printf("type mismatch in assignment: %s\n", compare_str[c]);
		} else {
			exp -> exp_type_flag = exp -> children[0] -> exp_type_flag;
			exp -> exp_type = exp -> children[0] -> exp_type;
		}

		// end of assignment
	} else if (exp -> flags == FLAG_EXP_BINOP) {		// NON-terminal
		check_expression(exp -> children[0]);
		check_expression(exp -> children[2]);

		// prune: non-basic types cannot take binary operations whatsoever
		if (exp -> children[0] -> exp_type_flag == TYPE_ARRAY  ||
			exp -> children[0] -> exp_type_flag == TYPE_STRUCT) {
			semerrorpos(ERROR_OTHER, exp -> children[1] -> line);
			printf("%s (on the left side) cannot take binary operation\n", 
				type_str[exp -> children[0] -> exp_type_flag]);
			exp -> exp_type_flag = exp -> children[0] -> exp_type_flag;
			return -1;
		}
		if (exp -> children[2] -> exp_type_flag == TYPE_ARRAY  ||
			exp -> children[2] -> exp_type_flag == TYPE_STRUCT) {
			semerrorpos(ERROR_OTHER, exp -> children[1] -> line);
			printf("%s (on the right side) cannot take binary operation\n", 
				type_str[exp -> children[2] -> exp_type_flag]);
			exp -> exp_type_flag = exp -> children[2] -> exp_type_flag;
			return -1;
		}

		// now they are both basic types.
		exp -> exp_type_flag = TYPE_BASIC;
		exp -> exp_type.basic_type = exp -> children[0] -> exp_type.basic_type;
		if (exp -> children[1] -> unit_name == TOKEN_RELOP)
			exp -> exp_type.basic_type = TYPE_INT;
		exp -> exp_is_lvalue = 0;
		int type_left = exp -> children[0] -> exp_type.basic_type;
		int type_right = exp -> children[2] -> exp_type.basic_type;
		// assert(type_left == TYPE_INT || type_left == TYPE_FLOAT);
		// assert(type_right == TYPE_INT || type_right == TYPE_FLOAT);
		if (type_left == type_right) {	
			// printf("types: %d, %d\n", type_left, type_right);
		} else {
			semerrorpos(ERROR_OPERAND_MISMATCH, exp->children[1] -> line);
			printf("expression type not match: %d and %d\n", type_left, type_right);
		}
		// end of binary operators: + - * / && || relop
	} else if (exp -> flags == FLAG_EXP_PAREN) {		// NON-terminal
		check_expression(exp -> children[1]);
		exp -> exp_type_flag = exp -> children[1] -> exp_type_flag;
		exp -> exp_type = exp -> children[1] -> exp_type;
		exp -> exp_is_lvalue = exp -> children[1] -> exp_is_lvalue;
		// end of parentheses
	} else if (exp -> flags == FLAG_EXP_UNOP) {			// NON-terminal
		check_expression(exp -> children[1]);

		if (exp -> exp_type_flag == TYPE_ARRAY || exp -> exp_type_flag == TYPE_STRUCT) {
			semerrorpos(ERROR_OTHER, exp -> line);
			printf("%s cannot take unary operator\n", type_str[exp -> exp_type_flag]);
		}

		exp -> exp_is_lvalue = 0;
		exp -> exp_type_flag = exp -> children[1] -> exp_type_flag;
		exp -> exp_type = exp -> children[1] -> exp_type;
		// end of unary operator
	} else if (exp -> flags == FLAG_EXP_CALL_ARGS) {	// NON-self-recursive
		// DONE: check arguments
		const char * f_name = exp -> children[0] -> id_extra -> name;
		struct func_entry * f = search_func_entry(f_name);
		struct tree_node * arguments = exp -> children[2];
		struct list_head * parameters_head = NULL;
		if (f == NULL) {
			semerrorpos(ERROR_FUNCTION_UNDEFINED, exp -> children[0] -> line);
			printf("function \'%s\' not defined\n", f_name);
			exp -> exp_type_flag = TYPE_ERROR;
			return -1;
		} else { // checking parameters_head
			parameters_head = &(f -> param_list);
			struct list_head * param_l = NULL;
			struct var_entry * param_ve = NULL;
/*for loop*/list_for_each(param_l, parameters_head) {
				struct tree_node * a = arguments -> children[0];
				param_ve = list_entry(param_l, struct param_entry, list_ptr) -> param_ptr;
				check_expression(a);
				int c = compare_type(param_ve -> type_flag, &(param_ve -> t),
					a -> exp_type_flag, &(a -> exp_type));
				if (c != COMPARE_GOOD) {
					semerrorpos(ERROR_PARAM_MISMATCH, a -> line);
					printf("argument and parameter type mismatch: %s\n", 
						compare_str[c]);
				}
				if (arguments -> flags == FLAG_ARGS_SINGLE) {
					// param_ve should be the last parameter
					if (param_l -> next != parameters_head) {
						semerrorpos(ERROR_PARAM_MISMATCH, a -> line);
						printf("more params not matched\n");
					}
					break;
				} else {
					assert(arguments -> flags == FLAG_ARGS_MORE);
					// but if parameters has reached its end...
					if (param_l -> next == parameters_head) {
						semerrorpos(ERROR_PARAM_MISMATCH, a -> line);
						printf("more arguments not matched\n");
						break;
					}
				}
				arguments = arguments -> children[2];
			}
		}
		while (arguments -> flags == FLAG_ARGS_MORE) {
			check_expression(arguments -> children[0]);
			arguments = arguments -> children[2];
		}

		exp -> exp_type_flag = f -> return_type_flag;
		exp -> exp_type = f -> return_type;
		// end of function calling with args
	} else if (exp -> flags == FLAG_EXP_CALL_NOARGS) {	// NON-self-recursive
Esempio n. 3
0
void semantic_analysis(struct tree_node * ptr) {
	if (!ptr) return;
	int i;

	if (ptr -> unit_name == NODE_EXTDEF) {
		if (ptr -> flags == FLAG_EXTDEF_VARIABLES) {
			
			struct tree_node * spec = ptr -> children[0];
			struct tree_node * declist = ptr -> children[1];
            
            push_anonymous_struct();
			// handle type first: if define struct, add struct; if basic, just use it, skip
			if (spec -> flags == FLAG_SPECIFIER_STRUCT && 
				spec -> children[0] -> flags == FLAG_STRUCTSPECIFIER_DEF) {
				symtab_add_struct(spec -> children[0]);
			}
			// whether or not spec is successfully added, just use them.
			while (declist -> flags == FLAG_EXTDECLIST_MORE) {
				symtab_add_variable(spec, declist -> children[0]);
				declist = declist -> children[2];
			}
			symtab_add_variable(spec, declist -> children[0]);
			
			pop_anonymous_struct();
			
			return;
			// end of EXTDEF_VARIABLES
		} else if (ptr -> flags == FLAG_EXTDEF_FUNCTION) {

			if (function_field != NULL) {
				semerrorpos(ERROR_OTHER, ptr->line);
				printf("nested function definition \'%s\' inside another function definition\'%s\'\n",
						ptr -> children[1] -> children[0] -> id_extra -> name,
						function_field -> name);
				return;
			}

			// register in the symbol table
			//   all the names in parameter list
			struct tree_node * spec = ptr -> children[0];
			struct tree_node * id = ptr -> children[1] -> children[0];
			struct func_entry * f = symtab_add_function(ptr -> children[1]);
			if (!f) {
				f = search_func_entry(id -> id_extra -> name);
				semerrorpos(ERROR_FUNCTION_CONFLICT, ptr -> line);
				printf("function \'%s\' already defined at %d\n",
					id -> id_extra -> name, f -> defined_at);
			}
			function_field = f;
			// check return type: if spec is a struct definition, add that.
            if (spec -> flags == FLAG_SPECIFIER_STRUCT) {
        	    struct struct_entry * se = NULL;
        	    push_anonymous_struct();
        		se = symtab_add_struct(spec -> children[0]);
        		f -> return_type_flag = TYPE_STRUCT;
        		f -> return_type.struct_type = se;
        		// return type may be NULL, checked by expression analysis
        		pop_anonymous_struct();
        	} else {
        	    assert(spec -> flags == FLAG_SPECIFIER_BASIC);
        	    f -> return_type_flag = TYPE_BASIC;
        	    f -> return_type.basic_type = spec -> children[0] -> type_name;
        	}
			// recursive analyze the definitions and statements in the compst
			struct tree_node * deflist = ptr -> children[2] -> children[1];
			while (deflist -> flags == FLAG_DEFLIST_MORE) {
				semantic_analysis(deflist -> children[0]);
				deflist = deflist -> children[1];
			}
			struct tree_node * stmtlist = ptr -> children[2] -> children[2];
			while (stmtlist -> flags == FLAG_STMTLIST_MORE) {
				semantic_analysis(stmtlist -> children[0]);
				stmtlist = stmtlist -> children[1];
			}
			function_field = NULL;
			// end of EXTDEF_FUNCTION
		} else if (ptr -> flags == FLAG_EXTDEF_TYPE) {
			if (ptr -> children[0] -> flags == FLAG_SPECIFIER_BASIC) return;
			else if (ptr -> children[0] -> flags == FLAG_SPECIFIER_STRUCT)
				symtab_add_struct(ptr -> children[0] -> children[0]);
			else assert(0);
		} else {
			assert(0);
		}
	} else if (ptr -> unit_name == NODE_EXP) {
		check_expression(ptr);
	} else if (ptr -> unit_name == NODE_DEF) {
		struct tree_node * spec = ptr -> children[0];
		struct tree_node * declist = ptr -> children[1];
		while (declist -> flags == FLAG_DECLIST_MORE) {
			symtab_add_variable(spec, declist -> children[0] -> children[0]);
			if (declist -> children[0] -> flags == FLAG_DEC_INITIALIZED) {
				check_expression(declist -> children[0] -> children[2]);
			}
			declist = declist -> children[2];
		}
		symtab_add_variable(spec, declist -> children[0] -> children[0]);
		if (declist -> children[0] -> flags == FLAG_DEC_INITIALIZED) {
			check_expression(declist -> children[0] -> children[2]);
		}
	} else if (ptr -> unit_name == NODE_STMT) {
		if (ptr -> flags == FLAG_STMT_EXP) {
			check_expression(ptr -> children[0]);
		} else if (ptr -> flags == FLAG_STMT_COMPST) {
			struct tree_node * deflist = ptr -> children[0] -> children[1];
			while (deflist -> flags == FLAG_DEFLIST_MORE) {
				semantic_analysis(deflist -> children[0]);
				deflist = deflist -> children[1];
			}
			struct tree_node * stmtlist = ptr -> children[0] -> children[2];
			while (stmtlist -> flags == FLAG_STMTLIST_MORE) {
				semantic_analysis(stmtlist -> children[0]);
				stmtlist = stmtlist -> children[1];
			}
		} else if (ptr -> flags == FLAG_STMT_IF) {
			check_expression(ptr -> children[2]);
			if (ptr -> children[2] -> exp_type_flag != TYPE_BASIC ||
				ptr -> children[2] -> exp_type.basic_type != TYPE_INT) {
				semerrorpos(ERROR_OTHER, ptr -> line);
				printf("non-integer in condition expression\n");
			}
			semantic_analysis(ptr -> children[4]);
		} else if (ptr -> flags == FLAG_STMT_IFELSE) {
			check_expression(ptr -> children[2]);
			if (ptr -> children[2] -> exp_type_flag != TYPE_BASIC ||
				ptr -> children[2] -> exp_type.basic_type != TYPE_INT) {
				semerrorpos(ERROR_OTHER, ptr -> line);
				printf("non-integer in condition expression\n");
			}
			semantic_analysis(ptr -> children[4]);
			semantic_analysis(ptr -> children[6]);
		} else if (ptr -> flags == FLAG_STMT_WHILE) {
			check_expression(ptr -> children[2]);
			if (ptr -> children[2] -> exp_type_flag != TYPE_BASIC ||
				ptr -> children[2] -> exp_type.basic_type != TYPE_INT) {
				semerrorpos(ERROR_OTHER, ptr -> line);
				printf("non-integer in condition expression\n");
			}
			semantic_analysis(ptr -> children[4]);
		} else if (ptr -> flags == FLAG_STMT_RETURN) {
			// done
			check_expression(ptr -> children[1]);
			if (function_field == NULL) {
				semerrorpos(ERROR_OTHER, ptr -> line);
				printf("no corresponding block to return operation\n");
				return;
			}
			int c = compare_type(ptr -> children[1] -> exp_type_flag, &(ptr -> children[1] -> exp_type),
				function_field -> return_type_flag, &(function_field -> return_type));
			if (c == COMPARE_GOOD) {
				// good
			} else {
				semerrorpos(ERROR_RETURN_MISMATCH, ptr -> line);
				printf("return type error: %s\n", compare_str[c]);
			}
			// end of return
		} else {
			assert(0);
		}
	} else {
		for (i = 0; i < ptr -> num_of_children; ++i) {
			assert(ptr -> children[i]);
			semantic_analysis(ptr -> children[i]);
		}
	}
	
}
static inline
int compare_type(const DisplayState& lhs, const DisplayState& rhs) {
    return compare_type(lhs.token, rhs.token);
}