774 lines
21 KiB
Plaintext
774 lines
21 KiB
Plaintext
/*
|
|
void PrsPush(ParseStack *ps,U4 val)
|
|
{
|
|
ps->stk[ps->ptr++]=val;
|
|
}
|
|
U8 PrsPop(ParseStack *ps)
|
|
{
|
|
return ps->stk[--ps->ptr];
|
|
}
|
|
*/
|
|
|
|
LTextern CP_PRSPUSH void PrsPush(ParseStack *ps,U4 val);
|
|
LTextern CP_PRSPOP U4 PrsPop(ParseStack *ps);
|
|
|
|
#define PRST_UNARY_TERM 0
|
|
#define PRST_UNARY_MODIFIERS 1
|
|
#define PRST_DEREFERRENCE 2
|
|
#define PRST_CHECK_BINARY_OPS 3
|
|
|
|
BoolU4 PrsParseExpression(LexStruct *l,BoolU4 add_esp=FALSE)
|
|
{
|
|
BoolU4 result=TRUE,question_clause=FALSE,
|
|
cont_unary,cont_check_binary_ops,is_lower;
|
|
I8 i,j,k;
|
|
IntermediateCode *tempi,*tempi_first=l->cb.cb_out_ptr;
|
|
ClassStruct *tempc;
|
|
ParseStack *ps=MAlloc(sizeof(ParseStack));
|
|
|
|
ps->ptr=0;
|
|
PrsPush(ps,0); //terminate
|
|
PrsPush(ps,0); //terminate
|
|
try {
|
|
do {
|
|
l->flags&=~(LF_PREINC+LF_PREDEC+LF_POSTINC+LF_POSTDEC+LF_FUNCTION);
|
|
do i=PrsUnaryTerm(l,ps);
|
|
while (i==PRST_UNARY_TERM);
|
|
|
|
while (i==PRST_UNARY_MODIFIERS)
|
|
i=PrsUnaryModifier(l,ps);
|
|
|
|
if (i==PRST_DEREFERRENCE)
|
|
PrsDereferrence(l,ps);
|
|
|
|
//Check for binary Ops
|
|
do {
|
|
i=PrsPop(ps);
|
|
tempc=PrsPop(ps);
|
|
if (i && i.u2[1]<=1) {
|
|
tempi=l->cb.cb_last_out_ptr;
|
|
i&=0xFFFF;
|
|
tempc=tempi->ic_class;
|
|
if (Bt(deref_bitmap,i) && tempc->pointer_cnt) {
|
|
tempc=tempc-sizeof(ClassStruct);
|
|
while (tempc->return_class)
|
|
tempc=tempc->return_class;
|
|
if (tempc->type & HTT_INTERNAL_TYPE)
|
|
i=EC_DEREF_U8+0x10000+it_to_ec_offset[tempc->sub_type];
|
|
else
|
|
i=EC_DEREF_U4+0x10000;
|
|
} else {
|
|
if (i==EC_ADDRESS) {
|
|
if (!(l->flags & (LF_EAX|LF_ARRAY))) {
|
|
j=tempi->ic_code.u2[0];
|
|
if (!Bt(deref_bitmap,j))
|
|
PrsExcept(l,"ST_INVALID_LVALUE");
|
|
tempi->ic_code=EC_NOP;
|
|
tempc=tempc+sizeof(ClassStruct);
|
|
}
|
|
}
|
|
}
|
|
CbAddIc(l,i,0,tempc);
|
|
cont_check_binary_ops=TRUE;
|
|
} else {
|
|
PrsPush(ps,tempc);
|
|
PrsPush(ps,i);
|
|
i=l->token;
|
|
k=binary_ops_table[i];
|
|
if (k.u2[0]==EC_QUESTION)
|
|
question_clause=TRUE;
|
|
else if (k.u2[0]==EC_COLON) {
|
|
if (!question_clause)
|
|
k=0;
|
|
else
|
|
question_clause=FALSE;
|
|
}
|
|
if (!k.u2[1]) {
|
|
cont_check_binary_ops=FALSE;
|
|
cont_unary=FALSE; //DONE
|
|
} else {
|
|
Lex(l); //skip op
|
|
if (Bt(assign_bitmap,k.u2[0])) {
|
|
tempi=l->cb.cb_last_out_ptr;
|
|
tempc=tempi->ic_class;
|
|
j=tempi->ic_code.u2[0];
|
|
if (!Bt(deref_bitmap,j))
|
|
PrsExcept(l,"ST_INVALID_LVALUE");
|
|
tempi->ic_code=EC_NOP;
|
|
while (tempc->return_class)
|
|
tempc=tempc->return_class;
|
|
if (!(tempc->type & HTT_INTERNAL_TYPE))
|
|
k=k.u2[0]+0x100000+it_to_ec_offset[IT_U4];
|
|
else
|
|
k=k.u2[0]+0x100000+it_to_ec_offset[tempc->sub_type];
|
|
}
|
|
do {
|
|
i=PrsPop(ps); //pop ops of higher prec
|
|
tempc=PrsPop(ps);
|
|
is_lower=FALSE;
|
|
if (i) {
|
|
if (k.u2[1]==i.u2[1]) {
|
|
if (!Bt(assign_bitmap,k.u2[0]) ||
|
|
!Bt(assign_bitmap,i.u2[0]))
|
|
is_lower=TRUE;
|
|
} else if (k.u2[1]>i.u2[1])
|
|
is_lower=TRUE;
|
|
}
|
|
if (is_lower)
|
|
CbAddIc(l,i,0,tempc);
|
|
else {
|
|
PrsPush(ps,tempc);
|
|
PrsPush(ps,i);
|
|
tempi=l->cb.cb_last_out_ptr;
|
|
tempc=tempi->ic_class;
|
|
PrsPush(ps,tempc);
|
|
PrsPush(ps,k);
|
|
cont_check_binary_ops=FALSE;
|
|
cont_unary=TRUE;
|
|
break;
|
|
}
|
|
} while (TRUE);
|
|
}
|
|
}
|
|
} while (cont_check_binary_ops);
|
|
} while (cont_unary);
|
|
while (TRUE) {
|
|
i=PrsPop(ps);
|
|
tempc=PrsPop(ps);
|
|
if (i)
|
|
CbAddIc(l,i,0,tempc);
|
|
else
|
|
break;
|
|
}
|
|
} catch {
|
|
if (Fs->except_argc>0) {
|
|
if (Fs->except_argv[0]==EXCEPT_COMPILER) {
|
|
l->statement_cnt=0;
|
|
l->braces_cnt=0;
|
|
result=FALSE;
|
|
Fs->catch_except=TRUE;
|
|
}
|
|
}
|
|
}
|
|
Free(ps);
|
|
if (add_esp && result) {
|
|
if (Bt(push_bitmap,tempi_first->ic_code.u2[0])) {
|
|
tempi_first->ic_flags|=ICF_NO_PUSHES;
|
|
CbAddIc(l,EC_END_EXP,0,0);
|
|
} else
|
|
CbAddIc(l,EC_ADD_ESP32,8,0);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
U8 PrsUnaryTerm(LexStruct *l,ParseStack *ps)
|
|
{
|
|
I8 i,*i_ptr;
|
|
I8 argc_cnt,size;
|
|
U8 d;
|
|
SysHashEntry *temph,**temph1;
|
|
ClassStruct *tempc,*tempc1,*tempc2;
|
|
GlblVarStruct *tempg;
|
|
MemberListStruct *tempm;
|
|
LexUndefEntry *templu;
|
|
CbMiscStruct *tempmc;
|
|
IntermediateCode *tempi;
|
|
BoolU4 needs_right_paren;
|
|
LexCbStack *templ,*templ1;
|
|
|
|
if (l->token==TK_INTEGER) {
|
|
if (l->cur_i<0)
|
|
CbAddIc(l,EC_U8,l->cur_i,sys_internal_types[IT_U8]);
|
|
else
|
|
CbAddIc(l,EC_U8,l->cur_i,sys_internal_types[IT_I8]);
|
|
Lex(l);
|
|
return PRST_CHECK_BINARY_OPS;
|
|
}
|
|
if (l->token==TK_DOUBLE) {
|
|
i_ptr=&l->cur_d;
|
|
CbAddIc(l,EC_DOUBLE,*i_ptr,sys_internal_types[IT_DOUBLE]);
|
|
Lex(l);
|
|
return PRST_CHECK_BINARY_OPS;
|
|
}
|
|
if (l->token==TK_STRING) {
|
|
d=LexExtendString(l,&size);
|
|
if (l->flags & LF_ASM_EXPRESSIONS)
|
|
CbAddIc(l,EC_U8,d,sys_internal_types[IT_I1]+sizeof(ClassStruct));
|
|
else {
|
|
tempmc=CbMiscNew(l,CBMT_STRING_CONSTANT);
|
|
CbAddIc(l,EC_STRING_CONSTANT,tempmc,sys_internal_types[IT_I1]+sizeof(ClassStruct));
|
|
tempmc->st_len=size;
|
|
tempmc->string=d;
|
|
l->flags|=LF_HAS_MISC_DATA;
|
|
}
|
|
return PRST_CHECK_BINARY_OPS;
|
|
}
|
|
if (l->token==TK_INSERT_BINARY) {
|
|
d=l->ident;
|
|
size=l->ident_len;
|
|
l->ident=NULL;
|
|
Lex(l);
|
|
if (l->flags & LF_ASM_EXPRESSIONS)
|
|
CbAddIc(l,EC_U8,d,sys_internal_types[IT_I1]+sizeof(ClassStruct));
|
|
else {
|
|
tempmc=CbMiscNew(l,CBMT_STRING_CONSTANT);
|
|
CbAddIc(l,EC_STRING_CONSTANT,tempmc,sys_internal_types[IT_I1]+sizeof(ClassStruct));
|
|
tempmc->st_len=size;
|
|
tempmc->string=d;
|
|
l->flags|=LF_HAS_MISC_DATA;
|
|
}
|
|
return PRST_CHECK_BINARY_OPS;
|
|
}
|
|
if (l->token==TK_INSERT_BINARY_TYPE ||
|
|
l->token==TK_INSERT_BINARY_SIZE) {
|
|
CbAddIc(l,EC_U8,l->cur_i,sys_internal_types[IT_U8]);
|
|
Lex(l);
|
|
return PRST_CHECK_BINARY_OPS;
|
|
}
|
|
if (l->token=='(') {
|
|
Lex(l); //Skip (
|
|
if (!PrsParseExpression(l))
|
|
throw(EXCEPT_COMPILER,2);
|
|
if (l->token!=')')
|
|
PrsExcept(l,"ST_MISSING_RIGHT_PAREN");
|
|
Lex(l); //skip )
|
|
l->flags=(l->flags & ~(LF_ARRAY+LF_FUNCTION)) | LF_EAX;
|
|
return PRST_UNARY_MODIFIERS;
|
|
}
|
|
|
|
i=unary_ops_table[l->token];
|
|
if (i.u2[1]) {
|
|
Lex(l); //Skip op
|
|
if (i.u2[0]==EC_ADDRESS && l->token==TK_IDENT) {
|
|
if (tempc=l->hash_entry) {
|
|
if (tempc->type & HTT_FUNCTION) {
|
|
if (!Bt(&tempc->flags,Cf_INTERNAL)) {
|
|
Lex(l); //skip fun name
|
|
if (Bt(&tempc->flags,Cf_EXTERN)) {
|
|
if (l->a)
|
|
CbAddIc(l,EC_ABSOLUTE_ADDRESS,
|
|
tempc->executable_address,sys_internal_types[IT_U4]);
|
|
else
|
|
CbAddIc(l,EC_U8,
|
|
&tempc->executable_address,sys_internal_types[IT_U4]);
|
|
CbAddIc(l,EC_DEREF_U4,0,
|
|
sys_internal_types[IT_U4]);
|
|
} else {
|
|
if (l->a)
|
|
CbAddIc(l,EC_ABSOLUTE_ADDRESS,
|
|
tempc->executable_address,sys_internal_types[IT_U4]);
|
|
else
|
|
CbAddIc(l,EC_U8,
|
|
tempc->executable_address,sys_internal_types[IT_U4]);
|
|
}
|
|
return PRST_CHECK_BINARY_OPS;
|
|
} //TODO: is this an error?
|
|
}//TODO: is this an error?
|
|
}//TODO: is this an error?
|
|
}
|
|
PrsPush(ps,tempc);
|
|
PrsPush(ps,i);
|
|
return PRST_UNARY_TERM;
|
|
}
|
|
if (l->token=='+') {
|
|
Lex(l);
|
|
return PRST_UNARY_TERM;
|
|
}
|
|
|
|
if (l->token!=TK_IDENT) {
|
|
if (l->token==TK_PLUS_PLUS) {
|
|
Lex(l);
|
|
l->flags|=LF_PREINC;
|
|
return PRST_UNARY_TERM;
|
|
}
|
|
if (l->token==TK_MINUS_MINUS) {
|
|
Lex(l);
|
|
l->flags|=LF_PREDEC;
|
|
return PRST_UNARY_TERM;
|
|
}
|
|
if (l->token=='$$' && l->flags & LF_ASM_EXPRESSIONS) {
|
|
Lex(l);
|
|
CbAddIc(l,EC_U8,l->instruction_pointer,sys_internal_types[IT_U4]);
|
|
return PRST_CHECK_BINARY_OPS;
|
|
}
|
|
PrsExcept(l,"ST_MISSING_EXPRESSION");
|
|
}
|
|
|
|
if (tempm=l->local_var_entry) {
|
|
l->flags&=~(LF_EAX+LF_ARRAY+LF_FUNCTION);
|
|
tempc=tempm->member_class+sizeof(ClassStruct);
|
|
if (tempm->flags & MLF_FUNCTION) {
|
|
l->flags|=LF_FUNCTION;
|
|
PrsPush(ps,0);
|
|
PrsPush(ps,tempm->parameter_cnt);
|
|
}
|
|
if (tempm->cnt) {
|
|
l->flags|=LF_ARRAY;
|
|
tempc+=sizeof(ClassStruct);
|
|
}
|
|
CbAddIc(l,EC_EBP,0,tempc);
|
|
CbAddIc(l,EC_U8,tempm->offset,tempc);
|
|
CbAddIc(l,EC_ADDITION,0,tempc);
|
|
Lex(l); //skip var name
|
|
return PRST_UNARY_MODIFIERS;
|
|
}
|
|
|
|
if (!(temph=l->hash_entry)) {
|
|
if (!(l->flags & LF_ASM_EXPRESSIONS))
|
|
PrsExcept(l,"ST_INVALID_LVALUE");
|
|
temph=MAllocZ(sizeof(SysHashEntry));
|
|
temph->string=l->ident;
|
|
l->ident=NULL;
|
|
if (temph->string[0]=='@' &&
|
|
temph->string[1]=='@') {
|
|
temph->type=HTT_SYS_SYMBOL | HTT_UNRESOLVED_LOCAL;
|
|
temph1=FindHashBucket(temph->string,l->local_hash_table);
|
|
} else {
|
|
temph->type=HTT_SYS_SYMBOL | HTT_UNRESOLVED_GLBL;
|
|
temph1=FindHashBucket(temph->string,l->glbl_hash_table);
|
|
}
|
|
temph->use_cnt=0;
|
|
SetSourceFileInfo(l,temph);
|
|
temph->next=*temph1;
|
|
*temph1=temph;
|
|
temph->user0=0;
|
|
}
|
|
|
|
if (temph->type & HTT_SYS_SYMBOL) {
|
|
if (!(temph->type & HTT_LITERAL) &&
|
|
!(temph->type & HTT_IMPORT))
|
|
l->absolute_address_cnt++;
|
|
if (temph->type & (HTT_UNRESOLVED_LOCAL|HTT_UNRESOLVED_GLBL)) {
|
|
templu=MAlloc(sizeof(LexUndefEntry));
|
|
templu->hash=temph;
|
|
templu->next=l->undef_hash_entry;
|
|
l->undef_hash_entry=templu;
|
|
if (temph->type & HTT_UNRESOLVED_LOCAL)
|
|
l->flags|=LF_UNRESOLVED_LOCAL;
|
|
else
|
|
l->flags|=LF_UNRESOLVED_GLBL;
|
|
CbAddIc(l,EC_U8,&temph->user0,sys_internal_types[IT_U4]);
|
|
CbAddIc(l,EC_DEREF_U4,0,sys_internal_types[IT_U4]);
|
|
} else {
|
|
if (l->a && !(temph->type & HTT_LITERAL))
|
|
CbAddIc(l,EC_ABSOLUTE_ADDRESS,temph->user0,sys_internal_types[IT_U4]);
|
|
else
|
|
CbAddIc(l,EC_U8,temph->user0,sys_internal_types[IT_U4]);
|
|
}
|
|
Lex(l);
|
|
return PRST_CHECK_BINARY_OPS;
|
|
}
|
|
|
|
if (temph->type & HTT_FUNCTION) {
|
|
Lex(l); //skip fun name
|
|
CbPush(l);
|
|
templ=l->cb.cb_next;
|
|
l->cb.cb_next=NULL;
|
|
tempc=temph;
|
|
i=tempc->parameter_cnt;
|
|
tempm=tempc->member_list;
|
|
argc_cnt=0;
|
|
if (l->token!='(')
|
|
needs_right_paren=FALSE;
|
|
else {
|
|
Lex(l);
|
|
needs_right_paren=TRUE;
|
|
}
|
|
while (i--) {
|
|
if (l->token==',')
|
|
Lex(l);
|
|
CbInitOutPtrs(&l->cb);
|
|
if (tempm->flags & MLF_DEFAULT_AVAILABLE &&
|
|
(l->token==')' || !needs_right_paren))
|
|
CbAddIc(l,EC_U8,tempm->default_value,tempm->member_class);
|
|
else
|
|
if (!PrsParseExpression(l))
|
|
throw(EXCEPT_COMPILER,3);
|
|
else {
|
|
CbPush(l);
|
|
CbAddIc(l,0,0,0);
|
|
tempi=CmpOptPass1(l,NULL,FALSE);
|
|
CbPop(l);
|
|
tempc1=tempi->ic_class;
|
|
while (tempc1->return_class)
|
|
tempc1=tempc1->return_class;
|
|
tempc2=tempm->member_class;
|
|
while (tempc2->return_class)
|
|
tempc2=tempc2->return_class;
|
|
if (tempc2->sub_type==IT_DOUBLE &&
|
|
tempc1->sub_type!=IT_DOUBLE)
|
|
tempi->ic_flags|=ICF_TO_DOUBLE;
|
|
else
|
|
if (tempc2->sub_type!=IT_DOUBLE &&
|
|
tempc1->sub_type==IT_DOUBLE)
|
|
tempi->ic_flags|=ICF_TO_INT;
|
|
}
|
|
CbAddIc(l,0,0,0);
|
|
CbPush(l);
|
|
tempm=tempm->next;
|
|
}
|
|
if (tempm && tempm->flags & MLF_DOT_DOT_DOT) {
|
|
CbInitOutPtrs(&l->cb);
|
|
CbAddIc(l,EC_U8,0,tempm->member_class);
|
|
tempi=l->cb.cb_last_out_ptr;
|
|
CbAddIc(l,0,0,0);
|
|
CbPush(l);
|
|
if (needs_right_paren) {
|
|
if (l->token!=')') {
|
|
do {
|
|
if (l->token==',')
|
|
Lex(l);
|
|
CbInitOutPtrs(&l->cb);
|
|
if (!PrsParseExpression(l))
|
|
throw(EXCEPT_COMPILER,4);
|
|
CbAddIc(l,0,0,0);
|
|
CbPush(l);
|
|
argc_cnt++;
|
|
} while (l->token==',');
|
|
}
|
|
}
|
|
tempi->ic_data=argc_cnt++; //++ so add_esp latter works
|
|
}
|
|
if (needs_right_paren) {
|
|
if (l->token!=')')
|
|
PrsExcept(l,"ST_MISSING_RIGHT_PAREN");
|
|
Lex(l);
|
|
}
|
|
templ1=templ->cb_next;
|
|
templ->cb_next=l->cb.cb_next;
|
|
l->cb.cb_next=templ;
|
|
CbPop(l);
|
|
templ=l->cb.cb_next;
|
|
l->cb.cb_next=templ1;
|
|
while (templ) {
|
|
templ1=templ->cb_next;
|
|
CbAppend(l,templ);
|
|
templ=templ1;
|
|
}
|
|
if (Bt(&tempc->flags,Cf_INTERNAL))
|
|
CbAddIc(l,tempc->executable_address,0,tempc->return_class);
|
|
else if (Bt(&tempc->flags,Cf_EXTERN)) {
|
|
if (l->a)
|
|
CbAddIc(l,EC_CALL_INDIRECT2,tempc->executable_address,tempc->return_class);
|
|
else
|
|
CbAddIc(l,EC_CALL_INDIRECT2,&tempc->executable_address,tempc->return_class);
|
|
CbAddIc(l,EC_ADD_ESP32,(argc_cnt+tempc->parameter_cnt)<<3,tempc->return_class);
|
|
} else {
|
|
CbAddIc(l,EC_CALL,tempc->executable_address,tempc->return_class);
|
|
CbAddIc(l,EC_ADD_ESP32,(argc_cnt+tempc->parameter_cnt)<<3,tempc->return_class);
|
|
}
|
|
l->flags=(l->flags|LF_EAX) & ~(LF_ARRAY|LF_FUNCTION);
|
|
return PRST_UNARY_MODIFIERS;
|
|
}
|
|
if (temph->type & HTT_GLBL_VAR) {
|
|
tempg=temph;
|
|
tempc=tempg->var_class+sizeof(ClassStruct);
|
|
l->flags&=~(LF_EAX|LF_ARRAY|LF_FUNCTION);
|
|
if (tempg->cnt) {
|
|
tempc+=sizeof(ClassStruct);
|
|
l->flags|=LF_ARRAY;
|
|
}
|
|
if (tempg->flags & GVAF_FUNCTION) {
|
|
//TODO:Not implemented
|
|
l->flags|=LF_FUNCTION;
|
|
}
|
|
if (l->a) {
|
|
if (tempg->flags & GVAF_EXTERN) { //TODO: Untested
|
|
CbAddIc(l,EC_U8,&tempg->data_address,tempc);
|
|
CbAddIc(l,EC_DEREF_U4,0,tempc);
|
|
} else {
|
|
CbAddIc(l,EC_ABSOLUTE_ADDRESS,tempg->data_address,tempc);
|
|
if (tempg->flags & GVAF_IMPORT)
|
|
CbAddIc(l,EC_DEREF_U4,0,tempc);
|
|
}
|
|
} else {
|
|
if (tempg->flags & GVAF_EXTERN) {
|
|
CbAddIc(l,EC_U8,&tempg->data_address,tempc);
|
|
CbAddIc(l,EC_DEREF_U4,0,tempc);
|
|
} else
|
|
CbAddIc(l,EC_U8,tempg->data_address,tempc);
|
|
}
|
|
Lex(l);
|
|
return PRST_UNARY_MODIFIERS;
|
|
}
|
|
if (!(temph->type & HTT_KEYWORD))
|
|
PrsExcept(l,"ST_MISSING_EXPRESSION");
|
|
if (temph->user0==KW_SIZEOF) {
|
|
if (Lex(l)!='(') PrsExcept(l,"ST_EXPECTING_LEFT_PAREN");
|
|
if (Lex(l)!=TK_IDENT)
|
|
PrsExcept(l,"ST_INVALID_CLASS");
|
|
if (tempm=l->local_var_entry) {
|
|
tempc=tempm->member_class;
|
|
i=(tempm->cnt) ? tempm->cnt:1;
|
|
CbAddIc(l,EC_U8,tempc->size*i,sys_internal_types[IT_U4]);
|
|
} else {
|
|
tempc=l->hash_entry;
|
|
if (!tempc || !(tempc->type & (HTT_CLASS|HTT_INTERNAL_TYPE|HTT_GLBL_VAR)))
|
|
PrsExcept(l,"ST_INVALID_CLASS");
|
|
CbAddIc(l,EC_U8,tempc->size,sys_internal_types[IT_U4]);
|
|
} //TODO: should allow '*' and '.member', etc;
|
|
if (Lex(l)!=')')
|
|
PrsExcept(l,"ST_MISSING_RIGHT_PAREN");
|
|
Lex(l);
|
|
return PRST_CHECK_BINARY_OPS;
|
|
} else if (temph->user0==KW_OFFSET) {
|
|
if (Lex(l)!='(') PrsExcept(l,"ST_EXPECTING_LEFT_PAREN");
|
|
if (Lex(l)!=TK_IDENT)
|
|
PrsExcept(l,"ST_INVALID_CLASS");
|
|
if (tempm=l->local_var_entry)
|
|
tempc=tempm->member_class;
|
|
else {
|
|
tempc=l->hash_entry;
|
|
if (!tempc || !(tempc->type & (HTT_CLASS|HTT_GLBL_VAR)))
|
|
PrsExcept(l,"ST_INVALID_CLASS");
|
|
else if (tempc->type & HTT_GLBL_VAR) {
|
|
tempg=tempc;
|
|
tempc=tempg->var_class;
|
|
}
|
|
}
|
|
if (Lex(l)!='.')
|
|
PrsExcept(l,"ST_EXPECTING_DOT");
|
|
if (Lex(l)!=TK_IDENT)
|
|
PrsExcept(l,"ST_INVALID_MEMBER");
|
|
if (!(tempm=FindMember(l->ident,tempc)))
|
|
PrsExcept(l,"ST_INVALID_MEMBER");
|
|
CbAddIc(l,EC_U8,tempm->offset,sys_internal_types[IT_U4]);
|
|
if (Lex(l)!=')')
|
|
PrsExcept(l,"ST_MISSING_RIGHT_PAREN");
|
|
Lex(l);
|
|
return PRST_CHECK_BINARY_OPS;
|
|
}
|
|
PrsExcept(l,"ST_MISSING_EXPRESSION");
|
|
}
|
|
|
|
U8 PrsUnaryModifier(LexStruct *l,ParseStack *ps)
|
|
{
|
|
I8 i,j;
|
|
LexCbStack *templ,*templ2,*templl;
|
|
ClassStruct *tempc,*tempc1;
|
|
MemberListStruct *tempm;
|
|
IntermediateCode *tempi;
|
|
if (l->flags & LF_ASM_EXPRESSIONS)
|
|
return PRST_CHECK_BINARY_OPS;
|
|
if (l->token==TK_DEREFERRENCE) {
|
|
tempi=l->cb.cb_last_out_ptr;
|
|
if (!(l->flags & (LF_EAX | LF_ARRAY))) {
|
|
tempc=tempi->ic_class-sizeof(ClassStruct);
|
|
CbAddIc(l,EC_DEREF_U4+0x10000,0,tempc);
|
|
} else
|
|
tempi->ic_class-=sizeof(ClassStruct);
|
|
}
|
|
if (l->token=='.' || l->token==TK_DEREFERRENCE) {
|
|
tempi=l->cb.cb_last_out_ptr;
|
|
tempc=tempi->ic_class;
|
|
if (!(l->flags & LF_EAX))
|
|
tempc-=sizeof(ClassStruct);
|
|
if (!(tempc->type & HTT_CLASS))
|
|
PrsExcept(l,"ST_INVALID_CLASS");
|
|
if (Lex(l)!=TK_IDENT)
|
|
PrsExcept(l,"ST_INVALID_MEMBER");
|
|
if (!(tempm=FindMember(l->ident,tempc)))
|
|
PrsExcept(l,"ST_INVALID_MEMBER");
|
|
Lex(l); //skip member name
|
|
tempc1=tempm->member_class+sizeof(ClassStruct);
|
|
CbAddIc(l,EC_U8,tempm->offset,tempc1);
|
|
l->flags&=~(LF_EAX|LF_ARRAY|LF_FUNCTION);
|
|
if (tempm->cnt) {
|
|
tempc1+=sizeof(ClassStruct);
|
|
l->flags|=LF_ARRAY;
|
|
}
|
|
if(tempm->flags & MLF_FUNCTION) {
|
|
PrsPush(ps,0);
|
|
PrsPush(ps,tempm->parameter_cnt);
|
|
l->flags|=LF_FUNCTION;
|
|
}
|
|
CbAddIc(l,EC_ADDITION,0,tempc1);
|
|
return PRST_UNARY_MODIFIERS;
|
|
}
|
|
if (l->token==TK_CAST) {
|
|
if (Lex(l)!='(')
|
|
PrsExcept(l,"ST_EXPECTING_LEFT_PAREN");
|
|
if (Lex(l)!=TK_IDENT)
|
|
PrsExcept(l,"ST_INVALID_CLASS");
|
|
tempc=l->hash_entry;
|
|
if (!tempc || !(tempc->type & (HTT_CLASS|HTT_INTERNAL_TYPE)))
|
|
PrsExcept(l,"ST_INVALID_CLASS");
|
|
while (Lex(l)=='*')
|
|
tempc+=sizeof(ClassStruct);
|
|
tempc+=sizeof(ClassStruct);
|
|
tempi=l->cb.cb_last_out_ptr;
|
|
tempi->ic_class=tempc;
|
|
if (l->token!=')')
|
|
PrsExcept(l,"ST_MISSING_RIGHT_PAREN");
|
|
Lex(l);
|
|
return PRST_UNARY_MODIFIERS;
|
|
}
|
|
if (l->token=='[') {
|
|
Lex(l);
|
|
tempi=l->cb.cb_last_out_ptr;
|
|
if (!(l->flags & (LF_ARRAY | LF_EAX))) {
|
|
tempc=tempi->ic_class-sizeof(ClassStruct);
|
|
while (!(tempc->type & HTT_INTERNAL_TYPE) && tempc->return_class)
|
|
tempc=tempc->return_class;
|
|
if (tempc->type==HTT_INTERNAL_TYPE)
|
|
i=EC_DEREF_U8+0x10000+it_to_ec_offset[tempc->sub_type];
|
|
else
|
|
i=EC_DEREF_U4+0x10000;
|
|
CbAddIc(l,i,0,tempc);
|
|
} else {
|
|
tempc=tempi->ic_class;
|
|
if (!(l->flags & LF_EAX))
|
|
tempc-=sizeof(ClassStruct);
|
|
}
|
|
tempc1=tempc-sizeof(ClassStruct);
|
|
CbAddIc(l,EC_U8,tempc1->size,tempc);
|
|
if (!PrsParseExpression(l))
|
|
throw(EXCEPT_COMPILER,5);
|
|
if (l->token!=']')
|
|
PrsExcept(l,"ST_MISSING_RIGHT_BRACKET");
|
|
Lex(l); //skip ]
|
|
CbAddIc(l,EC_MULTIPLICATION,0,tempc);
|
|
CbAddIc(l,EC_ADDITION,0,tempc);
|
|
l->flags&=~(LF_EAX|LF_ARRAY);
|
|
return PRST_UNARY_MODIFIERS;
|
|
}
|
|
if (l->token=='(' && l->flags & LF_FUNCTION) {
|
|
tempi=l->cb.cb_last_out_ptr;
|
|
if (!(l->flags & (LF_EAX | LF_ARRAY))) {
|
|
tempc=tempi->ic_class-sizeof(ClassStruct);
|
|
CbAddIc(l,EC_DEREF_U4+0x10000,0,tempc);
|
|
} else {
|
|
tempi->ic_class=tempi->ic_class-sizeof(ClassStruct);
|
|
tempc=tempi;
|
|
}
|
|
i=PrsPop(ps);
|
|
PrsPop(ps);
|
|
j=i;
|
|
Lex(l); //skip '('
|
|
CbPush(l);
|
|
templ=l->cb.cb_next;
|
|
l->cb.cb_next=NULL;
|
|
while (i--) {
|
|
if (l->token==',')
|
|
Lex(l);
|
|
CbInitOutPtrs(&l->cb);
|
|
if (!PrsParseExpression(l))
|
|
throw(EXCEPT_COMPILER,6);
|
|
CbAddIc(l,0,0,0);
|
|
CbPush(l);
|
|
}
|
|
if (l->token!=')')
|
|
PrsExcept(l,"ST_MISSING_RIGHT_PAREN");
|
|
Lex(l); //skip ')'
|
|
templl=templ->cb_next;
|
|
templ->cb_next=l->cb.cb_next;
|
|
l->cb.cb_next=templ;
|
|
CbPop(l);
|
|
templ=l->cb.cb_next;
|
|
l->cb.cb_next=templl;
|
|
while (templ) {
|
|
templ2=templ->cb_next;
|
|
CbAppend(l,templ);
|
|
templ=templ2;
|
|
}
|
|
CbAddIc(l,EC_CALL_INDIRECT,j<<3,tempc);
|
|
CbAddIc(l,EC_ADD_ESP32,j<<3+8,tempc);
|
|
l->flags=(l->flags | LF_EAX)&~(LF_ARRAY | LF_FUNCTION);
|
|
return PRST_UNARY_MODIFIERS;
|
|
}
|
|
if (l->token==TK_PLUS_PLUS) {
|
|
Lex(l);
|
|
l->flags|=LF_POSTINC;
|
|
return PRST_DEREFERRENCE;
|
|
}
|
|
if (l->token==TK_MINUS_MINUS) {
|
|
Lex(l);
|
|
l->flags|=LF_POSTDEC;
|
|
return PRST_DEREFERRENCE;
|
|
}
|
|
return PRST_DEREFERRENCE;
|
|
}
|
|
|
|
U8 PrsDereferrence(LexStruct *l,ParseStack *ps)
|
|
{
|
|
I8 i;
|
|
ClassStruct *tempc;
|
|
IntermediateCode *tempi;
|
|
if (l->flags & LF_FUNCTION) {
|
|
i=PrsPop(ps);
|
|
tempc=PrsPop(ps);
|
|
}
|
|
if (l->flags & LF_EAX)
|
|
return PRST_CHECK_BINARY_OPS;
|
|
tempi=l->cb.cb_last_out_ptr;
|
|
tempc=tempi->ic_class-sizeof(ClassStruct);
|
|
if (l->flags & LF_ARRAY) {
|
|
tempi->ic_class=tempc;
|
|
return PRST_CHECK_BINARY_OPS;
|
|
}
|
|
|
|
if (l->flags & LF_PREINC) {
|
|
l->flags&=~LF_PREINC;
|
|
i=EC_PP_U8;
|
|
} else if (l->flags & LF_PREDEC) {
|
|
l->flags&=~LF_PREDEC;
|
|
i=EC_MM_U8;
|
|
} else if (l->flags & LF_POSTINC) {
|
|
l->flags&=~LF_POSTINC;
|
|
i=EC_U8_PP;
|
|
} else if (l->flags & LF_POSTDEC) {
|
|
l->flags&=~LF_POSTDEC;
|
|
i=EC_U8_MM;
|
|
} else
|
|
i=EC_DEREF_U8;
|
|
|
|
while (tempc->return_class)
|
|
tempc=tempc->return_class;
|
|
if (tempc->type & HTT_INTERNAL_TYPE)
|
|
i+=it_to_ec_offset[tempc->sub_type];
|
|
else
|
|
i+=it_to_ec_offset[IT_U4];
|
|
CbAddIc(l,i+0x10000,0,tempc);
|
|
return PRST_CHECK_BINARY_OPS;
|
|
}
|
|
|
|
U1 *CompileExpression(LexStruct *l)
|
|
{
|
|
U1 *result;
|
|
U8 size;
|
|
DbgInfo *dbg=NULL;
|
|
CbPush(l);
|
|
CbInitOutPtrs(&l->cb);
|
|
if (PrsParseExpression(l,TRUE)) {
|
|
CbAddIc(l,EC_RET,0,0);
|
|
CbAddIc(l,0,0,0);
|
|
result=CbCompile(l,NULL,&size,&dbg);
|
|
} else
|
|
result=NULL;
|
|
CbPop(l);
|
|
Free(dbg);
|
|
return result;
|
|
}
|
|
|
|
BoolU4 GetExpression(LexStruct *l,U1 **e) //FALSE=no err
|
|
{
|
|
*e=CompileExpression(l);
|
|
if (*e)
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
I8 Expression(LexStruct *l) //FALSE=no err
|
|
{
|
|
I8 result;
|
|
U1 *e=CompileExpression(l);
|
|
if (e) {
|
|
result=Run(e);
|
|
DelExpression(e);
|
|
} else
|
|
result=0;
|
|
return result;
|
|
}
|