summaryrefslogtreecommitdiffstats
path: root/tools/mkclass/class_parser.yy
diff options
context:
space:
mode:
Diffstat (limited to 'tools/mkclass/class_parser.yy')
-rw-r--r--tools/mkclass/class_parser.yy558
1 files changed, 558 insertions, 0 deletions
diff --git a/tools/mkclass/class_parser.yy b/tools/mkclass/class_parser.yy
new file mode 100644
index 0000000..0524b2d
--- /dev/null
+++ b/tools/mkclass/class_parser.yy
@@ -0,0 +1,558 @@
+%{
+/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
+
+#include "classcompiler.hpp"
+#include <iostream>
+#include <vector>
+#include <cstring>
+
+using std::malloc;
+using std::free;
+using std::exit;
+
+using namespace icinga;
+
+#define YYLTYPE icinga::ClassDebugInfo
+
+%}
+
+%pure-parser
+
+%locations
+%defines
+%error-verbose
+
+%parse-param { ClassCompiler *context }
+%lex-param { void *scanner }
+
+%union {
+ char *text;
+ int num;
+ FieldType *type;
+ Field *field;
+ std::vector<Field> *fields;
+ Klass *klass;
+ FieldAccessor *fieldaccessor;
+ std::vector<FieldAccessor> *fieldaccessors;
+ Rule *rule;
+ std::vector<Rule> *rules;
+ Validator *validator;
+}
+
+%token T_INCLUDE "#include (T_INCLUDE)"
+%token T_IMPL_INCLUDE "#impl_include (T_IMPL_INCLUDE)"
+%token T_CLASS "class (T_CLASS)"
+%token T_CODE "code (T_CODE)"
+%token T_LOAD_AFTER "load_after (T_LOAD_AFTER)"
+%token T_ACTIVATION_PRIORITY "activation_priority (T_ACTIVATION_PRIORITY)"
+%token T_LIBRARY "library (T_LIBRARY)"
+%token T_NAMESPACE "namespace (T_NAMESPACE)"
+%token T_VALIDATOR "validator (T_VALIDATOR)"
+%token T_REQUIRED "required (T_REQUIRED)"
+%token T_NAVIGATION "navigation (T_NAVIGATION)"
+%token T_NAME "name (T_NAME)"
+%token T_ARRAY "array (T_ARRAY)"
+%token T_STRING "string (T_STRING)"
+%token T_ANGLE_STRING "angle_string (T_ANGLE_STRING)"
+%token T_FIELD_ATTRIBUTE "field_attribute (T_FIELD_ATTRIBUTE)"
+%token T_CLASS_ATTRIBUTE "class_attribute (T_CLASS_ATTRIBUTE)"
+%token T_IDENTIFIER "identifier (T_IDENTIFIER)"
+%token T_GET "get (T_GET)"
+%token T_SET "set (T_SET)"
+%token T_DEFAULT "default (T_DEFAULT)"
+%token T_FIELD_ACCESSOR_TYPE "field_accessor_type (T_FIELD_ACCESSOR_TYPE)"
+%token T_NUMBER "number (T_NUMBER)"
+%type <text> T_IDENTIFIER
+%type <text> T_STRING
+%type <text> T_ANGLE_STRING
+%type <text> identifier
+%type <text> alternative_name_specifier
+%type <text> inherits_specifier
+%type <text> type_base_specifier
+%type <text> include
+%type <text> angle_include
+%type <text> impl_include
+%type <text> angle_impl_include
+%type <text> code
+%type <num> T_FIELD_ATTRIBUTE
+%type <field> field_attribute
+%type <field> field_attributes
+%type <field> field_attribute_list
+%type <num> T_FIELD_ACCESSOR_TYPE
+%type <num> T_CLASS_ATTRIBUTE
+%type <num> class_attribute_list
+%type <type> field_type
+%type <field> class_field
+%type <fields> class_fields
+%type <klass> class
+%type <fieldaccessors> field_accessor_list
+%type <fieldaccessors> field_accessors
+%type <fieldaccessor> field_accessor
+%type <rule> validator_rule
+%type <rules> validator_rules
+%type <validator> validator
+%type <num> T_NUMBER
+
+%{
+
+int yylex(YYSTYPE *lvalp, YYLTYPE *llocp, void *scanner);
+
+void yyerror(YYLTYPE *locp, ClassCompiler *, const char *err)
+{
+ std::cerr << "in " << locp->path << " at " << locp->first_line << ":" << locp->first_column << "-"
+ << locp->last_line << ":" << locp->last_column << ": " << err << std::endl;
+ std::exit(1);
+}
+
+int yyparse(ClassCompiler *context);
+
+void ClassCompiler::Compile(void)
+{
+ try {
+ yyparse(this);
+ } catch (const std::exception& ex) {
+ std::cerr << "Exception: " << ex.what();
+ }
+
+ HandleMissingValidators();
+}
+
+#define scanner (context->GetScanner())
+
+%}
+
+%%
+
+statements: /* empty */
+ | statements statement
+ ;
+
+statement: include
+ {
+ context->HandleInclude($1, yylloc);
+ std::free($1);
+ }
+ | angle_include
+ {
+ context->HandleAngleInclude($1, yylloc);
+ std::free($1);
+ }
+ | impl_include
+ {
+ context->HandleImplInclude($1, yylloc);
+ std::free($1);
+ }
+ | angle_impl_include
+ {
+ context->HandleAngleImplInclude($1, yylloc);
+ std::free($1);
+ }
+ | class
+ {
+ context->HandleClass(*$1, yylloc);
+ delete $1;
+ }
+ | validator
+ {
+ context->HandleValidator(*$1, yylloc);
+ delete $1;
+ }
+ | namespace
+ | code
+ {
+ context->HandleCode($1, yylloc);
+ std::free($1);
+ }
+ | library
+ ;
+
+include: T_INCLUDE T_STRING
+ {
+ $$ = $2;
+ }
+ ;
+
+angle_include: T_INCLUDE T_ANGLE_STRING
+ {
+ $$ = $2;
+ }
+ ;
+
+impl_include: T_IMPL_INCLUDE T_STRING
+ {
+ $$ = $2;
+ }
+ ;
+
+angle_impl_include: T_IMPL_INCLUDE T_ANGLE_STRING
+ {
+ $$ = $2;
+ }
+ ;
+
+namespace: T_NAMESPACE identifier '{'
+ {
+ context->HandleNamespaceBegin($2, yylloc);
+ std::free($2);
+ }
+ statements '}'
+ {
+ context->HandleNamespaceEnd(yylloc);
+ }
+ ;
+
+code: T_CODE T_STRING
+ {
+ $$ = $2;
+ }
+ ;
+
+library: T_LIBRARY T_IDENTIFIER ';'
+ {
+ context->HandleLibrary($2, yylloc);
+ free($2);
+ }
+ ;
+
+class: class_attribute_list T_CLASS T_IDENTIFIER inherits_specifier type_base_specifier '{' class_fields '}' ';'
+ {
+ $$ = new Klass();
+
+ $$->Name = $3;
+ std::free($3);
+
+ if ($4) {
+ $$->Parent = $4;
+ std::free($4);
+ }
+
+ if ($5) {
+ $$->TypeBase = $5;
+ std::free($5);
+ }
+
+ $$->Attributes = $1;
+
+ for (const Field& field : *$7) {
+ if (field.Attributes & FALoadDependency) {
+ $$->LoadDependencies.push_back(field.Name);
+ } else if (field.Attributes & FAActivationPriority) {
+ $$->ActivationPriority = field.Priority;
+ } else
+ $$->Fields.push_back(field);
+ }
+
+ delete $7;
+
+ ClassCompiler::OptimizeStructLayout($$->Fields);
+ }
+ ;
+
+class_attribute_list: /* empty */
+ {
+ $$ = 0;
+ }
+ | T_CLASS_ATTRIBUTE
+ {
+ $$ = $1;
+ }
+ | class_attribute_list T_CLASS_ATTRIBUTE
+ {
+ $$ = $1 | $2;
+ }
+
+inherits_specifier: /* empty */
+ {
+ $$ = NULL;
+ }
+ | ':' identifier
+ {
+ $$ = $2;
+ }
+ ;
+
+type_base_specifier: /* empty */
+ {
+ $$ = NULL;
+ }
+ | '<' identifier
+ {
+ $$ = $2;
+ }
+ ;
+
+class_fields: /* empty */
+ {
+ $$ = new std::vector<Field>();
+ }
+ | class_fields class_field
+ {
+ $$->push_back(*$2);
+ delete $2;
+ }
+ ;
+
+field_type: identifier
+ {
+ $$ = new FieldType();
+ $$->IsName = false;
+ $$->TypeName = $1;
+ free($1);
+ }
+ | T_NAME '(' identifier ')'
+ {
+ $$ = new FieldType();
+ $$->IsName = true;
+ $$->TypeName = $3;
+ $$->ArrayRank = 0;
+ free($3);
+ }
+ | T_ARRAY '(' field_type ')'
+ {
+ $$ = $3;
+ $$->ArrayRank++;
+ }
+ ;
+
+class_field: field_attribute_list field_type identifier alternative_name_specifier field_accessor_list ';'
+ {
+ Field *field = $1;
+
+ if ((field->Attributes & (FAConfig | FAState)) == 0)
+ field->Attributes |= FAEphemeral;
+
+ field->Type = *$2;
+ delete $2;
+
+ field->Name = $3;
+ std::free($3);
+
+ if ($4) {
+ field->AlternativeName = $4;
+ std::free($4);
+ }
+
+ std::vector<FieldAccessor>::const_iterator it;
+ for (it = $5->begin(); it != $5->end(); it++) {
+ switch (it->Type) {
+ case FTGet:
+ field->GetAccessor = it->Accessor;
+ field->PureGetAccessor = it->Pure;
+ break;
+ case FTSet:
+ field->SetAccessor = it->Accessor;
+ field->PureSetAccessor = it->Pure;
+ break;
+ case FTDefault:
+ field->DefaultAccessor = it->Accessor;
+ break;
+ case FTTrack:
+ field->TrackAccessor = it->Accessor;
+ break;
+ case FTNavigate:
+ field->NavigateAccessor = it->Accessor;
+ field->PureNavigateAccessor = it->Pure;
+ break;
+ }
+ }
+
+ delete $5;
+
+ $$ = field;
+ }
+ | T_LOAD_AFTER identifier ';'
+ {
+ auto *field = new Field();
+ field->Attributes = FALoadDependency;
+ field->Name = $2;
+ std::free($2);
+ $$ = field;
+ }
+ | T_ACTIVATION_PRIORITY T_NUMBER ';'
+ {
+ auto *field = new Field();
+ field->Attributes = FAActivationPriority;
+ field->Priority = $2;
+ $$ = field;
+ }
+ ;
+
+alternative_name_specifier: /* empty */
+ {
+ $$ = NULL;
+ }
+ | '(' identifier ')'
+ {
+ $$ = $2;
+ }
+ ;
+
+field_attribute_list: /* empty */
+ {
+ $$ = new Field();
+ }
+ | '[' field_attributes ']'
+ {
+ $$ = $2;
+ }
+ ;
+
+field_attribute: T_FIELD_ATTRIBUTE
+ {
+ $$ = new Field();
+ $$->Attributes = $1;
+ }
+ | T_REQUIRED
+ {
+ $$ = new Field();
+ $$->Attributes = FARequired;
+ }
+ | T_NAVIGATION '(' identifier ')'
+ {
+ $$ = new Field();
+ $$->Attributes = FANavigation;
+ $$->NavigationName = $3;
+ std::free($3);
+ }
+ | T_NAVIGATION
+ {
+ $$ = new Field();
+ $$->Attributes = FANavigation;
+ }
+ ;
+
+field_attributes: /* empty */
+ {
+ $$ = new Field();
+ }
+ | field_attributes ',' field_attribute
+ {
+ $$ = $1;
+ $$->Attributes |= $3->Attributes;
+ if (!$3->NavigationName.empty())
+ $$->NavigationName = $3->NavigationName;
+ delete $3;
+ }
+ | field_attribute
+ {
+ $$ = $1;
+ }
+ ;
+
+field_accessor_list: /* empty */
+ {
+ $$ = new std::vector<FieldAccessor>();
+ }
+ | '{' field_accessors '}'
+ {
+ $$ = $2;
+ }
+ ;
+
+field_accessors: /* empty */
+ {
+ $$ = new std::vector<FieldAccessor>();
+ }
+ | field_accessors field_accessor
+ {
+ $$ = $1;
+ $$->push_back(*$2);
+ delete $2;
+ }
+ ;
+
+field_accessor: T_FIELD_ACCESSOR_TYPE T_STRING
+ {
+ $$ = new FieldAccessor(static_cast<FieldAccessorType>($1), $2, false);
+ std::free($2);
+ }
+ | T_FIELD_ACCESSOR_TYPE ';'
+ {
+ $$ = new FieldAccessor(static_cast<FieldAccessorType>($1), "", true);
+ }
+ ;
+
+validator_rules: /* empty */
+ {
+ $$ = new std::vector<Rule>();
+ }
+ | validator_rules validator_rule
+ {
+ $$->push_back(*$2);
+ delete $2;
+ }
+ ;
+
+validator_rule: T_NAME '(' T_IDENTIFIER ')' identifier ';'
+ {
+ $$ = new Rule();
+ $$->Attributes = 0;
+ $$->IsName = true;
+ $$->Type = $3;
+ std::free($3);
+ $$->Pattern = $5;
+ std::free($5);
+ }
+ | T_IDENTIFIER identifier ';'
+ {
+ $$ = new Rule();
+ $$->Attributes = 0;
+ $$->IsName = false;
+ $$->Type = $1;
+ std::free($1);
+ $$->Pattern = $2;
+ std::free($2);
+ }
+ | T_NAME '(' T_IDENTIFIER ')' identifier '{' validator_rules '}' ';'
+ {
+ $$ = new Rule();
+ $$->Attributes = 0;
+ $$->IsName = true;
+ $$->Type = $3;
+ std::free($3);
+ $$->Pattern = $5;
+ std::free($5);
+ $$->Rules = *$7;
+ delete $7;
+ }
+ | T_IDENTIFIER identifier '{' validator_rules '}' ';'
+ {
+ $$ = new Rule();
+ $$->Attributes = 0;
+ $$->IsName = false;
+ $$->Type = $1;
+ std::free($1);
+ $$->Pattern = $2;
+ std::free($2);
+ $$->Rules = *$4;
+ delete $4;
+ }
+ | T_REQUIRED identifier ';'
+ {
+ $$ = new Rule();
+ $$->Attributes = RARequired;
+ $$->IsName = false;
+ $$->Type = "";
+ $$->Pattern = $2;
+ std::free($2);
+ }
+ ;
+
+validator: T_VALIDATOR T_IDENTIFIER '{' validator_rules '}' ';'
+ {
+ $$ = new Validator();
+
+ $$->Name = $2;
+ std::free($2);
+
+ $$->Rules = *$4;
+ delete $4;
+ }
+ ;
+
+identifier: T_IDENTIFIER
+ | T_STRING
+ {
+ $$ = $1;
+ }
+ ;