Advertisement
RyDeR_

MathParser.inc

Feb 2nd, 2012
1,552
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pawn 18.62 KB | None | 0 0
  1. /*
  2.     SA-MP MathParser Include (v0.1.0)
  3.     Copyright ยฉ 2012 RyDeR`
  4. */
  5.  
  6. #include <a_samp>
  7.  
  8. #if defined MathParser_INC
  9.     #endinput
  10. #else
  11.     #define MathParser_INC
  12. #endif
  13.  
  14. #define Math:: Math_
  15. #define Parser:: Parser_
  16.  
  17. #if !defined PRECISION
  18.     #define PRECISION 3
  19. #endif
  20.  
  21. #define MAX_OPERATORS (32)
  22. #define MAX_OPERATOR_LENGTH (8)
  23. #define MAX_OPERATOR_FUNCTION_LENGTH (20)
  24.  
  25. #define MAX_CONSTANTS (32)
  26. #define MAX_CONSTANT_LENGTH (20)
  27.  
  28. #define MAX_FUNCTIONS (32)
  29. #define MAX_FUNCTION_LENGTH (16)
  30. #define MAX_FUNCTION_FUNCTION_LENGTH (20)
  31. #define MAX_FUNCTION_PARAMS (8)
  32. #define MAX_FUNCTION_PARAMS_LENGTH (32)
  33.  
  34. #define Debug(%0,%1,%2) \
  35.     printf("\n ยป [MathParser - " #%0 " @ " #%1 "] " %2)
  36.  
  37. #define Math_Operator%1(%2) \
  38.     Float:%1_Op(%2); public Float:%1_Op(%2)
  39.    
  40. #define Math_Function%1(%2) \
  41.     Float:%1_Fu(%2); public Float:%1_Fu(%2)
  42.  
  43. enum e_Assoc {
  44.     LEFT_TO_RIGHT,
  45.     RIGHT_TO_LEFT
  46. };
  47.  
  48. enum e_Operator {
  49.     Op_szOp[MAX_OPERATOR_LENGTH char],
  50.     Op_szFunc[MAX_OPERATOR_FUNCTION_LENGTH char],
  51.     Op_iPrecedence,
  52.     e_Assoc: Op_iAssoc
  53. };
  54.  
  55. enum e_Constant {
  56.     Const_szConst[MAX_CONSTANT_LENGTH char],
  57.     Float: Const_fValue
  58. }
  59.  
  60. enum e_Function {
  61.     Func_szName[MAX_FUNCTION_LENGTH char],
  62.     Func_szFunc[MAX_FUNCTION_FUNCTION_LENGTH char],
  63.     Func_iParams
  64. };
  65.  
  66. enum e_Index {
  67.     Operator,
  68.     Constant,
  69.     Function
  70. };
  71.  
  72. enum e_Stack {
  73.     Stk_iOpIdx,
  74.     Stk_iPrecedence,
  75.     e_Assoc: Stk_iAssoc,
  76.     Float: Stk_fValue
  77. };
  78.  
  79. enum e_Error {
  80.     ERROR_NONE,
  81.     ERROR_LOGICAL_VALUE,
  82.     ERROR_LOGICAL_OPERATOR,
  83.     ERROR_LOGICAL_PARANTHESES,
  84.     ERROR_PARAMETER_FUNCTION
  85. };
  86.  
  87. // Avoid warnings
  88. static stock Float: Parser::Calculate(const Float: fValue1, const Float: fValue2, const iOpIdx);
  89. static stock Float: Parser::ParseValue(const szExpr[], &e_Error: iError, &iIdx);
  90. static stock Float: Parser::Evaluate(const szExpr[], &e_Error: iError, &iIdx);
  91.  
  92. static
  93.     g_eiIndex[e_Index],
  94.    
  95.     g_aeOperator[MAX_OPERATORS][e_Operator],
  96.     g_aeConstant[MAX_CONSTANTS][e_Constant],
  97.     g_aeFunction[MAX_FUNCTIONS][e_Function]
  98. ;
  99.  
  100. MathParser(); public MathParser() { // Prevent crash from SYSREQ.C
  101.     CallRemoteFunction("_", "");
  102. }
  103.  
  104. stock Float: Math::ParseExpression(szExpr[], &e_Error: iError = ERROR_NONE, &iIdx = 0, const iSize = sizeof(szExpr)) {
  105.     static
  106.         bool: s_Init
  107.     ;
  108.     if(!s_Init) {
  109.         Math::AddOperator("E", "E", 25, RIGHT_TO_LEFT);
  110.         Math::AddOperator("^", "Pow", 20, RIGHT_TO_LEFT);
  111.         Math::AddOperator("*", "Mul", 15, LEFT_TO_RIGHT);
  112.         Math::AddOperator("/", "Div", 15, LEFT_TO_RIGHT);
  113.         Math::AddOperator("%", "Mod", 15, LEFT_TO_RIGHT);
  114.         Math::AddOperator("+", "Add", 10, LEFT_TO_RIGHT);
  115.         Math::AddOperator("-", "Sub", 10, LEFT_TO_RIGHT);
  116.        
  117.         Math::AddConstant("pi", 3.141592);
  118.         Math::AddConstant("e", 2.718281);
  119.        
  120.         Math::AddFunction("log", "Log", 2);
  121.         Math::AddFunction("sqrt", "Sqrt", 1);
  122.        
  123.         s_Init = !s_Init;
  124.     }
  125.     Parser::ReplaceConstants(szExpr, iSize);
  126.     Parser::ReplaceFunctions(szExpr, iError, iSize);
  127.    
  128.     if(iError != ERROR_NONE) {
  129.         Debug(Error, ParseExpression, "Something is wrong with your expression! \n");
  130.         return 0.0;
  131.     }
  132.     return Parser::Evaluate(szExpr, iError, iIdx);
  133. }
  134.  
  135. stock Math::AddFunction(const szName[], const szFunc[], const iParams) {
  136.     if(strlen(szName) >= MAX_FUNCTION_LENGTH) {
  137.         Debug(Error, AddFunction, "MAX_FUNCTION_LENGTH (%d) exceeded! \n", MAX_FUNCTION_LENGTH);
  138.         return -1;
  139.     }
  140.     if(strlen(szFunc) >= MAX_FUNCTION_FUNCTION_LENGTH) {
  141.         Debug(Error, AddFunction, "MAX_FUNCTION_FUNCTION_LENGTH (%d) exceeded! \n", MAX_FUNCTION_FUNCTION_LENGTH);
  142.         return -1;
  143.     }
  144.     if(!(-1 < iParams < MAX_FUNCTION_PARAMS)) {
  145.         Debug(Error, AddFunction, "MAX_FUNCTION_PARAMS (%d) exceeded! \n", MAX_FUNCTION_PARAMS);
  146.         return -1;
  147.     }
  148.     new
  149.         i = g_eiIndex[Function]
  150.     ;
  151.     if(-1 < i < MAX_FUNCTIONS) {
  152.         static
  153.             s_szFunc[MAX_FUNCTION_FUNCTION_LENGTH]
  154.         ;
  155.         format(s_szFunc, sizeof(s_szFunc), "%s_Fu", szFunc);
  156.        
  157.         if(funcidx(s_szFunc) != -1) {
  158.             strpack(g_aeFunction[i][Func_szName], szName, MAX_FUNCTION_LENGTH char);
  159.             strpack(g_aeFunction[i][Func_szFunc], s_szFunc, MAX_FUNCTION_FUNCTION_LENGTH char);
  160.            
  161.             g_aeFunction[i][Func_iParams] = iParams;
  162.            
  163.             do {
  164.                 g_eiIndex[Function]++;
  165.             } while(g_aeFunction[g_eiIndex[Function]][Func_szName][0] != EOS);
  166.            
  167.             return i;
  168.         } else {
  169.             Debug(Error, AddFunction, "Unable to find functions function \"%s\"! \n", szFunc);
  170.             return -1;
  171.         }
  172.     } else {
  173.         Debug(Error, AddFunction, "MAX_FUNCTIONS (%d) exceeded! \n", MAX_FUNCTIONS);
  174.         return -1;
  175.     }
  176. }
  177.  
  178. stock Math::RemoveFunction(const szName[]) {
  179.     for(new i = 0; i < MAX_FUNCTIONS; ++i) {
  180.         if(g_aeFunction[i][Func_szName][0] != EOS) {
  181.             static
  182.                 s_szName[MAX_FUNCTION_LENGTH]
  183.             ;
  184.             strunpack(s_szName, g_aeFunction[i][Func_szName], MAX_FUNCTION_LENGTH);
  185.            
  186.             if(!strcmp(s_szName, szName, false, MAX_FUNCTION_LENGTH)) {
  187.                 g_aeFunction[i][Func_szName][0] = EOS;
  188.                
  189.                 if(i < g_eiIndex[Function]) {
  190.                     g_eiIndex[Function] = i;
  191.                 }
  192.                 return 1;
  193.             }
  194.         }
  195.     }
  196.     Debug(Error, RemoveFunction, "Unable to find function \"%s\"! \n", szName);
  197.     return 0;
  198. }
  199.  
  200. static stock Parser::ReplaceFunctions(szExpr[], &e_Error: iError, const iSize) {
  201.     new
  202.         szFormat[MAX_FUNCTION_PARAMS] = {
  203.             'f', ...
  204.         },
  205.         szName[MAX_FUNCTION_LENGTH],
  206.         szFunc[MAX_FUNCTION_FUNCTION_LENGTH],
  207.        
  208.         aszParams[MAX_FUNCTION_PARAMS][MAX_FUNCTION_PARAMS_LENGTH]
  209.     ;
  210.     for(new i = 0; i < MAX_FUNCTIONS; ++i) {
  211.         if(g_aeFunction[i][Func_szName][0] != EOS) {
  212.             new
  213.                 iPos = -1
  214.             ;
  215.             strunpack(szName, g_aeFunction[i][Func_szName], MAX_FUNCTION_LENGTH);
  216.            
  217.             while((iPos = strfind(szExpr, szName, false, (iPos + 1))) != -1) {
  218.                 new
  219.                     iParanthese = Parser::GetParantheseClosePos(szExpr, iPos, iSize),
  220.                     iParams
  221.                 ;
  222.                 if(iParanthese != -1) {
  223.                     new
  224.                         iLen = strlen(szName)
  225.                     ;
  226.                     Parser::ReplaceFunctions(szExpr[iPos + iLen + 1], iError, iParanthese);
  227.                    
  228.                     szExpr[iParanthese] = EOS;
  229.                    
  230.                     if(g_aeFunction[i][Func_iParams] > 1) {
  231.                         iParams = Parser::Explode(szExpr[iPos + iLen + 1], ",", aszParams);
  232.                     } else {
  233.                         strmid(aszParams[0], szExpr, iPos + iLen + 1, iParanthese);
  234.                         iParams++;
  235.                     }
  236.                     szExpr[iParanthese] = ')';
  237.                    
  238.                     if(iParams != g_aeFunction[i][Func_iParams]) {
  239.                         Parser::PrintErrors((iError = ERROR_PARAMETER_FUNCTION), -1);
  240.                         return 0;
  241.                     }
  242.                     while(iParams--) {
  243.                         new
  244.                             iTemp
  245.                         ;
  246.                         format(aszParams[iParams], MAX_FUNCTION_PARAMS_LENGTH, "%." #PRECISION "f", Parser::Evaluate(aszParams[iParams], iError, iTemp));
  247.                     }
  248.                     iParams = (g_aeFunction[i][Func_iParams] + 2) << 2;
  249.                    
  250.                     new
  251.                         iIdx = g_aeFunction[i][Func_iParams],
  252.                         Float: fValue
  253.                     ;
  254.                     while(iIdx--) {
  255.                         fValue = floatstr(aszParams[iIdx]);
  256.                        
  257.                         #emit LOAD.S.PRI fValue
  258.                         #emit HEAP 4
  259.                         #emit STOR.I
  260.                         #emit PUSH.ALT
  261.                     }
  262.                     szFormat[g_aeFunction[i][Func_iParams]] = EOS;
  263.                     #emit PUSH.ADR szFormat
  264.                    
  265.                     strunpack(szFunc, g_aeFunction[i][Func_szFunc], MAX_FUNCTION_FUNCTION_LENGTH);
  266.                     #emit PUSH.ADR szFunc
  267.                     #emit PUSH.S iParams
  268.                    
  269.                     #emit SYSREQ.C CallRemoteFunction
  270.                     #emit STOR.S.PRI fValue
  271.                    
  272.                     szFormat[g_aeFunction[i][Func_iParams]] = 'f';
  273.                    
  274.                     iParams += 4;
  275.                    
  276.                     #emit LCTRL 4
  277.                     #emit LOAD.S.ALT iParams
  278.                     #emit ADD
  279.                     #emit SCTRL 4
  280.                    
  281.                     iParams = (g_aeFunction[i][Func_iParams] << 2);
  282.                    
  283.                     #emit LCTRL 2
  284.                     #emit LOAD.S.ALT iParams
  285.                     #emit ADD
  286.                     #emit SCTRL 2
  287.                    
  288.                     strdel(szExpr, iPos, iParanthese + 1);
  289.                     strins(szExpr, Parser::ToString(fValue), iPos, iSize);
  290.                 } else {
  291.                     Parser::PrintErrors((iError = ERROR_LOGICAL_PARANTHESES), -1);
  292.                     return 0;
  293.                 }
  294.             }
  295.         }
  296.     }
  297.     return 1;
  298. }
  299.  
  300. stock Math::AddConstant(const szConst[], const Float: fValue) {
  301.     if(strlen(szConst) >= MAX_CONSTANT_LENGTH) {
  302.         Debug(Error, AddConstant, "MAX_CONSTANT_LENGTH (%d) exceeded! \n", MAX_CONSTANT_LENGTH);
  303.         return -1;
  304.     }
  305.     new
  306.         i = g_eiIndex[Constant]
  307.     ;
  308.     if(-1 < i < MAX_CONSTANTS) {
  309.         strpack(g_aeConstant[i][Const_szConst], szConst, MAX_CONSTANT_LENGTH char);
  310.         g_aeConstant[i][Const_fValue] = fValue;
  311.        
  312.         do {
  313.             g_eiIndex[Constant]++;
  314.         } while(g_aeConstant[g_eiIndex[Constant]][Const_szConst][0] != EOS);
  315.            
  316.         return i;
  317.     } else {
  318.         Debug(Error, AddConstant, "MAX_CONSTANTS (%d) exceeded! \n", MAX_CONSTANTS);
  319.         return -1;
  320.     }
  321. }
  322.  
  323. stock Math::RemoveConstant(const szConst[]) {
  324.     for(new i = 0; i < MAX_CONSTANTS; ++i) {
  325.         if(g_aeConstant[i][Const_szConst][0] != EOS) {
  326.             static
  327.                 s_szConst[MAX_CONSTANT_LENGTH]
  328.             ;
  329.             strunpack(s_szConst, g_aeConstant[i][Const_szConst], MAX_CONSTANT_LENGTH);
  330.            
  331.             if(!strcmp(s_szConst, szConst, false, MAX_CONSTANT_LENGTH)) {
  332.                 g_aeConstant[i][Const_szConst][0] = EOS;
  333.                
  334.                 if(i < g_eiIndex[Constant]) {
  335.                     g_eiIndex[Constant] = i;
  336.                 }
  337.                 return 1;
  338.             }
  339.         }
  340.     }
  341.     Debug(Error, RemoveConstant, "Unable to find constant \"%s\"! \n", szConst);
  342.     return 0;
  343. }
  344.  
  345. static stock Parser::ReplaceConstants(szExpr[], const iSize = sizeof(szExpr)) {
  346.     for(new i = 0; i < MAX_CONSTANTS; ++i) {
  347.         if(g_aeConstant[i][Const_szConst][0] != EOS) {
  348.             static
  349.                 s_szConst[MAX_CONSTANT_LENGTH],
  350.                 s_iPos,
  351.                 s_iLen
  352.             ;
  353.             strunpack(s_szConst, g_aeConstant[i][Const_szConst], MAX_CONSTANT_LENGTH);
  354.  
  355.             s_iPos = -1;
  356.             s_iLen = strlen(s_szConst);
  357.            
  358.             while((s_iPos = strfind(szExpr, s_szConst, false, (s_iPos + 1))) != -1) {
  359.                 if(s_iPos < s_iLen || s_iPos >= MAX_CONSTANT_LENGTH) {
  360.                     goto SkipCheck;
  361.                 }
  362.                 if(!(Parser::IsAlpha(szExpr[s_iPos - 1]) || Parser::IsAlpha(szExpr[s_iPos + s_iLen]))) {
  363.                     SkipCheck: {
  364.                         strdel(szExpr, s_iPos, s_iPos + s_iLen);
  365.                         strins(szExpr, Parser::ToString(g_aeConstant[i][Const_fValue]), s_iPos, iSize);
  366.                     }
  367.                 }
  368.             }
  369.         }
  370.     }
  371. }
  372.  
  373. stock Math::AddOperator(const szOp[], const szFunc[], const iPrecedence, const e_Assoc: iAssoc) {
  374.     if(strlen(szOp) >= MAX_OPERATOR_LENGTH) {
  375.         Debug(Error, AddOperator, "MAX_OPERATOR_LENGTH (%d) exceeded! \n", MAX_OPERATOR_LENGTH);
  376.         return -1;
  377.     }
  378.     if(strlen(szFunc) >= MAX_OPERATOR_FUNCTION_LENGTH) {
  379.         Debug(Error, AddOperator, "MAX_OPERATOR_FUNCTION_LENGTH (%d) exceeded! \n", MAX_OPERATOR_FUNCTION_LENGTH);
  380.         return -1;
  381.     }
  382.     new
  383.         i = g_eiIndex[Operator]
  384.     ;
  385.     if(-1 < i < MAX_OPERATORS) {
  386.         static
  387.             s_szFunc[MAX_OPERATOR_FUNCTION_LENGTH]
  388.         ;
  389.         format(s_szFunc, sizeof(s_szFunc), "%s_Op", szFunc);
  390.        
  391.         if(funcidx(s_szFunc) != -1) {
  392.             strpack(g_aeOperator[i][Op_szOp], szOp, MAX_OPERATOR_LENGTH char);
  393.             strpack(g_aeOperator[i][Op_szFunc], s_szFunc, MAX_OPERATOR_FUNCTION_LENGTH char);
  394.            
  395.             g_aeOperator[i][Op_iPrecedence] = iPrecedence;
  396.             g_aeOperator[i][Op_iAssoc] = iAssoc;
  397.            
  398.             do {
  399.                 g_eiIndex[Operator]++;
  400.             } while(g_aeOperator[g_eiIndex[Operator]][Op_szOp][0] != EOS);
  401.            
  402.             return i;
  403.         } else {
  404.             Debug(Error, AddOperator, "Unable to find operator function \"%s\"! \n", szFunc);
  405.             return -1;
  406.         }
  407.     } else {
  408.         Debug(Error, AddOperator, "MAX_OPERATORS (%d) exceeded! \n", MAX_OPERATORS);
  409.         return -1;
  410.     }
  411. }
  412.  
  413. stock Math::RemoveOperator(const szOp[]) {
  414.     for(new i = 0; i < MAX_OPERATORS; ++i) {
  415.         if(g_aeOperator[i][Op_szOp][0] != EOS) {
  416.             if(!strcmp(g_aeOperator[i][Op_szOp], szOp, false, MAX_OPERATOR_LENGTH)) {
  417.                 g_aeOperator[i][Op_szOp][0] = EOS;
  418.                
  419.                 if(i < g_eiIndex[Operator]) {
  420.                     g_eiIndex[Operator] = i;
  421.                 }
  422.                 return 1;
  423.             }
  424.         }
  425.     }
  426.     Debug(Error, RemoveOperator, "Unable to find operator \"%s\"! \n", szOp);
  427.     return 0;
  428. }
  429.  
  430. static stock Float: Parser::Evaluate(const szExpr[], &e_Error: iError, &iIdx) {
  431.     new
  432.         iStack,
  433.         eStack[e_Stack],
  434.         aeStack[MAX_OPERATORS][e_Stack],
  435.         Float: fValue = Parser::ParseValue(szExpr, iError, iIdx)
  436.     ;
  437.     aeStack[0][Stk_iOpIdx] = -1;
  438.    
  439.     while(iStack > -1) {
  440.         if(iError != ERROR_NONE) {
  441.             return 0.0;
  442.         }
  443.         Parser::ParseOperator(szExpr, iError, iIdx, eStack);
  444.        
  445.         while(eStack[Stk_iPrecedence] < aeStack[iStack][Stk_iPrecedence] || (eStack[Stk_iPrecedence] == aeStack[iStack][Stk_iPrecedence] && eStack[Stk_iAssoc] == LEFT_TO_RIGHT)) {
  446.             if(aeStack[iStack][Stk_iOpIdx] == -1) {
  447.                 return fValue;
  448.             }
  449.             fValue = Parser::Calculate(aeStack[iStack][Stk_fValue], fValue, aeStack[iStack][Stk_iOpIdx]);
  450.             iStack--;
  451.         }
  452.         aeStack[++iStack][Stk_iOpIdx] = eStack[Stk_iOpIdx];
  453.         aeStack[iStack][Stk_iPrecedence] = eStack[Stk_iPrecedence];
  454.         aeStack[iStack][Stk_iAssoc] = eStack[Stk_iAssoc];
  455.         aeStack[iStack][Stk_fValue] = fValue;
  456.            
  457.         fValue = Parser::ParseValue(szExpr, iError, iIdx);
  458.     }
  459.     return 0.0;
  460. }
  461.  
  462. static stock Float: Parser::Calculate(const Float: fValue1, const Float: fValue2, const iOpIdx) {
  463.     if(g_aeOperator[iOpIdx][Op_szOp][0] != EOS) {
  464.         static
  465.             s_szFunc[MAX_OPERATOR_FUNCTION_LENGTH]
  466.         ;
  467.         strunpack(s_szFunc, g_aeOperator[iOpIdx][Op_szFunc], MAX_OPERATOR_FUNCTION_LENGTH);
  468.        
  469.         return Float: CallRemoteFunction(s_szFunc, "ff", fValue1, fValue2);
  470.     }
  471.     return 0.0;
  472. }
  473.  
  474. static stock Parser::ParseOperator(const szExpr[], &e_Error: iError, &iIdx, eStack[e_Stack]) {
  475.     Parser::StripSpaces(szExpr, iIdx);
  476.    
  477.     eStack[Stk_iOpIdx] = 0;
  478.     eStack[Stk_iPrecedence] = 0;
  479.     eStack[Stk_iAssoc] = LEFT_TO_RIGHT;
  480.  
  481.     if(szExpr[iIdx] == ')') {
  482.         return 1;
  483.     }
  484.     if(iError == ERROR_NONE) {
  485.         for(new i = 0, iLen = 0; i < MAX_OPERATORS; ++i) {
  486.             static
  487.                 s_szOp[MAX_OPERATOR_LENGTH]
  488.             ;
  489.             strunpack(s_szOp, g_aeOperator[i][Op_szOp], MAX_OPERATOR_LENGTH);
  490.                
  491.             if(s_szOp[0] == szExpr[iIdx]) {
  492.                 if(!strcmp(szExpr[iIdx], s_szOp, false, (iLen = strlen(s_szOp)))) {
  493.                     iIdx += iLen;
  494.                        
  495.                     eStack[Stk_iOpIdx] = i;
  496.                     eStack[Stk_iPrecedence] = g_aeOperator[i][Op_iPrecedence];
  497.                     eStack[Stk_iAssoc] = g_aeOperator[i][Op_iAssoc];
  498.                     return 1;
  499.                 }
  500.             }
  501.         }
  502.     }
  503.     Parser::PrintErrors((iError = ERROR_LOGICAL_OPERATOR), iIdx);
  504.     return 0;
  505. }
  506.  
  507. static stock Float: Parser::ParseValue(const szExpr[], &e_Error: iError, &iIdx) {
  508.     Parser::StripSpaces(szExpr, iIdx);
  509.    
  510.     if(iError == ERROR_NONE) {
  511.         switch(szExpr[iIdx]) {
  512.             case '0' .. '9': {
  513.                 switch(szExpr[iIdx + 1]) {
  514.                     case 'x', 'X': {
  515.                         iIdx += 2;
  516.                        
  517.                         new
  518.                             iValue
  519.                         ;
  520.                         while(('a' <= szExpr[iIdx] <= 'f' || 'A' <= szExpr[iIdx] <= 'F' || ('0' <= szExpr[iIdx] <= '9'))) {
  521.                             switch(szExpr[iIdx]) {
  522.                                 case 'a' .. 'f': {
  523.                                     iValue = (iValue << 4) + (10 + szExpr[iIdx] - 'a');
  524.                                 }
  525.                                 case 'A' .. 'F': {
  526.                                     iValue = (iValue << 4) + (10 + szExpr[iIdx] - 'A');
  527.                                 }
  528.                                 case '0' .. '9': {
  529.                                     iValue = (iValue << 4) + (szExpr[iIdx] - '0');
  530.                                 }
  531.                             }
  532.                             iIdx++;
  533.                         }
  534.                         return float(iValue);
  535.                     }
  536.                     case 'b', 'B': {
  537.                         iIdx += 2;
  538.                        
  539.                         new
  540.                             iValue
  541.                         ;
  542.                         while(('0' <= szExpr[iIdx] <= '1')) {
  543.                             iValue = (iValue << 1) | (szExpr[iIdx++] - '0');
  544.                         }
  545.                         return float(iValue);
  546.                     }
  547.                     default: {
  548.                         new
  549.                             Float: fValue,
  550.                             Float: fScale
  551.                         ;
  552.                         while(('0' <= szExpr[iIdx] <= '9' || szExpr[iIdx] == '.')) {
  553.                             if(szExpr[iIdx] == '.') {
  554.                                 fScale = 1.0;
  555.                             } else {
  556.                                 fValue = (fValue * 10.0) + (szExpr[iIdx] - '0');
  557.                                 fScale *= 10.0;                            
  558.                             }
  559.                             iIdx++;
  560.                         }
  561.                         return fValue / ((fScale != 0.0) ? (fScale) : (1.0));
  562.                     }
  563.                 }
  564.             }
  565.             case '(': {
  566.                 iIdx++;
  567.                
  568.                 new
  569.                     Float: fValue = Parser::Evaluate(szExpr, iError, iIdx)
  570.                 ;
  571.                 Parser::StripSpaces(szExpr, iIdx);
  572.                
  573.                 if(szExpr[iIdx] != ')') {
  574.                     Parser::PrintErrors((iError = ERROR_LOGICAL_PARANTHESES), iIdx);
  575.                     return 0.0;
  576.                 }
  577.                 iIdx++;
  578.                
  579.                 return fValue;
  580.             }
  581.             case '+': {
  582.                 iIdx++;
  583.                 return Parser::ParseValue(szExpr, iError, iIdx);
  584.             }
  585.             case '-': {
  586.                 iIdx++;
  587.                 return -Parser::ParseValue(szExpr, iError, iIdx);
  588.             }
  589.             default: {
  590.                 Parser::PrintErrors((iError = ERROR_LOGICAL_VALUE), iIdx);
  591.             }
  592.         }
  593.     }
  594.     return 0.0;
  595. }
  596.  
  597. static stock Parser::GetParantheseClosePos(szExpr[], iPos, const iSize) {
  598.     new
  599.         iOpened,
  600.         iClosed
  601.     ;
  602.     while(iPos < iSize-1) {
  603.         if(szExpr[iPos] == '(') {
  604.             iOpened++;
  605.         } else if(szExpr[iPos] == ')') {
  606.             iClosed++;
  607.            
  608.             if(iOpened == iClosed) {
  609.                 break;
  610.             }
  611.         }
  612.         ++iPos;
  613.     }
  614.     if(iOpened != iClosed) {
  615.         return -1;
  616.     }
  617.     return iPos;
  618. }
  619.  
  620. static stock Parser::Explode(szSrc[], const szDelim[], aszDest[][], iSize = sizeof(aszDest), iLen = sizeof(aszDest[])) { // Slice
  621.     new
  622.         iPos = -1,
  623.         iLastPos,
  624.         i
  625.     ;
  626.     goto LoopEnd;
  627.    
  628.     do {
  629.         strcat((aszDest[i][0] = EOS, aszDest[i]), szSrc[iLastPos], min(iLen, iPos - iLastPos + 1));
  630.        
  631.         if (++i >= iSize)
  632.             break;
  633.        
  634.     LoopEnd:
  635.         iLastPos = ++iPos;
  636.     } while((iPos = strfind(szSrc, szDelim, false, iPos)) != -1);
  637.    
  638.     if(i < iSize) {
  639.         strcat((aszDest[i][0] = EOS, aszDest[i++]), szSrc[iLastPos], iLen);
  640.     }
  641.     return i;
  642. }
  643.  
  644. static stock Parser::PrintErrors(const e_Error: iError, const iIdx) {
  645.     switch(iError) {
  646.         case ERROR_LOGICAL_VALUE: {
  647.             Debug(Syntax Error, Parsing, "Invalid value found at index %d! \n", iIdx);
  648.         }
  649.         case ERROR_LOGICAL_OPERATOR: {
  650.             Debug(Syntax Error, Parsing, "Invalid operator found at index %d! \n", iIdx);
  651.         }
  652.         case ERROR_LOGICAL_PARANTHESES: {
  653.             Debug(Syntax Error, Parsing, "Invalid paranthese logic found at index %d! \n", iIdx);
  654.         }
  655.         case ERROR_PARAMETER_FUNCTION: {
  656.             Debug(Syntax Error, Parsing, "Invalid parameters found in a function! \n");
  657.         }
  658.     }
  659. }
  660.  
  661. static stock Parser::StripSpaces(const szInput[], &iIdx) {
  662.     while(Parser::IsSpace(szInput[iIdx]) != 0) {
  663.         iIdx++;
  664.     }
  665. }
  666.  
  667. static stock Parser::IsSpace(const iChar) {
  668.     switch(iChar) {
  669.         case ' ', '\n', '\r', '\t': {
  670.             return 1;
  671.         }
  672.     }
  673.     return 0;
  674. }
  675.  
  676. static stock Parser::IsAlpha(const iChar) {
  677.     switch(iChar) {
  678.         case 'a' .. 'z', 'A' .. 'Z': {
  679.             return 1;
  680.         }
  681.     }
  682.     return 0;
  683. }
  684.  
  685. static stock Parser::ToString(const Float: fValue) {
  686.     static
  687.         szValue[16]
  688.     ;
  689.     format(szValue, sizeof(szValue), "%." #PRECISION "f", fValue);
  690.     return szValue;
  691. }
  692.  
  693. Math::Operator E(const Float: fValue, const Float: fExponent) {
  694.     return fValue * floatpower(10.0, fExponent);
  695. }
  696.  
  697. Math::Operator Pow(const Float: fValue1, const Float: fValue2) {
  698.     return floatpower(fValue1, fValue2);
  699. }
  700.  
  701. Math::Operator Mul(const Float: fValue1, const Float: fValue2) {
  702.     return fValue1 * fValue2;
  703. }
  704.  
  705. Math::Operator Div(const Float: fValue1, const Float: fValue2) {
  706.     return fValue1 / fValue2;
  707. }
  708.  
  709. Math::Operator Mod(const Float: fValue1, const Float: fValue2) {
  710.     return fValue1 - fValue2 * floatround((fValue1 / fValue2), floatround_floor);
  711. }
  712.  
  713. Math::Operator Add(const Float: fValue1, const Float: fValue2) {
  714.     return fValue1 + fValue2;
  715. }
  716.  
  717. Math::Operator Sub(const Float: fValue1, const Float: fValue2) {
  718.     return fValue1 - fValue2;
  719. }
  720.  
  721. Math::Function Log(const Float: fValue, const Float: fBase) {
  722.     return floatlog(fValue, fBase);
  723. }
  724.  
  725. Math::Function Sqrt(const Float: fValue) {
  726.     return floatsqroot(fValue);
  727. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement