Use my tools, if you like. I use my tools. You can download them from
Code: Select all
$PJ,"Project: OSMain2.SPZ","/LT/OSMain2/OSMain2.SPZ"$
LTextern CP_PRSPUSH void PrsPush(ParseStack *ps,I8 val);
LTextern CP_PRSPOP I8 PrsPop(ParseStack *ps);
void ParenWarning(LexStruct *lx)
{
if (Bt(&lx->opts,OPTf_PAREN_WARN) &&
!(lx->cur_lfn->flags&LFSF_IS_DEFINE))
PutLexWarn(lx,"ST_UNNECESSARY_PARENTHESIS");
}
#define PRST_UNARY_TERM 0
#define PRST_UNARY_MODIFIERS 1
#define PRST_DEREFERRENCE 2
#define PRST_CHECK_BINARY_OPS 3
BoolI8 PrsParseExpression(LexStruct *lx,I8 *_max_precedence,BoolI1 end_exp)
{
BoolI1 result=TRUE,question_clause=FALSE,
cont_unary,cont_check_binary_ops,is_lower,div_sizeof;
I8 i,j,k,old_flags=lx->flags,old_start_line=lx->expression_start_line,
max_precedence=PREC_NULL,unary_precedence,
left_precedence=PREC_MAX;
IntermediateCode *tempi,*tempi_first=lx->cb.cb_out_ptr,*tempi2;
ClassStruct *tempc,*tempcc;
ParseStack *ps=MAlloc(sizeof(ParseStack));
MemberListStruct *local_var;
ArrayDimStruct *tempad=NULL;
if (!(lx->flags&LF_INSIDE_EXPRESSION))
lx->expression_start_line=lx->start_line_num;
lx->flags|=LF_INSIDE_EXPRESSION;
ps->ptr=0;
PrsPush(ps,0); //terminate
PrsPush(ps,0); //terminate
if (Btr(&lx->flags,Lf_BY_ADDRESS)) {
PrsPush(ps,tempc);
PrsPush(ps,unary_ops_table['&']);
}
try {
do {
unary_precedence=PREC_NULL;
lx->flags&=~(LF_PREINC+LF_PREDEC+LF_POSTINC+LF_POSTDEC+LF_FUNCTION);
do i=PrsUnaryTerm(lx,ps,&local_var,&tempad,&max_precedence,&unary_precedence);
while (i==PRST_UNARY_TERM);
while (i==PRST_UNARY_MODIFIERS)
i=PrsUnaryModifier(lx,ps,&local_var,&tempad,&max_precedence);
if (i==PRST_DEREFERRENCE)
PrsDereferrence(lx,ps);
//Check for binary Ops
do {
i=PrsPop(ps);
tempc=PrsPop(ps);
if (i && i.u1[2]<=PREC_UNARY+PRECF_NON_ASSOCIATIVE) {
tempi=lx->cb.cb_last_out_ptr;
i=i.u2[0];
tempc=tempi->ic_class;
if (Bt(deref_bitmap,i) && tempc->ptr_cnt) {
tempc--;
while (tempc->return_class)
tempc=tempc->return_class;
i=EC_DEREF+PREC_UNARY<<16;
} else {
if (i==EC_ADDRESS) {
if (!(lx->flags & (LF_RAX|LF_ARRAY))) {
j=tempi->ic_opcode;
if (!Bt(deref_bitmap,j))
PrsExcept(lx,"ST_INVALID_LVALUE");
tempi->ic_opcode=EC_NOP;
tempc++;
} else {
if (lx->flags & LF_ARRAY)
tempc++;
}
}
}
CbAddIc(lx,i,0,tempc);
cont_check_binary_ops=TRUE;
} else {
PrsPush(ps,tempc);
PrsPush(ps,i);
i=lx->token;
if (lx->opts&1<<OPTf_STD_C)
k=c_binary_ops_table[i];
else
k=binary_ops_table[i];
switch (k.u2[0]) {
case EC_ADD:
case EC_SUB:
tempi=lx->cb.cb_last_out_ptr;
if (!tempi->ic_class->ptr_cnt &&
tempi->ic_class->sub_type!=IT_DOUBLE) {
CbAddIc(lx,EC_SIZEOF,1,sys_internal_types[IT_I8]);
CbAddIc(lx,EC_MUL,0,sys_internal_types[IT_I8]);
}
break;
case EC_AND_AND:
case EC_OR_OR:
CbAddIc(lx,EC_NOP,0,sys_internal_types[IT_I8]);
break;
case EC_QUESTION:
question_clause=TRUE;
break;
case EC_COLON:
if (!question_clause)
k=0;
else
question_clause=FALSE;
break;
}
if (k.u1[2]==PREC_NULL) {
if (unary_precedence>PREC_UNARY+PRECF_NON_ASSOCIATIVE) {
if (unary_precedence&PRECF_NON_ASSOCIATIVE ||
left_precedence&PRECF_NON_ASSOCIATIVE) {
if (unary_precedence&~PRECF_NON_ASSOCIATIVE<left_precedence&~PRECF_NON_ASSOCIATIVE)
ParenWarning(lx);
} else {
if (unary_precedence&~PRECF_NON_ASSOCIATIVE<=left_precedence&~PRECF_NON_ASSOCIATIVE)
ParenWarning(lx);
}
}
cont_check_binary_ops=FALSE;
cont_unary=FALSE; //DONE
} else {
Lex(lx); //skip op
if (unary_precedence>PREC_UNARY+PRECF_NON_ASSOCIATIVE) {
if (unary_precedence&PRECF_NON_ASSOCIATIVE ||
left_precedence&PRECF_NON_ASSOCIATIVE) {
if (unary_precedence&~PRECF_NON_ASSOCIATIVE<left_precedence&~PRECF_NON_ASSOCIATIVE &&
unary_precedence&~PRECF_NON_ASSOCIATIVE<=k.u1[2]&~PRECF_NON_ASSOCIATIVE)
ParenWarning(lx);
} else {
if (unary_precedence&~PRECF_NON_ASSOCIATIVE<=left_precedence&~PRECF_NON_ASSOCIATIVE &&
unary_precedence&~PRECF_NON_ASSOCIATIVE<=k.u1[2]&~PRECF_NON_ASSOCIATIVE)
ParenWarning(lx);
}
}
if (k.u1[2]>max_precedence)
max_precedence=k.u1[2];
left_precedence=k.u1[2];
if (Bt(assign_bitmap,k.u2[0])) {
tempi=lx->cb.cb_last_out_ptr;
tempc=tempi->ic_class;
j=tempi->ic_opcode;
if (!Bt(deref_bitmap,j))
PrsExcept(lx,"ST_INVALID_LVALUE");
tempi->ic_opcode=EC_NOP;
while (tempc->return_class)
tempc=tempc->return_class;
k.u1[2]=PREC_ASSIGN;
#assert (PREC_ASSIGN==C_PREC_ASSIGN)
}
do {
i=PrsPop(ps); //pop ops of higher prec
tempc=PrsPop(ps);
is_lower=FALSE;
if (i) {
if (k.u1[2]&~PRECF_NON_ASSOCIATIVE==i.u1[2]&~PRECF_NON_ASSOCIATIVE) {
if (!Bt(assign_bitmap,k.u2[0]) ||
!Bt(assign_bitmap,i.u2[0]))
is_lower=TRUE;
} else if (k.u1[2]&~PRECF_NON_ASSOCIATIVE>i.u1[2]&~PRECF_NON_ASSOCIATIVE)
is_lower=TRUE;
}
div_sizeof=FALSE;
if (is_lower) {
switch (i.u2[0]) {
case EC_ADD:
if (tempc->ptr_cnt) {
tempi=lx->cb.cb_last_out_ptr;
if (!tempi->ic_class->ptr_cnt &&
tempi->ic_class->sub_type!=IT_DOUBLE) {
CbAddIc(lx,EC_SIZEOF,1,sys_internal_types[IT_I8]);
CbAddIc(lx,EC_MUL,0,sys_internal_types[IT_I8]);
}
}
break;
case EC_SUB:
if (tempc->ptr_cnt) {
tempi=lx->cb.cb_last_out_ptr;
if (!tempi->ic_class->ptr_cnt &&
tempi->ic_class->sub_type!=IT_DOUBLE) {
CbAddIc(lx,EC_SIZEOF,1,sys_internal_types[IT_I8]);
CbAddIc(lx,EC_MUL,0,sys_internal_types[IT_I8]);
} else
div_sizeof=TRUE;
}
break;
case EC_AND_AND:
case EC_OR_OR:
CbAddIc(lx,EC_NOP,0,sys_internal_types[IT_I8]);
break;
case EC_ADD_EQUAL:
case EC_SUB_EQUAL:
if (tempc->ptr_cnt) {
CbAddIc(lx,EC_SIZEOF,1,sys_internal_types[IT_I8]);
CbAddIc(lx,EC_MUL,0,sys_internal_types[IT_I8]);
}
break;
}
CbAddIc(lx,i,0,tempc);
tempi2=lx->cb.cb_last_out_ptr;
if (i.u1[3]&ECF_HAS_PUSH_CMP) {
tempi2->ic_flags|=ICF_POP_CMP;
CbAddIc(lx,EC_NOP,0,sys_internal_types[IT_I8]);
CbAddIc(lx,EC_AND_AND,0,sys_internal_types[IT_I8]);
tempi=lx->cb.cb_last_out_ptr;
tempi->ic_flags|=ICF_POP_CMP;
}
if (Bt(cmp_bitmap,k.u2[0]) &&
Bt(cmp_bitmap,i.u2[0]) && !(lx->opts&1<<OPTf_STD_C)) {
tempi2->ic_flags|=ICF_PUSH_CMP;
CbAddIc(lx,EC_NOP,0,sys_internal_types[IT_I8]);
CbAddIc(lx,EC_PUSH_CMP,0,tempc);
k.u1[3]|=ECF_HAS_PUSH_CMP;
} else if (k.u2[0]==EC_AND_AND || k.u2[0]==EC_OR_OR)
CbAddIc(lx,EC_NOP,0,sys_internal_types[IT_I8]);
if (div_sizeof) {
tempcc=tempc-1;
if (tempcc->size!=1) {
CbAddIc(lx,EC_IMM,tempcc->size,sys_internal_types[IT_I8]);
CbAddIc(lx,EC_DIV,0,sys_internal_types[IT_I8]);
tempc=sys_internal_types[IT_I8];
}
}
} else {
PrsPush(ps,tempc);
PrsPush(ps,i);
tempi=lx->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);
div_sizeof=FALSE;
switch (i.u2[0]) {
case 0:
goto done3;
case EC_ADD:
if (tempc->ptr_cnt) {
tempi=lx->cb.cb_last_out_ptr;
if (!tempi->ic_class->ptr_cnt &&
tempi->ic_class->sub_type!=IT_DOUBLE) {
CbAddIc(lx,EC_SIZEOF,1,sys_internal_types[IT_I8]);
CbAddIc(lx,EC_MUL,0,sys_internal_types[IT_I8]);
}
}
break;
case EC_SUB:
if (tempc->ptr_cnt) {
tempi=lx->cb.cb_last_out_ptr;
if (tempi->ic_class->sub_type!=IT_DOUBLE) {
if (!tempi->ic_class->ptr_cnt) {
CbAddIc(lx,EC_SIZEOF,1,sys_internal_types[IT_I8]);
CbAddIc(lx,EC_MUL,0,sys_internal_types[IT_I8]);
} else
div_sizeof=TRUE;
}
}
break;
case EC_AND_AND:
case EC_OR_OR:
CbAddIc(lx,EC_NOP,0,sys_internal_types[IT_I8]);
break;
case EC_ADD_EQUAL:
case EC_SUB_EQUAL:
if (tempc->ptr_cnt) {
CbAddIc(lx,EC_SIZEOF,1,sys_internal_types[IT_I8]);
CbAddIc(lx,EC_MUL,0,sys_internal_types[IT_I8]);
}
break;
}
CbAddIc(lx,i,0,tempc);
if (i.u1[3]&ECF_HAS_PUSH_CMP) {
tempi=lx->cb.cb_last_out_ptr;
tempi->ic_flags|=ICF_POP_CMP;
CbAddIc(lx,EC_NOP,0,sys_internal_types[IT_I8]);
CbAddIc(lx,EC_AND_AND,0,sys_internal_types[IT_I8]);
tempi=lx->cb.cb_last_out_ptr;
tempi->ic_flags|=ICF_POP_CMP;
}
if (div_sizeof) {
tempcc=tempc-1;
if (tempcc->size!=1) {
CbAddIc(lx,EC_IMM,tempcc->size,sys_internal_types[IT_I8]);
CbAddIc(lx,EC_DIV,0,sys_internal_types[IT_I8]);
tempc=sys_internal_types[IT_I8];
}
}
}
done3:
} catch {
if (Fs->except_argc>0) {
if (Fs->except_argv[0]==EXCEPT_COMPILER) {
lx->statement_cnt=0;
lx->braces_cnt=0;
lx->last_indent_level=lx->indent_level=0;
result=FALSE;
Fs->catch_except=TRUE;
}
}
}
Free(ps);
if (end_exp && result)
CbAddIc(lx,EC_END_EXP,0,0);
if (_max_precedence)
*_max_precedence=max_precedence;
lx->flags=lx->flags&~LF_INSIDE_EXPRESSION |
old_flags&LF_INSIDE_EXPRESSION;
lx->expression_start_line=old_start_line;
return result;
}
U8 PrsUnaryTerm(LexStruct *lx,ParseStack *ps,MemberListStruct **local_var,ArrayDimStruct **tempad,
I8 *max_precedence,I8 *unary_precedence)
{
I8 i,*i_ptr,j;
I8 argc_cnt,size;
U8 d;
SysSymHashEntry *tempss;
ClassStruct *tempc,*tempc1,*tempc2;
GlblVarStruct *tempg;
MemberListStruct *tempm;
LexUndefEntry *templu;
CbMiscStruct *tempmc;
IntermediateCode *tempi;
BoolI1 needs_right_paren,is_first_arg,paren_warn;
LexCbStack *templ,*templ1;
*local_var=NULL;
switch (lx->token) {
case TK_INTEGER:
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
if (lx->cur_i<0)
CbAddIc(lx,EC_IMM,lx->cur_i,sys_internal_types[IT_U8]);
else
CbAddIc(lx,EC_IMM,lx->cur_i,sys_internal_types[IT_I8]);
Lex(lx);
return PRST_CHECK_BINARY_OPS;
case TK_DOUBLE:
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
i_ptr=&lx->cur_d;
CbAddIc(lx,EC_DOUBLE,*i_ptr,sys_internal_types[IT_DOUBLE]);
Lex(lx);
return PRST_CHECK_BINARY_OPS;
case TK_STR:
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
d=LexExtendStr(lx,&size);
tempmc=CbMiscNew(lx,CBMT_STR_CONST);
CbAddIc(lx,EC_STR_CONST,tempmc,sys_internal_types[IT_I1]+1);
tempmc->st_len=size;
tempmc->str=d;
lx->flags|=LF_HAS_MISC_DATA;
return PRST_CHECK_BINARY_OPS;
case TK_INSERT_BINARY:
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
d=lx->ident;
size=lx->ident_len;
lx->ident=NULL;
Lex(lx);
tempmc=CbMiscNew(lx,CBMT_STR_CONST);
CbAddIc(lx,EC_STR_CONST,tempmc,sys_internal_types[IT_I1]+1);
tempmc->st_len=size;
tempmc->str=d;
lx->flags|=LF_HAS_MISC_DATA;
return PRST_CHECK_BINARY_OPS;
case TK_INSERT_BINARY_TYPE:
case TK_INSERT_BINARY_SIZE:
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
CbAddIc(lx,EC_IMM,lx->cur_i,sys_internal_types[IT_U8]);
Lex(lx);
return PRST_CHECK_BINARY_OPS;
case '(':
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
Lex(lx); //Skip (
if (lx->cur_lfn->flags&LFSF_IS_DEFINE ||
*unary_precedence!=PREC_NULL)
paren_warn=FALSE;
else
paren_warn=TRUE;
*unary_precedence=PREC_NULL;
if (!PrsParseExpression(lx,unary_precedence,FALSE))
throw(EXCEPT_COMPILER,2);
if (!paren_warn)
*unary_precedence=PREC_NULL;
else if (*unary_precedence==PREC_TERM)
ParenWarning(lx);
if (lx->token!=')')
PrsExcept(lx,"ST_MISSING_RIGHT_PAREN");
Lex(lx); //skip )
lx->flags= lx->flags & ~(LF_ARRAY+LF_FUNCTION) | LF_RAX;
return PRST_UNARY_MODIFIERS;
}
i=unary_ops_table[lx->token];
if (i.u1[2]) {
if (i.u1[2]>*max_precedence)
*max_precedence=i.u1[2];
if (i.u1[2]>*unary_precedence)
*unary_precedence=i.u1[2];
Lex(lx); //Skip op
if (i.u2[0]==EC_ADDRESS && lx->token==TK_IDENT) {
if (tempc=lx->hash_entry) {
if (tempc->s.h.type & HTT_FUNCTION) {
if (!Bt(tempc->flags,Cf_INTERNAL)) {
Lex(lx); //skip fun name
if (Bt(tempc->flags,Cf_EXTERN)) {
if (lx->flags&LF_STATIC_COMPILE)
PrsExcept(lx,"ST_ADDRESS_EXTERN");
else
CbAddIc(lx,EC_IMM,
&tempc->executable_address,sys_internal_types[IT_PTR]);
CbAddIc(lx,EC_DEREF,0,
sys_internal_types[IT_PTR]);
} else {
if (lx->flags&LF_STATIC_COMPILE)
CbAddIc(lx,EC_ABSOLUTE_ADDRESS,
tempc->executable_address,sys_internal_types[IT_PTR]);
else
CbAddIc(lx,EC_IMM,
tempc->executable_address,sys_internal_types[IT_PTR]);
}
return PRST_CHECK_BINARY_OPS;
}
}
}
}
PrsPush(ps,tempc);
PrsPush(ps,i);
return PRST_UNARY_TERM;
}
if (lx->token=='+') {
if (PREC_UNARY>*max_precedence)
*max_precedence=PREC_UNARY;
if (PREC_UNARY>*unary_precedence)
*unary_precedence=PREC_UNARY;
Lex(lx);
return PRST_UNARY_TERM;
}
if (lx->token!=TK_IDENT) {
if (lx->token==TK_PLUS_PLUS) {
if (PREC_UNARY>*max_precedence)
*max_precedence=PREC_UNARY;
if (PREC_UNARY>*unary_precedence)
*unary_precedence=PREC_UNARY;
Lex(lx);
lx->flags|=LF_PREINC;
return PRST_UNARY_TERM;
}
if (lx->token==TK_MINUS_MINUS) {
if (PREC_UNARY>*max_precedence)
*max_precedence=PREC_UNARY;
if (PREC_UNARY>*unary_precedence)
*unary_precedence=PREC_UNARY;
Lex(lx);
lx->flags|=LF_PREDEC;
return PRST_UNARY_TERM;
}
if (lx->token=='$$') {
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
Lex(lx);
if (lx->flags & LF_ASM_EXPRESSIONS) {
lx->absolute_address_cnt++;
if (lx->flags&LF_STATIC_COMPILE)
CbAddIc(lx,EC_ABSOLUTE_ADDRESS,lx->instruction_ptr,sys_internal_types[IT_PTR]);
else
CbAddIc(lx,EC_IMM,lx->instruction_ptr,sys_internal_types[IT_PTR]);
} else
CbAddIc(lx,EC_RIP,0,sys_internal_types[IT_PTR]);
return PRST_CHECK_BINARY_OPS;
}
PrsExcept(lx,"ST_MISSING_EXPRESSION");
}
if (tempm=lx->local_var_entry) {
lx->local_var_entry->use_cnt++;
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
lx->flags&=~(LF_RAX+LF_ARRAY+LF_FUNCTION);
tempc=tempm->member_class+1;
if (tempm->flags & MLF_FUNCTION) {
lx->flags|=LF_FUNCTION;
PrsPush(ps,tempm->return_class);
PrsPush(ps,tempm->arg_cnt);
}
if (tempm->dim.next) {
*tempad=tempm->dim.next;
lx->flags|=LF_ARRAY;
}
if (tempm->flags&MLF_STATIC) {
if (lx->flags&LF_STATIC_COMPILE)
CbAddIc(lx,EC_ABSOLUTE_ADDRESS,tempm->static_data,tempc);
else
CbAddIc(lx,EC_IMM,tempm->static_data,tempc);
} else {
CbAddIc(lx,EC_RBP,0,tempc);
CbAddIc(lx,EC_IMM,tempm->offset,tempc);
CbAddIc(lx,EC_ADD,0,tempc);
}
Lex(lx); //skip var name
*local_var=tempm;
return PRST_UNARY_MODIFIERS;
}
if (!(tempss=lx->hash_entry)) {
if (!(lx->flags & LF_ASM_EXPRESSIONS))
PrsExcept(lx,"ST_INVALID_LVALUE");
tempss=MAllocZ(sizeof(SysSymHashEntry));
tempss->s.h.str=lx->ident;
lx->ident=NULL;
if (*tempss->s.h.str=='@' &&
tempss->s.h.str[1]=='@') {
tempss->s.h.type=HTT_SYS_SYMBOL | HTT_UNRESOLVED_LOCAL;
if (IsReplaceSyms)
ReplaceSysHashEntry(tempss,lx->local_hash_table);
else
AddSysHashEntry(tempss,lx->local_hash_table);
} else {
tempss->s.h.type=HTT_SYS_SYMBOL | HTT_UNRESOLVED_GLBL;
if (IsReplaceSyms)
ReplaceSysHashEntry(tempss,lx->glbl_hash_table);
else
AddSysHashEntry(tempss,lx->glbl_hash_table);
}
}
if (tempss->s.h.type & HTT_SYS_SYMBOL) {
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
if (!(tempss->s.h.type & HTT_LITERAL) &&
!(tempss->s.h.type & HTT_IMPORT))
lx->absolute_address_cnt++;
if (tempss->s.h.type & (HTT_UNRESOLVED_LOCAL|HTT_UNRESOLVED_GLBL)) {
templu=MAlloc(sizeof(LexUndefEntry));
templu->hash=tempss;
templu->next=lx->undef_hash_entry;
lx->undef_hash_entry=templu;
if (tempss->s.h.type & HTT_UNRESOLVED_LOCAL)
lx->flags|=LF_UNRESOLVED_LOCAL;
else
lx->flags|=LF_UNRESOLVED_GLBL;
CbAddIc(lx,EC_IMM,&tempss->val,sys_internal_types[IT_PTR]);
CbAddIc(lx,EC_DEREF,0,sys_internal_types[IT_PTR]);
} else {
if (lx->flags&LF_STATIC_COMPILE && !(tempss->s.h.type & HTT_LITERAL))
CbAddIc(lx,EC_ABSOLUTE_ADDRESS,tempss->val,sys_internal_types[IT_PTR]);
else
CbAddIc(lx,EC_IMM,tempss->val,sys_internal_types[IT_PTR]);
}
Lex(lx);
return PRST_CHECK_BINARY_OPS;
}
if (tempss->s.h.type & HTT_FUNCTION) {
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
is_first_arg=TRUE;
Lex(lx); //skip fun name
CbAddIc(lx,EC_NOP,0,0); //record indent_level
CbPush(lx);
templ=lx->cb.cb_next;
lx->cb.cb_next=NULL;
tempc=tempss;
i=tempc->arg_cnt;
tempm=tempc->member_list;
argc_cnt=0;
if (lx->token!='(')
needs_right_paren=FALSE;
else {
Lex(lx);
needs_right_paren=TRUE;
}
while (i--) {
CbInitOutPtrs(&lx->cb);
if (needs_right_paren && !is_first_arg) {
if (lx->token==',')
Lex(lx);
else if (lx->token!=')')
PrsExcept(lx,"ST_EXPECTING_COMMA");
}
if (tempm->flags & MLF_DEFAULT_AVAILABLE &&
(lx->token==')' || lx->token==',' || !needs_right_paren))
CbAddIc(lx,EC_IMM,tempm->default_value,tempm->member_class);
else {
if (tempm->flags&MLF_BY_ADDRESS)
lx->flags|=LF_BY_ADDRESS;
if (!PrsParseExpression(lx,NULL,FALSE))
throw(EXCEPT_COMPILER,3);
else {
CbPush(lx);
CbAddIc(lx,EC_NULL,0,0);
tempi=CmpOptPass012(lx,NULL,FALSE,0);
CbPop(lx);
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_R_TO_DOUBLE;
else
if (tempc2->sub_type!=IT_DOUBLE &&
tempc1->sub_type==IT_DOUBLE)
tempi->ic_flags|=ICF_R_TO_INT;
}
}
CbAddIc(lx,EC_NULL,0,0);
CbPush(lx);
is_first_arg=FALSE;
tempm=tempm->next;
}
if (tempm && tempm->flags & MLF_DOT_DOT_DOT) {
CbInitOutPtrs(&lx->cb);
CbAddIc(lx,EC_IMM,0,tempm->member_class);
tempi=lx->cb.cb_last_out_ptr;
CbAddIc(lx,EC_NULL,0,0);
CbPush(lx);
if (needs_right_paren) {
if (lx->token!=')') {
do {
if (!is_first_arg) {
if (lx->token==',')
Lex(lx);
else
PrsExcept(lx,"ST_EXPECTING_COMMA");
}
CbInitOutPtrs(&lx->cb);
if (!PrsParseExpression(lx,NULL,FALSE))
throw(EXCEPT_COMPILER,4);
CbAddIc(lx,EC_NULL,0,0);
CbPush(lx);
is_first_arg=FALSE;
argc_cnt++;
} while (lx->token==',');
}
}
tempi->ic_data=argc_cnt++; //++ so add_esp latter works
}
if (needs_right_paren) {
if (lx->token!=')')
PrsExcept(lx,"ST_MISSING_RIGHT_PAREN");
Lex(lx);
}
templ1=templ->cb_next;
templ->cb_next=lx->cb.cb_next;
lx->cb.cb_next=templ;
CbPop(lx);
templ=lx->cb.cb_next;
lx->cb.cb_next=templ1;
CbAddIc(lx,EC_CALL_START,tempc,0);
while (templ) {
templ1=templ->cb_next;
CbAppend(lx,templ);
if (!Bt(tempc->flags,Cf_INTERNAL))
lx->cb.cb_last_out_ptr->ic_flags|=ICF_PUSH_RESULT;
templ=templ1;
}
if (Bt(tempc->flags,Cf_INTERNAL))
CbAddIc(lx,tempc->executable_address,0,tempc->return_class);
else if (Bt(tempc->flags,Cf_EXTERN)) {
if (lx->flags&LF_STATIC_COMPILE) {
if (tempc->s.h.type&HTT_IMPORT)
CbAddIc(lx,EC_CALL_IMPORT,tempc,tempc->return_class);
else
CbAddIc(lx,EC_CALL_EXTERN,tempc,tempc->return_class);
} else
CbAddIc(lx,EC_CALL_INDIRECT2,&tempc->executable_address,tempc->return_class);
CbAddIc(lx,EC_ADD_RSP,(argc_cnt+tempc->arg_cnt)<<3,tempc->return_class);
} else {
CbAddIc(lx,EC_CALL,tempc->executable_address,tempc->return_class);
CbAddIc(lx,EC_ADD_RSP,(argc_cnt+tempc->arg_cnt)<<3,tempc->return_class);
}
CbAddIc(lx,EC_CALL_END,tempc,tempc->return_class);
lx->flags=(lx->flags|LF_RAX) & ~(LF_ARRAY|LF_FUNCTION);
return PRST_UNARY_MODIFIERS;
}
if (tempss->s.h.type & HTT_GLBL_VAR) {
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
tempg=tempss;
tempc=tempg->var_class+1;
lx->flags&=~(LF_RAX|LF_ARRAY|LF_FUNCTION);
if (tempg->dim.next) {
*tempad=tempg->dim.next;
lx->flags|=LF_ARRAY;
}
if (tempg->flags & GVAF_FUNCTION) {
//TODO:Not implemented
lx->flags|=LF_FUNCTION;
}
if (lx->flags&LF_STATIC_COMPILE) {
if (tempg->flags & GVAF_EXTERN) //TODO
PrsExcept(lx,"ST_NOT_IMPLEMENTED");
else {
if (tempg->flags & GVAF_IMPORT)
CbAddIc(lx,EC_ADDRESS_IMPORT,tempg,tempc);
else {
if (tempg->flags&GVAF_DATA_HEAP)
CbAddIc(lx,EC_HEAP_GLBL,tempg->data,tempc);
else
CbAddIc(lx,EC_ABSOLUTE_ADDRESS,tempg->data_address,tempc);
}
}
} else {
if (tempg->flags & GVAF_EXTERN) {
CbAddIc(lx,EC_IMM,&tempg->data_address,tempc);
CbAddIc(lx,EC_DEREF,0,tempc);
} else
CbAddIc(lx,EC_IMM,tempg->data_address,tempc);
}
Lex(lx);
return PRST_UNARY_MODIFIERS;
}
if (!(tempss->s.h.type & HTT_KEYWORD))
PrsExcept(lx,"ST_MISSING_EXPRESSION");
if (tempss><(GenericHashEntry *)->user_data0==KW_SIZEOF) {
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
Lex(lx); //skip sizeof
j=0;
while (lx->token=='(') {
Lex(lx);
j++;
}
if (lx->token!=TK_IDENT)
PrsExcept(lx,"ST_INVALID_CLASS");
if (tempm=lx->local_var_entry) {
lx->local_var_entry->use_cnt++;
tempc=tempm->member_class;
i=tempc->size*tempm->dim.total_cnt;
} else {
tempc=lx->hash_entry;
if (!tempc || !(tempc->s.h.type & (HTT_CLASS|HTT_INTERNAL_TYPE|HTT_GLBL_VAR|HTT_TYPEDEF)))
PrsExcept(lx,"ST_INVALID_CLASS");
i=tempc->size;
} //TODO: should allow '.member', etc;
if (Lex(lx)=='*') {
while (Lex(lx)=='*');
i=sizeof(void *);
}
CbAddIc(lx,EC_IMM,i,sys_internal_types[IT_I8]);
while (j--) {
if (lx->token!=')')
PrsExcept(lx,"ST_MISSING_RIGHT_PAREN");
Lex(lx);
}
return PRST_CHECK_BINARY_OPS;
} else if (tempss><(GenericHashEntry *)->user_data0==KW_OFFSET && !(lx->opts&1<<OPTf_STD_C)) {
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
Lex(lx); //skip offset
j=0;
while (lx->token=='(') {
Lex(lx);
j++;
}
if (lx->token!=TK_IDENT)
PrsExcept(lx,"ST_INVALID_CLASS");
if (tempm=lx->local_var_entry) {
lx->local_var_entry->use_cnt++;
tempc=tempm->member_class;
} else {
tempc=lx->hash_entry;
if (!tempc || !(tempc->s.h.type & (HTT_CLASS|HTT_GLBL_VAR)))
PrsExcept(lx,"ST_INVALID_CLASS");
else if (tempc->s.h.type & HTT_GLBL_VAR)
tempc=tempc><(GlblVarStruct *)->var_class;
}
if (Lex(lx)!='.')
PrsExcept(lx,"ST_EXPECTING_DOT");
if (Lex(lx)!=TK_IDENT)
PrsExcept(lx,"ST_INVALID_MEMBER");
if (!(tempm=FindMember(lx->ident,tempc)))
PrsExcept(lx,"ST_INVALID_MEMBER");
CbAddIc(lx,EC_IMM,tempm->offset,sys_internal_types[IT_I8]);
Lex(lx);
while (j--) {
if (lx->token!=')')
PrsExcept(lx,"ST_MISSING_RIGHT_PAREN");
Lex(lx);
}
return PRST_CHECK_BINARY_OPS;
}
PrsExcept(lx,"ST_MISSING_EXPRESSION");
}
U8 PrsUnaryModifier(LexStruct *lx,ParseStack *ps,MemberListStruct **local_var,ArrayDimStruct **tempad,I8 *max_precedence)
{
I8 i,j;
LexCbStack *templ,*templ2,*templl;
ClassStruct *tempc,*tempc1;
MemberListStruct *tempm;
IntermediateCode *tempi,*tempi1;
ArrayDimStruct *tempad1;
if (lx->flags & LF_ASM_EXPRESSIONS)
return PRST_CHECK_BINARY_OPS;
if (tempm=*local_var) {
if (tempm->flags&MLF_BY_ADDRESS) {
tempi=lx->cb.cb_last_out_ptr;
if (!(lx->flags & (LF_RAX | LF_ARRAY)))
CbAddIc(lx,EC_DEREF+PREC_UNARY<<16,0,tempi->ic_class-1);
else {
tempi->ic_class--;
lx->flags&=~(LF_RAX|LF_ARRAY);
}
}
}
if (lx->token==TK_DEREFERRENCE) {
if (PREC_UNARY>*max_precedence)
*max_precedence=PREC_UNARY;
tempi=lx->cb.cb_last_out_ptr;
if (!(lx->flags & (LF_RAX | LF_ARRAY)))
CbAddIc(lx,EC_DEREF+PREC_UNARY<<16,0,tempi->ic_class-1);
else
tempi->ic_class--;
} else if (lx->token=='.') {
if (PREC_UNARY>*max_precedence)
*max_precedence=PREC_UNARY;
if (tempm)
tempm->flags|=MLF_NO_REG_VARIABLE;
}
*local_var=NULL;
if (lx->token=='.' || lx->token==TK_DEREFERRENCE) {
if (PREC_UNARY>*max_precedence)
*max_precedence=PREC_UNARY;
tempi=lx->cb.cb_last_out_ptr;
tempc=tempi->ic_class;
if (!(lx->flags & LF_RAX))
tempc--;
if (!(tempc->s.h.type & HTT_CLASS))
PrsExcept(lx,"ST_INVALID_CLASS");
if (Lex(lx)!=TK_IDENT)
PrsExcept(lx,"ST_INVALID_MEMBER");
if (!(tempm=FindMember(lx->ident,tempc)))
PrsExcept(lx,"ST_INVALID_MEMBER");
Lex(lx); //skip member name
tempc1=tempm->member_class+1;
CbAddIc(lx,EC_IMM,tempm->offset,tempc1);
lx->flags&=~(LF_RAX|LF_ARRAY|LF_FUNCTION);
if (tempm->dim.next) {
*tempad=tempm->dim.next;
lx->flags|=LF_ARRAY;
}
if(tempm->flags & MLF_FUNCTION) {
PrsPush(ps,tempm->return_class);
PrsPush(ps,tempm->arg_cnt);
lx->flags|=LF_FUNCTION;
}
CbAddIc(lx,EC_ADD,0,tempc1);
return PRST_UNARY_MODIFIERS;
}
if (lx->token==TK_CAST) {
if (PREC_UNARY>*max_precedence)
*max_precedence=PREC_UNARY;
if (Lex(lx)!='(')
PrsExcept(lx,"ST_EXPECTING_LEFT_PAREN");
if (Lex(lx)!=TK_IDENT)
PrsExcept(lx,"ST_INVALID_CLASS");
tempc=lx->hash_entry;
if (!tempc || !(tempc->s.h.type & (HTT_CLASS|HTT_INTERNAL_TYPE)))
PrsExcept(lx,"ST_INVALID_CLASS");
while (Lex(lx)=='*')
tempc++;
if (!(lx->flags&(LF_RAX|LF_ARRAY)))
tempc++;
tempi=lx->cb.cb_last_out_ptr;
tempi->ic_class=tempc;
CbAddIc(lx,EC_TYPECAST,0,tempc);
if (lx->token!=')')
PrsExcept(lx,"ST_MISSING_RIGHT_PAREN");
Lex(lx);
return PRST_UNARY_MODIFIERS;
}
if (lx->token=='[') {
if (PREC_UNARY>*max_precedence)
*max_precedence=PREC_UNARY;
Lex(lx);
tempi=lx->cb.cb_last_out_ptr;
if (!(lx->flags & (LF_ARRAY | LF_RAX))) {
tempc=tempi->ic_class-1;
while (tempc->return_class)
tempc=tempc->return_class;
i=EC_DEREF+PREC_UNARY<<16;
CbAddIc(lx,i,0,tempc);
} else {
tempc=tempi->ic_class;
while (tempc->return_class)
tempc=tempc->return_class;
}
tempc1=tempc-1;
if (tempad1=*tempad) {
CbAddIc(lx,EC_IMM,tempad1->total_cnt*tempc1->size,tempc);
if (*tempad=tempad1->next) {
if (!PrsParseExpression(lx,NULL,FALSE))
throw(EXCEPT_COMPILER,5);
if (lx->token!=']')
PrsExcept(lx,"ST_MISSING_RIGHT_BRACKET");
Lex(lx); //skip ]
tempi1=lx->cb.cb_last_out_ptr;
if (tempi1->ic_class->sub_type==IT_DOUBLE)
tempi1->ic_flags|=ICF_R_TO_INT;
CbAddIc(lx,EC_MUL,0,tempc);
tempi1=lx->cb.cb_last_out_ptr;
tempi1->ic_flags|=ICF_USE_INT;
CbAddIc(lx,EC_ADD,0,tempc);
tempi1=lx->cb.cb_last_out_ptr;
tempi1->ic_flags|=ICF_USE_INT;
lx->flags|=LF_RAX;
return PRST_UNARY_MODIFIERS;
}
} else
CbAddIc(lx,EC_IMM,tempc1->size,tempc);
if (!PrsParseExpression(lx,NULL,FALSE))
throw(EXCEPT_COMPILER,5);
if (lx->token!=']')
PrsExcept(lx,"ST_MISSING_RIGHT_BRACKET");
Lex(lx); //skip ]
tempi1=lx->cb.cb_last_out_ptr;
if (tempi1->ic_class->sub_type==IT_DOUBLE)
tempi1->ic_flags|=ICF_R_TO_INT;
CbAddIc(lx,EC_MUL,0,tempc);
tempi1=lx->cb.cb_last_out_ptr;
tempi1->ic_flags|=ICF_USE_INT;
CbAddIc(lx,EC_ADD,0,tempc);
tempi1=lx->cb.cb_last_out_ptr;
tempi1->ic_flags|=ICF_USE_INT;
lx->flags&=~(LF_RAX|LF_ARRAY);
return PRST_UNARY_MODIFIERS;
}
if (lx->token=='(' && lx->flags & LF_FUNCTION) {
if (PREC_TERM>*max_precedence)
*max_precedence=PREC_TERM;
tempi=lx->cb.cb_last_out_ptr;
tempc=tempi->ic_class-1;
if (!(lx->flags & (LF_RAX | LF_ARRAY)))
CbAddIc(lx,EC_DEREF,0,sys_internal_types[IT_PTR]);
else if (!(lx->flags & LF_ARRAY))
tempi->ic_class=tempc;
CbAddIc(lx,EC_SET_RAX,0,sys_internal_types[IT_PTR]);
CbAddIc(lx,EC_NOP1,1,sys_internal_types[IT_PTR]); //balance the books
CbAddIc(lx,EC_CALL_START,0,tempc);
CbAddIc(lx,EC_PUSH_REGS,1<<CREG_RAX,tempc);
i=PrsPop(ps);
tempc=PrsPop(ps);
j=i;
Lex(lx); //skip '('
CbAddIc(lx,EC_NOP,0,0); //record indent_level
CbPush(lx);
templ=lx->cb.cb_next;
lx->cb.cb_next=NULL;
while (i--) {
if (lx->token==',')
Lex(lx);
CbInitOutPtrs(&lx->cb);
if (!PrsParseExpression(lx,NULL,FALSE))
throw(EXCEPT_COMPILER,6);
CbAddIc(lx,EC_NULL,0,0);
CbPush(lx);
}
if (lx->token!=')')
PrsExcept(lx,"ST_MISSING_RIGHT_PAREN");
Lex(lx); //skip ')'
templl=templ->cb_next;
templ->cb_next=lx->cb.cb_next;
lx->cb.cb_next=templ;
CbPop(lx);
templ=lx->cb.cb_next;
lx->cb.cb_next=templl;
while (templ) {
templ2=templ->cb_next;
CbAppend(lx,templ);
lx->cb.cb_last_out_ptr->ic_flags|=ICF_PUSH_RESULT;
templ=templ2;
}
CbAddIc(lx,EC_CALL_INDIRECT,j<<3,tempc);
CbAddIc(lx,EC_ADD_RSP,j<<3+8,tempc);
CbAddIc(lx,EC_CALL_END,0,tempc);
lx->flags=(lx->flags | LF_RAX)&~(LF_ARRAY | LF_FUNCTION);
return PRST_UNARY_MODIFIERS;
}
if (lx->token==TK_PLUS_PLUS) {
if (PREC_UNARY>*max_precedence)
*max_precedence=PREC_UNARY;
Lex(lx);
lx->flags|=LF_POSTINC;
return PRST_DEREFERRENCE;
}
if (lx->token==TK_MINUS_MINUS) {
if (PREC_UNARY>*max_precedence)
*max_precedence=PREC_UNARY;
Lex(lx);
lx->flags|=LF_POSTDEC;
return PRST_DEREFERRENCE;
}
return PRST_DEREFERRENCE;
}
U8 PrsDereferrence(LexStruct *lx,ParseStack *ps)
{
I8 i;
ClassStruct *tempc;
IntermediateCode *tempi;
if (lx->flags & LF_FUNCTION) {
ps->ptr--;
tempc=PrsPop(ps);
}
if (lx->flags & (LF_RAX|LF_ARRAY))
return PRST_CHECK_BINARY_OPS;
tempi=lx->cb.cb_last_out_ptr;
tempc=tempi->ic_class-1;
if (lx->flags & LF_PREINC) {
lx->flags&=~LF_PREINC;
i=EC_PP_;
} else if (lx->flags & LF_PREDEC) {
lx->flags&=~LF_PREDEC;
i=EC_MM_;
} else if (lx->flags & LF_POSTINC) {
lx->flags&=~LF_POSTINC;
i=EC__PP;
} else if (lx->flags & LF_POSTDEC) {
lx->flags&=~LF_POSTDEC;
i=EC__MM;
} else
i=EC_DEREF;
while (tempc->return_class)
tempc=tempc->return_class;
CbAddIc(lx,i+PREC_UNARY<<16,0,tempc);
return PRST_CHECK_BINARY_OPS;
}
void *CompileExpression(LexStruct *lx,U8 *type=NULL)
{
void *result;
U8 size;
DbgInfo *dbg=NULL;
IndentInfo *indent=NULL;
BoolI1 old_trace=Btr(&lx->flags,LFf_OPT_TRACE_PRESENT);
CbPush(lx);
CbInitOutPtrs(&lx->cb);
CbAddIc(lx,EC_RETURN_START,0,0);
if (PrsParseExpression(lx,NULL,TRUE)) {
CbAddIc(lx,EC_RETURN_END,0,sys_internal_types[IT_I8]);
CbAddIc(lx,EC_RET,0,0);
CbAddIc(lx,EC_NULL,0,0);
result=CbCompile(lx,NULL,&size,&dbg,&indent,type);
} else
result=NULL;
CbPop(lx);
Free(dbg);
Free(indent);
AssignBit(&lx->flags,LFf_OPT_TRACE_PRESENT,old_trace);
return result;
}
BoolI8 GetExpression(LexStruct *lx,void **ex) //FALSE=no err
{
*ex=CompileExpression(lx);
if (*ex)
return TRUE;
else
return FALSE;
}
I8 Expression(LexStruct *lx) //FALSE=no err
{
I8 result;
void *ex=CompileExpression(lx);
if (ex) {
result=Call(ex);
ExpressionDel(ex);
} else
result=0;
return result;
}
I wouldn't use my tools if I were you, I'd write my own.
I just wanted to show I'm not bullsh*tting.
Seriously an unoptimized compiler is easy compared to many operating system things. Surprisingly when I added major optimizations, i could hardly tell a difference because the intel chips are so smart that unoptimized code is just as fast, almost.