Trivial Solutions
                    The LoseThos 64-bit PC Operating System
File:/LT/Compiler/ExpParser.CPZ
This, and all LoseThos files, are public domain.  Do whatever you like.
God is watching; God is just; God is never out-done in generosity.  He talks!

LoseThos code compiles with the 64-bit LoseThos compiler/assembler I wrote.
Boot the LoseThos CD and you can compile it.  Not in Kansas anymore!

Click here for preliminary compiler information you need.

Project: Compiler.SPZ

U0 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

BoolI64 PrsExpression(LexStruct *lx,I64 *_max_prec,BoolI8 end_exp)
{
  BoolI8 result=TRUE,cont_unary,cont_check_binary_ops,is_lower,div_sizeof;
  I64 i,k,old_flags=lx->flags,old_start_line=lx->expression_start_line,
      max_prec=PREC_NULL,unary_pre_prec,paren_prec,unary_post_prec,
      left_prec=PREC_MAX,question_clauses=0;
  IntermediateCode *tempi,*tempi2;
  ClassStruct *tempc,*tempcc;
  ParseStk *ps=MAlloc(sizeof(ParseStk));
  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_pre_prec=PREC_NULL;
      lx->flags&=~(LF_PAREN+LF_PREINC+LF_PREDEC+LF_POSTINC+LF_POSTDEC+LF_FUN_EXP);
      do i=PrsUnaryTerm(lx,ps,&local_var,&tempad,&max_prec,&unary_pre_prec,&paren_prec);
      while (i==PRST_UNARY_TERM);

      unary_post_prec=PREC_NULL;
      while (i==PRST_UNARY_MODIFIERS)
        i=PrsUnaryModifier(lx,ps,&local_var,&tempad,&unary_post_prec);

      if (paren_prec) {
        if (unary_pre_prec || unary_post_prec) {
          if (paren_prec<=unary_pre_prec && !unary_post_prec)
            ParenWarning(lx);
          paren_prec=PREC_NULL;
        } else if (paren_prec<=PREC_UNARY_PRE+ASSOC_MASK)
            ParenWarning(lx);
      }

      if (i==PRST_DEREFERRENCE)
        PrsDereferrence(lx,ps);

        //Check for binary Ops
      do {
        i=PrsPop(ps);
        tempc=PrsPop(ps);
        if (0<i.u8[2]<=PREC_UNARY_PRE+ASSOC_MASK) {
          if (lx->opts&1<<OPTf_STD_C)
            k=c_binary_ops_table[lx->token];
          else
            k=binary_ops_table[lx->token];
          if (k.u16[0]==EC_POWER &&
              i.u16[0]==EC_UNARY_MINUS) {
            Lex(lx); //skip ` op
            left_prec=k.i8[2];
            PrsPush(ps,tempc);
            PrsPush(ps,i);
            PrsPush(ps,lx->cbh.cb_last_out_ptr->ic_class);
            PrsPush(ps,k);
            cont_check_binary_ops=FALSE;
            cont_unary=TRUE;
          } else {
            tempi=lx->cbh.cb_last_out_ptr;
            tempc=tempi->ic_class;
            if (i.u16[0]==EC_DEREF && tempc->ptr_cnt)
              tempc--;
            else if (i.u16[0]==EC_ADDRESS) {
              lx->abs_cnts.c_addresses++;
              if (!(lx->flags & (LF_RAX|LF_ARRAY))) {
                if (!Bt(deref_bitmap,tempi->ic_opcode))
                  PrsExcept(lx,"ST_INVALID_LVAL");
                tempi->ic_opcode=EC_NOP;
                tempc++;
              } else if (lx->flags & LF_ARRAY)
                tempc++;
            }
            while (tempc->forward_class)
              tempc=tempc->forward_class;
            CbIcAdd(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.u16[0]) {
            case EC_ADD:
            case EC_SUB:
              tempi=lx->cbh.cb_last_out_ptr;
              if (!tempi->ic_class->ptr_cnt &&
                  tempi->ic_class->sub_type!=IT_F64) {
                CbIcAdd(lx,EC_SIZEOF,1,sys_internal_types[IT_I64]);
                CbIcAdd(lx,EC_MUL,0,sys_internal_types[IT_I64]);
              }
              break;
            case EC_AND_AND:
            case EC_OR_OR:
              CbIcAdd(lx,EC_NOP,0,sys_internal_types[IT_I64]);
              break;
            case EC_QUESTION:
              question_clauses++;
              break;
            case EC_COLON:
              if (!question_clauses)
                k=0;
              else
                question_clauses--;
              break;
          }
          if (!k.u8[2]) {
            if (paren_prec>PREC_UNARY_PRE+ASSOC_MASK &&
                paren_prec&~ASSOC_MASK<=left_prec&~ASSOC_MASK-
                paren_prec&ASSOCF_LEFT-left_prec&ASSOCF_LEFT)
              ParenWarning(lx);
            cont_check_binary_ops=FALSE;
            cont_unary=FALSE; //DONE
          } else {
            Lex(lx); //skip op
            if (paren_prec>PREC_UNARY_PRE+ASSOC_MASK &&
                paren_prec&~ASSOC_MASK<left_prec&~ASSOC_MASK+
                   paren_prec&ASSOCF_RIGHT &&
                 paren_prec&~ASSOC_MASK<k.u8[2]&~ASSOC_MASK+
                   !(paren_prec&ASSOCF_RIGHT))
                ParenWarning(lx);
            if (k.u8[2]>max_prec)
              max_prec=k.u8[2];
            left_prec=k.u8[2];
            if (Bt(assign_bitmap,k.u16[0])) {
              tempi=lx->cbh.cb_last_out_ptr;
              tempc=tempi->ic_class;
              while (tempc->forward_class)
                tempc=tempc->forward_class;
              if (!Bt(deref_bitmap,tempi->ic_opcode) ||
                !tempc->ptr_cnt && !Bt(&tempc->flags,Cf_INTERNAL_TYPE))
                PrsExcept(lx,"ST_INVALID_LVAL");
              tempi->ic_opcode=EC_NOP;
              k.u8[2]=PREC_ASSIGN|ASSOCF_RIGHT;
#assert PREC_ASSIGN==C_PREC_ASSIGN
            }
            while (TRUE) {
              i=PrsPop(ps); //pop ops of higher prec
              tempc=PrsPop(ps);
              is_lower=FALSE;
              if (i) {
                if (k.u8[2]&~ASSOC_MASK==i.u8[2]&~ASSOC_MASK) {
                  if (!(k.u8[2]&ASSOCF_RIGHT))
                    is_lower=TRUE;
                } else if (k.u8[2]&~ASSOC_MASK>i.u8[2]&~ASSOC_MASK)
                  is_lower=TRUE;
              }
              div_sizeof=FALSE;
              if (is_lower) {
                switch (i.u16[0]) {
                  case EC_ADD:
                    if (tempc->ptr_cnt) {
                      tempi=lx->cbh.cb_last_out_ptr;
                      if (!tempi->ic_class->ptr_cnt &&
                          tempi->ic_class->sub_type!=IT_F64) {
                        CbIcAdd(lx,EC_SIZEOF,1,sys_internal_types[IT_I64]);
                        CbIcAdd(lx,EC_MUL,0,sys_internal_types[IT_I64]);
                      }
                    }
                    break;
                  case EC_SUB:
                    if (tempc->ptr_cnt) {
                      tempi=lx->cbh.cb_last_out_ptr;
                      if (!tempi->ic_class->ptr_cnt &&
                          tempi->ic_class->sub_type!=IT_F64) {
                        CbIcAdd(lx,EC_SIZEOF,1,sys_internal_types[IT_I64]);
                        CbIcAdd(lx,EC_MUL,0,sys_internal_types[IT_I64]);
                      } else
                        div_sizeof=TRUE;
                    }
                    break;
                  case EC_AND_AND:
                  case EC_OR_OR:
                    CbIcAdd(lx,EC_NOP,0,sys_internal_types[IT_I64]);
                    break;
                  case EC_ADD_EQUAL:
                  case EC_SUB_EQUAL:
                    if (tempc->ptr_cnt) {
                      CbIcAdd(lx,EC_SIZEOF,1,sys_internal_types[IT_I64]);
                      CbIcAdd(lx,EC_MUL,0,sys_internal_types[IT_I64]);
                    }
                    break;
                }
                tempi2=CbIcAdd(lx,i,0,tempc);
                if (i.u8[3]&ECF_HAS_PUSH_CMP) {
                  tempi2->ic_flags|=ICF_POP_CMP;
                  CbIcAdd(lx,EC_NOP,0,sys_internal_types[IT_I64]);
                  CbIcAdd(lx,EC_AND_AND,0,sys_internal_types[IT_I64],ICF_POP_CMP);
                }
                if (Bt(cmp_bitmap,k.u16[0]) &&
                    Bt(cmp_bitmap,i.u16[0]) && !(lx->opts&1<<OPTf_STD_C)) {
                  tempi2->ic_flags|=ICF_PUSH_CMP;
                  CbIcAdd(lx,EC_NOP,0,sys_internal_types[IT_I64]);
                  CbIcAdd(lx,EC_PUSH_CMP,0,tempc);
                  k.u8[3]|=ECF_HAS_PUSH_CMP;
                } else if (k.u16[0]==EC_AND_AND || k.u16[0]==EC_OR_OR)
                  CbIcAdd(lx,EC_NOP,0,sys_internal_types[IT_I64]);
                if (div_sizeof) {
                  tempcc=tempc-1;
                  if (tempcc->size!=1) {
                    CbIcAdd(lx,EC_IMM,tempcc->size,sys_internal_types[IT_I64]);
                    CbIcAdd(lx,EC_DIV,0,sys_internal_types[IT_I64]);
                    tempc=sys_internal_types[IT_I64];
                  }
                }
              } else {
                PrsPush(ps,tempc);
                PrsPush(ps,i);
                PrsPush(ps,lx->cbh.cb_last_out_ptr->ic_class);
                PrsPush(ps,k);
                cont_check_binary_ops=FALSE;
                cont_unary=TRUE;
                break;
              }
            }
          }
        }
      } while (cont_check_binary_ops);
    } while (cont_unary);
    while (TRUE) {
      i=PrsPop(ps);
      tempc=PrsPop(ps);
      div_sizeof=FALSE;
      tempi=lx->cbh.cb_last_out_ptr;
      switch (i.u16[0]) {
        case 0:
          goto done3;
        case EC_ADD:
          if (tempc->ptr_cnt && !tempi->ic_class->ptr_cnt &&
              tempi->ic_class->sub_type!=IT_F64) {
            CbIcAdd(lx,EC_SIZEOF,1,sys_internal_types[IT_I64]);
            CbIcAdd(lx,EC_MUL,0,sys_internal_types[IT_I64]);
          }
          break;
        case EC_SUB:
          if (tempc->ptr_cnt && tempi->ic_class->sub_type!=IT_F64) {
            if (!tempi->ic_class->ptr_cnt) {
              CbIcAdd(lx,EC_SIZEOF,1,sys_internal_types[IT_I64]);
              CbIcAdd(lx,EC_MUL,0,sys_internal_types[IT_I64]);
            } else
              div_sizeof=TRUE;
          }
          break;
        case EC_AND_AND:
        case EC_OR_OR:
          CbIcAdd(lx,EC_NOP,0,sys_internal_types[IT_I64]);
          break;
        case EC_ADD_EQUAL:
        case EC_SUB_EQUAL:
          if (tempc->ptr_cnt) {
            CbIcAdd(lx,EC_SIZEOF,1,sys_internal_types[IT_I64]);
            CbIcAdd(lx,EC_MUL,0,sys_internal_types[IT_I64]);
          }
          break;
      }
      tempi=CbIcAdd(lx,i,0,tempc);
      if (i.u8[3]&ECF_HAS_PUSH_CMP) {
        tempi->ic_flags|=ICF_POP_CMP;
        CbIcAdd(lx,EC_NOP,0,sys_internal_types[IT_I64]);
        CbIcAdd(lx,EC_AND_AND,0,sys_internal_types[IT_I64],ICF_POP_CMP);
      }
      if (div_sizeof) {
        tempcc=tempc-1;
        if (tempcc->size!=1) {
          CbIcAdd(lx,EC_IMM,tempcc->size,sys_internal_types[IT_I64]);
          CbIcAdd(lx,EC_DIV,0,sys_internal_types[IT_I64]);
          tempc=sys_internal_types[IT_I64];
        }
      }
    }
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)
    CbIcAdd(lx,EC_END_EXP,0,0);
  if (_max_prec)
    *_max_prec=max_prec;
  lx->flags=lx->flags&~LF_INSIDE_EXPRESSION |
      old_flags&(LF_INSIDE_EXPRESSION|LF_PREINC|LF_PREDEC);
  lx->expression_start_line=old_start_line;
  return result;
}

U64 PrsFunCall(LexStruct *lx,BoolI8 indirect,ClassStruct *tempc)
{
  I64 i,argc_cnt;
  BoolI8 is_first_arg,needs_right_paren;
  ClassStruct *tempc1,*tempc2;
  MemberListStruct *tempm;
  LexCbHeader *tempcbh,*tempcbh1;
  CbMiscStruct *mc;
  IntermediateCode *tempi;

  if (indirect) {
    if (!(lx->flags & (LF_RAX | LF_ARRAY)))
      CbIcAdd(lx,EC_DEREF,0,sys_internal_types[IT_PTR]);
    lx->cbh.cb_last_out_ptr->ic_class=sys_internal_types[IT_PTR];
    CbIcAdd(lx,EC_SET_RAX,0,sys_internal_types[IT_PTR]);
    CbIcAdd(lx,EC_NOP1,1,sys_internal_types[IT_PTR]); //balance the books
  }
  is_first_arg=TRUE;
  CbIcAdd(lx,EC_NOP,0,0); //record indent_level
  CbPush(lx);
  tempcbh=lx->cbh.cb_next;
  lx->cbh.cb_next=NULL;
  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--) {
    CbOutPtrsInit(lx);
    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_DFT_AVAILABLE &&
        (lx->token==')' || lx->token==',' || !needs_right_paren)) {
      if (tempm->flags & MLF_STR_DFT_AVAILABLE &&
          lx->flags&LF_STATIC_COMPILE) {
        mc=CbMiscNew(lx,CBMT_STR_CONST);
        CbIcAdd(lx,EC_STR_CONST,mc,sys_internal_types[IT_U8]+1);
        mc->st_len=StrLen(tempm->dft_val)+1;
        mc->str=StrNew(tempm->dft_val);
        lx->flags|=LF_HAS_MISC_DATA;
      } else
        CbIcAdd(lx,EC_IMM,tempm->dft_val,tempm->member_class);
    } else {
      if (tempm->flags&MLF_BY_ADDRESS)
        lx->flags|=LF_BY_ADDRESS;
      if (!PrsExpression(lx,NULL,FALSE))
        throw(EXCEPT_COMPILER,3);
      else {
        CbPush(lx);
        CbIcAdd(lx,EC_END,0,0);
        lx->pass=0;
              OptPass012(lx,NULL,FALSE);
        lx->pass=1;
        tempi=OptPass012(lx,NULL,FALSE);
        CbPop(lx);
        tempc1=tempi->ic_class;
        while (tempc1->forward_class)
          tempc1=tempc1->forward_class;
        tempc2=tempm->member_class;
        while (tempc2->forward_class)
          tempc2=tempc2->forward_class;
        if (tempc2->sub_type==IT_F64 &&
            tempc1->sub_type!=IT_F64)
          tempi->ic_flags|=ICF_R_TO_F64;
        else
        if (tempc2->sub_type!=IT_F64 &&
            tempc1->sub_type==IT_F64)
          tempi->ic_flags|=ICF_R_TO_INT;
      }
    }
    CbIcAdd(lx,EC_END,0,0);
    CbPush(lx);
    is_first_arg=FALSE;
    tempm=tempm->next;
  }
  if (tempm && tempm->flags & MLF_DOT_DOT_DOT) {
    CbOutPtrsInit(lx);
    tempi=CbIcAdd(lx,EC_IMM,0,tempm->member_class);
    CbIcAdd(lx,EC_END,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");
          }
          CbOutPtrsInit(lx);
          if (!PrsExpression(lx,NULL,FALSE))
            throw(EXCEPT_COMPILER,4);
          CbIcAdd(lx,EC_END,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);
  }
  tempcbh1=tempcbh->cb_next;
  tempcbh->cb_next=lx->cbh.cb_next;
  lx->cbh.cb_next=tempcbh;
  CbPop(lx);
  tempcbh=lx->cbh.cb_next;
  lx->cbh.cb_next=tempcbh1;
  CbIcAdd(lx,EC_CALL_START,tempc,0);
  if (indirect)
    CbIcAdd(lx,EC_PUSH_REGS,1<<CREG_RAX,tempc->return_class);
  while (tempcbh) {
    tempcbh1=tempcbh->cb_next;
    CbAppend(lx,tempcbh);
    if (!Bt(tempc->flags,Cf_INTERNAL_FUN))
      lx->cbh.cb_last_out_ptr->ic_flags|=ICF_PUSH_RESULT;
    tempcbh=tempcbh1;
  }
  if (Bt(tempc->flags,Cf_INTERNAL_FUN))
    CbIcAdd(lx,tempc->executable_address,0,tempc->return_class);
  else {
    if (indirect)
      CbIcAdd(lx,EC_CALL_INDIRECT,(argc_cnt+tempc->arg_cnt)<<3,tempc->return_class);
    else if (Bt(tempc->flags,Cf_EXTERN)) {
      lx->abs_cnts.externs++;
      if (lx->flags&LF_STATIC_COMPILE) {
        if (tempc->s.h.type&HTT_IMPORT)
          CbIcAdd(lx,EC_CALL_IMPORT,tempc,tempc->return_class);
        else
          CbIcAdd(lx,EC_CALL_EXTERN,tempc,tempc->return_class);
      } else
        CbIcAdd(lx,EC_CALL_INDIRECT2,&tempc->executable_address,tempc->return_class);
    } else {
      CbIcAdd(lx,EC_CALL,tempc->executable_address,tempc->return_class);
    }
    if ((Bt(tempc->flags,Cf_RET1) || Bt(tempc->flags,Cf_ARGPOP)) && !Bt(tempc->flags,Cf_NOARGPOP)) {
      if (indirect) {
        CbIcAdd(lx,EC_ADD_RSP1,(argc_cnt+tempc->arg_cnt)<<3,tempc->return_class);
        CbIcAdd(lx,EC_ADD_RSP,8,tempc->return_class);
      } else
        CbIcAdd(lx,EC_ADD_RSP1,(argc_cnt+tempc->arg_cnt)<<3,tempc->return_class);
    } else {
      if (indirect)
        argc_cnt++;
      CbIcAdd(lx,EC_ADD_RSP,(argc_cnt+tempc->arg_cnt)<<3,tempc->return_class);
    }
  }
  CbIcAdd(lx,EC_CALL_END,tempc,tempc->return_class);
  lx->flags=(lx->flags|LF_RAX) & ~(LF_ARRAY|LF_FUN_EXP);
  return PRST_UNARY_MODIFIERS;
}

U64 PrsUnaryTerm(LexStruct *lx,ParseStk *ps,MemberListStruct **local_var,ArrayDimStruct **tempad,
    I64 *max_prec,I64 *unary_pre_prec,I64 *paren_prec)
{
  I64 i,*i_ptr,j,size;
  U64 d;
  ExportSysSymHashEntry *tempess;
  ClassStruct *tempc;
  GlblVarStruct *tempg;
  MemberListStruct *tempm;
  LexUndefEntry *templu;
  CbMiscStruct *mc;
  BoolI8 paren_warn;
  DbgInfo *dbg;

  *local_var=NULL;
  *paren_prec=PREC_NULL;
  switch (lx->token) {
    case TK_INTEGER:
      if (PREC_TERM>*max_prec)
        *max_prec=PREC_TERM;
      if (lx->cur_i<0)
        CbIcAdd(lx,EC_IMM,lx->cur_i,sys_internal_types[IT_U64]);
      else
        CbIcAdd(lx,EC_IMM,lx->cur_i,sys_internal_types[IT_I64]);
      if (Lex(lx)==TK_CAST) {
        lx->flags|=LF_RAX;
        return PRST_UNARY_MODIFIERS;
      } else
        return PRST_CHECK_BINARY_OPS;
    case TK_F64:
      if (PREC_TERM>*max_prec)
        *max_prec=PREC_TERM;
      i_ptr=&lx->cur_f;
      CbIcAdd(lx,EC_F64,*i_ptr,sys_internal_types[IT_F64]);
      if (Lex(lx)==TK_CAST) {
        lx->flags|=LF_RAX;
        return PRST_UNARY_MODIFIERS;
      } else
        return PRST_CHECK_BINARY_OPS;
    case TK_STR:
      if (PREC_TERM>*max_prec)
        *max_prec=PREC_TERM;
      d=LexExtStr(lx,&size);
      mc=CbMiscNew(lx,CBMT_STR_CONST);
      CbIcAdd(lx,EC_STR_CONST,mc,sys_internal_types[IT_U8]+1);
      mc->st_len=size;
      mc->str=d;
      lx->flags|=LF_HAS_MISC_DATA;
      if (lx->token==TK_CAST) {
        lx->flags|=LF_RAX;
        return PRST_UNARY_MODIFIERS;
      } else
        return PRST_CHECK_BINARY_OPS;
    case TK_INSERT_BINARY:
      if (PREC_TERM>*max_prec)
        *max_prec=PREC_TERM;
      d=lx->ident;
      size=lx->ident_len;
      lx->ident=NULL;
      mc=CbMiscNew(lx,CBMT_STR_CONST);
      CbIcAdd(lx,EC_STR_CONST,mc,sys_internal_types[IT_U8]+1);
      mc->st_len=size;
      mc->str=d;
      lx->flags|=LF_HAS_MISC_DATA;
      if (Lex(lx)==TK_CAST) {
        lx->flags|=LF_RAX;
        return PRST_UNARY_MODIFIERS;
      } else
        return PRST_CHECK_BINARY_OPS;
    case TK_INSERT_BINARY_TYPE:
    case TK_INSERT_BINARY_SIZE:
      if (PREC_TERM>*max_prec)
        *max_prec=PREC_TERM;
      CbIcAdd(lx,EC_IMM,lx->cur_i,sys_internal_types[IT_U64]);
      if (Lex(lx)==TK_CAST) {
        lx->flags|=LF_RAX;
        return PRST_UNARY_MODIFIERS;
      } else
        return PRST_CHECK_BINARY_OPS;
    case '(':
      if (Lex(lx)==TK_IDENT && lx->hash_entry && lx->hash_entry->h.type & (HTT_CLASS|HTT_INTERNAL_TYPE|HTT_TYPEDEF))
        PrsExcept(lx,"ST_USE_POSTFIX_CAST");
      else {
        if (PREC_TERM>*max_prec)
          *max_prec=PREC_TERM;
        if (lx->cur_lfn->flags&LFSF_IS_DEFINE)
          paren_warn=FALSE;
        else
          paren_warn=TRUE;
        if (!PrsExpression(lx,paren_prec,FALSE))
          throw(EXCEPT_COMPILER,2);
        if (!paren_warn)
          *paren_prec=PREC_NULL;
        if (lx->token!=')')
          PrsExcept(lx,"ST_MISSING_RIGHT_PAREN");
        Lex(lx); //skip )
        lx->flags= lx->flags & ~(LF_ARRAY+LF_FUN_EXP) | LF_RAX | LF_PAREN;
        return PRST_UNARY_MODIFIERS;
      }
  }
  i=unary_ops_table[lx->token];
  if (i.u8[2]) {
    if (i.u8[2]>*max_prec)
      *max_prec=i.u8[2];
    *unary_pre_prec=i.u8[2];
    Lex(lx); //Skip op
    if (i.u16[0]==EC_ADDRESS && lx->token==TK_IDENT) {
      if (tempc=lx->hash_entry) {
        if (tempc->s.h.type & HTT_FUN) {
          if (!Bt(tempc->flags,Cf_INTERNAL_FUN)) {
            if (Bt(tempc->flags,Cf_EXTERN)) {
              if (lx->flags&LF_STATIC_COMPILE) {
                if (lx->flags&LF_ASM_EXPRESSIONS) {
                  if (tempess=HashFind(tempc->s.h.str,lx->hash_table_list,HTT_EXPORT_SYS_SYM))
                    goto pu_export_sys_sym;
                  else
                    goto pu_new_sys_sym;
                }
                PrsExcept(lx,"ST_ADDRESS_EXTERN");
              }
              lx->abs_cnts.externs++;
              CbIcAdd(lx,EC_IMM,
                  &tempc->executable_address,sys_internal_types[IT_PTR]);
              CbIcAdd(lx,EC_DEREF,0,
                  sys_internal_types[IT_PTR]);
            } else {
              if (lx->flags&LF_STATIC_COMPILE) {
                CbIcAdd(lx,EC_ABSOLUTE_ADDRESS,
                    tempc->executable_address,sys_internal_types[IT_PTR]);
                if (lx->flags&LF_ASM_EXPRESSIONS)
                  lx->abs_cnts.absolute_addresses++;
              } else
                CbIcAdd(lx,EC_IMM,
                    tempc->executable_address,sys_internal_types[IT_PTR]);
            }
            lx->abs_cnts.c_addresses++;
            if (Lex(lx)==TK_CAST) {
              lx->flags|=LF_RAX;
              return PRST_UNARY_MODIFIERS;
            } else
              return PRST_CHECK_BINARY_OPS;
          }
        } else if (tempc->s.h.type & HTT_EXPORT_SYS_SYM) {
          tempess=tempc;
          if (lx->flags&LF_ASM_EXPRESSIONS && !(lx->flags&LF_STATIC_COMPILE) &&
              !HashSingleTableFind(tempess->s.h.str,lx->local_hash_table,HTT_EXPORT_SYS_SYM) &&
              !HashSingleTableFind(tempess->s.h.str,lx->glbl_hash_table,HTT_EXPORT_SYS_SYM)) {
            lx->abs_cnts.c_addresses++;
            CbIcAdd(lx,EC_IMM,
                tempess->val,sys_internal_types[IT_PTR]);
            if (Lex(lx)==TK_CAST) {
              lx->flags|=LF_RAX;
              return PRST_UNARY_MODIFIERS;
            } else
              return PRST_CHECK_BINARY_OPS;
          } else
            goto pu_export_sys_sym;
        }
      } else if (lx->flags&LF_ASM_EXPRESSIONS && !lx->local_var_entry)
        goto pu_ident_but_not_local_var;
    }
    PrsPush(ps,tempc);
    PrsPush(ps,i);
    return PRST_UNARY_TERM;
  }
  if (lx->token=='+') {
    if (PREC_UNARY_PRE>*max_prec)
      *max_prec=PREC_UNARY_PRE;
    *unary_pre_prec=PREC_UNARY_PRE;
    Lex(lx);
    return PRST_UNARY_TERM;
  }

  if (lx->token!=TK_IDENT) {
    if (lx->token==TK_PLUS_PLUS) {
      if (PREC_UNARY_PRE>*max_prec)
        *max_prec=PREC_UNARY_PRE;
      *unary_pre_prec=PREC_UNARY_PRE;
      Lex(lx);
      lx->flags|=LF_PREINC;
      return PRST_UNARY_TERM;
    }
    if (lx->token==TK_MINUS_MINUS) {
      if (PREC_UNARY_PRE>*max_prec)
        *max_prec=PREC_UNARY_PRE;
      *unary_pre_prec=PREC_UNARY_PRE;
      Lex(lx);
      lx->flags|=LF_PREDEC;
      return PRST_UNARY_TERM;
    }
    if (lx->token=='$') {
      if (PREC_TERM>*max_prec)
        *max_prec=PREC_TERM;
      if (lx->flags & LF_ASM_EXPRESSIONS) {
        lx->abs_cnts.absolute_addresses++;
        if (lx->flags&LF_STATIC_COMPILE)
          CbIcAdd(lx,EC_ABSOLUTE_ADDRESS,lx->instruction_ptr,sys_internal_types[IT_PTR]);
        else
          CbIcAdd(lx,EC_IMM,lx->instruction_ptr,sys_internal_types[IT_PTR]);
      } else
        CbIcAdd(lx,EC_RIP,0,sys_internal_types[IT_PTR]);
      if (Lex(lx)==TK_CAST) {
        lx->flags|=LF_RAX;
        return PRST_UNARY_MODIFIERS;
      } else
        return PRST_CHECK_BINARY_OPS;
    }
    PrsExcept(lx,"ST_MISSING_EXPRESSION");
  }

  if (tempm=lx->local_var_entry) {
    if (PREC_TERM>*max_prec)
      *max_prec=PREC_TERM;
    lx->flags&=~(LF_RAX|LF_ARRAY|LF_FUN_EXP);
    tempc=tempm->member_class+1;
    if (tempm->flags & MLF_FUN && !(lx->flags&LF_ASM_EXPRESSIONS)) {
      lx->flags|=LF_FUN_EXP;
      PrsPush(ps,tempm->fun_ptr-tempm->fun_ptr->ptr_cnt);
    }
    if (tempm->dim.next) {
      *tempad=tempm->dim.next;
      lx->flags|=LF_ARRAY;
    }
    if (tempm->flags&MLF_STATIC) {
      if (lx->flags&LF_STATIC_COMPILE) {
      //        if (tempg->flags&GVAF_DATA_HEAP) //TODO
      //          CbIcAdd(lx,EC_HEAP_GLBL,tempm->static_data,tempc);
      //        else
        CbIcAdd(lx,EC_ABSOLUTE_ADDRESS,tempm->static_data_ip,tempc);
      } else
        CbIcAdd(lx,EC_IMM,tempm->static_data,tempc);
    } else {
      if (lx->flags&LF_ASM_EXPRESSIONS) {
        i=PrsPop(ps);
        PrsPop(ps);
        if (i.u16[0]!=EC_ADDRESS)
          PrsExcept(lx,"ST_EXPECTING_AMPERSAND");
        CbIcAdd(lx,EC_IMM,tempm->offset,sys_internal_types[IT_PTR]);
        *local_var=tempm;
        if (Lex(lx)==TK_CAST) {
          lx->flags|=LF_RAX;
          return PRST_UNARY_MODIFIERS;
        } else
          return PRST_CHECK_BINARY_OPS;
      } else {
        CbIcAdd(lx,EC_RBP,0,tempc);
        CbIcAdd(lx,EC_IMM,tempm->offset,tempc);
        CbIcAdd(lx,EC_ADD,0,tempc);
      }
    }
    Lex(lx); //skip var name
    *local_var=tempm;
    return PRST_UNARY_MODIFIERS;
  }

pu_ident_but_not_local_var:
  if (!(tempess=lx->hash_entry)) {
    if (!(lx->flags & LF_ASM_EXPRESSIONS))
      PrsExcept(lx,"ST_INVALID_LVAL");
    tempc=NULL;
pu_new_sys_sym:
    tempess=CAlloc(sizeof(ExportSysSymHashEntry),Fs->code_heap);
    tempess->s.h.str=lx->ident;
    lx->ident=NULL;
    if (*tempess->s.h.str=='@' &&
        tempess->s.h.str[1]=='@') {
      tempess->s.h.type=HTT_EXPORT_SYS_SYM | HTT_UNRESOLVED_LOCAL;
      if (IsReplaceSyms)
        HashReplace(tempess,lx->local_hash_table);
      else
        HashAdd(tempess,lx->local_hash_table);
    } else {
      tempess->s.h.type=HTT_EXPORT_SYS_SYM | HTT_UNRESOLVED_GLBL;
      if (tempc)
        HashAddAfter(tempess,tempc,lx->glbl_hash_table);
      else if (IsReplaceSyms)
        HashReplace(tempess,lx->glbl_hash_table);
      else
        HashAdd(tempess,lx->glbl_hash_table);
    }
  }

  if (tempess->s.h.type & HTT_EXPORT_SYS_SYM) {
pu_export_sys_sym:
    if (PREC_TERM>*max_prec)
      *max_prec=PREC_TERM;
    if (!(tempess->s.h.type & HTT_LITERAL) &&
        !(tempess->s.h.type & HTT_IMPORT))
      lx->abs_cnts.absolute_addresses++;
    if (tempess->s.h.type & (HTT_UNRESOLVED_LOCAL|HTT_UNRESOLVED_GLBL)) {
      templu=MAlloc(sizeof(LexUndefEntry));
      templu->hash=tempess;
      templu->next=lx->undef_hash_entry;
      lx->undef_hash_entry=templu;
      if (tempess->s.h.type & HTT_UNRESOLVED_LOCAL)
        lx->flags|=LF_UNRESOLVED_LOCAL;
      else
        lx->flags|=LF_UNRESOLVED_GLBL;
      CbIcAdd(lx,EC_IMM,&tempess->val,sys_internal_types[IT_PTR],ICF_NO_RIP);
      CbIcAdd(lx,EC_DEREF,0,sys_internal_types[IT_PTR]);
    } else {
      if (lx->flags&LF_STATIC_COMPILE && !(tempess->s.h.type & HTT_LITERAL))
        CbIcAdd(lx,EC_ABSOLUTE_ADDRESS,tempess->val,sys_internal_types[IT_PTR]);
      else
        CbIcAdd(lx,EC_IMM,tempess->val,sys_internal_types[IT_PTR]);
    }
    if (Lex(lx)==TK_CAST) {
      lx->flags|=LF_RAX;
      return PRST_UNARY_MODIFIERS;
    } else
      return PRST_CHECK_BINARY_OPS;
  }

  if (tempess->s.h.type & HTT_FUN) {
    if (PREC_TERM>*max_prec)
      *max_prec=PREC_TERM;
    Lex(lx);  //skip fun name
    return PrsFunCall(lx,FALSE,tempess);
  }
  if (tempess->s.h.type & HTT_GLBL_VAR) {
    if (PREC_TERM>*max_prec)
      *max_prec=PREC_TERM;
    tempg=tempess;
    tempc=tempg->var_class+1;
    lx->flags&=~(LF_RAX|LF_ARRAY|LF_FUN_EXP);
    if (tempg->dim.next) {
      *tempad=tempg->dim.next;
      lx->flags|=LF_ARRAY;
    }
    if (lx->flags&LF_STATIC_COMPILE) {
      if (tempg->flags & GVAF_EXTERN) //TODO
        PrsExcept(lx,"ST_NOT_IMPLEMENTED");
      else {
        if (tempg->flags & GVAF_IMPORT)
          CbIcAdd(lx,EC_ADDRESS_IMPORT,tempg,tempc);
        else {
          if (tempg->flags&GVAF_DATA_HEAP)
            CbIcAdd(lx,EC_HEAP_GLBL,tempg->heap_glbl,tempc);
          else
            CbIcAdd(lx,EC_ABSOLUTE_ADDRESS,tempg->data_address_ip,tempc);
        }
      }
    } else {
      if (tempg->flags & GVAF_EXTERN) {
        lx->abs_cnts.externs++;
        CbIcAdd(lx,EC_IMM,&tempg->data_address,tempc);
        CbIcAdd(lx,EC_DEREF,0,tempc);
      } else
        CbIcAdd(lx,EC_IMM,tempg->data_address,tempc);
    }
    Lex(lx);
    if (tempg->flags & GVAF_FUN) {
      lx->flags|=LF_FUN_EXP;
      PrsPush(ps,tempg->fun_ptr-tempg->fun_ptr->ptr_cnt);
    }
    return PRST_UNARY_MODIFIERS;
  }
  if (!(tempess->s.h.type & HTT_KEYWORD))
    PrsExcept(lx,"ST_MISSING_EXPRESSION");
  switch (tempess><(GenericHashEntry *)->user_data0) {
    case KW_SIZEOF:
      if (PREC_TERM>*max_prec)
        *max_prec=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) {
        tempc=tempm->member_class;
        i=tempc->size*tempm->dim.total_cnt;
        if (Lex(lx)=='.')
          goto pu_sizeof_member;
      } else {
        tempc=lx->hash_entry;
        if (!tempc || !(tempc->s.h.type & (HTT_CLASS|HTT_INTERNAL_TYPE|HTT_GLBL_VAR|HTT_TYPEDEF|HTT_FUN)))
          PrsExcept(lx,"ST_INVALID_CLASS");
        if (tempc->s.h.type&HTT_FUN) {
          if (!(dbg=tempc->s.debug))
            PrsExcept(lx,"ST_FUN_SIZE_NOT_DEFINED");
          i=dbg->body[dbg->max_line+1-dbg->min_line]-dbg->body[0];
          Lex(lx);
        } else {
          i=tempc->size;
          while (Lex(lx)=='.') {
pu_sizeof_member:
            if (!(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)!=TK_IDENT || !(tempm=MemberFind(lx->ident,tempc)))
              PrsExcept(lx,"ST_INVALID_MEMBER");
            else if (lx->local_var_entry)
              lx->local_var_entry->use_cnt--;
            tempc=tempm->member_class;
            i=tempc->size*tempm->dim.total_cnt;
          }
        }
      }
      if (lx->token=='*') {
        while (Lex(lx)=='*');
        i=sizeof(U0 *);
      }
      CbIcAdd(lx,EC_IMM,i,sys_internal_types[IT_I64]);
      while (j--) {
        if (lx->token!=')')
          PrsExcept(lx,"ST_MISSING_RIGHT_PAREN");
        Lex(lx);
      }
      if (lx->token==TK_CAST) {
        lx->flags|=LF_RAX;
        return PRST_UNARY_MODIFIERS;
      } else
        return PRST_CHECK_BINARY_OPS;
    case KW_OFFSET:
      if (lx->opts&1<<OPTf_STD_C)
        PrsExcept(lx,"ST_MISSING_EXPRESSION");
      if (PREC_TERM>*max_prec)
        *max_prec=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)
        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");

      i=0;
      do {
        if (Lex(lx)!=TK_IDENT || !(tempm=MemberFind(lx->ident,tempc)))
          PrsExcept(lx,"ST_INVALID_MEMBER");
        else if (lx->local_var_entry)
          lx->local_var_entry->use_cnt--;
        i+=tempm->offset;
        tempc=tempm->member_class;
      } while (Lex(lx)=='.');
      CbIcAdd(lx,EC_IMM,i,sys_internal_types[IT_I64]);

      while (j--) {
        if (lx->token!=')')
          PrsExcept(lx,"ST_MISSING_RIGHT_PAREN");
        Lex(lx);
      }
      if (lx->token==TK_CAST) {
        lx->flags|=LF_RAX;
        return PRST_UNARY_MODIFIERS;
      } else
        return PRST_CHECK_BINARY_OPS;
    case KW_DEFINED:
      if (PREC_TERM>*max_prec)
        *max_prec=PREC_TERM;
      Lex(lx); //skip defined
      j=0;
      while (lx->token=='(') {
        Lex(lx);
        j++;
      }
      if (lx->token==TK_IDENT &&
          (lx->hash_entry || lx->local_var_entry))
        CbIcAdd(lx,EC_IMM,TRUE,sys_internal_types[IT_I64]);
      else
        CbIcAdd(lx,EC_IMM,FALSE,sys_internal_types[IT_I64]);
      Lex(lx);
      while (j--) {
        if (lx->token!=')')
          PrsExcept(lx,"ST_MISSING_RIGHT_PAREN");
        Lex(lx);
      }
      if (lx->token==TK_CAST) {
        lx->flags|=LF_RAX;
        return PRST_UNARY_MODIFIERS;
      } else
        return PRST_CHECK_BINARY_OPS;
  }
  PrsExcept(lx,"ST_MISSING_EXPRESSION");
}

U64 PrsUnaryModifier(LexStruct *lx,ParseStk *ps,MemberListStruct **local_var,ArrayDimStruct **tempad,I64 *unary_post_prec)
{
  ClassStruct *tempc,*tempc1,*fun_ptr;
  MemberListStruct *tempm;
  IntermediateCode *tempi,*tempi1;
  ArrayDimStruct *tempad1,tempad2;
  CbMiscStruct *mc;
  I64 mode,old_flags;
  BoolI8 was_paren=Btr(&lx->flags,Lf_PAREN);
  if (tempm=*local_var) {
    if (tempm->flags&MLF_BY_ADDRESS) {
      tempi=lx->cbh.cb_last_out_ptr;
      if (!(lx->flags & (LF_RAX | LF_ARRAY)))
        CbIcAdd(lx,EC_DEREF+PREC_UNARY_PRE<<16,0,tempi->ic_class-1);
      else {
        tempi->ic_class--;
        lx->flags&=~(LF_RAX|LF_ARRAY);
      }
    }
  }
  if (lx->token==TK_DEREFERRENCE) {
    if (!*unary_post_prec)
      *unary_post_prec=PREC_TERM;
    tempi=lx->cbh.cb_last_out_ptr;
    if (!(lx->flags & (LF_RAX | LF_ARRAY)))
      CbIcAdd(lx,EC_DEREF+PREC_UNARY_PRE<<16,0,tempi->ic_class-1);
    else
      tempi->ic_class--;
  } else if (lx->token=='.') {
    if (!*unary_post_prec)
      *unary_post_prec=PREC_TERM;
    if (tempm)
      tempm->register=CREG_NONE;
  }
  *local_var=NULL;
  switch (lx->token) {
    case '.':
    case TK_DEREFERRENCE:
      if (!*unary_post_prec)
        *unary_post_prec=PREC_TERM;
      tempc=lx->cbh.cb_last_out_ptr->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=MemberFind(lx->ident,tempc)))
        PrsExcept(lx,"ST_INVALID_MEMBER");
      else if (lx->local_var_entry)
        lx->local_var_entry->use_cnt--;
      Lex(lx);  //skip member name
      tempc1=tempm->member_class+1;
      CbIcAdd(lx,EC_IMM,tempm->offset,tempc1);
      lx->flags&=~(LF_RAX|LF_ARRAY|LF_FUN_EXP);
      if (tempm->dim.next) {
        *tempad=tempm->dim.next;
        lx->flags|=LF_ARRAY;
      }
      if(tempm->flags & MLF_FUN) {
        PrsPush(ps,tempm->fun_ptr-tempm->fun_ptr->ptr_cnt);
        lx->flags|=LF_FUN_EXP;
      }
      CbIcAdd(lx,EC_ADD,0,tempc1);
      return PRST_UNARY_MODIFIERS;
    case TK_CAST:
      if (!*unary_post_prec)
        *unary_post_prec=PREC_TERM;
      if (Lex(lx)!='(')
        PrsExcept(lx,"ST_EXPECTING_LEFT_PAREN");
      if (Lex(lx)!=TK_IDENT)
        PrsExcept(lx,"ST_INVALID_CLASS");
      if (Btr(&lx->flags,Lf_FUN_EXP))
        ps->ptr--;
      tempc=lx->hash_entry;
      Lex(lx);
      mode=PRS_TYPECAST;
      tempc=PrsType(lx,&tempc,&mode,NULL,NULL,&fun_ptr,NULL,&tempad2,0);
      if (fun_ptr) {
        Bts(&lx->flags,Lf_FUN_EXP);
        PrsPush(ps,fun_ptr);
        mc=CbMiscNew(lx,CBMT_HASH_ENTRY);
        mc->h=fun_ptr;
      }
      if (*tempad=tempad2.next) {
        lx->flags|=LF_ARRAY;
        tempc++;
        mc=CbMiscNew(lx,CBMT_ARRAY_DIM);
        mc->dim=*tempad;
      }
      if (!(lx->flags&(LF_RAX|LF_ARRAY)))
        tempc++;
      tempi=lx->cbh.cb_last_out_ptr;
      tempi->ic_class=tempc;
      CbIcAdd(lx,EC_LT_TYPECAST,was_paren,tempc);
      if (lx->token!=')')
        PrsExcept(lx,"ST_MISSING_RIGHT_PAREN");
      Lex(lx);
      return PRST_UNARY_MODIFIERS;
    case '[':
      if (!*unary_post_prec)
        *unary_post_prec=PREC_TERM;
      Lex(lx);
      tempc=lx->cbh.cb_last_out_ptr->ic_class;
      while (tempc->forward_class)
        tempc=tempc->forward_class;
      if (!tempc->ptr_cnt)
        PrsExcept(lx,"ST_NOT_ARRAY_OR_PTR");
      if (!(lx->flags & (LF_ARRAY | LF_RAX))) {
        tempc--;
        while (tempc->forward_class)
          tempc=tempc->forward_class;
        if (!tempc->ptr_cnt)
          PrsExcept(lx,"ST_NOT_ARRAY_OR_PTR");
        CbIcAdd(lx,EC_DEREF+PREC_UNARY_PRE<<16,0,tempc);
      }
      tempc1=tempc-1;
      if (tempad1=*tempad) {
        CbIcAdd(lx,EC_IMM,tempad1->total_cnt*tempc1->size,tempc);
        if (*tempad=tempad1->next) {
          old_flags=lx->flags;
          if (!PrsExpression(lx,NULL,FALSE))
            throw(EXCEPT_COMPILER,5);
          lx->flags=lx->flags&~LF_FUN_EXP|old_flags&LF_FUN_EXP;
          if (lx->token!=']')
            PrsExcept(lx,"ST_MISSING_RIGHT_BRACKET");
          Lex(lx); //skip ]
          tempi1=lx->cbh.cb_last_out_ptr;
          if (tempi1->ic_class->sub_type==IT_F64)
            tempi1->ic_flags|=ICF_R_TO_INT;
          CbIcAdd(lx,EC_MUL,0,tempc,ICF_USE_INT);
          CbIcAdd(lx,EC_ADD,0,tempc,ICF_USE_INT);
          lx->flags|=LF_RAX;
          return PRST_UNARY_MODIFIERS;
        }
      } else
        CbIcAdd(lx,EC_IMM,tempc1->size,tempc);
      old_flags=lx->flags;
      if (!PrsExpression(lx,NULL,FALSE))
        throw(EXCEPT_COMPILER,5);
      lx->flags=lx->flags&~LF_FUN_EXP|old_flags&LF_FUN_EXP;
      if (lx->token!=']')
        PrsExcept(lx,"ST_MISSING_RIGHT_BRACKET");
      Lex(lx); //skip ]
      tempi1=lx->cbh.cb_last_out_ptr;
      if (tempi1->ic_class->sub_type==IT_F64)
        tempi1->ic_flags|=ICF_R_TO_INT;
      CbIcAdd(lx,EC_MUL,0,tempc,ICF_USE_INT);
      CbIcAdd(lx,EC_ADD,0,tempc,ICF_USE_INT);
      lx->flags&=~(LF_RAX|LF_ARRAY);
      return PRST_UNARY_MODIFIERS;
    case '(':
      if (lx->flags & LF_FUN_EXP) {
        if (!*unary_post_prec)
          *unary_post_prec=PREC_TERM;
        return PrsFunCall(lx,TRUE,PrsPop(ps));
      }
      break;
    case TK_PLUS_PLUS:
      if (!*unary_post_prec)
        *unary_post_prec=PREC_UNARY_POST;
      Lex(lx);
      lx->flags|=LF_POSTINC;
      return PRST_DEREFERRENCE;
    case TK_MINUS_MINUS:
      if (!*unary_post_prec)
        *unary_post_prec=PREC_UNARY_POST;
      Lex(lx);
      lx->flags|=LF_POSTDEC;
      return PRST_DEREFERRENCE;
  }
  return PRST_DEREFERRENCE;
}

U64 PrsDereferrence(LexStruct *lx,ParseStk *ps)
{
  I64 i;
  ClassStruct *tempc;
  IntermediateCode *tempi;
  if (lx->flags & LF_FUN_EXP)
    PrsPop(ps);
  if (!(lx->flags&(LF_PREINC|LF_PREDEC|LF_POSTINC|LF_POSTDEC)))
    i=EC_DEREF+PREC_UNARY_PRE<<16;
  else {
    if (lx->flags & LF_PREINC)
      i=EC_PP_+PREC_UNARY_PRE<<16;
    else if (lx->flags & LF_PREDEC)
      i=EC_MM_+PREC_UNARY_PRE<<16;
    else if (lx->flags & LF_POSTINC)
      i=EC__PP+PREC_UNARY_POST<<16;
    else
      i=EC__MM+PREC_UNARY_POST<<16;
    lx->flags&=~(LF_PREINC|LF_PREDEC|LF_POSTINC|LF_POSTDEC);
  }
  tempi=lx->cbh.cb_last_out_ptr;
  if (lx->flags & (LF_RAX|LF_ARRAY)) {
    if (tempi->ic_opcode==EC_DEREF)
      tempi->ic_opcode=i;
    if (lx->token==TK_CAST) {
      lx->flags|=LF_RAX;
      return PRST_UNARY_MODIFIERS;
    } else
      return PRST_CHECK_BINARY_OPS;
  } else {
    tempc=tempi->ic_class-1;
    while (tempc->forward_class)
      tempc=tempc->forward_class;
    CbIcAdd(lx,i,0,tempc);
    if (lx->token==TK_CAST) {
      lx->flags|=LF_RAX;
      return PRST_UNARY_MODIFIERS;
    } else
      return PRST_CHECK_BINARY_OPS;
  }
}

U0 *CmpExpression(LexStruct *lx,U64 *type=NULL)
{
  U0 *result;
  U64 size;
  DbgInfo *dbg=NULL;
  IndentInfo *indent=NULL;
  BoolI8 old_trace=Btr(&lx->flags,LFf_OPT_TRACE_PRESENT);
  CbPush(lx);
  CbOutPtrsInit(lx);
  CbIcAdd(lx,EC_START,0,0); //So we can scan back an instruction
  if (PrsExpression(lx,NULL,FALSE)) {
    CbIcAdd(lx,EC_RETURN_VAL,0,NULL);
    CbIcAdd(lx,EC_RET,0,0);
    CbIcAdd(lx,EC_END,0,0);
    result=CbCompile(lx,NULL,&size,&dbg,&indent,type);
  } else
    result=NULL;
  CbPop(lx);
  Free(dbg);
  Free(indent);
  BEqu(&lx->flags,LFf_OPT_TRACE_PRESENT,old_trace);
  return result;
}

BoolI64 GetExpression(LexStruct *lx,U0 **ex)
{
  return ToBool(*ex=CmpExpression(lx));
}

I64 Expression(LexStruct *lx)
{
  I64 result;
  U0 *ex=CmpExpression(lx);
  if (ex) {
    result=Call(ex);
    ExpressionDel(ex);
  } else
    result=0;
  return result;
}
Historical capture: 2010-11-18. Home | Power on LoseThos | Sources and changes