]> granicus.if.org Git - icinga2/blob - tools/mkclass/class_parser.yy
Merge pull request #5602 from Icinga/fix/config-validation-fails-on-windows-with...
[icinga2] / tools / mkclass / class_parser.yy
1 %{
2 /******************************************************************************
3  * Icinga 2                                                                   *
4  * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/)  *
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 "classcompiler.hpp"
22 #include <iostream>
23 #include <vector>
24 #include <cstring>
25
26 using std::malloc;
27 using std::free;
28 using std::exit;
29
30 using namespace icinga;
31
32 #define YYLTYPE icinga::ClassDebugInfo
33
34 %}
35
36 %pure-parser
37
38 %locations
39 %defines
40 %error-verbose
41
42 %parse-param { ClassCompiler *context }
43 %lex-param { void *scanner }
44
45 %union {
46         char *text;
47         int num;
48         FieldType *type;
49         Field *field;
50         std::vector<Field> *fields;
51         Klass *klass;
52         FieldAccessor *fieldaccessor;
53         std::vector<FieldAccessor> *fieldaccessors;
54         Rule *rule;
55         std::vector<Rule> *rules;
56         Validator *validator;
57 }
58
59 %token T_INCLUDE "#include (T_INCLUDE)"
60 %token T_IMPL_INCLUDE "#impl_include (T_IMPL_INCLUDE)"
61 %token T_CLASS "class (T_CLASS)"
62 %token T_CODE "code (T_CODE)"
63 %token T_LOAD_AFTER "load_after (T_LOAD_AFTER)"
64 %token T_LIBRARY "library (T_LIBRARY)"
65 %token T_NAMESPACE "namespace (T_NAMESPACE)"
66 %token T_VALIDATOR "validator (T_VALIDATOR)"
67 %token T_REQUIRED "required (T_REQUIRED)"
68 %token T_NAVIGATION "navigation (T_NAVIGATION)"
69 %token T_NAME "name (T_NAME)"
70 %token T_ARRAY "array (T_ARRAY)"
71 %token T_STRING "string (T_STRING)"
72 %token T_ANGLE_STRING "angle_string (T_ANGLE_STRING)"
73 %token T_FIELD_ATTRIBUTE "field_attribute (T_FIELD_ATTRIBUTE)"
74 %token T_CLASS_ATTRIBUTE "class_attribute (T_CLASS_ATTRIBUTE)"
75 %token T_IDENTIFIER "identifier (T_IDENTIFIER)"
76 %token T_GET "get (T_GET)"
77 %token T_SET "set (T_SET)"
78 %token T_DEFAULT "default (T_DEFAULT)"
79 %token T_FIELD_ACCESSOR_TYPE "field_accessor_type (T_FIELD_ACCESSOR_TYPE)"
80 %type <text> T_IDENTIFIER
81 %type <text> T_STRING
82 %type <text> T_ANGLE_STRING
83 %type <text> identifier
84 %type <text> alternative_name_specifier
85 %type <text> inherits_specifier
86 %type <text> type_base_specifier
87 %type <text> include
88 %type <text> angle_include
89 %type <text> impl_include
90 %type <text> angle_impl_include
91 %type <text> code
92 %type <num> T_FIELD_ATTRIBUTE
93 %type <field> field_attribute
94 %type <field> field_attributes
95 %type <field> field_attribute_list
96 %type <num> T_FIELD_ACCESSOR_TYPE
97 %type <num> T_CLASS_ATTRIBUTE
98 %type <num> class_attribute_list
99 %type <type> field_type
100 %type <field> class_field
101 %type <fields> class_fields
102 %type <klass> class
103 %type <fieldaccessors> field_accessor_list
104 %type <fieldaccessors> field_accessors
105 %type <fieldaccessor> field_accessor
106 %type <rule> validator_rule
107 %type <rules> validator_rules
108 %type <validator> validator
109
110 %{
111
112 int yylex(YYSTYPE *lvalp, YYLTYPE *llocp, void *scanner);
113
114 void yyerror(YYLTYPE *locp, ClassCompiler *, const char *err)
115 {
116         std::cerr << "in " << locp->path << " at " << locp->first_line << ":" << locp->first_column << "-" << locp->last_line << ":" << locp->last_column << ": "
117                           << err
118                           << std::endl;
119         std::exit(1);
120 }
121
122 int yyparse(ClassCompiler *context);
123
124 void ClassCompiler::Compile(void)
125 {
126         try {
127                 yyparse(this);
128         } catch (const std::exception& ex) {
129                 std::cerr << "Exception: " << ex.what();
130         }
131
132         HandleMissingValidators();
133 }
134
135 #define scanner (context->GetScanner())
136
137 %}
138
139 %%
140
141 statements: /* empty */
142         | statements statement
143         ;
144
145 statement: include
146         {
147                 context->HandleInclude($1, yylloc);
148                 std::free($1);
149         }
150         | angle_include
151         {
152                 context->HandleAngleInclude($1, yylloc);
153                 std::free($1);
154         }
155         | impl_include
156         {
157                 context->HandleImplInclude($1, yylloc);
158                 std::free($1);
159         }
160         | angle_impl_include
161         {
162                 context->HandleAngleImplInclude($1, yylloc);
163                 std::free($1);
164         }
165         | class
166         {
167                 context->HandleClass(*$1, yylloc);
168                 delete $1;
169         }
170         | validator
171         {
172                 context->HandleValidator(*$1, yylloc);
173                 delete $1;
174         }
175         | namespace
176         | code
177         {
178                 context->HandleCode($1, yylloc);
179                 std::free($1);
180         }
181         | library
182         ;
183
184 include: T_INCLUDE T_STRING
185         {
186                 $$ = $2;
187         }
188         ;
189
190 angle_include: T_INCLUDE T_ANGLE_STRING
191         {
192                 $$ = $2;
193         }
194         ;
195
196 impl_include: T_IMPL_INCLUDE T_STRING
197         {
198                 $$ = $2;
199         }
200         ;
201
202 angle_impl_include: T_IMPL_INCLUDE T_ANGLE_STRING
203         {
204                 $$ = $2;
205         }
206         ;
207
208 namespace: T_NAMESPACE identifier '{'
209         {
210                 context->HandleNamespaceBegin($2, yylloc);
211                 std::free($2);
212         }
213         statements '}'
214         {
215                 context->HandleNamespaceEnd(yylloc);
216         }
217         ;
218
219 code: T_CODE T_STRING
220         {
221                 $$ = $2;
222         }
223         ;
224
225 library: T_LIBRARY T_IDENTIFIER ';'
226         {
227                 context->HandleLibrary($2, yylloc);
228                 free($2);
229         }
230         ;
231
232 class: class_attribute_list T_CLASS T_IDENTIFIER inherits_specifier type_base_specifier '{' class_fields '}' ';'
233         {
234                 $$ = new Klass();
235
236                 $$->Name = $3;
237                 std::free($3);
238
239                 if ($4) {
240                         $$->Parent = $4;
241                         std::free($4);
242                 }
243
244                 if ($5) {
245                         $$->TypeBase = $5;
246                         std::free($5);
247                 }
248
249                 $$->Attributes = $1;
250
251                 for (const Field& field : *$7) {
252                         if (field.Attributes & FALoadDependency) {
253                                 $$->LoadDependencies.push_back(field.Name);
254                         } else
255                                 $$->Fields.push_back(field);
256                 }
257
258                 delete $7;
259
260                 ClassCompiler::OptimizeStructLayout($$->Fields);
261         }
262         ;
263
264 class_attribute_list: /* empty */
265         {
266                 $$ = 0;
267         }
268         | T_CLASS_ATTRIBUTE
269         {
270                 $$ = $1;
271         }
272         | class_attribute_list T_CLASS_ATTRIBUTE
273         {
274                 $$ = $1 | $2;
275         }
276
277 inherits_specifier: /* empty */
278         {
279                 $$ = NULL;
280         }
281         | ':' identifier
282         {
283                 $$ = $2;
284         }
285         ;
286
287 type_base_specifier: /* empty */
288         {
289                 $$ = NULL;
290         }
291         | '<' identifier
292         {
293                 $$ = $2;
294         }
295         ;
296
297 class_fields: /* empty */
298         {
299                 $$ = new std::vector<Field>();
300         }
301         | class_fields class_field
302         {
303                 $$->push_back(*$2);
304                 delete $2;
305         }
306         ;
307
308 field_type: identifier
309         {
310                 $$ = new FieldType();
311                 $$->IsName = false;
312                 $$->TypeName = $1;
313                 free($1);
314         }
315         | T_NAME '(' identifier ')'
316         {
317                 $$ = new FieldType();
318                 $$->IsName = true;
319                 $$->TypeName = $3;
320                 $$->ArrayRank = 0;
321                 free($3);
322         }
323         | T_ARRAY '(' field_type ')'
324         {
325                 $$ = $3;
326                 $$->ArrayRank++;
327         }
328         ;
329
330 class_field: field_attribute_list field_type identifier alternative_name_specifier field_accessor_list ';'
331         {
332                 Field *field = $1;
333
334                 if ((field->Attributes & (FAConfig | FAState)) == 0)
335                         field->Attributes |= FAEphemeral;
336
337                 field->Type = *$2;
338                 delete $2;
339
340                 field->Name = $3;
341                 std::free($3);
342
343                 if ($4) {
344                         field->AlternativeName = $4;
345                         std::free($4);
346                 }
347
348                 std::vector<FieldAccessor>::const_iterator it;
349                 for (it = $5->begin(); it != $5->end(); it++) {
350                         switch (it->Type) {
351                                 case FTGet:
352                                         field->GetAccessor = it->Accessor;
353                                         field->PureGetAccessor = it->Pure;
354                                         break;
355                                 case FTSet:
356                                         field->SetAccessor = it->Accessor;
357                                         field->PureSetAccessor = it->Pure;
358                                         break;
359                                 case FTDefault:
360                                         field->DefaultAccessor = it->Accessor;
361                                         break;
362                                 case FTTrack:
363                                         field->TrackAccessor = it->Accessor;
364                                         break;
365                                 case FTNavigate:
366                                         field->NavigateAccessor = it->Accessor;
367                                         field->PureNavigateAccessor = it->Pure;
368                                         break;
369                         }
370                 }
371
372                 delete $5;
373
374                 $$ = field;
375         }
376         | T_LOAD_AFTER identifier ';'
377         {
378                 Field *field = new Field();
379                 field->Attributes = FALoadDependency;
380                 field->Name = $2;
381                 std::free($2);
382                 $$ = field;
383         }
384         ;
385
386 alternative_name_specifier: /* empty */
387         {
388                 $$ = NULL;
389         }
390         | '(' identifier ')'
391         {
392                 $$ = $2;
393         }
394         ;
395
396 field_attribute_list: /* empty */
397         {
398                 $$ = new Field();
399         }
400         | '[' field_attributes ']'
401         {
402                 $$ = $2;
403         }
404         ;
405
406 field_attribute: T_FIELD_ATTRIBUTE
407         {
408                 $$ = new Field();
409                 $$->Attributes = $1;
410         }
411         | T_REQUIRED
412         {
413                 $$ = new Field();
414                 $$->Attributes = FARequired;
415         }
416         | T_NAVIGATION '(' identifier ')'
417         {
418                 $$ = new Field();
419                 $$->Attributes = FANavigation;
420                 $$->NavigationName = $3;
421                 std::free($3);
422         }
423         | T_NAVIGATION
424         {
425                 $$ = new Field();
426                 $$->Attributes = FANavigation;
427         }
428         ;
429
430 field_attributes: /* empty */
431         {
432                 $$ = new Field();
433         }
434         | field_attributes ',' field_attribute
435         {
436                 $$ = $1;
437                 $$->Attributes |= $3->Attributes;
438                 if (!$3->NavigationName.empty())
439                         $$->NavigationName = $3->NavigationName;
440                 delete $3;
441         }
442         | field_attribute
443         {
444                 $$ = $1;
445         }
446         ;
447
448 field_accessor_list: /* empty */
449         {
450                 $$ = new std::vector<FieldAccessor>();
451         }
452         | '{' field_accessors '}'
453         {
454                 $$ = $2;
455         }
456         ;
457
458 field_accessors: /* empty */
459         {
460                 $$ = new std::vector<FieldAccessor>();
461         }
462         | field_accessors field_accessor
463         {
464                 $$ = $1;
465                 $$->push_back(*$2);
466                 delete $2;
467         }
468         ;
469
470 field_accessor: T_FIELD_ACCESSOR_TYPE T_STRING
471         {
472                 $$ = new FieldAccessor(static_cast<FieldAccessorType>($1), $2, false);
473                 std::free($2);
474         }
475         | T_FIELD_ACCESSOR_TYPE ';'
476         {
477                 $$ = new FieldAccessor(static_cast<FieldAccessorType>($1), "", true);
478         }
479         ;
480
481 validator_rules: /* empty */
482         {
483                 $$ = new std::vector<Rule>();
484         }
485         | validator_rules validator_rule
486         {
487                 $$->push_back(*$2);
488                 delete $2;
489         }
490         ;
491
492 validator_rule: T_NAME '(' T_IDENTIFIER ')' identifier ';'
493         {
494                 $$ = new Rule();
495                 $$->Attributes = 0;
496                 $$->IsName = true;
497                 $$->Type = $3;
498                 std::free($3);
499                 $$->Pattern = $5;
500                 std::free($5);
501         }
502         | T_IDENTIFIER identifier ';'
503         {
504                 $$ = new Rule();
505                 $$->Attributes = 0;
506                 $$->IsName = false;
507                 $$->Type = $1;
508                 std::free($1);
509                 $$->Pattern = $2;
510                 std::free($2);
511         }
512         | T_NAME '(' T_IDENTIFIER ')' identifier '{' validator_rules '}' ';'
513         {
514                 $$ = new Rule();
515                 $$->Attributes = 0;
516                 $$->IsName = true;
517                 $$->Type = $3;
518                 std::free($3);
519                 $$->Pattern = $5;
520                 std::free($5);
521                 $$->Rules = *$7;
522                 delete $7;
523         }
524         | T_IDENTIFIER identifier '{' validator_rules '}' ';'
525         {
526                 $$ = new Rule();
527                 $$->Attributes = 0;
528                 $$->IsName = false;
529                 $$->Type = $1;
530                 std::free($1);
531                 $$->Pattern = $2;
532                 std::free($2);
533                 $$->Rules = *$4;
534                 delete $4;
535         }
536         | T_REQUIRED identifier ';'
537         {
538                 $$ = new Rule();
539                 $$->Attributes = RARequired;
540                 $$->IsName = false;
541                 $$->Type = "";
542                 $$->Pattern = $2;
543                 std::free($2);
544         }
545         ;
546
547 validator: T_VALIDATOR T_IDENTIFIER '{' validator_rules '}' ';'
548         {
549                 $$ = new Validator();
550
551                 $$->Name = $2;
552                 std::free($2);
553
554                 $$->Rules = *$4;
555                 delete $4;
556         }
557         ;
558
559 identifier: T_IDENTIFIER
560         | T_STRING
561         {
562                 $$ = $1;
563         }
564         ;