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