1// re2c $INPUT -o $OUTPUT -b 2/* re2c lesson 001_upn_calculator, calc_007, (c) M. Boerger 2006 - 2007 */ 3/*!ignore:re2c 4 5- optimizing the generated code by using -b command line switch of re2c 6 . This tells re2c to generate code that uses a decision table. The -b switch 7 also contains the -s behavior. And -b also requires the input to be 8 unsigned chars. 9*/ 10 11#include <stdlib.h> 12#include <stdio.h> 13#include <string.h> 14 15#define DEBUG(stmt) stmt 16 17int stack[4]; 18int depth = 0; 19 20int push_num(const unsigned char *t, const unsigned char *l, int radix) 21{ 22 int num = 0; 23 24 if (depth >= sizeof(stack)) 25 { 26 return 3; 27 } 28 29 --t; 30 while(++t < l) 31 { 32 num = num * radix + (*t - (unsigned char)'0'); 33 } 34 DEBUG(printf("Num: %d\n", num)); 35 36 stack[depth++] = num; 37 return 0; 38} 39 40int stack_add() 41{ 42 if (depth < 2) return 4; 43 44 --depth; 45 stack[depth-1] = stack[depth-1] + stack[depth]; 46 DEBUG(printf("+\n")); 47 return 0; 48} 49 50int stack_sub() 51{ 52 if (depth < 2) return 4; 53 54 --depth; 55 stack[depth-1] = stack[depth-1] - stack[depth]; 56 DEBUG(printf("+\n")); 57 return 0; 58} 59 60int scan(char *s) 61{ 62 unsigned char *p = (unsigned char*)s; 63 unsigned char *t; 64 int res = 0; 65 66#define YYCTYPE unsigned char 67#define YYCURSOR p 68 69 while(!res) 70 { 71 t = p; 72/*!re2c 73 re2c:indent:top = 2; 74 re2c:yyfill:enable = 0; 75 76 DIGIT = [0-9] ; 77 OCT = "0" DIGIT+ ; 78 INT = "0" | ( [1-9] DIGIT* ) ; 79 WS = [ \t]+ ; 80 81 WS { continue; } 82 OCT { res = push_num(t, p, 8); continue; } 83 INT { res = push_num(t, p, 10); continue; } 84 "+" { res = stack_add(); continue; } 85 "-" { res = stack_sub(); continue; } 86 "\000" { res = depth == 1 ? 0 : 2; break; } 87 [^] { res = 1; continue; } 88*/ 89 } 90 return res; 91} 92 93int main(int argc, char **argv) 94{ 95 if (argc > 1) 96 { 97 char *inp; 98 int res = 0, argp = 0, len; 99 100 while(!res && ++argp < argc) 101 { 102 inp = strdup(argv[argp]); 103 len = strlen(inp); 104 if (inp[0] == '\"' && inp[len-1] == '\"') 105 { 106 inp[len - 1] = '\0'; 107 ++inp; 108 } 109 res = scan(inp); 110 free(inp); 111 } 112 switch(res) 113 { 114 case 0: 115 printf("Result: %d\n", stack[0]); 116 return 0; 117 case 1: 118 fprintf(stderr, "Illegal character in input.\n"); 119 return 1; 120 case 2: 121 fprintf(stderr, "Premature end of input.\n"); 122 return 2; 123 case 3: 124 fprintf(stderr, "Stack overflow.\n"); 125 return 3; 126 case 4: 127 fprintf(stderr, "Stack underflow.\n"); 128 return 4; 129 } 130 } 131 else 132 { 133 fprintf(stderr, "%s <expr>\n", argv[0]); 134 return 0; 135 } 136} 137