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

📄 expression.c

📁 一个编译器修改的例子
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "error.h"#include "expression.h"#include "salloc.h"#include "declaration.h"#include <assert.h>#include <string.h>#include <limits.h>#include <float.h>#include <errno.h>#include <ctype.h>/* Variable to temporarily hold a Expression pointer for subtype check. Used * in the ASSERT_EXPR_SUBTYPE macro. */Expression *__expr;List *string_list;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;      case expr_record:            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;           case expr_record:                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_record:            return is_lvalue_(expr->operand[0],offence); /*add : check if members of expression is lvalue*/	        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",		  expr->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;    /* Koen: fill type in now so caller won't complain when we detect a     * problem with the parameters down below     */    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);        /*add : check if parameters have the same struct when call a function */        if (formal_type!=0&&actual_type!=0&&formal_type->subtype==record_type&&actual_type->subtype==record_type)          {            if(strcmp(RECORD_TYPE(formal_type).decl->token->name,RECORD_TYPE(actual_type).decl->token->name)!=0)              error(expr->token,"argument %u: two record types has not the same struct", 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 ((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;		break;          case record_decl: /*do nothing*/            break;	}	inc_ref_count(expr->type, 1);    }}/* add : check if an expression of a record is correct */static void type_check_expr_record(Expression *expr){  if(expr->subtype!=expr_record&&expr->subtype!=expr_index&&expr->subtype!=expr_ident&&expr->subtype!=expr_func_call)   {     error(expr->token, "%s is illegal in an expression of record", expr->token->name);   } else   {      if (expr->subtype==expr_ident)         {             type_check_identifier(expr);         }      if (expr->subtype==expr_index)         {              type_check_expression(expr->operand[0]);              type_check_expression(expr);         }      if (expr->subtype==expr_func_call)         {              type_check_function_call(expr);         }       if (expr->subtype==expr_record)         {              type_check_expr_record(expr->operand[0]);               if(expr->operand[0]->type==0||expr->operand[0]->type->subtype != record_type)                    error(expr->operand[0]->token,"%s an undeclared variable or not a struct ",expr->operand[0]->token->name);              else                {                    Declaration *decl=lookup_in_this_scope(RECORD_DECL(RECORD_TYPE(expr->operand[0]->type).decl).formal_var_scope,expr->token->name);                    if(decl==0)                         error(expr->token,"%s an undeclared variable ",expr->token->name);                    else                        expr->type=VAR_DECL(decl).type;               }         }   }}/* Check escapes in given string (may also be character constant),   and calculate the length after interpretation of escapes. */static unsigned check_string_escapes(Token *string, unsigned length) {    unsigned i, j, output_length = 0;    const char *str = string->name + 1;    for (i = 0; i < length; i++) {	if (str[i] != '\\') {	    output_length++;	    continue;	}	/* An unterminated string may end in '\' */	if (++i == length)	    return output_length;	if (str[i] == 'x') {	    for (j = i + 1; j < length; j++) {		if (!((str[j] >= '0' && str[j] <= '9') ||			(str[j] >= 'a' && str[j] <= 'f') ||			(str[j] >= 'A' && str[j] <= 'F')))		    break;	    }	    if (j - i == 1)		error(string, "invalid esacape sequence '\\x'");	    else if (j - i > 3)		error(string, "too long hex escape sequence '\\%.*s'", j - i, str + i);	    i = j - 1;	} else if (str[i] >= '0' && str[i] <= '7') {	    unsigned value = str[i] - '0';	    for (j = 1; j < 3 && j + i < length; j++) {		if (str[i+j] >= '0' && str[i+j] <= '7')		    value = value * 8 + (str[i+j] - '0');		else		    break;	    }	    if (value > 255)		error(string, "octal escape sequence out of range '\\%.*s'", j, str + i);	    i += j - 1;	} else if (strchr("ntvbrfa\\?'\"", str[i]) == 0) {	    error(string, "invalid escape sequence '\\%c'", str[i]);	}	output_length++;    }    return output_length;}static void check_char_const(Token *string) {    unsigned length = strlen(string->name);    if (length < 2) /* single ' */	return;    if (length == 2 && string->name[1] == '\'')	error(string, "empty character constant");    length = check_string_escapes(string, length - 2);    if (length > 1)	error(string, "more than one character in character constant %s", string->name);}static unsigned check_string_const(Token *string) {    unsigned length = strlen(string->name);    if (length <= 2)	return 0;    return check_string_escapes(string, length - 2);}Type *type_check_expression(Expression *expr){    if (expr == 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);	    check_char_const(expr->token);	    break;

⌨️ 快捷键说明

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