⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 expression.c

📁 一个编译器修改的例子
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "error.h"#include "expression.h"#include "salloc.h"#include "statement.h"#include <assert.h>#include <string.h>#include <limits.h>#include <float.h>#include <errno.h>#include <ctype.h>#include "declaration.h"static void string_check_escapes(Token *t);List *string_list;int and_number;int global_equal,local_offset;Scope *record_expr_scope;Scope *expr_scope;Declaration *decl;Type *type;Expression *new_expression(Expr_subtype subtype, Token *token,			   Expression *left_operand, Expression *right_operand){    Expression *expr	= safe_malloc(sizeof(Expression));    expr->subtype   	= subtype;    expr->token		= token;    expr->operand [0]	= left_operand;    expr->operand [1]	= right_operand;    expr->type		= 0;    switch (subtype)    {	case expr_func_call:	    EXPR_FUNC_CALL(expr).formal_args = 0;	    EXPR_FUNC_CALL(expr).actual_args = 0;	    break;	case expr_ident:	    EXPR_IDENT(expr).scope = 0;	    break;	default:	    break;    }    return expr;}void delete_expression(Expression *expr){    if (expr != 0)    {		delete_token(expr->token);		delete_expression(expr->operand [0]);		delete_expression(expr->operand [1]);		delete_type(expr->type);	switch (expr->subtype)	{	    List     *actuals;	    unsigned i;	    case expr_func_call:		actuals = EXPR_FUNC_CALL(expr).actual_args;		for (i = 0; i < list_size(actuals); i ++)		    delete_expression(list_index(actuals, i));		delete_list(actuals);		break;	    default:		break;	}	free(expr);    }}Bool is_lvalue_(Expression *expr, char **offence){    if (expr == 0 || expr->type == 0)	return true;    if (offence != NULL) *offence = expr->token->name;    switch (expr->subtype)    {	case expr_ident:	    return expr->type->subtype != subprog_type;	case expr_index:	    return true;	case expr_func_call:	    if (offence != NULL) *offence = "a function call";	    return false;			case expr_dot:		if (is_lvalue_(expr->operand[0],offence))		return true;	default:	    return false;    }}/* Type check expr, and see it is of the proper type */static Type *match_type(Expression *expr, Type_subtype subtype_set,			const char *expected){    Type *type = type_check_expression(expr);    if (type != 0 && (type->subtype & subtype_set) == 0)    {	error(expr->token, "expected %s type", expected);	type = 0;    }    return type;}static void check_operands_compatibility(Expression *expr){    Expression *operand_0 = expr->operand [0], *operand_1 = expr->operand [1];    if (operand_0 != 0 && operand_1 != 0 && !types_compatible(operand_0->type, operand_1->type))	{			error(expr->token, "incompatible types for %s operator\n", expr->token->name);	}	else	{		if (operand_0->subtype==record_type && operand_0->type!=0)		{			if (expr->subtype==expr_eq || expr->subtype==expr_ne)			{				error(expr->token,"connot compare structs\n");			}		}	}}static void type_check_expr_dot(Expression *expr){	if ((expr->operand[0]) != NULL){		Type *tempType = type_check_expression(expr->operand[0]);		if (tempType==NULL)			{			return;			}		if ((tempType)->subtype == record_type) {			Declaration *decl, *declTemp;			Type  *typeL;			char *nameL;						typeL = expr->operand[0]->type;			nameL = RECORD_TYPE(typeL).decl->token->name;			decl = RECORD_TYPE(typeL).decl;			if (lookup_in_this_scope(RECORD_DECL(decl).member_scope,expr->operand[1]->token->name) != 0 ){				declTemp = lookup_in_this_scope(RECORD_DECL(decl).member_scope,expr->operand[1]->token->name);				expr->type = VAR_DECL(declTemp).type;				inc_ref_count(expr->type,1);			}			else {#ifdef DEBUG				printf(" %s not found in memberscope\n",expr->operand[1]->token->name);#endif				error(expr->operand[1]->token, "%s is not found in the member_scope \n ", expr->operand[1]->token->name);			}			} else {#ifdef DEBUG			printf("Not a record type!\n");#endif				error(expr->operand[0]->token, "The used type %s is not of record_type \n ", expr->operand[0]->token->name);			}	} 	else 	{#ifdef DEBUG		printf("expr->operand[0] == NULL POINTER!!\n");#endif		error(expr->operand[0]->token, "%s is a NULL pointer \n ", expr->operand[0]->token->name);	}	type_check_expression(expr->operand[1]);		if ((expr->operand[1]) != NULL){#ifdef DEBUG				printf("Not a NULL type!\n");#endif	} else {#ifdef DEBUG		printf("expr->operand[1] == NULL POINTER!!\n");#endif		error(expr->operand[1]->token, "%s is a NULL pointer \n ", expr->operand[1]->token->name);	}}static void type_check_function_call(Expression *expr){    List	*formals, *actuals;    unsigned	i;    Declaration *decl;    Expression	*func;    Type	*func_type;        if (expr == 0)	return;    func = expr->operand [0];    func_type = type_check_expression(func);    if (func_type == 0)	return;    if (func_type->subtype != subprog_type)    {	error(func->token, "called object is not a subprogram");	return;    }    if ((decl = SUBPROG_TYPE(func_type).decl) == 0)	return;        if ((expr->type = SUBPROG_DECL(decl).return_type) != 0)	inc_ref_count(expr->type, 1);    formals = EXPR_FUNC_CALL(expr).formal_args = SUBPROG_DECL(decl).formal_args;    if (formals == 0)	return;    if ((actuals = EXPR_FUNC_CALL(expr).actual_args) == 0)	return;    if (list_size(formals) != list_size(actuals))    {	error(expr->token, "parameter count mismatch");	return;    }    for (i = 0; i < list_size(actuals); i ++)    {	Declaration *formal_arg  = list_index(formals, i);	Type	    *formal_type = VAR_DECL(formal_arg).type;	Expression  *actual_arg  = list_index(actuals, i);	Type	    *actual_type = type_check_expression(actual_arg);	Bool	    call_by_ref  = formal_type != 0 && formal_type->call_by_ref;	if (!types_compatible(formal_type, actual_type))	    error(actual_arg->token, "argument %u: incompatible type", i + 1);	if (call_by_ref && !is_lvalue(actual_arg))	    error(actual_arg->token,		  "actual value of call-by-reference argument must be lvalue");    }}static void type_check_identifier(Expression *expr){    Declaration *decl;	if (EXPR_IDENT(expr).scope != 0x0)	{		if ((decl = lookup(EXPR_IDENT(expr).scope, expr->token->name)) == 0)		{			error(expr->token, "%s not declared", expr->token->name);		}		else    		{			switch (decl->subtype)			{	    			case subprog_decl:				expr->type = SUBPROG_DECL(decl).type;				break;		  	    			case var_decl:				expr->type = VAR_DECL(decl).type;							if (VAR_DECL(decl).type->subtype == record_type)				{					expr_scope=RECORD_DECL(RECORD_TYPE(   VAR_DECL(decl).type    ).decl).member_scope;				}				break;							case record_decl:				error(expr->token,"error record %s seen as IDENTIFIER\n",expr->token->name);			break;			}		}	}	else if (expr_scope != 0x0)	{		if ((decl = lookup(expr_scope,expr->token->name))  == 0)		{			error(expr->token, "%s not declared", expr->token->name);		}		else    		{			switch (decl->subtype)			{	    			case subprog_decl:				expr->type = SUBPROG_DECL(decl).type;				break;		  	    			case var_decl:				expr->type = VAR_DECL(decl).type;							if (VAR_DECL(decl).type->subtype == record_type)				{					expr_scope=RECORD_DECL(RECORD_TYPE(   VAR_DECL(decl).type    ).decl).member_scope;				}				break;							case record_decl:				error(expr->token,"error record %s seen as IDENTIFIER\n",expr->token->name);				break;			}		}    	}	inc_ref_count(expr->type, 1);}Type *type_check_expression(Expression *expr){	Token *token;    if (expr == 0 || expr->subtype == 0)	return 0;    switch (expr->subtype)    {	Type *type;	case expr_bool_const:	    expr->type	= new_simple_type(bool_type);	    break;	case expr_char_const:	    expr->type	= new_simple_type(char_type);	    break;	case expr_int_const:	    expr->type = new_simple_type(int_type);	    break;	case expr_real_const:	    expr->type = new_simple_type(real_type);	    break;	case expr_string_const:	    expr->type = new_array_type(new_simple_type(char_type));	    string_check_escapes(expr->token);	    EXPR_STRING_CONST(expr).index = list_size(string_list);	    list_append(string_list, expr->token->name);	    break;	case expr_null:	    expr->type = new_null_type();	    break;	case expr_and:	case expr_or:	    match_type(expr->operand [0], bool_type, "bool");	    match_type(expr->operand [1], bool_type, "bool");	    expr->type = new_simple_type(bool_type);	    break;	case expr_div:	case expr_min:	case expr_mul:	case expr_plus:	    expr->type = match_type(expr->operand [0], arithmetic_type,	    			    "arithmetic");	    match_type(expr->operand [1], arithmetic_type, "arithmetic");	    check_operands_compatibility(expr);	    inc_ref_count(expr->type, 1);	    break;	case expr_eq:	case expr_ne:		{		Type *temptype1 = match_type(expr->operand [0], any_type, "");		Type *temptype2 = match_type(expr->operand [1], any_type, "");		if (temptype1 != 0 ){			if (temptype1->subtype == record_type)			{				error(expr->operand[0]->token, "Cannot compare structures or Unions\n");			}		} else {			error(expr->operand[0]->token, "Cannot check subtype of a nullpointer\n");		}		if (temptype2 != 0 ){ 			if (temptype2->subtype == record_type) /*RECHTER KIND HEEFT NULL-TYPE nog controleren ERICK */			{				error(expr->operand[1]->token, "Cannot compare structures or Unions\n");			}		} else {			error(expr->operand[1]->token, "Cannot check subtype of a nullpointer\n");		}			check_operands_compatibility(expr);			expr->type = new_simple_type(bool_type);		}	    break;	case expr_ge:	case expr_gt:	case expr_se:	case expr_st:	    match_type(expr->operand [0], scalar_type, "scalar");	    match_type(expr->operand [1], scalar_type, "scalar");	    check_operands_compatibility(expr);	    expr->type = new_simple_type(bool_type);	    break;	case expr_not:	    match_type(expr->operand [0], bool_type, "bool");	    expr->type = new_simple_type(bool_type);	    break;	case expr_unary_min:	case expr_unary_plus:	    expr->type = match_type(expr->operand [0], arithmetic_type,				    "arithmetic");	    inc_ref_count(expr->type, 1);	    break;	case expr_ident:	    type_check_identifier(expr);	    break;		case expr_new:	    match_type(expr->operand [0], int_type, "int");	    break;	case expr_index:	    if ((type = match_type(expr->operand[0], array_type, "array")) != 0)	    {		expr->type = ARRAY_TYPE(type).base_type;		inc_ref_count(expr->type, 1);/*		expr_scope = EXPR_IDENT(expr->operand[0]).scope;*/		expr_scope = bepaal_scope(expr,true);		token = bepaal_token(expr,true);		decl = lookup(expr_scope,token->name);		if (ARRAY_TYPE(VAR_DECL(decl).type).base_type->subtype == record_type)		{			expr_scope = RECORD_DECL(RECORD_TYPE(ARRAY_TYPE(VAR_DECL(decl).type).base_type).decl).member_scope;		}	    }	    match_type(expr->operand [1], int_type, "int");		break;	case expr_size:	    match_type(expr->operand [0], array_type, "array");	    expr->type = new_simple_type(int_type);	    break;	case expr_func_call:	    type_check_function_call(expr);	    break;    	case expr_dot:			type_check_expr_dot(expr);		break;	default:		error(expr->token,"Subtype cannot be NULL during typechecking");		break;		}	    return expr->type;}static void generate_prefix_operator(Expression *expr, const char *symbol){    fprintf(c_out, "(%s", symbol);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -