]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/locale/src/shared/mo_lambda.cpp
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / boost / libs / locale / src / shared / mo_lambda.cpp
CommitLineData
7c673cae
FG
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
12namespace boost {
13namespace locale {
14namespace gnu_gettext {
15namespace lambda {
16
17namespace { // 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
7c673cae
FG
220 static inline bool is_in(int v,int *p)
221 {
222 int len=*p;
223 p++;
224 while(len && *p!=v) { p++;len--; }
225 return len!=0;
226 }
227
228
229 class tokenizer {
230 public:
231 tokenizer(char const *s) { text=s; pos=0; step(); };
232 int get(int *val=NULL){
233 int iv=int_value;
234 int res=next_tocken;
235 step();
236 if(val && res==NUM){
237 *val=iv;
238 }
239 return res;
240 };
241 int next(int *val=NULL) {
242 if(val && next_tocken==NUM) {
243 *val=int_value;
244 return NUM;
245 }
246 return next_tocken;
247 }
248 private:
249 char const *text;
250 int pos;
251 int next_tocken;
252 int int_value;
253 bool is_blank(char c)
254 {
255 return c==' ' || c=='\r' || c=='\n' || c=='\t';
256 }
257 bool isdigit(char c)
258 {
259 return '0'<=c && c<='9';
260 }
261 void step()
262 {
263 while(text[pos] && is_blank(text[pos])) pos++;
264 char const *ptr=text+pos;
265 char *tmp_ptr;
266 if(strncmp(ptr,"<<",2)==0) { pos+=2; next_tocken=SHL; }
267 else if(strncmp(ptr,">>",2)==0) { pos+=2; next_tocken=SHR; }
268 else if(strncmp(ptr,"&&",2)==0) { pos+=2; next_tocken=AND; }
269 else if(strncmp(ptr,"||",2)==0) { pos+=2; next_tocken=OR; }
270 else if(strncmp(ptr,"<=",2)==0) { pos+=2; next_tocken=LTE; }
271 else if(strncmp(ptr,">=",2)==0) { pos+=2; next_tocken=GTE; }
272 else if(strncmp(ptr,"==",2)==0) { pos+=2; next_tocken=EQ; }
273 else if(strncmp(ptr,"!=",2)==0) { pos+=2; next_tocken=NEQ; }
274 else if(*ptr=='n') { pos++; next_tocken=VARIABLE; }
275 else if(isdigit(*ptr)) { int_value=strtol(text+pos,&tmp_ptr,0); pos=tmp_ptr-text; next_tocken=NUM; }
276 else if(*ptr=='\0') { next_tocken=0; }
277 else { next_tocken=*ptr; pos++; }
278 }
279 };
280
281
282 #define BINARY_EXPR(expr,hexpr,list) \
283 plural_ptr expr() \
284 { \
285 plural_ptr op1,op2; \
286 if((op1=hexpr()).get()==0) \
287 return plural_ptr(); \
288 while(is_in(t.next(),list)) { \
289 int o=t.get(); \
290 if((op2=hexpr()).get()==0) \
291 return plural_ptr(); \
292 op1=bin_factory(o,op1,op2); \
293 } \
294 return op1; \
295 }
296
297 class parser {
298 public:
299
300 parser(tokenizer &tin) : t(tin) {};
301
302 plural_ptr compile()
303 {
304 plural_ptr res=cond_expr();
305 if(res.get() && t.next()!=END) {
306 return plural_ptr();
307 };
308 return res;
309 }
310
311 private:
312
313 plural_ptr value_expr()
314 {
315 plural_ptr op;
316 if(t.next()=='(') {
317 t.get();
318 if((op=cond_expr()).get()==0)
319 return plural_ptr();
320 if(t.get()!=')')
321 return plural_ptr();
322 return op;
323 }
324 else if(t.next()==NUM) {
325 int value;
326 t.get(&value);
327 return plural_ptr(new number(value));
328 }
329 else if(t.next()==VARIABLE) {
330 t.get();
331 return plural_ptr(new identity());
332 }
333 return plural_ptr();
334 };
335
336 plural_ptr un_expr()
337 {
338 plural_ptr op1;
339 static int level_unary[]={3,'-','!','~'};
340 if(is_in(t.next(),level_unary)) {
341 int op=t.get();
342 if((op1=un_expr()).get()==0)
343 return plural_ptr();
344 switch(op) {
345 case '-':
346 return plural_ptr(new minus(op1));
347 case '!':
348 return plural_ptr(new l_not(op1));
349 case '~':
350 return plural_ptr(new bin_not(op1));
351 default:
352 return plural_ptr();
353 }
354 }
355 else {
356 return value_expr();
357 }
358 };
359
360 BINARY_EXPR(l10,un_expr,level10);
361 BINARY_EXPR(l9,l10,level9);
362 BINARY_EXPR(l8,l9,level8);
363 BINARY_EXPR(l7,l8,level7);
364 BINARY_EXPR(l6,l7,level6);
365 BINARY_EXPR(l5,l6,level5);
366 BINARY_EXPR(l4,l5,level4);
367 BINARY_EXPR(l3,l4,level3);
368 BINARY_EXPR(l2,l3,level2);
369 BINARY_EXPR(l1,l2,level1);
370
371 plural_ptr cond_expr()
372 {
373 plural_ptr cond,case1,case2;
374 if((cond=l1()).get()==0)
375 return plural_ptr();
376 if(t.next()=='?') {
377 t.get();
378 if((case1=cond_expr()).get()==0)
379 return plural_ptr();
380 if(t.get()!=':')
381 return plural_ptr();
382 if((case2=cond_expr()).get()==0)
383 return plural_ptr();
384 }
385 else {
386 return cond;
387 }
388 return plural_ptr(new conditional(cond,case1,case2));
389 }
390
391 tokenizer &t;
392
393 };
394
395} // namespace anon
396
397plural_ptr compile(char const *str)
398{
399 tokenizer t(str);
400 parser p(t);
401 return p.compile();
402}
403
404
405} // lambda
406} // gnu_gettext
407} // locale
408} // boost
409
410// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
411