]> granicus.if.org Git - icinga2/blob - lib/config/config_parser.yy
Fix location messages.
[icinga2] / lib / config / config_parser.yy
1 %{
2  #define YYDEBUG 1
3  
4 /******************************************************************************
5  * Icinga 2                                                                   *
6  * Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org)    *
7  *                                                                            *
8  * This program is free software; you can redistribute it and/or              *
9  * modify it under the terms of the GNU General Public License                *
10  * as published by the Free Software Foundation; either version 2             *
11  * of the License, or (at your option) any later version.                     *
12  *                                                                            *
13  * This program is distributed in the hope that it will be useful,            *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
16  * GNU General Public License for more details.                               *
17  *                                                                            *
18  * You should have received a copy of the GNU General Public License          *
19  * along with this program; if not, write to the Free Software Foundation     *
20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
21  ******************************************************************************/
22
23 #include "i2-config.h"
24 #include "config/expression.h"
25 #include "config/expressionlist.h"
26 #include "config/configitembuilder.h"
27 #include "config/configcompiler.h"
28 #include "config/configcompilercontext.h"
29 #include "config/configerror.h"
30 #include "config/typerule.h"
31 #include "config/typerulelist.h"
32 #include "config/aexpression.h"
33 #include "config/applyrule.h"
34 #include "base/value.h"
35 #include "base/utility.h"
36 #include "base/array.h"
37 #include "base/scriptvariable.h"
38 #include "base/exception.h"
39 #include "base/dynamictype.h"
40 #include <sstream>
41 #include <stack>
42 #include <boost/foreach.hpp>
43
44 #define YYLTYPE icinga::DebugInfo
45 #define YYERROR_VERBOSE
46
47 #define YYLLOC_DEFAULT(Current, Rhs, N)                                 \
48 do {                                                                    \
49         if (N) {                                                        \
50                 (Current).Path = YYRHSLOC(Rhs, 1).Path;                 \
51                 (Current).FirstLine = YYRHSLOC(Rhs, 1).FirstLine;       \
52                 (Current).FirstColumn = YYRHSLOC(Rhs, 1).FirstColumn;   \
53                 (Current).LastLine = YYRHSLOC(Rhs, N).LastLine;         \
54                 (Current).LastColumn = YYRHSLOC(Rhs, N).LastColumn;     \
55         } else {                                                        \
56                 (Current).Path = YYRHSLOC(Rhs, 0).Path;                 \
57                 (Current).FirstLine = (Current).LastLine =              \
58                 YYRHSLOC(Rhs, 0).LastLine;                              \
59                 (Current).FirstColumn = (Current).LastColumn =          \
60                 YYRHSLOC(Rhs, 0).LastColumn;                            \
61         }                                                               \
62 } while (0)
63
64 #define YY_LOCATION_PRINT(file, loc)                    \
65 do {                                                    \
66        std::ostringstream msgbuf;                       \
67        msgbuf << loc;                                   \
68        std::string str = msgbuf.str();                  \
69        fputs(str.c_str(), file);                        \
70 } while (0)
71
72 using namespace icinga;
73
74 %}
75
76 %pure-parser
77
78 %locations
79 %defines
80 %error-verbose
81
82 %parse-param { ConfigCompiler *context }
83 %lex-param { void *scanner }
84
85 %union {
86         char *text;
87         double num;
88         icinga::Value *variant;
89         icinga::ExpressionOperator op;
90         icinga::TypeSpecifier type;
91         std::vector<String> *slist;
92         Expression *expr;
93         ExpressionList *exprl;
94         Array *array;
95         Value *aexpr;
96 }
97
98 %token <text> T_STRING
99 %token <text> T_STRING_ANGLE
100 %token <num> T_NUMBER
101 %token T_NULL
102 %token <text> T_IDENTIFIER
103 %token <op> T_SET "= (T_SET)"
104 %token <op> T_PLUS_EQUAL "+= (T_PLUS_EQUAL)"
105 %token <op> T_MINUS_EQUAL "-= (T_MINUS_EQUAL)"
106 %token <op> T_MULTIPLY_EQUAL "*= (T_MULTIPLY_EQUAL)"
107 %token <op> T_DIVIDE_EQUAL "/= (T_DIVIDE_EQUAL)"
108 %token T_VAR "var (T_VAR)"
109 %token T_CONST "const (T_CONST)"
110 %token T_SHIFT_LEFT "<< (T_SHIFT_LEFT)"
111 %token T_SHIFT_RIGHT ">> (T_SHIFT_RIGHT)"
112 %token T_EQUAL "== (T_EQUAL)"
113 %token T_NOT_EQUAL "!= (T_NOT_EQUAL)"
114 %token T_IN "in (T_IN)"
115 %token T_NOT_IN "!in (T_NOT_IN)"
116 %token T_LOGICAL_AND "&& (T_LOGICAL_AND)"
117 %token T_LOGICAL_OR "|| (T_LOGICAL_OR)"
118 %token T_LESS_THAN_OR_EQUAL "<= (T_LESS_THAN_OR_EQUAL)"
119 %token T_GREATER_THAN_OR_EQUAL ">= (T_GREATER_THAN_OR_EQUAL)"
120 %token <type> T_TYPE_DICTIONARY "dictionary (T_TYPE_DICTIONARY)"
121 %token <type> T_TYPE_ARRAY "array (T_TYPE_ARRAY)"
122 %token <type> T_TYPE_NUMBER "number (T_TYPE_NUMBER)"
123 %token <type> T_TYPE_STRING "string (T_TYPE_STRING)"
124 %token <type> T_TYPE_SCALAR "scalar (T_TYPE_SCALAR)"
125 %token <type> T_TYPE_ANY "any (T_TYPE_ANY)"
126 %token <type> T_TYPE_NAME "name (T_TYPE_NAME)"
127 %token T_VALIDATOR "%validator (T_VALIDATOR)"
128 %token T_REQUIRE "%require (T_REQUIRE)"
129 %token T_ATTRIBUTE "%attribute (T_ATTRIBUTE)"
130 %token T_TYPE "type (T_TYPE)"
131 %token T_OBJECT "object (T_OBJECT)"
132 %token T_TEMPLATE "template (T_TEMPLATE)"
133 %token T_INCLUDE "include (T_INCLUDE)"
134 %token T_INCLUDE_RECURSIVE "include_recursive (T_INCLUDE_RECURSIVE)"
135 %token T_LIBRARY "library (T_LIBRARY)"
136 %token T_INHERITS "inherits (T_INHERITS)"
137 %token T_PARTIAL "partial (T_PARTIAL)"
138 %token T_APPLY "apply (T_APPLY)"
139 %token T_TO "to (T_TO)"
140 %token T_WHERE "where (T_WHERE)"
141 %type <text> identifier
142 %type <array> array_items
143 %type <array> array_items_inner
144 %type <variant> value
145 %type <expr> expression
146 %type <exprl> expressions
147 %type <exprl> expressions_inner
148 %type <exprl> expressionlist
149 %type <variant> typerulelist
150 %type <op> operator
151 %type <type> type
152 %type <num> partial_specifier
153 %type <slist> object_inherits_list
154 %type <slist> object_inherits_specifier
155 %type <aexpr> aexpression
156 %type <num> variable_decl
157 %left T_LOGICAL_OR
158 %left T_LOGICAL_AND
159 %left T_IN
160 %left T_NOT_IN
161 %nonassoc T_EQUAL
162 %nonassoc T_NOT_EQUAL
163 %left '+' '-'
164 %left '*' '/'
165 %left '&'
166 %left '|'
167 %right '~'
168 %right '!'
169 %{
170
171 int yylex(YYSTYPE *lvalp, YYLTYPE *llocp, void *scanner);
172
173 void yyerror(YYLTYPE *locp, ConfigCompiler *, const char *err)
174 {
175         std::ostringstream message;
176         message << *locp << ": " << err;
177         ConfigCompilerContext::GetInstance()->AddMessage(true, message.str(), *locp);
178 }
179
180 int yyparse(ConfigCompiler *context);
181
182 static std::stack<Array::Ptr> m_Arrays;
183 static bool m_Abstract;
184
185 static std::stack<TypeRuleList::Ptr> m_RuleLists;
186 static ConfigType::Ptr m_Type;
187
188 void ConfigCompiler::Compile(void)
189 {
190         try {
191                 yyparse(this);
192         } catch (const ConfigError& ex) {
193                 ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), ex.GetDebugInfo());
194         } catch (const std::exception& ex) {
195                 ConfigCompilerContext::GetInstance()->AddMessage(true, DiagnosticInformation(ex));
196         }
197 }
198
199 #define scanner (context->GetScanner())
200
201 %}
202
203 %%
204 statements: /* empty */
205         | statements statement
206         ;
207
208 statement: object | type | include | include_recursive | library | variable | apply
209         ;
210
211 include: T_INCLUDE value
212         {
213                 context->HandleInclude(*$2, false, DebugInfoRange(@1, @2));
214                 delete $2;
215         }
216         | T_INCLUDE T_STRING_ANGLE
217         {
218                 context->HandleInclude($2, true, DebugInfoRange(@1, @2));
219                 free($2);
220         }
221         ;
222
223 include_recursive: T_INCLUDE_RECURSIVE value
224         {
225                 context->HandleIncludeRecursive(*$2, "*.conf", DebugInfoRange(@1, @2));
226                 delete $2;
227         }
228         | T_INCLUDE_RECURSIVE value value
229         {
230                 context->HandleIncludeRecursive(*$2, *$3, DebugInfoRange(@1, @3));
231                 delete $2;
232                 delete $3;
233         }
234         ;
235
236 library: T_LIBRARY T_STRING
237         {
238                 context->HandleLibrary($2);
239                 free($2);
240         }
241         ;
242
243 variable: variable_decl identifier T_SET value
244         {
245                 Value *value = $4;
246                 if (value->IsObjectType<ExpressionList>()) {
247                         Dictionary::Ptr dict = make_shared<Dictionary>();
248                         ExpressionList::Ptr exprl = *value;
249                         exprl->Execute(dict);
250                         delete value;
251                         value = new Value(dict);
252                 }
253
254                 ScriptVariable::Ptr sv = ScriptVariable::Set($2, *value);
255                 sv->SetConstant(true);
256
257                 free($2);
258                 delete value;
259         }
260         ;
261
262 variable_decl: T_VAR
263         {
264                 $$ = true;
265         }
266         | T_CONST
267         {
268                 $$ = false;
269         }
270         ;
271
272 identifier: T_IDENTIFIER
273         | T_STRING
274         {
275                 $$ = $1;
276         }
277         ;
278
279 type: partial_specifier T_TYPE identifier
280         {
281                 String name = String($3);
282                 free($3);
283
284                 m_Type = ConfigType::GetByName(name);
285
286                 if (!m_Type) {
287                         if ($1)
288                                 BOOST_THROW_EXCEPTION(ConfigError("Partial type definition for unknown type '" + name + "'", DebugInfoRange(@1, @3)));
289
290                         m_Type = make_shared<ConfigType>(name, DebugInfoRange(@1, @3));
291                         m_Type->Register();
292                 }
293         }
294         type_inherits_specifier typerulelist
295         {
296                 TypeRuleList::Ptr ruleList = *$6;
297                 m_Type->GetRuleList()->AddRules(ruleList);
298                 m_Type->GetRuleList()->AddRequires(ruleList);
299
300                 String validator = ruleList->GetValidator();
301                 if (!validator.IsEmpty())
302                         m_Type->GetRuleList()->SetValidator(validator);
303
304                 delete $6;
305         }
306         ;
307
308 partial_specifier: /* Empty */
309         {
310                 $$ = 0;
311         }
312         | T_PARTIAL
313         {
314                 $$ = 1;
315         }
316         ;
317
318 typerulelist: '{'
319         {
320                 m_RuleLists.push(make_shared<TypeRuleList>());
321         }
322         typerules
323         '}'
324         {
325                 $$ = new Value(m_RuleLists.top());
326                 m_RuleLists.pop();
327         }
328         ;
329
330 typerules: typerules_inner
331         | typerules_inner ','
332
333 typerules_inner: /* empty */
334         | typerule
335         | typerules_inner ',' typerule
336         ;
337
338 typerule: T_REQUIRE T_STRING
339         {
340                 m_RuleLists.top()->AddRequire($2);
341                 free($2);
342         }
343         | T_VALIDATOR T_STRING
344         {
345                 m_RuleLists.top()->SetValidator($2);
346                 free($2);
347         }
348         | T_ATTRIBUTE type T_STRING
349         {
350                 TypeRule rule($2, String(), $3, TypeRuleList::Ptr(), DebugInfoRange(@1, @3));
351                 free($3);
352
353                 m_RuleLists.top()->AddRule(rule);
354         }
355         | T_ATTRIBUTE T_TYPE_NAME '(' identifier ')' T_STRING
356         {
357                 TypeRule rule($2, $4, $6, TypeRuleList::Ptr(), DebugInfoRange(@1, @6));
358                 free($4);
359                 free($6);
360
361                 m_RuleLists.top()->AddRule(rule);
362         }
363         | T_ATTRIBUTE type T_STRING typerulelist
364         {
365                 TypeRule rule($2, String(), $3, *$4, DebugInfoRange(@1, @4));
366                 free($3);
367                 delete $4;
368                 m_RuleLists.top()->AddRule(rule);
369         }
370         ;
371
372 type_inherits_specifier: /* empty */
373         | T_INHERITS identifier
374         {
375                 m_Type->SetParent($2);
376                 free($2);
377         }
378         ;
379
380 type: T_TYPE_DICTIONARY
381         | T_TYPE_ARRAY
382         | T_TYPE_NUMBER
383         | T_TYPE_STRING
384         | T_TYPE_SCALAR
385         | T_TYPE_ANY
386         | T_TYPE_NAME
387         {
388                 $$ = $1;
389         }
390         ;
391
392 object:
393         {
394                 m_Abstract = false;
395         }
396         object_declaration identifier T_STRING object_inherits_specifier expressionlist
397         {
398                 DebugInfo di = DebugInfoRange(@2, @6);
399                 ConfigItemBuilder::Ptr item = make_shared<ConfigItemBuilder>(di);
400
401                 ConfigItem::Ptr oldItem = ConfigItem::GetObject($3, $4);
402
403                 if (oldItem) {
404                         std::ostringstream msgbuf;
405                         msgbuf << "Object '" << $4 << "' of type '" << $3 << "' re-defined: " << di << "; previous definition: " << oldItem->GetDebugInfo();
406                         free($3);
407                         free($4);
408                         delete $5;
409                         BOOST_THROW_EXCEPTION(ConfigError(msgbuf.str(), di));
410                 }
411
412                 item->SetType($3);
413
414                 if (strchr($4, '!') != NULL) {
415                         std::ostringstream msgbuf;
416                         msgbuf << "Name for object '" << $4 << "' of type '" << $3 << "' is invalid: Object names may not contain '!'";
417                         free($3);
418                         BOOST_THROW_EXCEPTION(ConfigError(msgbuf.str(), @4));
419                 }
420
421                 free($3);
422
423                 item->SetName($4);
424                 free($4);
425
426                 if ($5) {
427                         BOOST_FOREACH(const String& parent, *$5) {
428                                 item->AddParent(parent);
429                         }
430
431                         delete $5;
432                 }
433
434                 if ($6) {
435                         ExpressionList::Ptr exprl = ExpressionList::Ptr($6);
436                         item->AddExpressionList(exprl);
437                 }
438
439                 item->SetAbstract(m_Abstract);
440
441                 item->Compile()->Register();
442                 item.reset();
443         }
444         ;
445
446 object_declaration: T_OBJECT
447         | T_TEMPLATE
448         {
449                 m_Abstract = true;
450         }
451
452 object_inherits_list:
453         {
454                 $$ = NULL;
455         }
456         | T_STRING
457         {
458                 $$ = new std::vector<String>();
459                 $$->push_back($1);
460                 free($1);
461         }
462         | object_inherits_list ',' T_STRING
463         {
464                 if ($1)
465                         $$ = $1;
466                 else
467                         $$ = new std::vector<String>();
468
469                 $$->push_back($3);
470                 free($3);
471         }
472         ;
473
474 object_inherits_specifier:
475         {
476                 $$ = NULL;
477         }
478         | T_INHERITS object_inherits_list
479         {
480                 $$ = $2;
481         }
482         ;
483
484 expressionlist: '{' expressions '}'
485         {
486                 if ($2)
487                         $$ = $2;
488                 else
489                         $$ = new ExpressionList();
490         }
491         ;
492
493 expressions: expressions_inner
494         {
495                 $$ = $1;
496         }
497         | expressions_inner ','
498         {
499                 $$ = $1;
500         }
501
502 expressions_inner: /* empty */
503         {
504                 $$ = NULL;
505         }
506         | expression
507         {
508                 $$ = new ExpressionList();
509                 $$->AddExpression(*$1);
510                 delete $1;
511         }
512         | expressions_inner ',' expression
513         {
514                 if ($1)
515                         $$ = $1;
516                 else
517                         $$ = new ExpressionList();
518
519                 $$->AddExpression(*$3);
520                 delete $3;
521         }
522         ;
523
524 expression: identifier operator value
525         {
526                 $$ = new Expression($1, $2, *$3, DebugInfoRange(@1, @3));
527                 free($1);
528                 delete $3;
529         }
530         | identifier '[' T_STRING ']' operator value
531         {
532                 Expression subexpr($3, $5, *$6, DebugInfoRange(@1, @6));
533                 free($3);
534                 delete $6;
535
536                 ExpressionList::Ptr subexprl = make_shared<ExpressionList>();
537                 subexprl->AddExpression(subexpr);
538
539                 $$ = new Expression($1, OperatorPlus, subexprl, DebugInfoRange(@1, @6));
540                 free($1);
541         }
542         ;
543
544 operator: T_SET
545         | T_PLUS_EQUAL
546         | T_MINUS_EQUAL
547         | T_MULTIPLY_EQUAL
548         | T_DIVIDE_EQUAL
549         {
550                 $$ = $1;
551         }
552         ;
553
554 array_items: array_items_inner
555         {
556                 $$ = $1;
557         }
558         | array_items_inner ','
559         {
560                 $$ = $1;
561         }
562
563 array_items_inner: /* empty */
564         {
565                 $$ = NULL;
566         }
567         | aexpression
568         {
569                 $$ = new Array();
570                 $$->Add(*$1);
571                 delete $1;
572         }
573         | array_items_inner ',' aexpression
574         {
575                 if ($1)
576                         $$ = $1;
577                 else
578                         $$ = new Array();
579
580                 $$->Add(*$3);
581                 delete $3;
582         }
583         ;
584
585 aexpression: T_STRING
586         {
587                 $$ = new Value(make_shared<AExpression>(AEReturn, AValue(ATSimple, $1), @1));
588                 free($1);
589         }
590         | T_NUMBER
591         {
592                 $$ = new Value(make_shared<AExpression>(AEReturn, AValue(ATSimple, $1), @1));
593         }
594         | T_NULL
595         {
596                 $$ = new Value(make_shared<AExpression>(AEReturn, AValue(ATSimple, Empty), @1));
597         }
598         | T_IDENTIFIER '(' array_items ')'
599         {
600                 Array::Ptr arguments = Array::Ptr($3);
601                 $$ = new Value(make_shared<AExpression>(AEFunctionCall, AValue(ATSimple, $1), AValue(ATSimple, arguments), DebugInfoRange(@1, @4)));
602                 free($1);
603         }
604         | T_IDENTIFIER
605         {
606                 $$ = new Value(make_shared<AExpression>(AEReturn, AValue(ATVariable, $1), @1));
607                 free($1);
608         }
609         | '!' aexpression
610         {
611                 $$ = new Value(make_shared<AExpression>(AENegate, static_cast<AExpression::Ptr>(*$2), DebugInfoRange(@1, @2)));
612                 delete $2;
613         }
614         | '~' aexpression
615         {
616                 $$ = new Value(make_shared<AExpression>(AENegate, static_cast<AExpression::Ptr>(*$2), DebugInfoRange(@1, @2)));
617                 delete $2;
618         }
619         | '[' array_items ']'
620         {
621                 $$ = new Value(make_shared<AExpression>(AEArray, AValue(ATSimple, Array::Ptr($2)), DebugInfoRange(@1, @3)));
622         }
623         | '(' aexpression ')'
624         {
625                 $$ = $2;
626         }
627         | aexpression '+' aexpression
628         {
629                 $$ = new Value(make_shared<AExpression>(AEAdd, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
630                 delete $1;
631                 delete $3;
632         }
633         | aexpression '-' aexpression
634         {
635                 $$ = new Value(make_shared<AExpression>(AESubtract, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
636                 delete $1;
637                 delete $3;
638         }
639         | aexpression '*' aexpression
640         {
641                 $$ = new Value(make_shared<AExpression>(AEMultiply, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
642                 delete $1;
643                 delete $3;
644         }
645         | aexpression '/' aexpression
646         {
647                 $$ = new Value(make_shared<AExpression>(AEDivide, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
648                 delete $1;
649                 delete $3;
650         }
651         | aexpression '&' aexpression
652         {
653                 $$ = new Value(make_shared<AExpression>(AEBinaryAnd, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
654                 delete $1;
655                 delete $3;
656         }
657         | aexpression '|' aexpression
658         {
659                 $$ = new Value(make_shared<AExpression>(AEBinaryOr, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @2)));
660                 delete $1;
661                 delete $3;
662         }
663         | aexpression T_IN aexpression
664         {
665                 $$ = new Value(make_shared<AExpression>(AEIn, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
666                 delete $1;
667                 delete $3;
668         }
669         | aexpression T_NOT_IN aexpression
670         {
671                 $$ = new Value(make_shared<AExpression>(AENotIn, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
672                 delete $1;
673                 delete $3;
674         }
675         | aexpression T_LESS_THAN_OR_EQUAL aexpression
676         {
677                 $$ = new Value(make_shared<AExpression>(AELessThanOrEqual, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
678                 delete $1;
679                 delete $3;
680         }
681         | aexpression T_GREATER_THAN_OR_EQUAL aexpression
682         {
683                 $$ = new Value(make_shared<AExpression>(AEGreaterThanOrEqual, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
684                 delete $1;
685                 delete $3;
686         }
687         | aexpression '<' aexpression
688         {
689                 $$ = new Value(make_shared<AExpression>(AELessThan, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
690                 delete $1;
691                 delete $3;
692         }
693         | aexpression '>' aexpression
694         {
695                 $$ = new Value(make_shared<AExpression>(AEGreaterThan, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
696                 delete $1;
697                 delete $3;
698         }
699         | aexpression T_EQUAL aexpression
700         {
701                 $$ = new Value(make_shared<AExpression>(AEEqual, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
702                 delete $1;
703                 delete $3;
704         }
705         | aexpression T_NOT_EQUAL aexpression
706         {
707                 $$ = new Value(make_shared<AExpression>(AENotEqual, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
708                 delete $1;
709                 delete $3;
710         }
711         | aexpression T_SHIFT_LEFT aexpression
712         {
713                 $$ = new Value(make_shared<AExpression>(AEShiftLeft, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
714                 delete $1;
715                 delete $3;
716         }
717         | aexpression T_SHIFT_RIGHT aexpression
718         {
719                 $$ = new Value(make_shared<AExpression>(AEShiftRight, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
720                 delete $1;
721                 delete $3;
722         }
723         | aexpression T_LOGICAL_AND aexpression
724         {
725                 $$ = new Value(make_shared<AExpression>(AELogicalAnd, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
726                 delete $1;
727                 delete $3;
728         }
729         | aexpression T_LOGICAL_OR aexpression
730         {
731                 $$ = new Value(make_shared<AExpression>(AELogicalOr, static_cast<AExpression::Ptr>(*$1), static_cast<AExpression::Ptr>(*$3), DebugInfoRange(@1, @3)));
732                 delete $1;
733                 delete $3;
734         }
735         ;
736
737 value: expressionlist
738         {
739                 ExpressionList::Ptr exprl = ExpressionList::Ptr($1);
740                 $$ = new Value(exprl);
741         }
742         | aexpression
743         {
744                 AExpression::Ptr aexpr = *$1;
745                 $$ = new Value(aexpr->Evaluate(Dictionary::Ptr()));
746                 delete $1;
747         }
748         ;
749
750 optional_template: /* empty */
751         | T_TEMPLATE
752         ;
753
754 apply: T_APPLY optional_template identifier identifier T_TO identifier T_WHERE aexpression
755         {
756                 if (!ApplyRule::IsValidCombination($3, $6)) {
757                         BOOST_THROW_EXCEPTION(ConfigError("'apply' cannot be used with types '" + String($3) + "' and '" + String($6) + "'.", @1));
758                 }
759
760                 Array::Ptr arguments = make_shared<Array>();
761                 arguments->Add(*$8);
762                 delete $8;
763
764                 AExpression::Ptr aexpr = make_shared<AExpression>(AEFunctionCall, AValue(ATSimple, "bool"), AValue(ATSimple, arguments), @8);
765
766                 ApplyRule::AddRule($3, $4, $6, aexpr, DebugInfoRange(@1, @8));
767         }
768 %%