Advertisement
overloop

excel formula compiler 130% done

Apr 10th, 2013
177
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.67 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4.  
  5. #define MAX_OPERANDS 100
  6. #define MAX_DICT 1024
  7. #define FILE_BUF 1024
  8.  
  9. /* dict.dat
  10. add2    ($0+$1)
  11. add3    ($0+$1+$2)
  12. add4    ($0+$1+$2+$3)
  13. add5    ($0+$1+$2+$3+$4)
  14. add6    ($0+$1+$2+$3+$4+$5)
  15. add15   ($0+$1+$2+$3+$4+$5+$6+$7+$8+$9+$10+$11+$12+$13+$14)
  16. mul2    ($0*$1)
  17. mul3    ($0*$1*$2)
  18. mul4    ($0*$1*$2*$3)
  19. mul5    ($0*$1*$2*$3*$4)
  20. mul6    ($0*$1*$2*$3*$4*$5)
  21. div2    ($0/$1)
  22. sub2    ($0-$1)
  23. sub1    (-$0)
  24. ifthen  И($0)*($1)
  25. and2    И($0;$1)*($2)
  26. # 1d линейная интерполяция по двум точкам f(x x1 x2 y1 y2)
  27. interp1d    И($0>=$1;$0<$2)*(($0-$1)/($2-$1)*($4-$3)+$3)
  28. # 2d линейная интерполяция по четырём точкам f(x y x1 x2 y1 y2 z11 z12 z21 z22)
  29. interp2d    И($0>=$2;$0<$3;$1>=$4;$1<$5)*((($1-$4)/($5-$4)*($9-$7-$8+$6)+$7-$6)*($0-$2)/($3-$2)+($1-$4)/($5-$4)*($8-$6)+$6)
  30.  
  31.  */
  32.  
  33. /* try me
  34.  
  35. add3(ifthen(B1<7;add6(interp1d(A1;0,45;0,55;4;4);interp1d(A1;0,55;0,65;4;3,5);interp1d(A1;0,65;0,75;3,5;3);interp1d(A1;0,75;0,85;3;2);interp1d(A1;0,85;0,95;0;0);interp1d(A1;0,95;1,05;0;0)));and2(B1>=7;B1<17;add6(interp1d(A1;0,45;0,55;5;5);interp1d(A1;0,55;0,65;5;4,5);interp1d(A1;0,65;0,75;4,5;4);interp1d(A1;0,75;0,85;4;3);interp1d(A1;0,85;0,95;3;2,5);interp1d(A1;0,95;1,05;2,5;2)));ifthen(B1>=17;add6(interp1d(A1;0,45;0,55;0;0);interp1d(A1;0,55;0,65;0;0);interp1d(A1;0,65;0,75;6;6);interp1d(A1;0,75;0,85;6;5,5);interp1d(A1;0,85;0,95;5,5;5);interp1d(A1;0,95;1,05;5;4,5))))
  36.  
  37. */
  38.  
  39. struct excel_exp;
  40.  
  41. char* excel_alloc_string(size_t len);
  42.  
  43. struct excel_rewrite {
  44.     char* name[MAX_DICT];
  45.     char* val[MAX_DICT];
  46.     int num;
  47. } excel_rewrite_dict;
  48.  
  49. /** Читает список функций из файла dict.dat, заполняет ими excel_rewrite_dict.
  50.  *
  51.  */
  52. void excel_init_dict() {
  53.     FILE* f = fopen("dict.dat","r");
  54.     memset(&excel_rewrite_dict,0,sizeof(struct excel_rewrite));
  55.    
  56.     char buf[FILE_BUF];
  57.     if ( f==0 )
  58.     {
  59.         fprintf(stderr,"error opening file dict.dat\n");
  60.         return ;
  61.     }
  62.     int n = 0;
  63.     while (!feof(f))
  64.     {
  65.         fgets(buf,FILE_BUF,f);
  66.         char* p = strchr(buf,'\t');
  67.        
  68.         if (buf[0] == '#')
  69.             continue ;
  70.        
  71.         if (p) {
  72.             int l1 = strlen(buf);
  73.             int l2 = strlen(p);
  74.            
  75.             char* name = excel_alloc_string(l1-l2);
  76.             strncat(name,buf,l1-l2);
  77.             char* val = excel_alloc_string(l2-1);
  78.             strncat(val,p+1,l2-2);
  79.            
  80.             excel_rewrite_dict.name[n] = name;
  81.             excel_rewrite_dict.val[n] = val;
  82.             ++n;
  83.         }
  84.     }
  85.     excel_rewrite_dict.num = n-1;
  86. }
  87.  
  88. /** Освобождает память, очищая список определенных функций
  89.  *
  90.  */
  91. void excel_uninit_dict() {
  92.     int i;
  93.     for (i=0;i<excel_rewrite_dict.num;i++)
  94.     {
  95.         free(excel_rewrite_dict.name[i]);
  96.         free(excel_rewrite_dict.val[i]);
  97.     }
  98. }
  99.  
  100. /** Выражение: имя, операнды, значение.
  101.  *  Операнды могут быть как строками op, так и вложеными выражениями ope
  102.  */
  103. struct excel_exp {
  104.     char* name;
  105.     char* op[MAX_OPERANDS];
  106.     struct excel_exp* ope[MAX_OPERANDS];
  107.     int num;
  108.     char* val;
  109. };
  110.  
  111. struct excel_exp* excel_parse(char* exp);
  112.  
  113. /** Выделяет память под выражение
  114.  *
  115.  */
  116. struct excel_exp* excel_alloc_exp() {
  117.     struct excel_exp* exp;
  118.     exp = malloc(sizeof(struct excel_exp));
  119.     memset(exp,0,sizeof(struct excel_exp));
  120.     return exp;
  121. }
  122.  
  123. /** Выделяет память под строку
  124.  *
  125.  */
  126. char* excel_alloc_string(size_t len) {
  127.     char* s = (char*) malloc(len+1);
  128.     memset(s,0,len+1);
  129.     return s;
  130. }
  131.  
  132. /** Определяет является ли строка выражением.
  133.  *  Другими словами, содержит ли строка ';'
  134.  */
  135. int excel_isexp(char* exp) {
  136.     if (strchr(exp,';')!=0) {
  137.         //printf("%s is exp",exp);
  138.         return 1;
  139.     }
  140.     //printf("%s is not exp",exp);
  141.     return 0;
  142. }
  143.  
  144. /** Определяет есть ли в выражении нераспарсеные вложеные выражения
  145.  *
  146.  */
  147. int excel_isleaf(struct excel_exp* exp) {
  148.     int i=-1;
  149.     while (++i<exp->num) {
  150.         if (exp->ope[i]) return 0;
  151.     }
  152.     return 1;
  153. }
  154.  
  155. /** Очищает память, выделенную под операнды и имя функции
  156.  *
  157.  */
  158. void excel_free_op(struct excel_exp* exp) {
  159.     int j;
  160.     free(exp->name);
  161.     exp->name = 0;
  162.     for (j=0;j<exp->num;j++)
  163.     {
  164.         free(exp->op[j]);
  165.         free(exp->ope[j]);
  166.         exp->op[j] = 0;
  167.         exp->ope[j] = 0;
  168.     }
  169.     exp->num = 0;
  170. }
  171.  
  172. /** Подсчитывает число использования операндов в шаблоне
  173.  *  Операнды в шаблоне обозначаются как $0, $1 ... $9
  174.  *  @todo escaping \$
  175.  */
  176. int excel_count_vars(char* val) {
  177.     int n = 0;
  178.     char* p = val;
  179.     while (p) {
  180.         p = strchr(p+1,'$');
  181.         if (p) n++;
  182.     }
  183.     return n;
  184. }
  185.  
  186. /** Определяет длинну самого длинного операнда
  187.  *
  188.  */
  189. int excel_max_op_length(struct excel_exp* exp) {
  190.     int maxl = 0;
  191.     int li = 0;
  192.     int j;
  193.     for (j=0;j<exp->num;j++)
  194.     {
  195.         li = strlen(exp->op[j]);
  196.         if (li>maxl) maxl = li;
  197.     }
  198.     return maxl;
  199. }
  200.  
  201. /** Очищает память выделенную под выражение
  202.  *
  203.  */
  204. void excel_free_exp(struct excel_exp* exp) {
  205.     excel_free_op(exp);
  206.     free(exp->val);
  207.     free(exp); // не догоняю почему всё падает
  208. }
  209.  
  210. /** Переписывает выражение, используя словарь excel_rewrite_dict
  211.  *  Находит в словаре шаблон по имени функции и подставляет в него операнды.
  212.  *  Если не найдет поставит undefined
  213.  */
  214. void excel_rewrite(struct excel_exp* exp) {
  215.     int i,j;
  216.     for (i=0;i<excel_rewrite_dict.num;i++)
  217.     {
  218.         if (strcmp(exp->name,excel_rewrite_dict.name[i]) == 0)
  219.         {
  220.             // на результирующую строку будет достаточно n символов, где
  221.             // n = длинна шаблона + число использования операндов в шаблоне * длинна самого длинного операнда
  222.             int li = excel_max_op_length(exp);
  223.             int n = excel_count_vars(excel_rewrite_dict.val[i]);
  224.             int l = li * n + strlen(excel_rewrite_dict.val[i]);
  225.             char* val = excel_alloc_string(l);
  226.            
  227.             char* p = excel_rewrite_dict.val[i];
  228.             while(*p) {
  229.                 if (*p == '$') {
  230.                     ++p;
  231.                    
  232.                     int i = 0;
  233.                     char d1,d2;
  234.                     d1 = *p;
  235.                     d2 = *(p+1);
  236.                    
  237.                     if (d2>='0' && d2 <='9') {
  238.                         i = (d1 - '0')*10 + (d2 - '0');
  239.                         ++p;
  240.                     } else {
  241.                         i = (d1 - '0');
  242.                     }
  243.                    
  244.                     if (i>=0 && i<MAX_OPERANDS && exp->op[i])
  245.                         strcat(val,exp->op[i]);
  246.                 } else {
  247.                     strncat(val,p,1);
  248.                 }
  249.                 ++p;
  250.             }
  251.             excel_free_op(exp);
  252.             exp->val = val;
  253.             return;
  254.         }
  255.     }
  256.     fprintf(stderr,"%s undefined\n",exp->name);
  257.     excel_free_op(exp);
  258.     char* undef = excel_alloc_string(10);
  259.     strcat(undef,"undefined");
  260.     exp->val = undef;
  261. }
  262.  
  263. /** Поднимается по дереву выражений, переписывая функции по словарю в бездетных
  264.  *  (крайних) нодах, разбирая дерево.
  265.  *  Если всё дерево разобрано, возвращает 1
  266.  */
  267. int excel_collapse(struct excel_exp* exp) {
  268.     int i;
  269.    
  270.     if (exp->val)
  271.         return 1;
  272.     if (excel_isleaf(exp))
  273.         excel_rewrite(exp);
  274.    
  275.     for (i=0;i<exp->num;i++)
  276.     {
  277.         if (exp->ope[i]) {
  278.             excel_collapse(exp->ope[i]);
  279.             if (exp->ope[i]->val) {
  280.                
  281.                 free(exp->op[i]);
  282.                 exp->op[i] = exp->ope[i]->val;
  283.                
  284.                 excel_free_op(exp->ope[i]);
  285.                 free(exp->ope[i]);
  286.                 exp->ope[i] = 0;
  287.             }
  288.         }
  289.     }
  290.     return 0;
  291. }
  292.  
  293. struct excel_exp* excel_build_tree(char* exp);
  294.  
  295. /** Парсит строку в дерево выражений
  296.  */
  297. struct excel_exp* excel_build_tree(char* exp) {
  298.  
  299.     struct excel_exp* root = excel_alloc_exp();
  300.    
  301.     /* идем по строке отмечая ; не вложеные в скобки, также отмечаем первую
  302.      * открывающую и последнюю закрывающую скобку, чтобы выделить называние
  303.      * функции и операнды
  304.      * название_функции(операнд;операнд;вложеная_функция(операнд;операнд);операнд)
  305.      * semicolon:     [0]     [1]     [2]                               [3]     [4]
  306.      * j==5; exp->num = j-1
  307.      */
  308.     size_t l = strlen(exp);
  309.     int semicolon[MAX_OPERANDS+1];
  310.     int parenthesis = 0;
  311.     int i = -1;
  312.     int j = 0;
  313.     while (++i<l) {
  314.         switch (exp[i]) {
  315.             case '(' : if (j==0) {semicolon[j++] = i;} parenthesis++; break;
  316.             case ')' : parenthesis--; if (parenthesis == 0) semicolon[j++] = i; break;
  317.             case ';' : if (parenthesis == 1) semicolon[j++] = i; break;
  318.         }
  319.         if (j>MAX_OPERANDS+1) {
  320.             fprintf(stderr,"MAX_OPERANDS exceeded in %s\n",exp);
  321.             return 0;
  322.         }
  323.     }
  324.     if (parenthesis > 0)
  325.         fprintf(stderr,"unmatched parenthesis, need %i ) more\n",parenthesis);
  326.     if (parenthesis < 0)
  327.         fprintf(stderr,"unmatched parenthesis, need %i ( more\n",-parenthesis);
  328.     --j;
  329.    
  330.     size_t li = semicolon[0];
  331.     char* name = excel_alloc_string(li);
  332.     strncpy(name,exp,li);
  333.     root->name = name;
  334.     root->num = j;
  335.    
  336.     for (i=0;i<j;i++)
  337.     {
  338.         li = semicolon[i+1] - semicolon[i] - 1;
  339.        
  340.         if (li>0)
  341.         {
  342.             char* opi = excel_alloc_string(li);
  343.             strncpy(opi, exp + semicolon[i]+1,li);
  344.            
  345.             if (excel_isexp(opi))
  346.                 root->ope[i] = excel_build_tree(opi);
  347.             root->op[i] = opi;
  348.         } else {
  349.             root->num = root->num - 1;
  350.         }
  351.     }
  352.    
  353.     return root;
  354. }
  355.  
  356. /** Переписывает фунции двигаясь
  357.  *  от ветвей к корню. В exp->val оказывается результат
  358.  */
  359. char* excel_collapse_tree(struct excel_exp* exp) {
  360.     // трясём дерево пока не упадёт
  361.     int r = 0;
  362.     while (r != 1)
  363.         r = excel_collapse(exp);
  364.     return exp->val;
  365. }
  366.  
  367. int main(int argc, char** argv) {
  368.     char* exp_string = 0;
  369.     excel_init_dict();
  370.     if (excel_rewrite_dict.num < 1) {
  371.         fprintf(stderr,"dict.dat has no records, please create dict.dat\n");
  372.         fprintf(stderr,"dict.dat format: each line has the name of the function\n");
  373.         fprintf(stderr,"and value to replace it with, separated with tab\n");
  374.         fprintf(stderr,"example:\nadd2  ($0+$1)\nmul2   ($0*$1)\n");
  375.         return 0;
  376.     }
  377.  
  378.     if (argc>1 && strcmp(argv[1],"--help")!=0 && strcmp(argv[1],"-h")!=0 && strcmp(argv[1],"/?")!=0)
  379.     {
  380.         exp_string = argv[1];
  381.     }
  382.     else
  383.     {
  384.         printf("usage: compiler.exe \"formula\"\nexample: compiler.exe \"add2(mul2(A1;A2);2)\"\n");
  385.         return 0;
  386.     }
  387.    
  388.     struct excel_exp* exp = excel_build_tree(exp_string);
  389.     char* val = excel_collapse_tree(exp);
  390.     printf("=%s",val);
  391.     excel_free_exp(exp);
  392.    
  393.     excel_uninit_dict();
  394.     return 0;
  395. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement