Advertisement
NovaYoshi

SYACalc

Oct 14th, 2011
209
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.42 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <ctype.h>
  4. #include <stdlib.h>
  5.  
  6. typedef unsigned char  u8;
  7. typedef unsigned short u16;
  8. typedef unsigned long  u32;
  9.  
  10. enum Operator {
  11.   OP_END_LIST, OP_COMMA,
  12.   OP_ADD,     OP_SUB,     OP_MUL,     OP_DIV,     OP_MOD,
  13.   OP_BIT_AND, OP_BIT_OR,  OP_BIT_XOR, OP_BIT_NOT,
  14.   OP_LOG_AND, OP_LOG_OR,  OP_LOG_XOR, OP_LOG_NOT,
  15.   OP_SHIFT_L, OP_SHIFT_R, OP_NEGATE,  OP_POWER,   OP_TERNARY,
  16.   OP_CMP_EQ,  OP_CMP_NE,  OP_CMP_LT,  OP_CMP_GT,  OP_CMP_LE,  OP_CMP_GE,
  17.   OP_PAREN_L, OP_PAREN_R,
  18. };
  19. // or__xxxx
  20. union TokenData{
  21.   long Long;
  22.   short Operator;
  23. };
  24. #define TOKEN_IS_NUMBER  0
  25. #define TOKEN_IS_OPERATOR 128
  26. #define TOKEN_IS_FUNCTION 64
  27. #define RIGHT_TO_LEFT 32
  28. #define TOKEN_PRIORITY_BITS 15
  29. static int RecognizeToken(char *Msg, const char *Cmd, char **ArgPtr) {
  30.   if(!memcmp(Msg, Cmd, strlen(Cmd))) {
  31.     if(ArgPtr != NULL)
  32.       *ArgPtr = Msg+strlen(Cmd);
  33.     if(**ArgPtr == 0) return 2; // different than NB
  34.     return 1;
  35.   }
  36.   return 0;
  37. }
  38. struct {
  39.   char *Token;
  40.   short unsigned Code;
  41.   short unsigned Flags;
  42. } const Ops[] = {
  43.   {"&&",  OP_LOG_AND, 15-11},
  44.   {"||",  OP_LOG_OR,  15-12},
  45.   {"+",   OP_ADD,     15- 4},
  46.   {"-",   OP_SUB,     15- 4},
  47.   {"*",   OP_MUL,     15- 3},
  48.   {"/",   OP_DIV,     15- 3},
  49.   {"%",   OP_MOD,     15- 3},
  50.   {"&",   OP_BIT_AND, 15- 8},
  51.   {"|",   OP_BIT_OR,  15-10},
  52.   {"^",   OP_BIT_XOR, 15- 9},
  53.   {"_",   OP_NEGATE,  15- 2|RIGHT_TO_LEFT},
  54.   {"!",   OP_LOG_NOT, 15- 2|RIGHT_TO_LEFT},
  55.   {"~",   OP_BIT_NOT, 15- 2|RIGHT_TO_LEFT},
  56.   {"<<",  OP_SHIFT_L, 15- 5},
  57.   {">>",  OP_SHIFT_R, 15- 5},
  58.   {"==",  OP_CMP_EQ,  15- 7},
  59.   {"!=",  OP_CMP_NE,  15- 7},
  60.   {"<=",  OP_CMP_LE,  15- 6},
  61.   {">=",  OP_CMP_GE,  15- 6},
  62.   {"<",   OP_CMP_LT,  15- 6},
  63.   {">",   OP_CMP_GT,  15- 6},
  64.   {NULL},
  65. };
  66.  
  67. // why am I even tokenizing this
  68. int SYA_Tokenize(char *Peek, int ListSize, unsigned char *TokFlags, union TokenData *TokData) {
  69.   int Index = 0;    // token list index
  70.   char *End = Peek+strlen(Peek);
  71.  
  72.   while(Peek < End) {
  73.     int i, ValidToken=0, NumberBase=0;
  74.     char *Ptr;
  75.     while(*Peek == ' ')
  76.       Peek++;
  77.     switch(*Peek) {
  78.       case '\'':
  79.         TokFlags[Index] = TOKEN_IS_NUMBER;
  80.         TokData[Index++].Long = Peek[1];
  81.         Peek+=2;
  82.         continue;
  83.       case '$':
  84.         NumberBase = 16;
  85.         break;
  86.       case '0':
  87.         NumberBase = 8;
  88.         break;
  89.       case '%':;
  90.         NumberBase = 2;
  91.         break;
  92.       case '(':
  93.         TokFlags[Index] = TOKEN_IS_OPERATOR|15;
  94.         TokData[Index++].Operator = OP_PAREN_L;
  95.         Peek++;
  96.         continue;
  97.       case ')':
  98.         TokFlags[Index] = TOKEN_IS_OPERATOR|15;
  99.         TokData[Index++].Operator = OP_PAREN_R;
  100.         Peek++;
  101.         continue;
  102.       case ',':
  103.         TokFlags[Index] = TOKEN_IS_OPERATOR;
  104.         TokData[Index++].Operator = OP_COMMA;
  105.         Peek++;
  106.         continue;
  107.     }
  108.     if(NumberBase || isdigit(*Peek)) {
  109.       if(NumberBase)
  110.         Peek++;
  111.       long N = strtol(Peek, &Peek, NumberBase?:10);
  112.       TokFlags[Index] = TOKEN_IS_NUMBER;
  113.       TokData[Index++].Long = N;
  114.       continue;
  115.     }
  116.     for(i=0; Ops[i].Token != NULL; i++)
  117.       if(RecognizeToken(Peek, Ops[i].Token, &Ptr)) {
  118.         TokFlags[Index] = TOKEN_IS_OPERATOR|Ops[i].Flags;
  119.         TokData[Index++].Operator = Ops[i].Code;
  120.         Peek = Ptr; ValidToken = 1;
  121.         break;
  122.       }
  123.     if(ValidToken)
  124.       continue;
  125.  
  126.     TokFlags[Index] = 127; // put end of list marker
  127.     TokData[Index].Operator = OP_END_LIST;
  128.     printf("Not tokenizable: \'%c\' \n", Peek[0]);
  129.     return -1;
  130.   }
  131.  
  132.   TokFlags[Index] = 127; // put end of list marker
  133.   TokData[Index].Operator = OP_END_LIST;
  134.  
  135.   int i;
  136.   for(i = 0; i<Index ; i++) {
  137.     if(TokFlags[i]&TOKEN_IS_OPERATOR)
  138.       printf("Opr %2x %i \n", TokFlags[i], TokData[i].Operator);
  139.     else
  140.       printf("Num %4i \n", TokData[i].Long);
  141.   }
  142.   putchar('\n');
  143.  
  144.   return 0;
  145. }
  146.  
  147. int SYA_ToRPN(unsigned char *InFlags, union TokenData *InData, int ListSize,
  148.               unsigned char *OutFlags, union TokenData *OutData) {
  149.   union TokenData OpDat[256];
  150.   unsigned char OpTyp[256];
  151.   int InIndex=0, OutIndex=0, OpIndex=0;
  152.  
  153.   int InEnd;
  154.   for(InEnd=0;InFlags[InEnd]!=127;InEnd++)
  155.     ;
  156.   while(InIndex < InEnd) {
  157.     // read a token
  158.     union TokenData CurTokenDat = InData[InIndex];
  159.     unsigned char CurTokenTyp = InFlags[InIndex++];
  160.     if(CurTokenTyp == 127)
  161.       break;
  162.     if(!(CurTokenTyp & TOKEN_IS_OPERATOR)) {
  163.       // If the token is a number, then add it to the output queue.
  164.       OutFlags[OutIndex] = TOKEN_IS_NUMBER|15;
  165.       OutData[OutIndex++] = CurTokenDat;
  166.     } else if(CurTokenDat.Operator == OP_PAREN_L) {
  167.       // if a left parenthesis push it onto the stack
  168.       OpTyp[OpIndex] = TOKEN_IS_OPERATOR|15;
  169.       OpDat[OpIndex++].Operator = OP_PAREN_L;
  170.     } else if(CurTokenDat.Operator == OP_PAREN_R) {
  171.       // if a right parenthesis push off stack until left paren
  172.       while(OpIndex != 0) {
  173.         if((OpTyp[OpIndex-1]&TOKEN_IS_OPERATOR) && (OpDat[OpIndex-1].Operator == OP_PAREN_L)) {
  174.           OpIndex--;
  175.           //puts("left paren found");
  176.           break;
  177.         }
  178.         OutFlags[OutIndex] = OpTyp[--OpIndex];
  179.         OutData[OutIndex++] = OpDat[OpIndex];
  180.       }
  181.  
  182.     } else {
  183.       // If the token is an operator, o1, then:
  184.       //while there is an operator token, o2, at the top of the stack, and
  185.       //either o1 is left-associative and its precedence is less than or equal to that of o2,
  186.       //or o1 is right-associative and its precedence is less than that of o2,
  187.       while(OpIndex != 0) {
  188.         unsigned char OpAtTopTyp = OpTyp[OpIndex-1];
  189.         if(OpDat[OpIndex-1].Operator == OP_PAREN_L)
  190.           break;
  191.  
  192.         if( (!(CurTokenTyp & RIGHT_TO_LEFT) &&
  193.              ((CurTokenTyp&TOKEN_PRIORITY_BITS) <= (OpAtTopTyp&TOKEN_PRIORITY_BITS))) ||
  194.             ((CurTokenTyp & RIGHT_TO_LEFT) &&
  195.              ((CurTokenTyp&TOKEN_PRIORITY_BITS) < (OpAtTopTyp&TOKEN_PRIORITY_BITS)))) {
  196.           //puts("pop");
  197.           OutFlags[OutIndex] = OpTyp[--OpIndex];
  198.           OutData[OutIndex++] = OpDat[OpIndex];
  199.         } else break;
  200.       }
  201.       OpTyp[OpIndex] = CurTokenTyp;
  202.       OpDat[OpIndex++] = CurTokenDat;
  203.     }
  204.   }
  205.   // pop all remaining ops onto the stack
  206.   while(OpIndex != 0) {
  207.     if(OpDat[OpIndex-1].Operator == OP_PAREN_L) {
  208.       puts("mismatched parenthesis");
  209.       OutFlags[OutIndex] = 127; // put end of list marker
  210.       OutData[OutIndex].Operator = OP_END_LIST;
  211.       return -5;
  212.     }
  213.     OutFlags[OutIndex] = OpTyp[--OpIndex];
  214.     OutData[OutIndex++] = OpDat[OpIndex];
  215.   }
  216.  
  217.   int i;
  218.  
  219.   OutFlags[OutIndex] = 127; // put end of list marker
  220.   OutData[OutIndex].Operator = OP_END_LIST;
  221.  
  222.   for(i = 0; i<OutIndex ; i++) {
  223.     if(OutFlags[i]&TOKEN_IS_OPERATOR)
  224.       printf("Opr %2x %i \n", OutFlags[i], OutData[i].Operator);
  225.     else
  226.       printf("Num %4i \n", (int)OutData[i].Long);
  227.   }
  228.   putchar('\n');
  229.  
  230.   return 0;  
  231. }
  232.  
  233.  
  234. long SYA_DoRPN(unsigned char *TokFlags, union TokenData *TokData) {
  235.   long Stack[100] = {0};
  236.   int StackPtr = 1;
  237.  
  238.   #define Pop(Var) { \
  239.    StackPtr--; \
  240.    if((StackPtr < 1) || (StackPtr > 25)) \
  241.      return -3; \
  242.    *Var = Stack[StackPtr]; \
  243.   }
  244.   #define Push(Var) { \
  245.    Stack[StackPtr++]=Var; \
  246.    if((StackPtr < 1) || (StackPtr > 25)) \
  247.      return -2; \
  248.   }
  249.  
  250.   int InPos = 0;
  251.   long a,b; // Scratch registers
  252.  
  253.   while(1) {
  254.     union TokenData CurTokenDat = TokData[InPos];
  255.     unsigned char CurTokenTyp = TokFlags[InPos++];
  256.  
  257.     if(CurTokenTyp == 127)
  258.       break;
  259.     if(!(CurTokenTyp & TOKEN_IS_OPERATOR)) {
  260.       Push(CurTokenDat.Long);
  261.     } else {
  262.       switch(CurTokenDat.Operator) {
  263.         case OP_ADD:Pop(&b);Pop(&a);Push(a+b);break;
  264.         case OP_SUB:Pop(&b);Pop(&a);Push(a-b);break;
  265.         case OP_MUL:Pop(&b);Pop(&a);Push(a*b);break;
  266.         case OP_DIV:Pop(&b);Pop(&a);if(!b)return -1;Push(a/b);break;
  267.         case OP_MOD:Pop(&b);Pop(&a);if(!b)return -1;Push(a%b);break;  
  268.  
  269.         case OP_SHIFT_L:Pop(&b);Pop(&a);Push(a<<b);break;
  270.         case OP_SHIFT_R:Pop(&b);Pop(&a);Push(a>>b);break;
  271.  
  272.         case OP_BIT_OR:Pop(&b);Pop(&a);Push(a|b);break;
  273.         case OP_BIT_AND:Pop(&b);Pop(&a);Push(a&b);break;
  274.         case OP_BIT_XOR:Pop(&b);Pop(&a);Push(a^b);break;
  275.         case OP_LOG_OR:Pop(&b);Pop(&a);Push(a||b);break;
  276.         case OP_LOG_AND:Pop(&b);Pop(&a);Push(a&&b);break;
  277.         case OP_CMP_LT:Pop(&b);Pop(&a);Push(a<b);break;
  278.         case OP_CMP_LE:Pop(&b);Pop(&a);Push(a<=b);break;
  279.         case OP_CMP_EQ:Pop(&b);Pop(&a);Push(a==b);break;
  280.         case OP_CMP_NE:Pop(&b);Pop(&a);Push(a!=b);break;
  281.         case OP_CMP_GT:Pop(&b);Pop(&a);Push(a>b);break;
  282.         case OP_CMP_GE:Pop(&b);Pop(&a);Push(a>=b);break;
  283.         case OP_NEGATE:Pop(&a);Push(-a);break;
  284.         case OP_LOG_NOT:Pop(&a);Push(!a);break;
  285.         case OP_BIT_NOT:Pop(&a);Push(~a);break;
  286.         default:
  287.           printf("unhandled operator (%i)\n", CurTokenDat.Operator);
  288.       }
  289.     }      
  290.  
  291.     putchar('{');
  292.     for(a=1;a<StackPtr;a++) {
  293.       printf("%4i, ",Stack[a]);
  294.     }
  295.     printf("}\n");
  296.     //printf("%3i %5i pos %2x \n", InPos, StackPtr, CurTokenTyp);
  297.   }
  298.  
  299.   Pop(&a);
  300.   return a;
  301. }
  302.  
  303.  
  304. int main() {
  305.   union TokenData Dat1[256], Dat2[256];
  306.   unsigned char Typ1[256], Typ2[256];
  307.   char Equ[512];
  308.   gets(Equ);
  309.  
  310.   if(-1<=SYA_Tokenize(Equ, 64, Typ1, Dat1));
  311.     if(-1<=SYA_ToRPN(Typ1, Dat1, 64, Typ2, Dat2));
  312.       printf("%i \n", (int)SYA_DoRPN(Typ2, Dat2));
  313.   return 0;
  314. }
  315.  
  316.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement