2 /******************************************************************************
4 * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
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. *
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. *
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 ******************************************************************************/
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"
35 #include <boost/smart_ptr/make_shared.hpp>
36 #include <boost/exception/diagnostic_information.hpp>
37 #include <boost/foreach.hpp>
39 using namespace icinga;
41 #define YYLTYPE icinga::DebugInfo
51 %parse-param { ConfigCompiler *context }
52 %lex-param { void *scanner }
57 icinga::Value *variant;
58 icinga::ExpressionOperator op;
59 icinga::TypeSpecifier type;
60 std::vector<String> *slist;
62 ExpressionList *exprl;
66 %token <text> T_STRING
67 %token <text> T_STRING_ANGLE
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
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
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
121 int yylex(YYSTYPE *lvalp, YYLTYPE *llocp, void *scanner);
123 void yyerror(YYLTYPE *locp, ConfigCompiler *, const char *err)
125 std::ostringstream message;
126 message << *locp << ": " << err;
127 ConfigCompilerContext::GetInstance()->AddError(false, message.str());
130 int yyparse(ConfigCompiler *context);
132 static std::stack<Array::Ptr> m_Arrays;
133 static bool m_Abstract;
135 static std::stack<TypeRuleList::Ptr> m_RuleLists;
136 static ConfigType::Ptr m_Type;
138 void ConfigCompiler::Compile(void)
142 } catch (const std::exception& ex) {
143 ConfigCompilerContext::GetInstance()->AddError(false, boost::diagnostic_information(ex));
147 #define scanner (context->GetScanner())
152 statements: /* empty */
153 | statements statement
156 statement: object | type | include | library | variable
159 include: T_INCLUDE T_STRING
161 context->HandleInclude($2, false, yylloc);
164 | T_INCLUDE T_STRING_ANGLE
166 context->HandleInclude($2, true, yylloc);
170 library: T_LIBRARY T_STRING
172 context->HandleLibrary($2);
176 variable: T_SET identifier T_EQUAL value
178 ScriptVariable::Set($2, *$4);
183 identifier: T_IDENTIFIER
190 type: partial_specifier T_TYPE identifier
192 String name = String($3);
195 m_Type = ConfigType::GetByName(name);
199 BOOST_THROW_EXCEPTION(std::invalid_argument("Partial type definition for unknown type '" + name + "'"));
201 m_Type = boost::make_shared<ConfigType>(name, yylloc);
205 type_inherits_specifier typerulelist
207 TypeRuleList::Ptr ruleList = *$6;
208 m_Type->GetRuleList()->AddRules(ruleList);
209 m_Type->GetRuleList()->AddRequires(ruleList);
211 String validator = ruleList->GetValidator();
212 if (!validator.IsEmpty())
213 m_Type->GetRuleList()->SetValidator(validator);
219 partial_specifier: /* Empty */
231 m_RuleLists.push(boost::make_shared<TypeRuleList>());
236 $$ = new Value(m_RuleLists.top());
241 typerules: typerules_inner
242 | typerules_inner ','
244 typerules_inner: /* empty */
246 | typerules_inner ',' typerule
249 typerule: T_REQUIRE T_STRING
251 m_RuleLists.top()->AddRequire($2);
254 | T_VALIDATOR T_STRING
256 m_RuleLists.top()->SetValidator($2);
259 | T_ATTRIBUTE type T_STRING
261 TypeRule rule($2, String(), $3, TypeRuleList::Ptr(), yylloc);
264 m_RuleLists.top()->AddRule(rule);
266 | T_ATTRIBUTE T_TYPE_NAME '(' identifier ')' T_STRING
268 TypeRule rule($2, $4, $6, TypeRuleList::Ptr(), yylloc);
272 m_RuleLists.top()->AddRule(rule);
274 | T_ATTRIBUTE type T_STRING typerulelist
276 TypeRule rule($2, String(), $3, *$4, yylloc);
279 m_RuleLists.top()->AddRule(rule);
283 type_inherits_specifier: /* empty */
284 | T_INHERITS identifier
286 m_Type->SetParent($2);
291 type: T_TYPE_DICTIONARY
307 object_declaration identifier T_STRING object_inherits_specifier expressionlist
309 ConfigItemBuilder::Ptr item = boost::make_shared<ConfigItemBuilder>(yylloc);
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 ':'";
317 BOOST_THROW_EXCEPTION(std::invalid_argument(msgbuf.str()));
326 BOOST_FOREACH(const String& parent, *$5) {
327 item->AddParent(parent);
334 ExpressionList::Ptr exprl = ExpressionList::Ptr($6);
335 item->AddExpressionList(exprl);
338 item->SetAbstract(m_Abstract);
340 item->Compile()->Register();
345 object_declaration: attributes T_OBJECT
351 attributes: /* empty */
352 | attributes attribute
355 attribute: T_ABSTRACT
361 object_inherits_list:
367 $$ = new std::vector<String>();
371 | object_inherits_list ',' T_STRING
376 $$ = new std::vector<String>();
383 object_inherits_specifier:
387 | T_INHERITS object_inherits_list
393 expressionlist: '{' expressions '}'
399 expressions: expressions_inner
403 | expressions_inner ','
408 expressions_inner: /* empty */
414 $$ = new ExpressionList();
415 $$->AddExpression(*$1);
418 | expressions_inner ',' expression
423 $$ = new ExpressionList();
425 $$->AddExpression(*$3);
430 expression: identifier operator value
432 $$ = new Expression($1, $2, *$3, yylloc);
436 | identifier '[' T_STRING ']' operator value
438 Expression subexpr($3, $5, *$6, yylloc);
442 ExpressionList::Ptr subexprl = boost::make_shared<ExpressionList>();
443 subexprl->AddExpression(subexpr);
445 $$ = new Expression($1, OperatorPlus, subexprl, yylloc);
460 array: '[' array_items ']'
466 array_items: array_items_inner
470 | array_items_inner ','
475 array_items_inner: /* empty */
483 if ($1->IsObjectType<ExpressionList>()) {
484 ExpressionList::Ptr exprl = *$1;
485 Dictionary::Ptr dict = boost::make_shared<Dictionary>();
486 exprl->Execute(dict);
488 $1 = new Value(dict);
494 | array_items_inner ',' value
501 if ($3->IsObjectType<ExpressionList>()) {
502 ExpressionList::Ptr exprl = *$3;
503 Dictionary::Ptr dict = boost::make_shared<Dictionary>();
504 exprl->Execute(dict);
506 $3 = new Value(dict);
514 simplevalue: T_STRING
532 Array::Ptr array = Array::Ptr($1);
533 $$ = new Value(array);
537 constterm: '(' constexpression ')'
542 constexpression: T_NUMBER
548 $$ = ScriptVariable::Get($1);
551 | constexpression '+' constexpression
555 | constexpression '-' constexpression
559 | constexpression '*' constexpression
563 | constexpression '/' constexpression
567 | constexpression '&' constexpression
569 $$ = (long)$1 & (long)$3;
571 | constexpression '|' constexpression
573 $$ = (long)$1 | (long)$3;
575 | constexpression T_SHIFT_LEFT constexpression
577 $$ = (long)$1 << (long)$3;
579 | constexpression T_SHIFT_RIGHT constexpression
581 $$ = (long)$1 >> (long)$3;
583 | '(' constexpression ')'
592 ExpressionList::Ptr exprl = ExpressionList::Ptr($1);
593 $$ = new Value(exprl);