📄 syntax.c
字号:
#include <stdio.h>
#include <string.h>
#include "syntax.h"
#include "utility.h"
struct _stmtnode *newDeclStmt(
struct _supertype *spec,
struct _sym *declist,
char *filename,
int lineno
)
{
StmtNode *stmt = dmalloc(sizeof(StmtNode), true);
stmt->stmtype = stmt_decl;
stmt->ss = NULL;
stmt->s1 = NULL;
stmt->s2 = NULL;
stmt->labelno = UNKNOWN;
stmt->declist = declist;
stmt->spec = spec;
stmt->filename =filename;
stmt->lineno =lineno;
return stmt;
}
struct _stmtnode *newCalcStmt(
int stmtype,
struct _expnode *exp,
struct _stmtnode *ss,
struct _stmtnode *s1,
struct _stmtnode *s2,
char *filename,
int lineno
)
{
StmtNode *stmt = dmalloc(sizeof(StmtNode), true);
stmt->stmtype = stmtype;
stmt->next = NULL;
stmt->exp = exp;
stmt->ss = ss;
stmt->s1 = s1;
stmt->s2 = s2;
stmt->labelno = UNKNOWN;
stmt->declist = NULL;
stmt->spec = NULL;
stmt->filename =filename;
stmt->lineno =lineno;
if(stmtype == stmt_switch)
preswitch(stmt);
else if(stmtype == stmt_return)
{
if(checkTypeSame(current_func->datatype->subtype,
exp->datatype)>1)
generror(ERR_TYPE_CONFLICT, "return value and the declaration");
}
return stmt;
}
void preswitch(struct _stmtnode *stmt)
{
StmtNode *curcase = NULL, *curstmt = NULL;
StmtNode *onecase=stmt->ss;// *defaultstmt = NULL;
stmt->s2=NULL;
if(onecase->stmtype == stmt_compound)
onecase = onecase->ss;
while(onecase)
{
if(onecase->stmtype == stmt_case)
{
if(curcase == NULL)
stmt->s1 = curcase = onecase;
else
curcase = curcase->next = onecase;
onecase->ss->next = onecase->next;
onecase = onecase->ss;
}
else if(onecase->stmtype == stmt_default)
{
if(stmt->s2)
generror(ERR_DEFAULT_MORE, NULL);
else
stmt->s2 = onecase;
onecase->ss->next = onecase->next;
onecase = onecase->ss;
}
else
{
if(curstmt == NULL)
stmt->ss = curstmt = onecase;
else
curstmt = curstmt->next = onecase;
onecase = onecase->next;
}
}
if(curcase)
curcase->next = NULL;
if(curstmt)
curstmt->next = NULL;
return;
}
struct _expnode *newInitExp(
int exptype
)
{
// HashNode *hashnode= NULL;
static Type defaulttype = {0, UNKNOWN,0};
ExpNode *exp = dmalloc(sizeof(ExpNode),true);
memset(exp, 0, sizeof(exp));
exp->exptype = exptype;
//to avoid the null pointer in type analysis
exp->datatype = &defaulttype;
return exp;
}
struct _expnode *evaluate_void_exp()
{
ExpNode *res = newInitExp(exp_void);
res->datatype = newType(NULL, bt_void, NULL);
return res;
}
struct _expnode *evaluate_brace_exp(
struct _expnode *exp
)
{
ExpNode *res = newInitExp(exp_brace);
res->val.opd[0]= exp;
return res;
}
//assume every const pointer is immediate addr mode
struct _expnode *evaluate_const_exp(
int bt,
void *value
)
{
ExpNode *res = newInitExp(exp_const);
res->datatype =newType(NULL, bt, 0);
if(bt == bt_pointer)
{
res->datatype->subtype = newType(NULL, bt_char, 0);
res->val.addr.base = "string"; //
res->val.addr.offset = add_const(value);
}
else if(bt == bt_long)
{
res->val.i = *((long*)value);
}
else if(bt == bt_unsignedlong)
{
res->val.u = *((unsigned long*)value);
}
else if(bt == bt_double)
{
res->val.f = *((double*)value);
}
else
{
generror(ERR_UNKNOWN_CONST, NULL);
}
return res;
}
struct _expnode *evaluate_id_exp(
char *name
)
{
HashNode *hashnode = lookup_node(symtab, SYMTABSIZE, name);
ExpNode *res = newInitExp(exp_vref);
Symbol *var;
if(hashnode)
{
var = hashnode->val;
if(var->storage_class == sc_label)
{
generror(ERR_TYPE_CONFLICT, name);
return res;
}
var->refcount++;
if(var->const_flag)
{
//in C named const only enum, function name
//wait for named const extension
//modify
res->datatype = var->datatype;
switch(var->datatype->basic_type)
{
case bt_funcptr:
res->val.addr.base = var->name;
res->exptype = exp_label;
break;
case bt_long://enum will be treated as long
res->exptype = exp_const;
res->val.i = var->value.i;
break;
default://name of array
res->exptype = exp_aref;
if(var->storage_class == sc_auto)
{
res->val.addr.base =NULL;
res->val.addr.offset = var->value.offset;
}
else
{
res->val.addr.base = var->value.linkname;
res->val.addr.offset = 0;
}
}
}
else
{
res->datatype = var->datatype;
if(var->storage_class == sc_auto)
res->val.addr.offset = var->value.offset;
else
res->val.addr.base = var->value.linkname;
}
}
else
generror(ERR_UNKNOWN_ID, name);
return res;
}
struct _expnode *evaluate_label_exp(
char *name
)
{
ExpNode *res = newInitExp(exp_label);
res->val.label = add_named_label(name, UNKNOWN);
return res;
}
struct _expnode *evaluate_call_exp(
struct _expnode *func,
struct _expnode *arglist
)
{
Symbol *para;
ExpNode *res = newInitExp(exp_call), *next, *arg, *topush = NULL;
if(func->datatype->basic_type == bt_funcptr)
{
para= func->datatype->arglist;
arg = arglist;
while(para&&arg)
{
if(checkTypeSame(para->datatype, arg->datatype)>1)
{
generror(ERR_ARG_NOTMATCH, para->name);
break;
}
next = arg->next;//reverse the order
arg ->next =topush;
topush = arg;
arg = next;
if(para->datatype->basic_type != bt_ellipsis)
para = para->next;
}
if(arg)
generror(ERR_FEW_ARG, NULL);// no name in exp, weak debug ability
else
{
res->val.opd[0] = func;
res->val.opd[1] = topush;
res->datatype = func->datatype->subtype;
}
}
else
generror(ERR_EXPECT_FUNC, NULL);
return res;
}
struct _expnode *evaluate_member_exp(
int exptype,
struct _expnode *var,
char *memname
)
{
Type *tmptype;
HashNode *hashnode=NULL;
Symbol *mem;
ExpNode *res =newInitExp(exptype);
tmptype = var->datatype;
if(exptype==exp_ptomem)
{
if(tmptype->basic_type == bt_pointer)
tmptype= tmptype->subtype;
else
{
generror(ERR_EXPECT_POINTER, NULL);
return res;
}
}
if(tmptype->basic_type != bt_struct
&& tmptype->basic_type != bt_union)
{
generror(ERR_EXPECT_STRUCT, NULL);
return res;
}
if(tmptype->memlist)
hashnode = lookup_node(tmptype->memlist, MEMTABSIZE, memname);
if(hashnode)
{
mem = hashnode ->val;
res->datatype = mem->datatype;
res->val.opd[0] = var;
res->val.opd[1] = evaluate_const_exp(bt_long, &(mem->value.offset));
}
else
{
generror(ERR_NOT_MEMBER, memname);
}
return res;
}
struct _expnode *evaluate_array_exp(
struct _expnode *array,
struct _expnode *index
)
{
ExpNode *res =newInitExp(exp_array), *tmpexp;
int size = array->datatype->subtype->size;
//to ensure the next step of analyzing
res->datatype = array->datatype->subtype;
if(array->datatype->basic_type != bt_pointer)
{
generror(ERR_EXPECT_POINTER,"on the left");
return res;
}
if(!(is_integer(index->datatype->basic_type)))
{
generror(ERR_EXPECT_INT, "on the right");
return res;
}
if(array->datatype->subtype->size == UNKNOWN)
{
generror(ERR_UNKNOWN_SIZE, "member of array");
return res;
}
else if(array->datatype->subtype->size == 0)
{
generror(ERR_ZERO_SIZE, "member of array");
return res;
}
if(array->exptype==exp_const && index->exptype == exp_const)
{
res->datatype = array->datatype->subtype;
if(res->datatype->array_vol == 0)
res->exptype = exp_vref;
res->val.addr.offset=index->val.i*size
+array->val.addr.offset;
res->val.addr.base = array->val.addr.base;
}
else
{
res->val.opd[0]=array;
if(size>1)
{
tmpexp = evaluate_const_exp(bt_long, &(size));
res->val.opd[1]=evaluate_binary_exp(exp_mul, tmpexp, index);
}
else res->val.opd[1]=index;
}
return res;
}
struct _expnode *evaluate_typecast_exp(
struct _datatype *target_type,
struct _expnode *origin
)
{
//from float to int need to call extra function
//no support for this moment
//??????????????
//wait for me
ExpNode *res ;
res = origin;
res->datatype = target_type;
return res;
}
struct _expnode *evaluate_sizeof_exp(
struct _datatype *type,
struct _expnode *exp
)
{
ExpNode *res = newInitExp(exp_const);
res->datatype =newType(NULL, bt_long, 0);
if(type)
{
res->val.i = type->size;
}
else
{
res->val.i = exp->datatype->size;
}
return res;
}
//increase or dcrease
struct _expnode *evaluate_indecr_exp(
int exptype, //if it is minus , means the opd is on the left , a little trick
struct _expnode *exp
)
{
int abstype = exptype>0?exptype:-exptype;
ExpNode *res = newInitExp(abstype);
res->datatype = exp->datatype;
if(!is_variable(exp->exptype))
{
generror(ERR_EXPECT_VAR, NULL);
return res;
}
if(exptype<0)
res->val.opd[0]=exp;
else
res->val.opd[1]=exp;
return res;
}
struct _expnode *evaluate_unary_exp(
int exptype,
struct _expnode *exp
)
{
ExpNode *res = newInitExp(exptype);
switch(exptype)
{
case exp_ptr:
if(!is_variable(exp->exptype))
{
generror(ERR_EXPECT_VAR, NULL);
break;
}
res->datatype= newType(NULL, bt_pointer, NULL);
compoundType(res->datatype, exp->datatype);
res->val.opd[1] = exp;
break;
case exp_val:
if(exp->datatype->basic_type != bt_pointer)
generror(ERR_EXPECT_POINTER, NULL);
res->datatype = exp->datatype->subtype;
res->val.opd[1] = exp;
break;
case exp_uplus:
res=exp;
break;
case exp_uminus:
if(!is_real(exp->datatype->basic_type))
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -