Subversion Repositories Kolibri OS

Rev

Rev 9763 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #include <math.h>
  2. #include <string.h>
  3.  
  4. #include <sys/ksys.h>
  5.  
  6. #include "func.h"
  7. #include "parser.h"
  8.  
  9. #define nullptr 0
  10.  
  11. // token types
  12. #define DELIMITER 1
  13. #define VARIABLE 2
  14. #define NUMBER 3
  15. #define FUNCTION 4
  16. #define FINISHED 10
  17.  
  18. // error codes
  19. #define ERR_BADFUNCTION -1
  20. #define ERR_BADNUMBER -2
  21. #define ERR_GENERAL -3
  22. #define ERR_NOBRACKET -4
  23. #define ERR_BADVARIABLE -5
  24. #define ERR_OVERFLOW -6
  25.  
  26. //I guess it's not the best idea but we need pointers to functions anyway
  27. double sin_p(double d) {
  28.         return sin(d);
  29. }
  30.  
  31. double cos_p(double d) {
  32.         return cos(d);
  33. }
  34.  
  35. double exp_p(double d) {
  36.         return exp(d);
  37. }
  38.  
  39. double sqrt_p(double d) {
  40.         return sqrt(d);
  41. }
  42.  
  43. double log_p(double d) {
  44.         return log(d);
  45. }
  46.  
  47. double tan_p(double d) {
  48.         return tan(d);
  49. }
  50.  
  51. double ctg(double d) {
  52.         return 1 / tan(d);
  53. }
  54.  
  55. double asin_p(double d) {
  56.         return asin(d);
  57. }
  58.  
  59. double acos_p(double d) {
  60.         return acos(d);
  61. }
  62.  
  63. double atan_p(double d) {
  64.         return atan(d);
  65. }
  66.  
  67. double fabs_p(double d) {
  68.         return fabs(d);
  69. }
  70.  
  71. double sgn(double d) {
  72.         if (d < 0) return -1;
  73.         return 1;
  74. }
  75.  
  76. double arcctg(double d) {
  77.         return atan(1 / d);
  78. }
  79.  
  80. double sec(double d) {
  81.         return 1 / sin(d);
  82. }
  83.  
  84. double cosec(double d) {
  85.         return 1 / cos(d);
  86. }
  87.  
  88. double log2_p(double d) {
  89.         return log2(d);
  90. }
  91.  
  92. double log10_p(double d) {
  93.         return log10(d);
  94. }
  95.  
  96. double log3(double d) {
  97.         return log(d) / log(3);
  98. }
  99.  
  100. // represents general mathematical function
  101. typedef double(*matfunc)(double);
  102.  
  103. // used to link function name to the function
  104. typedef struct {
  105.         char name[10];
  106.         matfunc f;
  107. } func;
  108.  
  109. // the list of functions
  110. #define MAX_FUNCS 26
  111. func functions[MAX_FUNCS] = {
  112.         "", (matfunc)nullptr,
  113.         "sin", (matfunc)&sin_p,
  114.         "cos", (matfunc)&cos_p,
  115.         "exp", (matfunc)&exp_p,
  116.         "sqrt", (matfunc)&sqrt_p,
  117.         "log", (matfunc)&log_p,
  118.         "tg", (matfunc)&tan_p,
  119.         "tan", (matfunc)&tan_p,
  120.         "ctg", (matfunc)&ctg,
  121.         "cot", (matfunc)&ctg,
  122.         "arcsin", (matfunc)&asin_p,
  123.         "arccos", (matfunc)&acos_p,
  124.         "arctg", (matfunc)&atan_p,
  125.         "arctan", (matfunc)&atan_p,
  126.         "abs", (matfunc)&fabs_p,
  127.         "sgn", (matfunc)&sgn,
  128.         "arcctg", (matfunc)&arcctg,
  129.         "arccot", (matfunc)&arcctg,
  130.         "sec", (matfunc)&sec,
  131.         "cosec", (matfunc)&cosec,
  132.         "lb", (matfunc)&log2_p,
  133.         "log2", (matfunc)&log2_p,
  134.         "lg", (matfunc)&log10_p,
  135.         "log10", (matfunc)&log10_p,
  136.         "log3", (matfunc)&log3,
  137.         "ln", (matfunc)&log_p
  138. };
  139.  
  140. // all delimiters
  141. const char* delim="+-*^/%=;(),><";              // not bad words
  142.  
  143. // structure for most parser functions
  144. char token[80];
  145. int token_type;
  146. char* prog;
  147. double x_value;
  148. int code;    // error code
  149.  
  150. int isdelim(char c) {
  151.         //return strchr(delim, c) != 0;
  152.         for (int i = 0; i < 14; i++)
  153.                 if (c == delim[i])
  154.                         return 1;
  155.         return 0;
  156. }
  157.  
  158. int isdigit(char c) {
  159.         return (c >= '0' && c <= '9');
  160. }
  161.  
  162. int isalpha2(char c) {
  163.         return ((c >= 'a' && c <= 'z')
  164.                 || (c >= 'A' && c <= 'Z'));
  165. }
  166.  
  167. int iswhite(char c) {
  168.         return (c==' ' || c=='\t');
  169. }
  170.  
  171. void serror(int code) {
  172.         /*switch (code) {
  173.                 case ERR_BADFUNCTION:
  174.                         _ksys_debug_puts("ERR_BADFUNCTION\n");
  175.                         break;
  176.                 case ERR_BADNUMBER:
  177.                         _ksys_debug_puts("ERR_BADNUMBER\n");
  178.                         break;
  179.                 case ERR_NOBRACKET:
  180.                         _ksys_debug_puts("ERR_NOBRACKET\n");
  181.                         break;
  182.                 case ERR_BADVARIABLE:
  183.                         _ksys_debug_puts("ERR_BADVARIABLE\n");
  184.                         break;
  185.                 case ERR_OVERFLOW:
  186.                         _ksys_debug_puts("ERR_OVERFLOW\n");
  187.                         break;
  188.         }*/
  189.         //TODO (vitalkrilov): for what?: "::code = code;"
  190.         // longjmp(j, code);
  191. }
  192.  
  193. void set_exp(char* exp, double x) {
  194.         prog = exp;
  195.         x_value = x;
  196. }
  197.  
  198. int get_token() {
  199.         int tok;
  200.         char* temp;
  201.         (token_type) = 0;
  202.         tok = 0;
  203.         temp = (token);
  204.  
  205.         if (*(prog) == '\0') {
  206.                 *(token) = 0;
  207.                 tok = FINISHED;
  208.                 return ((token_type) = DELIMITER);
  209.         }
  210.         while (iswhite(*(prog))) ++(prog);
  211.         if (isdelim(*(prog))) {
  212.                 *temp = *(prog);
  213.                 (prog)++;
  214.                 temp++;
  215.                 *temp = 0;
  216.                 return ((token_type) = DELIMITER);
  217.         }
  218.         if (isdigit(*(prog))) {
  219.                 while (!isdelim(*(prog)))
  220.                         *temp++=*(prog)++;
  221.                 *temp = '\0';
  222.                 return ((token_type) = NUMBER);
  223.         }
  224.         if (isalpha2(*(prog))) {
  225.                 while (!isdelim(*(prog)))
  226.                         *temp++=*(prog)++;
  227.                 (token_type) = VARIABLE;
  228.         }
  229.         *temp = '\0';
  230.         if ((token_type) == VARIABLE) {
  231.                 tok = look_up((token));
  232.                 if (tok)
  233.                         (token_type) = FUNCTION;
  234.         }
  235.         return (token_type);
  236. }
  237.  
  238. int sign(double d) {
  239.   if (d > 0.0)
  240.     return 1.0;
  241.   if (d < 0.0)
  242.     return -1.0;
  243.   return 0.0;
  244. }
  245.  
  246. void putback() {
  247.         char* t;
  248.         t = (token);
  249.         for (;*t;t++)
  250.                 (prog)--;
  251. }
  252.  
  253. int get_exp(double* hold) {
  254.   int res;
  255.   code = 0;
  256. //  if (res = setjmp(j) != 0)
  257. //    return code;
  258.         get_token();
  259.         if (!*(token)) {
  260.                 return 0;
  261.         }
  262.         level2( hold);
  263.         putback();
  264.   return 0;
  265. }
  266.  
  267. void level2(double* hold) {
  268.         char op;
  269.         double h;
  270.  
  271.         level3( hold);
  272.         while ((op=*(token)) == '+' || op == '-') {
  273.                 get_token();
  274.                 level3( &h);
  275.                 arith(op, hold, &h);
  276.         }
  277. }
  278.  
  279. void level3(double* hold) {
  280.         char op;
  281.         double h;
  282.  
  283.         level4( hold);
  284.         while ((op=*(token)) == '*' || op == '/' || op == '%') {
  285.                 get_token();
  286.                 level4( &h);
  287.                 arith( op, hold, &h);
  288.         }
  289. }
  290.  
  291. void level4(double* hold) {
  292.         double h;
  293.         level5( hold);
  294.  
  295.         if (*(token) == '^') {
  296.                 get_token();
  297.                 level5( &h);
  298.                 arith( '^', hold, &h);
  299.         }
  300. }
  301.  
  302. void level5(double* hold) {
  303.         char op;
  304.  
  305.         op = 0;
  306.         if (((token_type) == DELIMITER) && *(token) == '+' || *(token) == '-') {
  307.                 op = *(token);
  308.                 get_token();
  309.         }
  310.         level6( hold);
  311.  
  312.         if (op) unary(op, hold);
  313. }
  314.  
  315. void level6(double* hold) {
  316.         if ((*(token) == '(') && ((token_type) == DELIMITER)) {
  317.                 get_token();
  318.                 level2( hold);
  319.                 if (*(token) != ')')
  320.       serror( ERR_NOBRACKET);
  321.                 get_token();
  322.         }
  323.         else
  324.                 primitive( hold);
  325. }
  326.  
  327. void calc_function(double* hold) {
  328.         double d;
  329.         int i;
  330.  
  331.         i = look_up(token);
  332.  
  333.         if (i == 0)
  334.                 serror(ERR_BADFUNCTION);        // error
  335.  
  336.         get_token();
  337.         if (*(token) != '(')
  338.                 serror(ERR_NOBRACKET);  // error
  339.         get_token();
  340.         level2(hold);
  341.         get_token();
  342.  
  343.   d = functions[i].f(*hold);
  344.   *hold = (functions[i].f)(*hold);
  345. //  else
  346. //    serror( ERR_OVERFLOW);
  347.  
  348. }
  349.  
  350. void primitive(double* hold) {
  351.         switch (token_type) {
  352.                 case VARIABLE:
  353.                         *hold = find_var(token);
  354.                         get_token();
  355.                         return;
  356.                 case NUMBER:
  357.                 //*hold = atof((token));
  358.                 //if (sscanf(token, "%lf", hold) != 1)
  359.                                 *hold = convert(token, nullptr);
  360.                         if (*hold == ERROR)
  361.                                 serror( ERR_BADNUMBER);
  362.                         get_token();
  363.                         return;
  364.                 case FUNCTION:
  365.                         calc_function( hold);
  366.                         return;
  367.                 default:        // error
  368.                         return;
  369.         }
  370. }
  371.  
  372. void arith(char op, double* r, double* h) {
  373.         double t;
  374.         switch(op) {
  375.                 case '-':
  376.                         *r = *r - *h;
  377.                         break;
  378.                 case '+':
  379.                         *r = *r + *h;
  380.                         break;
  381.                 case '*':
  382.                         *r = *r * *h;
  383.                         break;
  384.                 case '/':
  385.             if (*h == 0)
  386.               serror( ERR_OVERFLOW);
  387.             else
  388.                           *r = (*r) / (*h);
  389.                         break;
  390.                 case '%':
  391.             if (*h == 0)
  392.               serror( ERR_OVERFLOW);
  393.             else
  394.                         *r = fmod(*r, *h);
  395.                         if (*r < 0) *r += *h;
  396.                         break;
  397.                 case '^':
  398.                         *r = pow(*r, *h);
  399.                         break;
  400.         }
  401. }
  402.  
  403. void unary(char op, double* r) {
  404.         if (op == '-')
  405.                 *r = -(*r);
  406. }
  407.  
  408. double find_var(const char* s) {
  409.         //return 0;     // not imp
  410.         //int i;
  411.  
  412.         //for (i = 0; i < kvar; i++)
  413.         //      if (strcmp(vars[i].name, s) == 0)
  414.         //              return vars[i].value;
  415.  
  416.         if (s[1] == '\0' && (s[0] == 'x' || s[0] == 'X'))
  417.         //if (strcmp(s,"x") == 0 || strcmp(s,"X") == 0)
  418.                 return x_value;
  419.  
  420.         serror( ERR_BADVARIABLE);
  421.   return 0; // to make compiler very happy
  422.  
  423.         //printf("\nPlease enter value for variable \"%s\": ", s);
  424.         //scanf("%lf", &vars[kvar].value);
  425.         //strcpy(vars[kvar].name, s);
  426.         //kvar++;
  427.         //return vars[kvar - 1].value;
  428. }
  429.  
  430. int look_up(const char* s) {
  431.         int i;
  432.  
  433.         for (i = 0; i < MAX_FUNCS; i++)
  434.                 if (strcmp(s, functions[i].name) == 0)
  435.                         return i;
  436.         return 0;       // search command/function name
  437. }
  438.