1 %{
2 
3 #define USE_PURE_PARSER
4 
5 #ifdef USE_PURE_PARSER
6 #define YY_DECL int yylex (YYSTYPE *lvalp)
7 #define YY_LVALP lvalp
8 #else
9 #define YY_LVALP (&yylval)
10 #endif
11 
12 /* get current pos (offset from start of line) */
13 #define YY_USER_ACTION lex_pos=yy_bp - YY_CURRENT_BUFFER->yy_ch_buf;
14 
15 #include <stdio.h>
16 #include <string.h>
17 #include <stdlib.h>
18 
19 #include "eval.h"
20 #include "evaltype.h"
21 #include "evalparse.h"
22 
23 static int lex_pos;
24 
char2int(char a,int base)25 static int char2int(char a, int base)
26 {
27 	int i;
28 	if ((a>='A') && (a<='Z')) {
29 		i=a-'A'+10;
30 	} else if ((a>='a') && (a<='z')) {
31 		i=a-'a'+10;
32 	} else if ((a>='0') && (a<='9')) {
33 		i=a-'0';
34 	} else return -1;
35 	if (i>=base) return -1;
36 	return i;
37 }
38 
parse_float(eval_scalar * f,char * fpn)39 static int parse_float(eval_scalar *f, char *fpn)
40 {
41 	char *end;
42 	double d;
43 	d=strtod(fpn, &end);
44 	if (*end == 0) {
45         	f->type=SCALAR_FLOAT;
46         	f->scalar.floatnum.value=d;
47 		return 1;
48 	}
49 	return 0;
50 }
51 
parse_integer(eval_scalar * i,char * num,int base,int lenmod)52 static int parse_integer(eval_scalar *i, char *num, int base, int lenmod)
53 {
54 	uint64 k = 0;
55 	int l = strlen(num) + lenmod;
56 	while (l--) {
57 		int c=char2int(*num, base);
58 		if (c==-1) return 0;
59 		k *= base;
60 		k += c;
61 		num++;
62 	}
63 	i->type=SCALAR_INT;
64 	i->scalar.integer.value=k;
65 	i->scalar.integer.type=TYPE_UNKNOWN;
66 	return 1;
67 }
68 
parse_cstring(eval_scalar * r,char * s,int len)69 static int parse_cstring(eval_scalar *r, char *s, int len)
70 {
71 	char *result;
72 
73 	int alloclen = len;
74 	if (alloclen < 1) alloclen = 1;
75 
76 	r->type = SCALAR_STR;
77 	r->scalar.str.value = (char*)malloc(alloclen);
78 	if (!r->scalar.str.value) return 0;
79 
80 	result = r->scalar.str.value;
81 
82 	// may not end with '\\'
83 	if (len && s[len-1] == '\\') return 0;
84 
85 	while (s && *s && len) {
86 		if (*s == '\\') {
87 			s++;len--;if (!len) break;
88 			switch (*s) {
89 				case '0':
90 					*result++='\0';
91 					break;
92 				case 'a':
93 					*result++='\a';
94 					break;
95 				case 'b':
96 					*result++='\b';
97 					break;
98 				case 'e':
99 					*result++='\e';
100 					break;
101 				case 'f':
102 					*result++='\f';
103 					break;
104 				case 'n':
105 					*result++='\n';
106 					break;
107 				case 'r':
108 					*result++='\r';
109 					break;
110 				case 't':
111 					*result++='\t';
112 					break;
113 				case 'v':
114 					*result++='\v';
115 					break;
116 				case '\"':
117 					*result++='"';
118 					break;
119 				case '\\':
120 					*result++='\\';
121 					break;
122 				case 'x': {
123 					int p, q;
124 					s++;len--;if (!len) break;
125 					p=char2int(*s, 16);
126 					if (p==-1)  return 0;
127 					s++;len--;if (!len) break;
128 					q=char2int(*s, 16);
129 					if (q==-1) return 0;
130 					*result++=(char)p*16+q;
131 					break;
132 				}
133 				default:
134 					*result++='\\';
135 					if (len) *result++=*s;
136 					break;
137 			}
138 		} else {
139 			*result++ = *s;
140 		}
141 		s++;len--;
142 	}
143 
144 	r->scalar.str.len=result-r->scalar.str.value;
145 
146 	return 1;
147 }
148 
parse_pstring(eval_scalar * s,char * cstr,int len)149 static int parse_pstring(eval_scalar *s, char *cstr, int len)
150 {
151 	int alloclen=len;
152 	if (!len) alloclen=1;
153 
154 	s->type=SCALAR_STR;
155 	s->scalar.str.value=(char*)malloc(alloclen);
156 	memcpy(s->scalar.str.value, cstr, len);
157 	s->scalar.str.len=len;
158 	return 1;
159 }
160 
lex_current_buffer()161 void *lex_current_buffer()
162 {
163 	return (void*)YY_CURRENT_BUFFER;
164 }
165 
lex_current_buffer_pos()166 int lex_current_buffer_pos()
167 {
168 	return lex_pos;
169 }
170 
lex_switch_buffer(void * buffer)171 void lex_switch_buffer(void *buffer)
172 {
173 	yy_switch_to_buffer(buffer);
174 }
175 
lex_delete_buffer(void * buffer)176 void lex_delete_buffer(void *buffer)
177 {
178 	yy_delete_buffer(buffer);
179 }
180 
lex_scan_string_buffer(const char * str)181 void *lex_scan_string_buffer(const char *str)
182 {
183 	return yy_scan_string(str);
184 }
185 
186 /*
187 */
188 %}
189 
190 %option noyywrap
191 
192 %%
193 
194 [ \t]+				/* nop */
195 \"(\\\"|[^"])*\"			if (parse_cstring(&YY_LVALP->scalar, yytext+1, strlen(yytext+1)-1)) return EVAL_STR;
196 '[^']*'				if (parse_pstring(&YY_LVALP->scalar, yytext+1, strlen(yytext+1)-1)) return EVAL_STR;
197 lt				return EVAL_STR_LT;
198 le				return EVAL_STR_LE;
199 gt				return EVAL_STR_GT;
200 ge				return EVAL_STR_GE;
201 eq				return EVAL_STR_EQ;
202 ne				return EVAL_STR_NE;
203 \*\*				return EVAL_POW;
204 \<\<				return EVAL_SHL;
205 \>\>				return EVAL_SHR;
206 \<				return EVAL_LT;
207 \<\=				return EVAL_LE;
208 \>				return EVAL_GT;
209 \>\=				return EVAL_GE;
210 \=\=				return EVAL_EQ;
211 \!\=				return EVAL_NE;
212 \&\&				return EVAL_LAND;
213 \|\|				return EVAL_LOR;
214 \^\^				return EVAL_LXOR;
215 [$@a-zA-Z_][a-zA-Z0-9_]*		YY_LVALP->ident=strdup(yytext); return EVAL_IDENT;
216 [0-9]+\.[0-9]+([eE][+-]?[0-9]+)?	if (parse_float(&YY_LVALP->scalar, yytext)) return EVAL_FLOAT;
217 [0-9]+				if (parse_integer(&YY_LVALP->scalar, yytext, 10, 0)) return EVAL_INT;
218 0x[0-9a-fA-F]+			if (parse_integer(&YY_LVALP->scalar, yytext+2, 16, 0)) return EVAL_INT;
219 [0-9][0-9a-fA-F]*h		if (parse_integer(&YY_LVALP->scalar, yytext, 16, -1)) return EVAL_INT;
220 [0-9]+d				if (parse_integer(&YY_LVALP->scalar, yytext, 10, -1)) return EVAL_INT;
221 [0-7]+o				if (parse_integer(&YY_LVALP->scalar, yytext, 8, -1)) return EVAL_INT;
222 [0-1]+b				if (parse_integer(&YY_LVALP->scalar, yytext, 2, -1)) return EVAL_INT;
223 .				return *yytext;
224 \n				return '\n';
225 
226 %%
227