]> granicus.if.org Git - icinga2/blob - lib/config/config_parser.yy
Remove the replication feature and clean up the code.
[icinga2] / lib / config / config_parser.yy
1 %code requires {
2 /******************************************************************************
3  * Icinga 2                                                                   *
4  * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/)        *
5  *                                                                            *
6  * This program is free software; you can redistribute it and/or              *
7  * modify it under the terms of the GNU General Public License                *
8  * as published by the Free Software Foundation; either version 2             *
9  * of the License, or (at your option) any later version.                     *
10  *                                                                            *
11  * This program is distributed in the hope that it will be useful,            *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
14  * GNU General Public License for more details.                               *
15  *                                                                            *
16  * You should have received a copy of the GNU General Public License          *
17  * along with this program; if not, write to the Free Software Foundation     *
18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
19  ******************************************************************************/
20
21 #include "i2-config.h"
22 #include "config/expression.h"
23 #include "config/expressionlist.h"
24 #include "config/configitembuilder.h"
25 #include "config/configcompiler.h"
26 #include "config/configcompilercontext.h"
27 #include "config/typerule.h"
28 #include "config/typerulelist.h"
29 #include "base/value.h"
30 #include "base/utility.h"
31 #include "base/array.h"
32 #include "base/scriptvariable.h"
33 #include <sstream>
34 #include <stack>
35 #include <boost/smart_ptr/make_shared.hpp>
36 #include <boost/exception/diagnostic_information.hpp>
37 #include <boost/foreach.hpp>
38
39 using namespace icinga;
40
41 #define YYLTYPE icinga::DebugInfo
42
43 }
44
45 %pure-parser
46
47 %locations
48 %defines
49 %error-verbose
50
51 %parse-param { ConfigCompiler *context }
52 %lex-param { void *scanner }
53
54 %union {
55         char *text;
56         double num;
57         icinga::Value *variant;
58         icinga::ExpressionOperator op;
59         icinga::TypeSpecifier type;
60         std::vector<String> *slist;
61         Expression *expr;
62         ExpressionList *exprl;
63         Array *array;
64 }
65
66 %token <text> T_STRING
67 %token <text> T_STRING_ANGLE
68 %token <num> T_NUMBER
69 %token T_NULL
70 %token <text> T_IDENTIFIER
71 %token <op> T_EQUAL "= (T_EQUAL)"
72 %token <op> T_PLUS_EQUAL "+= (T_PLUS_EQUAL)"
73 %token <op> T_MINUS_EQUAL "-= (T_MINUS_EQUAL)"
74 %token <op> T_MULTIPLY_EQUAL "*= (T_MULTIPLY_EQUAL)"
75 %token <op> T_DIVIDE_EQUAL "/= (T_DIVIDE_EQUAL)"
76 %token T_SET "set (T_SET)"
77 %token T_SHIFT_LEFT "<< (T_SHIFT_LEFT)"
78 %token T_SHIFT_RIGHT ">> (T_SHIFT_RIGHT)"
79 %token <type> T_TYPE_DICTIONARY "dictionary (T_TYPE_DICTIONARY)"
80 %token <type> T_TYPE_ARRAY "array (T_TYPE_ARRAY)"
81 %token <type> T_TYPE_NUMBER "number (T_TYPE_NUMBER)"
82 %token <type> T_TYPE_STRING "string (T_TYPE_STRING)"
83 %token <type> T_TYPE_SCALAR "scalar (T_TYPE_SCALAR)"
84 %token <type> T_TYPE_ANY "any (T_TYPE_ANY)"
85 %token <type> T_TYPE_NAME "name (T_TYPE_NAME)"
86 %token T_VALIDATOR "%validator (T_VALIDATOR)"
87 %token T_REQUIRE "%require (T_REQUIRE)"
88 %token T_ATTRIBUTE "%attribute (T_ATTRIBUTE)"
89 %token T_TYPE "type (T_TYPE)"
90 %token T_ABSTRACT "abstract (T_ABSTRACT)"
91 %token T_OBJECT "object (T_OBJECT)"
92 %token T_TEMPLATE "template (T_TEMPLATE)"
93 %token T_INCLUDE "include (T_INCLUDE)"
94 %token T_LIBRARY "library (T_LIBRARY)"
95 %token T_INHERITS "inherits (T_INHERITS)"
96 %token T_PARTIAL "partial (T_PARTIAL)"
97 %type <text> identifier
98 %type <array> array
99 %type <array> array_items
100 %type <array> array_items_inner
101 %type <variant> simplevalue
102 %type <variant> value
103 %type <expr> expression
104 %type <exprl> expressions
105 %type <exprl> expressions_inner
106 %type <exprl> expressionlist
107 %type <variant> typerulelist
108 %type <op> operator
109 %type <type> type
110 %type <num> partial_specifier
111 %type <slist> object_inherits_list
112 %type <slist> object_inherits_specifier
113 %type <num> constterm
114 %type <num> constexpression
115 %left '+' '-'
116 %left '*' '/'
117 %left '&'
118 %left '|'
119 %{
120
121 int yylex(YYSTYPE *lvalp, YYLTYPE *llocp, void *scanner);
122
123 void yyerror(YYLTYPE *locp, ConfigCompiler *, const char *err)
124 {
125         std::ostringstream message;
126         message << *locp << ": " << err;
127         ConfigCompilerContext::GetInstance()->AddError(false, message.str());
128 }
129
130 int yyparse(ConfigCompiler *context);
131
132 static std::stack<Array::Ptr> m_Arrays;
133 static bool m_Abstract;
134
135 static std::stack<TypeRuleList::Ptr> m_RuleLists;
136 static ConfigType::Ptr m_Type;
137
138 void ConfigCompiler::Compile(void)
139 {
140         try {
141                 yyparse(this);
142         } catch (const std::exception& ex) {
143                 ConfigCompilerContext::GetInstance()->AddError(false, boost::diagnostic_information(ex));
144         }
145 }
146
147 #define scanner (context->GetScanner())
148
149 %}
150
151 %%
152 statements: /* empty */
153         | statements statement
154         ;
155
156 statement: object | type | include | library | variable
157         ;
158
159 include: T_INCLUDE T_STRING
160         {
161                 context->HandleInclude($2, false, yylloc);
162                 free($2);
163         }
164         | T_INCLUDE T_STRING_ANGLE
165         {
166                 context->HandleInclude($2, true, yylloc);
167                 free($2);
168         }
169
170 library: T_LIBRARY T_STRING
171         {
172                 context->HandleLibrary($2);
173                 free($2);
174         }
175
176 variable: T_SET identifier T_EQUAL value
177         {
178                 ScriptVariable::Set($2, *$4);
179                 free($2);
180                 delete $4;
181         }
182
183 identifier: T_IDENTIFIER
184         | T_STRING
185         {
186                 $$ = $1;
187         }
188         ;
189
190 type: partial_specifier T_TYPE identifier
191         {
192                 String name = String($3);
193                 free($3);
194
195                 m_Type = ConfigType::GetByName(name);
196
197                 if (!m_Type) {
198                         if ($1)
199                                 BOOST_THROW_EXCEPTION(std::invalid_argument("Partial type definition for unknown type '" + name + "'"));
200
201                         m_Type = boost::make_shared<ConfigType>(name, yylloc);
202                         m_Type->Register();
203                 }
204         }
205         type_inherits_specifier typerulelist
206         {
207                 TypeRuleList::Ptr ruleList = *$6;
208                 m_Type->GetRuleList()->AddRules(ruleList);
209                 m_Type->GetRuleList()->AddRequires(ruleList);
210
211                 String validator = ruleList->GetValidator();
212                 if (!validator.IsEmpty())
213                         m_Type->GetRuleList()->SetValidator(validator);
214
215                 delete $6;
216         }
217         ;
218
219 partial_specifier: /* Empty */
220         {
221                 $$ = 0;
222         }
223         | T_PARTIAL
224         {
225                 $$ = 1;
226         }
227         ;
228
229 typerulelist: '{'
230         {
231                 m_RuleLists.push(boost::make_shared<TypeRuleList>());
232         }
233         typerules
234         '}'
235         {
236                 $$ = new Value(m_RuleLists.top());
237                 m_RuleLists.pop();
238         }
239         ;
240
241 typerules: typerules_inner
242         | typerules_inner ','
243
244 typerules_inner: /* empty */
245         | typerule
246         | typerules_inner ',' typerule
247         ;
248
249 typerule: T_REQUIRE T_STRING
250         {
251                 m_RuleLists.top()->AddRequire($2);
252                 free($2);
253         }
254         | T_VALIDATOR T_STRING
255         {
256                 m_RuleLists.top()->SetValidator($2);
257                 free($2);
258         }
259         | T_ATTRIBUTE type T_STRING
260         {
261                 TypeRule rule($2, String(), $3, TypeRuleList::Ptr(), yylloc);
262                 free($3);
263
264                 m_RuleLists.top()->AddRule(rule);
265         }
266         | T_ATTRIBUTE T_TYPE_NAME '(' identifier ')' T_STRING
267         {
268                 TypeRule rule($2, $4, $6, TypeRuleList::Ptr(), yylloc);
269                 free($4);
270                 free($6);
271
272                 m_RuleLists.top()->AddRule(rule);
273         }
274         | T_ATTRIBUTE type T_STRING typerulelist
275         {
276                 TypeRule rule($2, String(), $3, *$4, yylloc);
277                 free($3);
278                 delete $4;
279                 m_RuleLists.top()->AddRule(rule);
280         }
281         ;
282
283 type_inherits_specifier: /* empty */
284         | T_INHERITS identifier
285         {
286                 m_Type->SetParent($2);
287                 free($2);
288         }
289         ;
290
291 type: T_TYPE_DICTIONARY
292         | T_TYPE_ARRAY
293         | T_TYPE_NUMBER
294         | T_TYPE_STRING
295         | T_TYPE_SCALAR
296         | T_TYPE_ANY
297         | T_TYPE_NAME
298         {
299                 $$ = $1;
300         }
301         ;
302
303 object:
304         {
305                 m_Abstract = false;
306         }
307 object_declaration identifier T_STRING object_inherits_specifier expressionlist
308         {
309                 ConfigItemBuilder::Ptr item = boost::make_shared<ConfigItemBuilder>(yylloc);
310
311                 item->SetType($3);
312
313                 if (strchr($4, ':') != NULL) {
314                         std::ostringstream msgbuf;
315                         msgbuf << "Name for object '" << $4 << "' of type '" << $3 << "' is invalid: Object names may not contain ':'";
316                         free($3);
317                         BOOST_THROW_EXCEPTION(std::invalid_argument(msgbuf.str()));
318                 }
319
320                 free($3);
321
322                 item->SetName($4);
323                 free($4);
324
325                 if ($5) {
326                         BOOST_FOREACH(const String& parent, *$5) {
327                                 item->AddParent(parent);
328                         }
329
330                         delete $5;
331                 }
332
333                 if ($6) {
334                         ExpressionList::Ptr exprl = ExpressionList::Ptr($6);
335                         item->AddExpressionList(exprl);
336                 }
337
338                 item->SetAbstract(m_Abstract);
339
340                 item->Compile()->Register();
341                 item.reset();
342         }
343         ;
344
345 object_declaration: attributes T_OBJECT
346         | T_TEMPLATE
347         {
348                 m_Abstract = true;
349         }
350
351 attributes: /* empty */
352         | attributes attribute
353         ;
354
355 attribute: T_ABSTRACT
356         {
357                 m_Abstract = true;
358         }
359         ;
360
361 object_inherits_list:
362         {
363                 $$ = NULL;
364         }
365         | T_STRING
366         {
367                 $$ = new std::vector<String>();
368                 $$->push_back($1);
369                 free($1);
370         }
371         | object_inherits_list ',' T_STRING
372         {
373                 if ($1)
374                         $$ = $1;
375                 else
376                         $$ = new std::vector<String>();
377
378                 $$->push_back($3);
379                 free($3);
380         }
381         ;
382
383 object_inherits_specifier:
384         {
385                 $$ = NULL;
386         }
387         | T_INHERITS object_inherits_list
388         {
389                 $$ = $2;
390         }
391         ;
392
393 expressionlist: '{' expressions '}'
394         {
395                 $$ = $2;
396         }
397         ;
398
399 expressions: expressions_inner
400         {
401                 $$ = $1;
402         }
403         | expressions_inner ','
404         {
405                 $$ = $1;
406         }
407
408 expressions_inner: /* empty */
409         {
410                 $$ = NULL;
411         }
412         | expression
413         {
414                 $$ = new ExpressionList();
415                 $$->AddExpression(*$1);
416                 delete $1;
417         }
418         | expressions_inner ',' expression
419         {
420                 if ($1)
421                         $$ = $1;
422                 else
423                         $$ = new ExpressionList();
424
425                 $$->AddExpression(*$3);
426                 delete $3;
427         }
428         ;
429
430 expression: identifier operator value
431         {
432                 $$ = new Expression($1, $2, *$3, yylloc);
433                 free($1);
434                 delete $3;
435         }
436         | identifier '[' T_STRING ']' operator value
437         {
438                 Expression subexpr($3, $5, *$6, yylloc);
439                 free($3);
440                 delete $6;
441
442                 ExpressionList::Ptr subexprl = boost::make_shared<ExpressionList>();
443                 subexprl->AddExpression(subexpr);
444
445                 $$ = new Expression($1, OperatorPlus, subexprl, yylloc);
446                 free($1);
447         }
448         ;
449
450 operator: T_EQUAL
451         | T_PLUS_EQUAL
452         | T_MINUS_EQUAL
453         | T_MULTIPLY_EQUAL
454         | T_DIVIDE_EQUAL
455         {
456                 $$ = $1;
457         }
458         ;
459
460 array: '[' array_items ']'
461         {
462                 $$ = $2;
463         }
464         ;
465
466 array_items: array_items_inner
467         {
468                 $$ = $1;
469         }
470         | array_items_inner ','
471         {
472                 $$ = $1;
473         }
474
475 array_items_inner: /* empty */
476         {
477                 $$ = NULL;
478         }
479         | value
480         {
481                 $$ = new Array();
482
483                 if ($1->IsObjectType<ExpressionList>()) {
484                         ExpressionList::Ptr exprl = *$1;
485                         Dictionary::Ptr dict = boost::make_shared<Dictionary>();
486                         exprl->Execute(dict);
487                         delete $1;
488                         $1 = new Value(dict);
489                 }
490
491                 $$->Add(*$1);
492                 delete $1;
493         }
494         | array_items_inner ',' value
495         {
496                 if ($1)
497                         $$ = $1;
498                 else
499                         $$ = new Array();
500
501                 if ($3->IsObjectType<ExpressionList>()) {
502                         ExpressionList::Ptr exprl = *$3;
503                         Dictionary::Ptr dict = boost::make_shared<Dictionary>();
504                         exprl->Execute(dict);
505                         delete $3;
506                         $3 = new Value(dict);
507                 }
508
509                 $$->Add(*$3);
510                 delete $3;
511         }
512         ;
513
514 simplevalue: T_STRING
515         {
516                 $$ = new Value($1);
517                 free($1);
518         }
519         | T_NUMBER
520         {
521                 $$ = new Value($1);
522         }
523         | T_NULL
524         {
525                 $$ = new Value();
526         }
527         | array
528         {
529                 if ($1 == NULL)
530                         $1 = new Array();
531
532                 Array::Ptr array = Array::Ptr($1);
533                 $$ = new Value(array);
534         }
535         ;
536
537 constterm: '(' constexpression ')'
538         {
539                 $$ = $2;
540         }
541
542 constexpression: T_NUMBER
543         {
544                 $$ = $1;
545         }
546         | identifier
547         {
548                 $$ = ScriptVariable::Get($1);
549                 free($1);
550         }
551         | constexpression '+' constexpression
552         {
553                 $$ = $1 + $3;
554         }
555         | constexpression '-' constexpression
556         {
557                 $$ = $1 - $3;
558         }
559         | constexpression '*' constexpression
560         {
561                 $$ = $1 * $3;
562         }
563         | constexpression '/' constexpression
564         {
565                 $$ = $1 / $3;
566         }
567         | constexpression '&' constexpression
568         {
569                 $$ = (long)$1 & (long)$3;
570         }
571         | constexpression '|' constexpression
572         {
573                 $$ = (long)$1 | (long)$3;
574         }
575         | constexpression T_SHIFT_LEFT constexpression
576         {
577                 $$ = (long)$1 << (long)$3;
578         }
579         | constexpression T_SHIFT_RIGHT constexpression
580         {
581                 $$ = (long)$1 >> (long)$3;
582         }
583         | '(' constexpression ')'
584         {
585                 $$ = $2;
586         }
587         ;
588
589 value: simplevalue
590         | expressionlist
591         {
592                 ExpressionList::Ptr exprl = ExpressionList::Ptr($1);
593                 $$ = new Value(exprl);
594         }
595         | constterm
596         {
597                 $$ = new Value($1);
598         }
599         ;
600 %%