]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/locale/src/shared/mo_lambda.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / locale / src / shared / mo_lambda.cpp
1 //
2 // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 #include "mo_lambda.hpp"
9 #include <string.h>
10 #include <stdlib.h>
11
12 namespace boost {
13 namespace locale {
14 namespace gnu_gettext {
15 namespace lambda {
16
17 namespace { // anon
18 struct identity : public plural {
19 virtual int operator()(int n) const
20 {
21 return n;
22 };
23 virtual identity *clone() const
24 {
25 return new identity();
26 }
27 };
28
29 struct unary : public plural
30 {
31 unary(plural_ptr ptr) :
32 op1(ptr)
33 {
34 }
35 protected:
36 plural_ptr op1;
37 };
38
39
40 struct binary : public plural
41 {
42 binary(plural_ptr p1,plural_ptr p2) :
43 op1(p1),
44 op2(p2)
45 {
46 }
47 protected:
48 plural_ptr op1,op2;
49 };
50
51 struct number : public plural
52 {
53 number(int v) :
54 val(v)
55 {
56 }
57 virtual int operator()(int /*n*/) const
58 {
59 return val;
60 }
61 virtual number *clone() const
62 {
63 return new number(val);
64 }
65
66 private:
67 int val;
68 };
69
70 #define UNOP(name,oper) \
71 struct name: public unary { \
72 name(plural_ptr op) : unary(op) \
73 { \
74 }; \
75 virtual int operator()(int n) const \
76 { \
77 return oper (*op1)(n); \
78 } \
79 virtual name *clone() const \
80 { \
81 plural_ptr op1_copy(op1->clone()); \
82 return new name(op1_copy); \
83 } \
84 };
85
86 #define BINOP(name,oper) \
87 struct name : public binary \
88 { \
89 name(plural_ptr p1,plural_ptr p2) : \
90 binary(p1,p2) \
91 { \
92 } \
93 \
94 virtual int operator()(int n) const \
95 { \
96 return (*op1)(n) oper (*op2)(n); \
97 } \
98 virtual name *clone() const \
99 { \
100 plural_ptr op1_copy(op1->clone()); \
101 plural_ptr op2_copy(op2->clone()); \
102 return new name(op1_copy,op2_copy); \
103 } \
104 };
105
106 #define BINOPD(name,oper) \
107 struct name : public binary { \
108 name(plural_ptr p1,plural_ptr p2) : \
109 binary(p1,p2) \
110 { \
111 } \
112 virtual int operator()(int n) const \
113 { \
114 int v1=(*op1)(n); \
115 int v2=(*op2)(n); \
116 return v2==0 ? 0 : v1 oper v2; \
117 } \
118 virtual name *clone() const \
119 { \
120 plural_ptr op1_copy(op1->clone()); \
121 plural_ptr op2_copy(op2->clone()); \
122 return new name(op1_copy,op2_copy); \
123 } \
124 };
125
126 enum { END = 0 , SHL = 256, SHR, GTE,LTE, EQ, NEQ, AND, OR, NUM, VARIABLE };
127
128 UNOP(l_not,!)
129 UNOP(minus,-)
130 UNOP(bin_not,~)
131
132 BINOP(mul,*)
133 BINOPD(div,/)
134 BINOPD(mod,%)
135 static int level10[]={3,'*','/','%'};
136
137 BINOP(add,+)
138 BINOP(sub,-)
139 static int level9[]={2,'+','-'};
140
141 BINOP(shl,<<)
142 BINOP(shr,>>)
143 static int level8[]={2,SHL,SHR};
144
145 BINOP(gt,>)
146 BINOP(lt,<)
147 BINOP(gte,>=)
148 BINOP(lte,<=)
149 static int level7[]={4,'<','>',GTE,LTE};
150
151 BINOP(eq,==)
152 BINOP(neq,!=)
153 static int level6[]={2,EQ,NEQ};
154
155 BINOP(bin_and,&)
156 static int level5[]={1,'&'};
157
158 BINOP(bin_xor,^)
159 static int level4[]={1,'^'};
160
161 BINOP(bin_or,|)
162 static int level3[]={1,'|'};
163
164 BINOP(l_and,&&)
165 static int level2[]={1,AND};
166
167 BINOP(l_or,||)
168 static int level1[]={1,OR};
169
170 struct conditional : public plural {
171 conditional(plural_ptr p1,plural_ptr p2,plural_ptr p3) :
172 op1(p1),
173 op2(p2),
174 op3(p3)
175 {
176 }
177 virtual int operator()(int n) const
178 {
179 return (*op1)(n) ? (*op2)(n) : (*op3)(n);
180 }
181 virtual conditional *clone() const
182 {
183 plural_ptr op1_copy(op1->clone());
184 plural_ptr op2_copy(op2->clone());
185 plural_ptr op3_copy(op3->clone());
186 return new conditional(op1_copy,op2_copy,op3_copy);
187 }
188 private:
189 plural_ptr op1,op2,op3;
190 };
191
192
193 plural_ptr bin_factory(int value,plural_ptr left,plural_ptr right)
194 {
195
196 switch(value) {
197 case '/': return plural_ptr(new div(left,right));
198 case '*': return plural_ptr(new mul(left,right));
199 case '%': return plural_ptr(new mod(left,right));
200 case '+': return plural_ptr(new add(left,right));
201 case '-': return plural_ptr(new sub(left,right));
202 case SHL: return plural_ptr(new shl(left,right));
203 case SHR: return plural_ptr(new shr(left,right));
204 case '>': return plural_ptr(new gt(left,right));
205 case '<': return plural_ptr(new lt(left,right));
206 case GTE: return plural_ptr(new gte(left,right));
207 case LTE: return plural_ptr(new lte(left,right));
208 case EQ: return plural_ptr(new eq(left,right));
209 case NEQ: return plural_ptr(new neq(left,right));
210 case '&': return plural_ptr(new bin_and(left,right));
211 case '^': return plural_ptr(new bin_xor(left,right));
212 case '|': return plural_ptr(new bin_or (left,right));
213 case AND: return plural_ptr(new l_and(left,right));
214 case OR: return plural_ptr(new l_or(left,right));
215 default:
216 return plural_ptr();
217 }
218 }
219
220 plural_ptr un_factory(int value,plural_ptr op)
221 {
222 switch(value) {
223 case '!': return plural_ptr(new l_not(op));
224 case '~': return plural_ptr(new bin_not(op));
225 case '-': return plural_ptr(new minus(op));
226 default:
227 return plural_ptr();
228 }
229 }
230
231 static inline bool is_in(int v,int *p)
232 {
233 int len=*p;
234 p++;
235 while(len && *p!=v) { p++;len--; }
236 return len!=0;
237 }
238
239
240 class tokenizer {
241 public:
242 tokenizer(char const *s) { text=s; pos=0; step(); };
243 int get(int *val=NULL){
244 int iv=int_value;
245 int res=next_tocken;
246 step();
247 if(val && res==NUM){
248 *val=iv;
249 }
250 return res;
251 };
252 int next(int *val=NULL) {
253 if(val && next_tocken==NUM) {
254 *val=int_value;
255 return NUM;
256 }
257 return next_tocken;
258 }
259 private:
260 char const *text;
261 int pos;
262 int next_tocken;
263 int int_value;
264 bool is_blank(char c)
265 {
266 return c==' ' || c=='\r' || c=='\n' || c=='\t';
267 }
268 bool isdigit(char c)
269 {
270 return '0'<=c && c<='9';
271 }
272 void step()
273 {
274 while(text[pos] && is_blank(text[pos])) pos++;
275 char const *ptr=text+pos;
276 char *tmp_ptr;
277 if(strncmp(ptr,"<<",2)==0) { pos+=2; next_tocken=SHL; }
278 else if(strncmp(ptr,">>",2)==0) { pos+=2; next_tocken=SHR; }
279 else if(strncmp(ptr,"&&",2)==0) { pos+=2; next_tocken=AND; }
280 else if(strncmp(ptr,"||",2)==0) { pos+=2; next_tocken=OR; }
281 else if(strncmp(ptr,"<=",2)==0) { pos+=2; next_tocken=LTE; }
282 else if(strncmp(ptr,">=",2)==0) { pos+=2; next_tocken=GTE; }
283 else if(strncmp(ptr,"==",2)==0) { pos+=2; next_tocken=EQ; }
284 else if(strncmp(ptr,"!=",2)==0) { pos+=2; next_tocken=NEQ; }
285 else if(*ptr=='n') { pos++; next_tocken=VARIABLE; }
286 else if(isdigit(*ptr)) { int_value=strtol(text+pos,&tmp_ptr,0); pos=tmp_ptr-text; next_tocken=NUM; }
287 else if(*ptr=='\0') { next_tocken=0; }
288 else { next_tocken=*ptr; pos++; }
289 }
290 };
291
292
293 #define BINARY_EXPR(expr,hexpr,list) \
294 plural_ptr expr() \
295 { \
296 plural_ptr op1,op2; \
297 if((op1=hexpr()).get()==0) \
298 return plural_ptr(); \
299 while(is_in(t.next(),list)) { \
300 int o=t.get(); \
301 if((op2=hexpr()).get()==0) \
302 return plural_ptr(); \
303 op1=bin_factory(o,op1,op2); \
304 } \
305 return op1; \
306 }
307
308 class parser {
309 public:
310
311 parser(tokenizer &tin) : t(tin) {};
312
313 plural_ptr compile()
314 {
315 plural_ptr res=cond_expr();
316 if(res.get() && t.next()!=END) {
317 return plural_ptr();
318 };
319 return res;
320 }
321
322 private:
323
324 plural_ptr value_expr()
325 {
326 plural_ptr op;
327 if(t.next()=='(') {
328 t.get();
329 if((op=cond_expr()).get()==0)
330 return plural_ptr();
331 if(t.get()!=')')
332 return plural_ptr();
333 return op;
334 }
335 else if(t.next()==NUM) {
336 int value;
337 t.get(&value);
338 return plural_ptr(new number(value));
339 }
340 else if(t.next()==VARIABLE) {
341 t.get();
342 return plural_ptr(new identity());
343 }
344 return plural_ptr();
345 };
346
347 plural_ptr un_expr()
348 {
349 plural_ptr op1;
350 static int level_unary[]={3,'-','!','~'};
351 if(is_in(t.next(),level_unary)) {
352 int op=t.get();
353 if((op1=un_expr()).get()==0)
354 return plural_ptr();
355 switch(op) {
356 case '-':
357 return plural_ptr(new minus(op1));
358 case '!':
359 return plural_ptr(new l_not(op1));
360 case '~':
361 return plural_ptr(new bin_not(op1));
362 default:
363 return plural_ptr();
364 }
365 }
366 else {
367 return value_expr();
368 }
369 };
370
371 BINARY_EXPR(l10,un_expr,level10);
372 BINARY_EXPR(l9,l10,level9);
373 BINARY_EXPR(l8,l9,level8);
374 BINARY_EXPR(l7,l8,level7);
375 BINARY_EXPR(l6,l7,level6);
376 BINARY_EXPR(l5,l6,level5);
377 BINARY_EXPR(l4,l5,level4);
378 BINARY_EXPR(l3,l4,level3);
379 BINARY_EXPR(l2,l3,level2);
380 BINARY_EXPR(l1,l2,level1);
381
382 plural_ptr cond_expr()
383 {
384 plural_ptr cond,case1,case2;
385 if((cond=l1()).get()==0)
386 return plural_ptr();
387 if(t.next()=='?') {
388 t.get();
389 if((case1=cond_expr()).get()==0)
390 return plural_ptr();
391 if(t.get()!=':')
392 return plural_ptr();
393 if((case2=cond_expr()).get()==0)
394 return plural_ptr();
395 }
396 else {
397 return cond;
398 }
399 return plural_ptr(new conditional(cond,case1,case2));
400 }
401
402 tokenizer &t;
403
404 };
405
406 } // namespace anon
407
408 plural_ptr compile(char const *str)
409 {
410 tokenizer t(str);
411 parser p(t);
412 return p.compile();
413 }
414
415
416 } // lambda
417 } // gnu_gettext
418 } // locale
419 } // boost
420
421 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
422