Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include <stdlib.h>
- typedef unsigned char u8;
- typedef unsigned short u16;
- typedef unsigned long u32;
- enum Operator {
- OP_END_LIST, OP_COMMA,
- OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD,
- OP_BIT_AND, OP_BIT_OR, OP_BIT_XOR, OP_BIT_NOT,
- OP_LOG_AND, OP_LOG_OR, OP_LOG_XOR, OP_LOG_NOT,
- OP_SHIFT_L, OP_SHIFT_R, OP_NEGATE, OP_POWER, OP_TERNARY,
- OP_CMP_EQ, OP_CMP_NE, OP_CMP_LT, OP_CMP_GT, OP_CMP_LE, OP_CMP_GE,
- OP_PAREN_L, OP_PAREN_R,
- };
- // or__xxxx
- union TokenData{
- long Long;
- short Operator;
- };
- #define TOKEN_IS_NUMBER 0
- #define TOKEN_IS_OPERATOR 128
- #define TOKEN_IS_FUNCTION 64
- #define RIGHT_TO_LEFT 32
- #define TOKEN_PRIORITY_BITS 15
- static int RecognizeToken(char *Msg, const char *Cmd, char **ArgPtr) {
- if(!memcmp(Msg, Cmd, strlen(Cmd))) {
- if(ArgPtr != NULL)
- *ArgPtr = Msg+strlen(Cmd);
- if(**ArgPtr == 0) return 2; // different than NB
- return 1;
- }
- return 0;
- }
- struct {
- char *Token;
- short unsigned Code;
- short unsigned Flags;
- } const Ops[] = {
- {"&&", OP_LOG_AND, 15-11},
- {"||", OP_LOG_OR, 15-12},
- {"+", OP_ADD, 15- 4},
- {"-", OP_SUB, 15- 4},
- {"*", OP_MUL, 15- 3},
- {"/", OP_DIV, 15- 3},
- {"%", OP_MOD, 15- 3},
- {"&", OP_BIT_AND, 15- 8},
- {"|", OP_BIT_OR, 15-10},
- {"^", OP_BIT_XOR, 15- 9},
- {"_", OP_NEGATE, 15- 2|RIGHT_TO_LEFT},
- {"!", OP_LOG_NOT, 15- 2|RIGHT_TO_LEFT},
- {"~", OP_BIT_NOT, 15- 2|RIGHT_TO_LEFT},
- {"<<", OP_SHIFT_L, 15- 5},
- {">>", OP_SHIFT_R, 15- 5},
- {"==", OP_CMP_EQ, 15- 7},
- {"!=", OP_CMP_NE, 15- 7},
- {"<=", OP_CMP_LE, 15- 6},
- {">=", OP_CMP_GE, 15- 6},
- {"<", OP_CMP_LT, 15- 6},
- {">", OP_CMP_GT, 15- 6},
- {NULL},
- };
- // why am I even tokenizing this
- int SYA_Tokenize(char *Peek, int ListSize, unsigned char *TokFlags, union TokenData *TokData) {
- int Index = 0; // token list index
- char *End = Peek+strlen(Peek);
- while(Peek < End) {
- int i, ValidToken=0, NumberBase=0;
- char *Ptr;
- while(*Peek == ' ')
- Peek++;
- switch(*Peek) {
- case '\'':
- TokFlags[Index] = TOKEN_IS_NUMBER;
- TokData[Index++].Long = Peek[1];
- Peek+=2;
- continue;
- case '$':
- NumberBase = 16;
- break;
- case '0':
- NumberBase = 8;
- break;
- case '%':;
- NumberBase = 2;
- break;
- case '(':
- TokFlags[Index] = TOKEN_IS_OPERATOR|15;
- TokData[Index++].Operator = OP_PAREN_L;
- Peek++;
- continue;
- case ')':
- TokFlags[Index] = TOKEN_IS_OPERATOR|15;
- TokData[Index++].Operator = OP_PAREN_R;
- Peek++;
- continue;
- case ',':
- TokFlags[Index] = TOKEN_IS_OPERATOR;
- TokData[Index++].Operator = OP_COMMA;
- Peek++;
- continue;
- }
- if(NumberBase || isdigit(*Peek)) {
- if(NumberBase)
- Peek++;
- long N = strtol(Peek, &Peek, NumberBase?:10);
- TokFlags[Index] = TOKEN_IS_NUMBER;
- TokData[Index++].Long = N;
- continue;
- }
- for(i=0; Ops[i].Token != NULL; i++)
- if(RecognizeToken(Peek, Ops[i].Token, &Ptr)) {
- TokFlags[Index] = TOKEN_IS_OPERATOR|Ops[i].Flags;
- TokData[Index++].Operator = Ops[i].Code;
- Peek = Ptr; ValidToken = 1;
- break;
- }
- if(ValidToken)
- continue;
- TokFlags[Index] = 127; // put end of list marker
- TokData[Index].Operator = OP_END_LIST;
- printf("Not tokenizable: \'%c\' \n", Peek[0]);
- return -1;
- }
- TokFlags[Index] = 127; // put end of list marker
- TokData[Index].Operator = OP_END_LIST;
- int i;
- for(i = 0; i<Index ; i++) {
- if(TokFlags[i]&TOKEN_IS_OPERATOR)
- printf("Opr %2x %i \n", TokFlags[i], TokData[i].Operator);
- else
- printf("Num %4i \n", TokData[i].Long);
- }
- putchar('\n');
- return 0;
- }
- int SYA_ToRPN(unsigned char *InFlags, union TokenData *InData, int ListSize,
- unsigned char *OutFlags, union TokenData *OutData) {
- union TokenData OpDat[256];
- unsigned char OpTyp[256];
- int InIndex=0, OutIndex=0, OpIndex=0;
- int InEnd;
- for(InEnd=0;InFlags[InEnd]!=127;InEnd++)
- ;
- while(InIndex < InEnd) {
- // read a token
- union TokenData CurTokenDat = InData[InIndex];
- unsigned char CurTokenTyp = InFlags[InIndex++];
- if(CurTokenTyp == 127)
- break;
- if(!(CurTokenTyp & TOKEN_IS_OPERATOR)) {
- // If the token is a number, then add it to the output queue.
- OutFlags[OutIndex] = TOKEN_IS_NUMBER|15;
- OutData[OutIndex++] = CurTokenDat;
- } else if(CurTokenDat.Operator == OP_PAREN_L) {
- // if a left parenthesis push it onto the stack
- OpTyp[OpIndex] = TOKEN_IS_OPERATOR|15;
- OpDat[OpIndex++].Operator = OP_PAREN_L;
- } else if(CurTokenDat.Operator == OP_PAREN_R) {
- // if a right parenthesis push off stack until left paren
- while(OpIndex != 0) {
- if((OpTyp[OpIndex-1]&TOKEN_IS_OPERATOR) && (OpDat[OpIndex-1].Operator == OP_PAREN_L)) {
- OpIndex--;
- //puts("left paren found");
- break;
- }
- OutFlags[OutIndex] = OpTyp[--OpIndex];
- OutData[OutIndex++] = OpDat[OpIndex];
- }
- } else {
- // If the token is an operator, o1, then:
- //while there is an operator token, o2, at the top of the stack, and
- //either o1 is left-associative and its precedence is less than or equal to that of o2,
- //or o1 is right-associative and its precedence is less than that of o2,
- while(OpIndex != 0) {
- unsigned char OpAtTopTyp = OpTyp[OpIndex-1];
- if(OpDat[OpIndex-1].Operator == OP_PAREN_L)
- break;
- if( (!(CurTokenTyp & RIGHT_TO_LEFT) &&
- ((CurTokenTyp&TOKEN_PRIORITY_BITS) <= (OpAtTopTyp&TOKEN_PRIORITY_BITS))) ||
- ((CurTokenTyp & RIGHT_TO_LEFT) &&
- ((CurTokenTyp&TOKEN_PRIORITY_BITS) < (OpAtTopTyp&TOKEN_PRIORITY_BITS)))) {
- //puts("pop");
- OutFlags[OutIndex] = OpTyp[--OpIndex];
- OutData[OutIndex++] = OpDat[OpIndex];
- } else break;
- }
- OpTyp[OpIndex] = CurTokenTyp;
- OpDat[OpIndex++] = CurTokenDat;
- }
- }
- // pop all remaining ops onto the stack
- while(OpIndex != 0) {
- if(OpDat[OpIndex-1].Operator == OP_PAREN_L) {
- puts("mismatched parenthesis");
- OutFlags[OutIndex] = 127; // put end of list marker
- OutData[OutIndex].Operator = OP_END_LIST;
- return -5;
- }
- OutFlags[OutIndex] = OpTyp[--OpIndex];
- OutData[OutIndex++] = OpDat[OpIndex];
- }
- int i;
- OutFlags[OutIndex] = 127; // put end of list marker
- OutData[OutIndex].Operator = OP_END_LIST;
- for(i = 0; i<OutIndex ; i++) {
- if(OutFlags[i]&TOKEN_IS_OPERATOR)
- printf("Opr %2x %i \n", OutFlags[i], OutData[i].Operator);
- else
- printf("Num %4i \n", (int)OutData[i].Long);
- }
- putchar('\n');
- return 0;
- }
- long SYA_DoRPN(unsigned char *TokFlags, union TokenData *TokData) {
- long Stack[100] = {0};
- int StackPtr = 1;
- #define Pop(Var) { \
- StackPtr--; \
- if((StackPtr < 1) || (StackPtr > 25)) \
- return -3; \
- *Var = Stack[StackPtr]; \
- }
- #define Push(Var) { \
- Stack[StackPtr++]=Var; \
- if((StackPtr < 1) || (StackPtr > 25)) \
- return -2; \
- }
- int InPos = 0;
- long a,b; // Scratch registers
- while(1) {
- union TokenData CurTokenDat = TokData[InPos];
- unsigned char CurTokenTyp = TokFlags[InPos++];
- if(CurTokenTyp == 127)
- break;
- if(!(CurTokenTyp & TOKEN_IS_OPERATOR)) {
- Push(CurTokenDat.Long);
- } else {
- switch(CurTokenDat.Operator) {
- case OP_ADD:Pop(&b);Pop(&a);Push(a+b);break;
- case OP_SUB:Pop(&b);Pop(&a);Push(a-b);break;
- case OP_MUL:Pop(&b);Pop(&a);Push(a*b);break;
- case OP_DIV:Pop(&b);Pop(&a);if(!b)return -1;Push(a/b);break;
- case OP_MOD:Pop(&b);Pop(&a);if(!b)return -1;Push(a%b);break;
- case OP_SHIFT_L:Pop(&b);Pop(&a);Push(a<<b);break;
- case OP_SHIFT_R:Pop(&b);Pop(&a);Push(a>>b);break;
- case OP_BIT_OR:Pop(&b);Pop(&a);Push(a|b);break;
- case OP_BIT_AND:Pop(&b);Pop(&a);Push(a&b);break;
- case OP_BIT_XOR:Pop(&b);Pop(&a);Push(a^b);break;
- case OP_LOG_OR:Pop(&b);Pop(&a);Push(a||b);break;
- case OP_LOG_AND:Pop(&b);Pop(&a);Push(a&&b);break;
- case OP_CMP_LT:Pop(&b);Pop(&a);Push(a<b);break;
- case OP_CMP_LE:Pop(&b);Pop(&a);Push(a<=b);break;
- case OP_CMP_EQ:Pop(&b);Pop(&a);Push(a==b);break;
- case OP_CMP_NE:Pop(&b);Pop(&a);Push(a!=b);break;
- case OP_CMP_GT:Pop(&b);Pop(&a);Push(a>b);break;
- case OP_CMP_GE:Pop(&b);Pop(&a);Push(a>=b);break;
- case OP_NEGATE:Pop(&a);Push(-a);break;
- case OP_LOG_NOT:Pop(&a);Push(!a);break;
- case OP_BIT_NOT:Pop(&a);Push(~a);break;
- default:
- printf("unhandled operator (%i)\n", CurTokenDat.Operator);
- }
- }
- putchar('{');
- for(a=1;a<StackPtr;a++) {
- printf("%4i, ",Stack[a]);
- }
- printf("}\n");
- //printf("%3i %5i pos %2x \n", InPos, StackPtr, CurTokenTyp);
- }
- Pop(&a);
- return a;
- }
- int main() {
- union TokenData Dat1[256], Dat2[256];
- unsigned char Typ1[256], Typ2[256];
- char Equ[512];
- gets(Equ);
- if(-1<=SYA_Tokenize(Equ, 64, Typ1, Dat1));
- if(-1<=SYA_ToRPN(Typ1, Dat1, 64, Typ2, Dat2));
- printf("%i \n", (int)SYA_DoRPN(Typ2, Dat2));
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement