$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))
     PutLexWarning(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->cnt) {
         *tempad=tempm->dim_list;
         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;
         AddSysHashEntry(tempss,lx->local_hash_table);
     } else {
         tempss->s.h.type=HTT_SYS_SYMBOL | HTT_UNRESOLVED_GLBL;
         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 (lx->token==',' && needs_right_paren)
             Lex(lx);
         else if (!is_first_arg && lx->token!=')')
             PrsExcept(lx,"ST_EXPECTING_COMMA");
         if (tempm->flags & MLF_DEFAULT_AVAILABLE &&
                 (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 {
                 is_first_arg=FALSE;
                 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);
         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 (lx->token==',')
                         Lex(lx);
                     else if (!is_first_arg)
                         PrsExcept(lx,"ST_EXPECTING_COMMA");
                     CbInitOutPtrs(&lx->cb);
                     if (!PrsParseExpression(lx,NULL,FALSE))
                         throw(EXCEPT_COMPILER,4);
                     is_first_arg=FALSE;
                     CbAddIc(lx,EC_NULL,0,0);
                     CbPush(lx);
                     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->cnt) {
         *tempad=tempg->dim_list;
         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) {
             CbAddIc(lx,EC_IMM,&tempg->data_address,tempc);
             CbAddIc(lx,EC_DEREF,0,tempc);
         } else {
             if (tempg->flags & GVAF_IMPORT)
                 CbAddIc(lx,EC_ADDRESS_IMPORT,tempg,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;
         if (tempm->cnt)
             i*=tempm->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->cnt) {
         *tempad=tempm->dim_list;
         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->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;
}
Home

Kernel
StartUp
Scheduler
Memory
MultiCore
Interrupts
BitMaps
Screen
Plot
Compiler Frontend
Compiler Mid
Compiler Backend
Compiler Expression Parser