1// re2c $INPUT -o $OUTPUT -s 2/* re2c lesson 001_upn_calculator, calc_006, (c) M. Boerger 2006 - 2007 */ 3/*!ignore:re2c 4 5- avoiding YYFILL() 6 . We use the inplace configuration re2c:yyfill to suppress generation of 7 YYFILL() blocks. This of course means we no longer have to provide the 8 macro. 9 . We also drop the YYMARKER stuff since we know that re2c does not generate 10 it for this example. 11 . Since re2c does no longer check for out of data situations we must do this. 12 For that reason we first reintroduce our zero rule and second we need to 13 ensure that the scanner does not take more than one bytes in one go. 14 15 In the example suppose "0" is passed. The scanner reads the first "0" and 16 then is in an undecided state. The scanner can earliest decide on the next 17 char what the token is. In case of a zero the input ends and it was a 18 number, 0 to be precise. In case of a digit it is an octal number and the 19 next character needs to be read. In case of any other character the scanner 20 will detect an error with the any rule [^]. 21 22 Now the above shows that the scanner may read two characters directly. But 23 only if the first is a "0". So we could easily check that if the first char 24 is "0" and the next char is a digit then yet another charcter is present. 25 But we require our inut to be zero terminated. And that means we do not 26 have to check anything for this scanner. 27 28 However with other rule sets re2c might read more then one character in a 29 row. In those cases it is normally hard to impossible to avoid YYFILL. 30 31- optimizing the generated code by using -s command line switch of re2c 32 . This tells re2c to generate code that uses if statements rather 33 then endless switch/case expressions where appropriate. Note that the 34 generated code now requires the input to be unsigned char rather than char 35 due to the way comparisons are generated. 36*/ 37 38#include <stdlib.h> 39#include <stdio.h> 40#include <string.h> 41 42#define DEBUG(stmt) stmt 43 44int stack[4]; 45int depth = 0; 46 47int push_num(const unsigned char *t, const unsigned char *l, int radix) 48{ 49 int num = 0; 50 51 if (depth >= sizeof(stack)) 52 { 53 return 3; 54 } 55 56 --t; 57 while(++t < l) 58 { 59 num = num * radix + (*t - (unsigned char)'0'); 60 } 61 DEBUG(printf("Num: %d\n", num)); 62 63 stack[depth++] = num; 64 return 0; 65} 66 67int stack_add() 68{ 69 if (depth < 2) return 4; 70 71 --depth; 72 stack[depth-1] = stack[depth-1] + stack[depth]; 73 DEBUG(printf("+\n")); 74 return 0; 75} 76 77int stack_sub() 78{ 79 if (depth < 2) return 4; 80 81 --depth; 82 stack[depth-1] = stack[depth-1] - stack[depth]; 83 DEBUG(printf("-\n")); 84 return 0; 85} 86 87int scan(char *s) 88{ 89 unsigned char *p = (unsigned char*)s; 90 unsigned char *t; 91 int res = 0; 92 93#define YYCTYPE unsigned char 94#define YYCURSOR p 95 96 while(!res) 97 { 98 t = p; 99/*!re2c 100 re2c:indent:top = 2; 101 re2c:yyfill:enable = 0; 102 103 DIGIT = [0-9] ; 104 OCT = "0" DIGIT+ ; 105 INT = "0" | ( [1-9] DIGIT* ) ; 106 WS = [ \t]+ ; 107 108 WS { continue; } 109 OCT { res = push_num(t, p, 8); continue; } 110 INT { res = push_num(t, p, 10); continue; } 111 "+" { res = stack_add(); continue; } 112 "-" { res = stack_sub(); continue; } 113 "\000" { res = depth == 1 ? 0 : 2; break; } 114 [^] { res = 1; continue; } 115*/ 116 } 117 return res; 118} 119 120int main(int argc, char **argv) 121{ 122 if (argc > 1) 123 { 124 char *inp; 125 int res = 0, argp = 0, len; 126 127 while(!res && ++argp < argc) 128 { 129 inp = strdup(argv[argp]); 130 len = strlen(inp); 131 if (inp[0] == '\"' && inp[len-1] == '\"') 132 { 133 inp[len - 1] = '\0'; 134 ++inp; 135 } 136 res = scan(inp); 137 free(inp); 138 } 139 switch(res) 140 { 141 case 0: 142 printf("Result: %d\n", stack[0]); 143 return 0; 144 case 1: 145 fprintf(stderr, "Illegal character in input.\n"); 146 return 1; 147 case 2: 148 fprintf(stderr, "Premature end of input.\n"); 149 return 2; 150 case 3: 151 fprintf(stderr, "Stack overflow.\n"); 152 return 3; 153 case 4: 154 fprintf(stderr, "Stack underflow.\n"); 155 return 4; 156 } 157 } 158 else 159 { 160 fprintf(stderr, "%s <expr>\n", argv[0]); 161 return 0; 162 } 163} 164