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