📄 numexpr.c
字号:
*/ CALL(ScanForNext(scr, OP_LOGOR)); expr->flags = FPL_OPERAND; } continue; } else { expr->operator=OP_BINOR; scr->text++; } break; case CHAR_PLUS: expr->operator=OP_PLUS; ++scr->text; break; case CHAR_MINUS: expr->operator=OP_MINUS; ++scr->text; break; case CHAR_QUESTION: ++scr->text; /* * This is the first operator in a conditional operator sequence (?) */ /* * Get result from everything to the left of this! */ CALL(Calc(scr, val, basexpr)); /* * Clean the expression so far. */ Clean(scr, basexpr); /* erase the list */ /* * Start a new list with this result */ GETMEM(expr, sizeof(struct Expr)); memset(expr, 0, sizeof(struct Expr)); expr->flags = FPL_OPERAND; basexpr=expr; if(val->val.val) { /* * In this case, its like in the 'a ? b : c' expression and 'a' * equals 1. Then we should skip the 'c' expression. */ CALL(Expression(val, scr, CON_NORMAL, NULL)); if(*scr->text++!=CHAR_COLON) return FPLERR_ILLEGAL_CONDOP; CALL(ScanForNext(scr, OP_COND2)); } else { /* * In this case, its like in the 'a ? b : c' expression and 'a' * equals 0. Then we should skip the 'b' expression. */ CALL(ScanForNext(scr, OP_COND1)); if(*scr->text++!=CHAR_COLON) return FPLERR_ILLEGAL_CONDOP; CALL(Expression(val, scr, CON_NORMAL, NULL)); } expr->val.val = val->val.val; continue; /* check for next operator */ break;#if 0 case CHAR_COLON: if(conditional) { /* only if preceeded with the regular '?' operator! */ conditional--; expr->operator=OP_COND2; ++scr->text; } break;#endif case CHAR_MULTIPLY: expr->operator=OP_MULTIPLY; ++scr->text; break; case CHAR_DIVIDE: expr->operator=OP_DIVISION; ++scr->text; break; case CHAR_REMAIN: expr->operator=OP_REMAIN; ++scr->text; break; case CHAR_XOR: expr->operator=OP_BINXOR; ++scr->text; break; case CHAR_LESS_THAN: if(scr->text[1]==CHAR_ASSIGN) { scr->text+=2; expr->operator=OP_LESSEQ; } else if(scr->text[1]==CHAR_LESS_THAN) { scr->text+=2; expr->operator=OP_SHIFTL; } else { scr->text++; expr->operator=OP_LESS; } break; case CHAR_GREATER_THAN: if(scr->text[1]==CHAR_ASSIGN) { expr->operator= OP_GRETEQ; scr->text+=2; } else if(scr->text[1]==CHAR_GREATER_THAN) { scr->text+=2; expr->operator=OP_SHIFTR; } else { scr->text++; expr->operator=OP_GRET; } break; case CHAR_NOT_OPERATOR: if(scr->text[1]==CHAR_ASSIGN) { expr->operator=OP_NOTEQ; scr->text+=2; } break; case CHAR_COMMA: if(control&CON_GROUNDLVL) { /* * Get result from everything to the left of this! * For unary operators. */ CALL(Calc(scr, val, basexpr)); Clean(scr, basexpr); GETMEM(basexpr, sizeof(struct Expr)); expr=basexpr; expr->val.val=0; expr->unary=NULL; expr->operator=expr->flags=OP_NOTHING; expr->next=NULL; scr->text++; } break; } if(point==scr->text) break; expr->flags&=~FPL_OPERAND; /* clear the operand bit */ } } while(1); if(!(control&(CON_DECLARE /* |CON_ACTION */ ))) { /* * Get result of the current expression only if this isn't called * as a declaring (no one wants the return code from 'int a'!) * or a stand-alone (they have no receiver anyway) statement. */ CALL(Calc(scr, val, basexpr)); /* * If this was a stand alone statement, including no action returns an * error! */ if(control&CON_ACTION && !(val->flags&FPL_ACTION)) { CALL(Warn(scr, FPLERR_NO_ACTION)); /* but we can just as good keep on anyway! */ } } Clean(scr, basexpr); /* erase the rest of the list */ if(dims) FREE(dims); return(FPL_OK);}/********************************************************************** * * ReturnCode Calc(); * * Returns the result in the first Expr struct of the expression that * the second parameter holds. This function does not free the expression * list. * *******/ReturnCode REGARGSCalc(struct Data *scr, struct Expr *val, struct Expr *basexpr){ /* lower value=higher priority. Order as the operator list in script.h: *| + - / * << >> % & | ^ && || ~ ? : == <= >= < > != ! */ const static uchar priority[]={ (uchar)255, 1, 1, 0, 0, 2, 2, 0, 5, 7, 6, 8, 9, (uchar)255, 10, 10, 4, 3, 3, 3, 3, 4, (uchar)255 }; ReturnCode ret; uchar pri, minpri=(uchar)255, maxpri=0; struct Expr *expr=basexpr, *last; struct Unary *un, *next; /* first all Unary expressions */ if(!(expr->flags&FPL_STRING)) { while(expr) { if(priority[expr->operator]<minpri) minpri=priority[expr->operator]; /* get the lowest priority */ if(priority[expr->operator]>maxpri && expr->operator!=OP_NOTHING) maxpri=priority[expr->operator]; /* get the highest priority */ if(expr->flags&FPL_STRING) { CALL(Warn(scr, FPLERR_ILLEGAL_VARIABLE)); /* * A string among the integers! * We remove this and try next! */ last=expr->next; FREE(expr); /* delete this bastard from the expression!!! */ expr=last; } else { un=expr->unary; while(un) { switch(un->unary) { case OP_NOT: expr->val.val=!expr->val.val; break; case OP_COMPL: expr->val.val=~expr->val.val; break; case OP_MINUS: expr->val.val=-expr->val.val; break; /*simply ignored! case OP_PLUS: break; */ case OP_PREDEC: case OP_PREINC: CALL(Warn(scr, FPLERR_ILLEGAL_PREOPERATION)); /* just ignore it! */ } next=un->next; FREE(un); un=next; } } expr=expr->next; } } /* * Calculate all members of the linked list in the proper way and put * the result in "val->val.val" before returning "ret". Check for operators * with priority within `minpri' and `maxpri' which we got in the loop * above. * * Check priority level by priority level and perform the right actions. * When reaching the maxpri, there is only one number left: the result! */ for(pri=minpri; pri<=maxpri; pri++) { last=expr=basexpr; while(expr=expr->next) { if(priority[expr->operator]==pri) { last->flags|=expr->flags; switch(expr->operator) { case OP_MULTIPLY: last->val.val*=expr->val.val; break; case OP_DIVISION: if(!expr->val.val) { CALL(Warn(scr, FPLERR_DIVISION_BY_ZERO)); /* we give a zero as result! */ last->val.val=0; } else last->val.val/=expr->val.val; break; case OP_REMAIN: if(!expr->val.val) { CALL(Warn(scr, FPLERR_DIVISION_BY_ZERO)); last->val.val=0; } else last->val.val%=expr->val.val; break; case OP_SHIFTL: last->val.val<<=expr->val.val; break; case OP_SHIFTR: last->val.val>>=expr->val.val; break; case OP_BINAND: last->val.val&=expr->val.val; break; case OP_BINOR: last->val.val|=expr->val.val; break; case OP_BINXOR: last->val.val^=expr->val.val; break; case OP_PLUS: last->val.val+=expr->val.val; break; case OP_MINUS: last->val.val-=expr->val.val; break; case OP_EQUAL: last->val.val=last->val.val==expr->val.val; break; case OP_NOTEQ: last->val.val=last->val.val!=expr->val.val; break; case OP_LESSEQ: last->val.val=last->val.val<=expr->val.val; break; case OP_LESS: last->val.val=last->val.val<expr->val.val; break; case OP_GRETEQ: last->val.val=last->val.val>=expr->val.val; break; case OP_GRET: last->val.val=last->val.val>expr->val.val; break; case OP_LOGOR: last->val.val=last->val.val||expr->val.val; break; case OP_LOGAND: last->val.val=last->val.val&&expr->val.val; break; case OP_COND1: if(expr->next && expr->next->operator==OP_COND2) { last->val.val=last->val.val?expr->val.val:expr->next->val.val; } else { CALL(Warn(scr, FPLERR_ILLEGAL_CONDOP)); /* WARNING! */ last->val.val=expr->val.val; /* get the number we have! */ } break; } last->next=expr->next; FREE(expr); expr=last; } else last=expr; } } val->val.val=basexpr->val.val; /* get the final value */ val->flags=basexpr->flags; /* copy the flags */ return(FPL_OK);}/********************************************************************** * * AddUnary(); * * Build a linked list on the unary member of the Expr struct! * ******/ReturnCode REGARGSAddUnary(struct Data *scr, struct Expr *expr, Operator unary){ struct Unary *next=expr->unary; GETMEM(expr->unary, sizeof(struct Unary)); expr->unary->unary=unary; expr->unary->next=next; return(FPL_OK);}/********************************************************************** * * Clean() * * Erases e
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -