1%code requires {
2  #include <iostream>
3  #include <vector>
4  #include <list>
5  #include <map>
6
7  #include "declarations.h"
8  #include "logging.h"
9  #include "field_list.h"
10  #include "fields/all_fields.h"
11}
12%{
13  #include "language_y.h"
14  extern int yylex(yy::parser::semantic_type*, yy::parser::location_type*, void *);
15
16  ParseLocation toParseLocation(yy::parser::location_type loc) {
17    return ParseLocation(loc.begin.line);
18  }
19  #define LOC toParseLocation(yylloc)
20%}
21
22%parse-param { void* scanner }
23%parse-param { Declarations* decls }
24%lex-param { void* scanner }
25
26%glr-parser
27%skeleton "glr.cc"
28
29%expect-rr 0
30
31%debug
32%define parse.error verbose
33%locations
34%verbose
35
36%union {
37  uint64_t integer;
38  std::string* string;
39
40  EnumDef* enum_definition;
41  std::map<uint64_t, std::string>* enumeration_values;
42  std::pair<uint64_t, std::string>* enumeration_value;
43
44  PacketDef* packet_definition_value;
45  FieldList* packet_field_definitions;
46  PacketField* packet_field_type;
47
48  StructDef* struct_definition_value;
49
50  std::set<std::string*>* test_cases_t;
51  std::string* test_case_t;
52
53  std::map<std::string, std::variant<int64_t, std::string>>* constraint_list_t;
54  std::pair<std::string, std::variant<int64_t, std::string>>* constraint_t;
55}
56
57%token <integer> INTEGER
58%token <integer> IS_LITTLE_ENDIAN
59%token <string> IDENTIFIER
60%token <string> SIZE_MODIFIER
61%token <string> STRING
62
63%token ENUM "enum"
64%token PACKET "packet"
65%token PAYLOAD "payload"
66%token BODY "body"
67%token STRUCT "struct"
68%token SIZE "size"
69%token COUNT "count"
70%token FIXED "fixed"
71%token RESERVED "reserved"
72%token GROUP "group"
73%token CUSTOM_FIELD "custom_field"
74%token CHECKSUM "checksum"
75%token CHECKSUM_START "checksum_start"
76%token PADDING "padding"
77%token TEST "test"
78
79%type<enum_definition> enum_definition
80%type<enumeration_values> enumeration_list
81%type<enumeration_value> enumeration
82
83%type<packet_definition_value> packet_definition;
84%type<packet_field_definitions> field_definition_list;
85%type<packet_field_type> field_definition;
86%type<packet_field_type> group_field_definition;
87%type<packet_field_type> type_def_field_definition;
88%type<packet_field_type> scalar_field_definition;
89%type<packet_field_type> checksum_start_field_definition;
90%type<packet_field_type> padding_field_definition;
91%type<packet_field_type> size_field_definition;
92%type<packet_field_type> payload_field_definition;
93%type<packet_field_type> body_field_definition;
94%type<packet_field_type> fixed_field_definition;
95%type<packet_field_type> reserved_field_definition;
96%type<packet_field_type> array_field_definition;
97
98%type<struct_definition_value> struct_definition;
99
100%type<test_cases_t> test_definition;
101%type<test_cases_t> test_case_list;
102%type<test_case_t> test_case;
103
104%type<constraint_list_t> constraint_list;
105%type<constraint_t> constraint;
106%destructor { std::cout << "DESTROYING STRING " << *$$ << "\n"; delete $$; } IDENTIFIER STRING SIZE_MODIFIER
107
108%%
109
110file
111  : IS_LITTLE_ENDIAN declarations
112  {
113    decls->is_little_endian = ($1 == 1);
114    if (decls->is_little_endian) {
115      DEBUG() << "LITTLE ENDIAN ";
116    } else {
117      DEBUG() << "BIG ENDIAN ";
118    }
119  }
120
121declarations
122  : /* empty */
123  | declarations declaration
124
125declaration
126  : enum_definition
127    {
128      DEBUG() << "FOUND ENUM\n\n";
129      decls->AddTypeDef($1->name_, $1);
130    }
131  | packet_definition
132    {
133      DEBUG() << "FOUND PACKET\n\n";
134      decls->AddPacketDef($1->name_, $1);
135    }
136  | struct_definition
137    {
138      DEBUG() << "FOUND STRUCT\n\n";
139      decls->AddTypeDef($1->name_, $1);
140    }
141  | group_definition
142    {
143      // All actions are handled in group_definition
144    }
145  | checksum_definition
146    {
147      // All actions are handled in checksum_definition
148    }
149  | custom_field_definition
150    {
151      // All actions are handled in custom_field_definition
152    }
153  | test_definition
154    {
155      // All actions are handled in test_definition
156    }
157
158enum_definition
159  : ENUM IDENTIFIER ':' INTEGER '{' enumeration_list ',' '}'
160    {
161      DEBUG() << "Enum Declared: name=" << *$2
162                << " size=" << $4 << "\n";
163
164      $$ = new EnumDef(std::move(*$2), $4);
165      for (const auto& e : *$6) {
166        $$->AddEntry(e.second, e.first);
167      }
168      delete $2;
169      delete $6;
170    }
171
172enumeration_list
173  : enumeration
174    {
175      DEBUG() << "Enumerator with comma\n";
176      $$ = new std::map<uint64_t, std::string>();
177      $$->insert(std::move(*$1));
178      delete $1;
179    }
180  | enumeration_list ',' enumeration
181    {
182      DEBUG() << "Enumerator with list\n";
183      $$ = $1;
184      $$->insert(std::move(*$3));
185      delete $3;
186    }
187
188enumeration
189  : IDENTIFIER '=' INTEGER
190    {
191      DEBUG() << "Enumerator: name=" << *$1
192                << " value=" << $3 << "\n";
193      $$ = new std::pair($3, std::move(*$1));
194      delete $1;
195    }
196
197group_definition
198  : GROUP IDENTIFIER '{' field_definition_list '}'
199    {
200      decls->AddGroupDef(*$2, $4);
201      delete $2;
202    }
203
204checksum_definition
205  : CHECKSUM IDENTIFIER ':' INTEGER STRING
206    {
207      DEBUG() << "Checksum field defined\n";
208      decls->AddTypeDef(*$2, new ChecksumDef(*$2, *$5, $4));
209      delete $2;
210      delete $5;
211    }
212
213custom_field_definition
214  : CUSTOM_FIELD IDENTIFIER ':' INTEGER STRING
215    {
216      decls->AddTypeDef(*$2, new CustomFieldDef(*$2, *$5, $4));
217      delete $2;
218      delete $5;
219    }
220  | CUSTOM_FIELD IDENTIFIER STRING
221    {
222      decls->AddTypeDef(*$2, new CustomFieldDef(*$2, *$3));
223      delete $2;
224      delete $3;
225    }
226
227test_definition
228  : TEST IDENTIFIER '{' test_case_list ',' '}'
229    {
230      auto&& packet_name = *$2;
231      DEBUG() << "Test Declared: name=" << *$2 << "\n";
232      auto packet = decls->GetPacketDef(packet_name);
233      if (packet == nullptr) {
234        ERRORLOC(LOC) << "Could not find packet " << packet_name << "\n";
235      }
236
237      for (const auto& t : *$4) {
238        packet->AddTestCase(*t);
239      }
240      delete $2;
241      delete $4;
242    }
243
244test_case_list
245  : test_case
246    {
247      DEBUG() << "Test case with comma\n";
248      $$ = new std::set<std::string*>();
249      $$->insert($1);
250    }
251  | test_case_list ',' test_case
252    {
253      DEBUG() << "Test case with list\n";
254      $$ = $1;
255      $$->insert($3);
256    }
257
258test_case
259  : STRING
260    {
261      DEBUG() << "Test Case: name=" << *$1 << "\n";
262      $$ = $1;
263    }
264
265struct_definition
266  : STRUCT IDENTIFIER '{' field_definition_list '}'
267    {
268      auto&& struct_name = *$2;
269      auto&& field_definition_list = *$4;
270
271      DEBUG() << "Struct " << struct_name << " with no parent";
272      DEBUG() << "STRUCT FIELD LIST SIZE: " << field_definition_list.size();
273      auto struct_definition = new StructDef(std::move(struct_name), std::move(field_definition_list));
274      struct_definition->AssignSizeFields();
275
276      $$ = struct_definition;
277      delete $2;
278      delete $4;
279    }
280  | STRUCT IDENTIFIER ':' IDENTIFIER '{' field_definition_list '}'
281    {
282      auto&& struct_name = *$2;
283      auto&& parent_struct_name = *$4;
284      auto&& field_definition_list = *$6;
285
286      DEBUG() << "Struct " << struct_name << " with parent " << parent_struct_name << "\n";
287      DEBUG() << "STRUCT FIELD LIST SIZE: " << field_definition_list.size() << "\n";
288
289      auto parent_struct = decls->GetTypeDef(parent_struct_name);
290      if (parent_struct == nullptr) {
291        ERRORLOC(LOC) << "Could not find struct " << parent_struct_name
292                  << " used as parent for " << struct_name;
293      }
294
295      if (parent_struct->GetDefinitionType() != TypeDef::Type::STRUCT) {
296        ERRORLOC(LOC) << parent_struct_name << " is not a struct";
297      }
298      auto struct_definition = new StructDef(std::move(struct_name), std::move(field_definition_list), (StructDef*)parent_struct);
299      struct_definition->AssignSizeFields();
300
301      $$ = struct_definition;
302      delete $2;
303      delete $4;
304      delete $6;
305    }
306  | STRUCT IDENTIFIER ':' IDENTIFIER '(' constraint_list ')' '{' field_definition_list '}'
307    {
308      auto&& struct_name = *$2;
309      auto&& parent_struct_name = *$4;
310      auto&& constraints = *$6;
311      auto&& field_definition_list = *$9;
312
313      auto parent_struct = decls->GetTypeDef(parent_struct_name);
314      if (parent_struct == nullptr) {
315        ERRORLOC(LOC) << "Could not find struct " << parent_struct_name
316                  << " used as parent for " << struct_name;
317      }
318
319      if (parent_struct->GetDefinitionType() != TypeDef::Type::STRUCT) {
320        ERRORLOC(LOC) << parent_struct_name << " is not a struct";
321      }
322
323      auto struct_definition = new StructDef(std::move(struct_name), std::move(field_definition_list), (StructDef*)parent_struct);
324      struct_definition->AssignSizeFields();
325
326      for (const auto& constraint : constraints) {
327        const auto& constraint_name = constraint.first;
328        const auto& constraint_value = constraint.second;
329        DEBUG() << "Parent constraint on " << constraint_name;
330        struct_definition->AddParentConstraint(constraint_name, constraint_value);
331      }
332
333      $$ = struct_definition;
334
335      delete $2;
336      delete $4;
337      delete $6;
338      delete $9;
339    }
340
341packet_definition
342  : PACKET IDENTIFIER '{' field_definition_list '}'  /* Packet with no parent */
343    {
344      auto&& packet_name = *$2;
345      auto&& field_definition_list = *$4;
346
347      DEBUG() << "Packet " << packet_name << " with no parent";
348      DEBUG() << "PACKET FIELD LIST SIZE: " << field_definition_list.size();
349      auto packet_definition = new PacketDef(std::move(packet_name), std::move(field_definition_list));
350      packet_definition->AssignSizeFields();
351
352      $$ = packet_definition;
353      delete $2;
354      delete $4;
355    }
356  | PACKET IDENTIFIER ':' IDENTIFIER '{' field_definition_list '}'
357    {
358      auto&& packet_name = *$2;
359      auto&& parent_packet_name = *$4;
360      auto&& field_definition_list = *$6;
361
362      DEBUG() << "Packet " << packet_name << " with parent " << parent_packet_name << "\n";
363      DEBUG() << "PACKET FIELD LIST SIZE: " << field_definition_list.size() << "\n";
364
365      auto parent_packet = decls->GetPacketDef(parent_packet_name);
366      if (parent_packet == nullptr) {
367        ERRORLOC(LOC) << "Could not find packet " << parent_packet_name
368                  << " used as parent for " << packet_name;
369      }
370
371
372      auto packet_definition = new PacketDef(std::move(packet_name), std::move(field_definition_list), parent_packet);
373      packet_definition->AssignSizeFields();
374
375      $$ = packet_definition;
376      delete $2;
377      delete $4;
378      delete $6;
379    }
380  | PACKET IDENTIFIER ':' IDENTIFIER '(' constraint_list ')' '{' field_definition_list '}'
381    {
382      auto&& packet_name = *$2;
383      auto&& parent_packet_name = *$4;
384      auto&& constraints = *$6;
385      auto&& field_definition_list = *$9;
386
387      DEBUG() << "Packet " << packet_name << " with parent " << parent_packet_name << "\n";
388      DEBUG() << "PACKET FIELD LIST SIZE: " << field_definition_list.size() << "\n";
389      DEBUG() << "CONSTRAINT LIST SIZE: " << constraints.size() << "\n";
390
391      auto parent_packet = decls->GetPacketDef(parent_packet_name);
392      if (parent_packet == nullptr) {
393        ERRORLOC(LOC) << "Could not find packet " << parent_packet_name
394                  << " used as parent for " << packet_name << "\n";
395      }
396
397      auto packet_definition = new PacketDef(std::move(packet_name), std::move(field_definition_list), parent_packet);
398      packet_definition->AssignSizeFields();
399
400      for (const auto& constraint : constraints) {
401        const auto& constraint_name = constraint.first;
402        const auto& constraint_value = constraint.second;
403        DEBUG() << "Parent constraint on " << constraint_name;
404        packet_definition->AddParentConstraint(constraint_name, constraint_value);
405      }
406
407      $$ = packet_definition;
408
409      delete $2;
410      delete $4;
411      delete $6;
412      delete $9;
413    }
414
415field_definition_list
416  : /* empty */
417    {
418      DEBUG() << "Empty Field definition\n";
419      $$ = new FieldList();
420    }
421  | field_definition
422    {
423      DEBUG() << "Field definition\n";
424      $$ = new FieldList();
425
426      if ($1->GetFieldType() == GroupField::kFieldType) {
427        auto group_fields = static_cast<GroupField*>($1)->GetFields();
428	FieldList reversed_fields(group_fields->rbegin(), group_fields->rend());
429        for (auto& field : reversed_fields) {
430          $$->PrependField(field);
431        }
432	delete $1;
433        break;
434      }
435
436      $$->PrependField($1);
437    }
438  | field_definition ',' field_definition_list
439    {
440      DEBUG() << "Field definition with list\n";
441      $$ = $3;
442
443      if ($1->GetFieldType() == GroupField::kFieldType) {
444        auto group_fields = static_cast<GroupField*>($1)->GetFields();
445	FieldList reversed_fields(group_fields->rbegin(), group_fields->rend());
446        for (auto& field : reversed_fields) {
447          $$->PrependField(field);
448        }
449	delete $1;
450        break;
451      }
452
453      $$->PrependField($1);
454    }
455
456field_definition
457  : group_field_definition
458    {
459      DEBUG() << "Group Field";
460      $$ = $1;
461    }
462  | type_def_field_definition
463    {
464      DEBUG() << "Field with a pre-defined type\n";
465      $$ = $1;
466    }
467  | scalar_field_definition
468    {
469      DEBUG() << "Scalar field\n";
470      $$ = $1;
471    }
472  | checksum_start_field_definition
473    {
474      DEBUG() << "Checksum start field\n";
475      $$ = $1;
476    }
477  | padding_field_definition
478    {
479      DEBUG() << "Padding field\n";
480      $$ = $1;
481    }
482  | size_field_definition
483    {
484      DEBUG() << "Size field\n";
485      $$ = $1;
486    }
487  | body_field_definition
488    {
489      DEBUG() << "Body field\n";
490      $$ = $1;
491    }
492  | payload_field_definition
493    {
494      DEBUG() << "Payload field\n";
495      $$ = $1;
496    }
497  | fixed_field_definition
498    {
499      DEBUG() << "Fixed field\n";
500      $$ = $1;
501    }
502  | reserved_field_definition
503    {
504      DEBUG() << "Reserved field\n";
505      $$ = $1;
506    }
507  | array_field_definition
508    {
509      DEBUG() << "ARRAY field\n";
510      $$ = $1;
511    }
512
513group_field_definition
514  : IDENTIFIER
515    {
516      auto group = decls->GetGroupDef(*$1);
517      if (group == nullptr) {
518        ERRORLOC(LOC) << "Could not find group with name " << *$1;
519      }
520
521      std::list<PacketField*>* expanded_fields;
522      expanded_fields = new std::list<PacketField*>(group->begin(), group->end());
523      $$ = new GroupField(LOC, expanded_fields);
524      delete $1;
525    }
526  | IDENTIFIER '{' constraint_list '}'
527    {
528      DEBUG() << "Group with fixed field(s) " << *$1 << "\n";
529      auto group = decls->GetGroupDef(*$1);
530      if (group == nullptr) {
531        ERRORLOC(LOC) << "Could not find group with name " << *$1;
532      }
533
534      std::list<PacketField*>* expanded_fields = new std::list<PacketField*>();
535      for (const auto field : *group) {
536        const auto constraint = $3->find(field->GetName());
537        if (constraint != $3->end()) {
538          if (field->GetFieldType() == ScalarField::kFieldType) {
539            DEBUG() << "Fixing group scalar value\n";
540            expanded_fields->push_back(new FixedScalarField(field->GetSize().bits(), std::get<int64_t>(constraint->second), LOC));
541          } else if (field->GetFieldType() == EnumField::kFieldType) {
542            DEBUG() << "Fixing group enum value\n";
543
544            auto type_def = decls->GetTypeDef(field->GetDataType());
545            EnumDef* enum_def = (type_def->GetDefinitionType() == TypeDef::Type::ENUM ? (EnumDef*)type_def : nullptr);
546            if (enum_def == nullptr) {
547              ERRORLOC(LOC) << "No enum found of type " << field->GetDataType();
548            }
549            if (!enum_def->HasEntry(std::get<std::string>(constraint->second))) {
550              ERRORLOC(LOC) << "Enum " << field->GetDataType() << " has no enumeration " << std::get<std::string>(constraint->second);
551            }
552
553            expanded_fields->push_back(new FixedEnumField(enum_def, std::get<std::string>(constraint->second), LOC));
554          } else {
555            ERRORLOC(LOC) << "Unimplemented constraint of type " << field->GetFieldType();
556          }
557          $3->erase(constraint);
558        } else {
559          expanded_fields->push_back(field);
560        }
561      }
562      if ($3->size() > 0) {
563        ERRORLOC(LOC) << "Could not find member " << $3->begin()->first << " in group " << *$1;
564      }
565
566      $$ = new GroupField(LOC, expanded_fields);
567      delete $1;
568      delete $3;
569    }
570
571constraint_list
572  : constraint ',' constraint_list
573    {
574      DEBUG() << "Group field value list\n";
575      $3->insert(*$1);
576      $$ = $3;
577      delete($1);
578    }
579  | constraint
580    {
581      DEBUG() << "Group field value\n";
582      $$ = new std::map<std::string, std::variant<int64_t, std::string>>();
583      $$->insert(*$1);
584      delete($1);
585    }
586
587constraint
588  : IDENTIFIER '=' INTEGER
589    {
590      DEBUG() << "Group with a fixed integer value=" << $1 << " value=" << $3 << "\n";
591
592      $$ = new std::pair(*$1, std::variant<int64_t,std::string>((int64_t)$3));
593      delete $1;
594    }
595  | IDENTIFIER '=' IDENTIFIER
596    {
597      DEBUG() << "Group with a fixed enum field value=" << *$3 << " enum=" << *$1;
598
599      $$ = new std::pair(*$1, std::variant<int64_t,std::string>(*$3));
600      delete $1;
601      delete $3;
602    }
603
604type_def_field_definition
605  : IDENTIFIER ':' IDENTIFIER
606    {
607      DEBUG() << "Predefined type field " << *$1 << " : " << *$3 << "\n";
608      if (auto type_def = decls->GetTypeDef(*$3)) {
609        $$ = type_def->GetNewField(*$1, LOC);
610      } else {
611        ERRORLOC(LOC) << "No type with this name\n";
612      }
613      delete $1;
614      delete $3;
615    }
616
617scalar_field_definition
618  : IDENTIFIER ':' INTEGER
619    {
620      DEBUG() << "Scalar field " << *$1 << " : " << $3 << "\n";
621      $$ = new ScalarField(*$1, $3, LOC);
622      delete $1;
623    }
624
625body_field_definition
626  : BODY
627    {
628      DEBUG() << "Body field\n";
629      $$ = new BodyField(LOC);
630    }
631
632payload_field_definition
633  : PAYLOAD ':' '[' SIZE_MODIFIER ']'
634    {
635      DEBUG() << "Payload field with modifier " << *$4 << "\n";
636      $$ = new PayloadField(*$4, LOC);
637      delete $4;
638    }
639  | PAYLOAD
640    {
641      DEBUG() << "Payload field\n";
642      $$ = new PayloadField("", LOC);
643    }
644
645checksum_start_field_definition
646  : CHECKSUM_START '(' IDENTIFIER ')'
647    {
648      DEBUG() << "ChecksumStart field defined\n";
649      $$ = new ChecksumStartField(*$3, LOC);
650      delete $3;
651    }
652
653padding_field_definition
654  : PADDING '[' INTEGER ']'
655    {
656      DEBUG() << "Padding field defined\n";
657      $$ = new PaddingField($3, LOC);
658    }
659
660size_field_definition
661  : SIZE '(' IDENTIFIER ')' ':' INTEGER
662    {
663      DEBUG() << "Size field defined\n";
664      $$ = new SizeField(*$3, $6, LOC);
665      delete $3;
666    }
667  | SIZE '(' PAYLOAD ')' ':' INTEGER
668    {
669      DEBUG() << "Size for payload defined\n";
670      $$ = new SizeField("payload", $6, LOC);
671    }
672  | SIZE '(' BODY ')' ':' INTEGER
673    {
674      DEBUG() << "Size for body defined\n";
675      $$ = new SizeField("body", $6, LOC);
676    }
677  | COUNT '(' IDENTIFIER ')' ':' INTEGER
678    {
679      DEBUG() << "Count field defined\n";
680      $$ = new CountField(*$3, $6, LOC);
681      delete $3;
682    }
683
684fixed_field_definition
685  : FIXED '=' INTEGER ':' INTEGER
686    {
687      DEBUG() << "Fixed field defined value=" << $3 << " size=" << $5 << "\n";
688      $$ = new FixedScalarField($5, $3, LOC);
689    }
690  | FIXED '=' IDENTIFIER ':' IDENTIFIER
691    {
692      DEBUG() << "Fixed enum field defined value=" << *$3 << " enum=" << *$5;
693      auto type_def = decls->GetTypeDef(*$5);
694      if (type_def != nullptr) {
695        EnumDef* enum_def = (type_def->GetDefinitionType() == TypeDef::Type::ENUM ? (EnumDef*)type_def : nullptr);
696        if (!enum_def->HasEntry(*$3)) {
697          ERRORLOC(LOC) << "Previously defined enum " << enum_def->GetTypeName() << " has no entry for " << *$3;
698        }
699
700        $$ = new FixedEnumField(enum_def, *$3, LOC);
701      } else {
702        ERRORLOC(LOC) << "No enum found with name " << *$5;
703      }
704
705      delete $3;
706      delete $5;
707    }
708
709reserved_field_definition
710  : RESERVED ':' INTEGER
711    {
712      DEBUG() << "Reserved field of size=" << $3 << "\n";
713      $$ = new ReservedField($3, LOC);
714    }
715
716array_field_definition
717  : IDENTIFIER ':' INTEGER '[' ']'
718    {
719      DEBUG() << "Vector field defined name=" << *$1 << " element_size=" << $3;
720      $$ = new VectorField(*$1, $3, "", LOC);
721      delete $1;
722    }
723  | IDENTIFIER ':' INTEGER '[' SIZE_MODIFIER ']'
724    {
725      DEBUG() << "Vector field defined name=" << *$1 << " element_size=" << $3
726             << " size_modifier=" << *$5;
727      $$ = new VectorField(*$1, $3, *$5, LOC);
728      delete $1;
729      delete $5;
730    }
731  | IDENTIFIER ':' INTEGER '[' INTEGER ']'
732    {
733      DEBUG() << "Array field defined name=" << *$1 << " element_size=" << $3
734             << " fixed_size=" << $5;
735      $$ = new ArrayField(*$1, $3, $5, LOC);
736      delete $1;
737    }
738  | IDENTIFIER ':' IDENTIFIER '[' ']'
739    {
740      DEBUG() << "Vector field defined name=" << *$1 << " type=" << *$3;
741      if (auto type_def = decls->GetTypeDef(*$3)) {
742        $$ = new VectorField(*$1, type_def, "", LOC);
743      } else {
744        ERRORLOC(LOC) << "Can't find type used in array field.";
745      }
746      delete $1;
747      delete $3;
748    }
749  | IDENTIFIER ':' IDENTIFIER '[' SIZE_MODIFIER ']'
750    {
751      DEBUG() << "Vector field defined name=" << *$1 << " type=" << *$3
752             << " size_modifier=" << *$5;
753      if (auto type_def = decls->GetTypeDef(*$3)) {
754        $$ = new VectorField(*$1, type_def, *$5, LOC);
755      } else {
756        ERRORLOC(LOC) << "Can't find type used in array field.";
757      }
758      delete $1;
759      delete $3;
760      delete $5;
761    }
762  | IDENTIFIER ':' IDENTIFIER '[' INTEGER ']'
763    {
764      DEBUG() << "Array field defined name=" << *$1 << " type=" << *$3
765             << " fixed_size=" << $5;
766      if (auto type_def = decls->GetTypeDef(*$3)) {
767        $$ = new ArrayField(*$1, type_def, $5, LOC);
768      } else {
769        ERRORLOC(LOC) << "Can't find type used in array field.";
770      }
771      delete $1;
772      delete $3;
773    }
774
775%%
776
777
778void yy::parser::error(const yy::parser::location_type& loc, const std::string& error) {
779  ERROR() << error << " at location " << loc << "\n";
780  abort();
781}
782