• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <cctype>
17 #include <cerrno>
18 
19 #include <iterator>
20 
21 #include "assembly-type.h"
22 #include "libpandafile/type_helper.h"
23 #include "ins_emit.h"
24 #include "modifiers.h"
25 #include "opcode_parsing.h"
26 #include "operand_types_print.h"
27 #include "utils/number-utils.h"
28 
29 namespace ark::pandasm {
30 
ParseRecordFields()31 bool Parser::ParseRecordFields()
32 {
33     if (!open_ && *context_ == Token::Type::DEL_BRACE_L) {
34         currRecord_->bodyLocation.begin = GetCurrentPosition(false);
35         open_ = true;
36 
37         ++context_;
38     }
39 
40     currRecord_->bodyPresence = true;
41 
42     if (!open_) {
43         context_.err = GetError("Expected keyword.", Error::ErrorType::ERR_BAD_KEYWORD);
44         return false;
45     }
46 
47     if (context_.Mask()) {
48         return true;
49     }
50 
51     if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
52         currRecord_->bodyLocation.end = GetCurrentPosition(true);
53         ++context_;
54 
55         open_ = false;
56 
57         return true;
58     }
59 
60     currRecord_->fieldList.emplace_back(program_.lang);
61     currFld_ = &(currRecord_->fieldList[currRecord_->fieldList.size() - 1]);
62     currFld_->lineOfDef = lineStric_;
63     context_.insNumber = currRecord_->fieldList.size();
64 
65     LOG(DEBUG, ASSEMBLER) << "parse line " << lineStric_ << " as field (.field name)";
66     if (!ParseRecordField()) {
67         if (context_.err.err != Error::ErrorType::ERR_NONE) {
68             return false;
69         }
70 
71         if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
72             currRecord_->bodyLocation.end = GetCurrentPosition(true);
73             ++context_;
74             open_ = false;
75         } else {
76             context_.err = GetError("Expected a new field on the next line.", Error::ErrorType::ERR_BAD_KEYWORD);
77             return false;
78         }
79     }
80 
81     return true;
82 }
83 
ParseFieldName()84 bool Parser::ParseFieldName()
85 {
86     if (PrefixedValidName()) {
87         std::string fieldName = std::string(context_.GiveToken().data(), context_.GiveToken().length());
88 
89         currFld_ = &(currRecord_->fieldList[currRecord_->fieldList.size() - 1]);
90 
91         currFld_->name = fieldName;
92 
93         ++context_;
94 
95         return true;
96     }
97 
98     context_.err = GetError("Invalid name of field.", Error::ErrorType::ERR_BAD_OPERATION_NAME);
99 
100     return false;
101 }
102 
ParseType(Type * type)103 bool Parser::ParseType(Type *type)
104 {
105     ASSERT(TypeValidName());
106 
107     std::string componentName(context_.GiveToken());
108     size_t rank = 0;
109 
110     ++context_;
111 
112     while (*context_ == Token::Type::DEL_SQUARE_BRACKET_L) {
113         ++context_;
114         if (*context_ != Token::Type::DEL_SQUARE_BRACKET_R) {
115             context_.err = GetError("Expected ']'.", Error::ErrorType::ERR_BAD_ARRAY_TYPE_BOUND);
116             return false;
117         }
118         ++context_;
119         ++rank;
120     }
121 
122     *type = Type(componentName, rank);
123 
124     if (type->IsArray()) {
125         program_.arrayTypes.insert(*type);
126     }
127 
128     return true;
129 }
130 
ParseFieldType()131 bool Parser::ParseFieldType()
132 {
133     LOG(DEBUG, ASSEMBLER) << "started searching field type value (line " << lineStric_
134                           << "): " << context_.tokens[context_.number - 1].wholeLine;
135 
136     if (!TypeValidName()) {
137         context_.err = GetError("Not a correct type.", Error::ErrorType::ERR_BAD_FIELD_VALUE_TYPE);
138         return false;
139     }
140 
141     if (!ParseType(&currFld_->type)) {
142         return false;
143     }
144 
145     currFld_->metadata->SetFieldType(currFld_->type);
146 
147     LOG(DEBUG, ASSEMBLER) << "field type found (line " << lineStric_ << "): " << context_.GiveToken();
148 
149     return true;
150 }
151 
IsSameField(const pandasm::Field & field,std::string_view fieldName,bool isStatic)152 bool IsSameField(const pandasm::Field &field, std::string_view fieldName, bool isStatic)
153 {
154     return field.IsStatic() == isStatic && field.name == fieldName;
155 }
156 
IsSameField(const pandasm::Field & field1,const pandasm::Field & field2)157 bool IsSameField(const pandasm::Field &field1, const pandasm::Field &field2)
158 {
159     return field1.IsStatic() == field2.IsStatic() && field1.name == field2.name;
160 }
161 
ParseRecordField()162 bool Parser::ParseRecordField()
163 {
164     if (!ParseFieldType()) {
165         return false;
166     }
167 
168     if (context_.Mask()) {
169         context_.err = GetError("Expected field name.", Error::ErrorType::ERR_BAD_FIELD_MISSING_NAME, +1);
170         return false;
171     }
172 
173     if (!ParseFieldName()) {
174         return false;
175     }
176 
177     if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
178         currRecord_->bodyLocation.end = GetCurrentPosition(true);
179         ++context_;
180         open_ = false;
181         return true;
182     }
183 
184     metadata_ = currFld_->metadata.get();
185     ParseMetaDef();
186 
187     auto matchNames = [currFld = currFld_](const pandasm::Field &f) { return IsSameField(f, *currFld); };
188     auto identicalField = currRecord_->fieldList.end() - 1;
189     const auto iter = std::find_if(currRecord_->fieldList.begin(), identicalField, matchNames);
190     if (iter != identicalField) {
191         if (iter->isDefined) {
192             context_.err =
193                 GetError("Repeating field names in the same record.", Error::ErrorType::ERR_REPEATING_FIELD_NAME);
194 
195             return false;
196         }
197 
198         currRecord_->fieldList.erase(iter);
199     }
200 
201     return context_.Mask();
202 }
203 
IsConstArray()204 bool Parser::IsConstArray()
205 {
206     return isConstArray_;
207 }
208 
ArrayElementsValidNumber()209 bool Parser::ArrayElementsValidNumber()
210 {
211     if (!IsConstArray()) {
212         return true;
213     }
214 
215     ASSERT(currArray_->literals.size() > 1);
216 
217     auto initSize = std::get<uint32_t>(currArray_->literals[1].value);
218     if (initSize < 1) {
219         return false;
220     }
221     if (currArray_->literals.size() != initSize + INTRO_CONST_ARRAY_LITERALS_NUMBER) {
222         return false;
223     }
224 
225     return true;
226 }
227 
ParseAsArray(const std::vector<Token> & tokens)228 void Parser::ParseAsArray(const std::vector<Token> &tokens)
229 {
230     LOG(DEBUG, ASSEMBLER) << "started parsing of array (line " << lineStric_ << "): " << tokens[0].wholeLine;
231     funcDef_ = false;
232     recordDef_ = false;
233     arrayDef_ = true;
234 
235     if (!open_) {
236         ++context_;
237     } else {
238         context_.err =
239             GetError("No one array can be defined inside another array.", Error::ErrorType::ERR_BAD_DEFINITION);
240         return;
241     }
242 
243     if (ParseArrayFullSign()) {
244         if (!open_ && *context_ == Token::Type::DEL_BRACE_L) {
245             ++context_;
246 
247             LOG(DEBUG, ASSEMBLER) << "array body is open, line " << lineStric_ << ": " << tokens[0].wholeLine;
248 
249             open_ = true;
250         }
251 
252         uint32_t iterNumber = 1;
253         if (IsConstArray()) {
254             iterNumber = std::get<uint32_t>(currArray_->literals[1].value);
255         }
256 
257         if (iterNumber < 1) {
258             context_.err =
259                 GetError("Сonstant array must contain at least one element.", Error::ErrorType::ERR_BAD_ARRAY_SIZE);
260             return;
261         }
262 
263         for (uint32_t i = 0; i < iterNumber; i++) {
264             if (open_ && !context_.Mask() && *context_ != Token::Type::DEL_BRACE_R) {
265                 ParseArrayElements();
266             } else {
267                 break;
268             }
269         }
270 
271         if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
272             if (!ArrayElementsValidNumber()) {
273                 context_.err =
274                     GetError("Constant array must contain at least one element.", Error::ErrorType::ERR_BAD_ARRAY_SIZE);
275                 return;
276             }
277             LOG(DEBUG, ASSEMBLER) << "array body is closed, line " << lineStric_ << ": " << tokens[0].wholeLine;
278 
279             ++context_;
280 
281             open_ = false;
282         }
283     }
284 }
285 
ParseArrayElements()286 bool Parser::ParseArrayElements()
287 {
288     if (!open_ && *context_ == Token::Type::DEL_BRACE_L) {
289         open_ = true;
290 
291         ++context_;
292     }
293 
294     if (!open_) {
295         context_.err = GetError("Expected keyword.", Error::ErrorType::ERR_BAD_KEYWORD);
296         return false;
297     }
298 
299     if (context_.Mask()) {
300         return true;
301     }
302 
303     if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
304         if (!ArrayElementsValidNumber()) {
305             context_.err =
306                 GetError("Constant array must contain at least one element.", Error::ErrorType::ERR_BAD_ARRAY_SIZE);
307             return false;
308         }
309         ++context_;
310 
311         open_ = false;
312 
313         return true;
314     }
315 
316     currArray_->literals.emplace_back();
317     currArrayElem_ = &(currArray_->literals[currArray_->literals.size() - 1]);
318 
319     LOG(DEBUG, ASSEMBLER) << "parse line " << lineStric_ << " as array elem (.array_elem value)";
320     if (!ParseArrayElement()) {
321         if (context_.err.err != Error::ErrorType::ERR_NONE) {
322             return false;
323         }
324 
325         if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
326             ++context_;
327             open_ = false;
328 
329             if (!ArrayElementsValidNumber()) {
330                 context_.err =
331                     GetError("Constant array must contain at least one element.", Error::ErrorType::ERR_BAD_ARRAY_SIZE);
332                 return false;
333             }
334         } else {
335             context_.err =
336                 GetError("Expected a new array element on the next line.", Error::ErrorType::ERR_BAD_KEYWORD);
337             return false;
338         }
339     }
340 
341     return true;
342 }
343 
ParseArrayElement()344 bool Parser::ParseArrayElement()
345 {
346     if (IsConstArray()) {
347         currArrayElem_->tag = static_cast<panda_file::LiteralTag>(std::get<uint8_t>(currArray_->literals[0].value));
348     } else {
349         if (!ParseArrayElementType()) {
350             return false;
351         }
352 
353         auto valTag = currArrayElem_->tag;
354 
355         currArrayElem_->value = static_cast<uint8_t>(currArrayElem_->tag);
356         currArrayElem_->tag = panda_file::LiteralTag::TAGVALUE;
357 
358         currArray_->literals.emplace_back();
359         currArrayElem_ = &(currArray_->literals[currArray_->literals.size() - 1]);
360         currArrayElem_->tag = valTag;
361     }
362 
363     if (context_.Mask()) {
364         context_.err =
365             GetError("Expected array element value.", Error::ErrorType::ERR_BAD_ARRAY_ELEMENT_MISSING_VALUE, +1);
366         return false;
367     }
368 
369     if (!ParseArrayElementValue()) {
370         return false;
371     }
372 
373     if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
374         ++context_;
375         open_ = false;
376 
377         if (!ArrayElementsValidNumber()) {
378             context_.err =
379                 GetError("Constant array must contain at least one element.", Error::ErrorType::ERR_BAD_ARRAY_SIZE);
380             return false;
381         }
382         return true;
383     }
384 
385     return IsConstArray() ? true : context_.Mask();
386 }
387 
ParseArrayElementType()388 bool Parser::ParseArrayElementType()
389 {
390     LOG(DEBUG, ASSEMBLER) << "started searching array element type value (line " << lineStric_
391                           << "): " << context_.tokens[context_.number - 1].wholeLine;
392 
393     if (!TypeValidName()) {
394         context_.err = GetError("Not a correct type.", Error::ErrorType::ERR_BAD_ARRAY_ELEMENT_VALUE_TYPE);
395         return false;
396     }
397 
398     Type type;
399     if (!ParseType(&type)) {
400         return false;
401     }
402 
403     // workaround until #5776 is done
404     auto typeName = type.GetName();
405     std::replace(typeName.begin(), typeName.end(), '.', '/');
406     auto typeWithSlash = Type(typeName, 0);
407 
408     if (ark::pandasm::Type::IsPandaPrimitiveType(type.GetName())) {
409         if (IsConstArray()) {
410             currArrayElem_->tag = ark::pandasm::LiteralArray::GetArrayTagFromComponentType(type.GetId());
411         } else {
412             currArrayElem_->tag = ark::pandasm::LiteralArray::GetLiteralTagFromComponentType(type.GetId());
413         }
414 
415         if (program_.arrayTypes.find(type) == program_.arrayTypes.end()) {
416             program_.arrayTypes.emplace(type, 1);
417         }
418     } else if (ark::pandasm::Type::IsStringType(typeWithSlash.GetName(), program_.lang)) {
419         if (IsConstArray()) {
420             currArrayElem_->tag = panda_file::LiteralTag::ARRAY_STRING;
421         } else {
422             currArrayElem_->tag = panda_file::LiteralTag::STRING;
423         }
424 
425         if (program_.arrayTypes.find(typeWithSlash) == program_.arrayTypes.end()) {
426             program_.arrayTypes.emplace(typeWithSlash, 1);
427         }
428     } else {
429         return false;
430     }
431 
432     LOG(DEBUG, ASSEMBLER) << "array element type found (line " << lineStric_ << "): " << context_.GiveToken();
433 
434     return true;
435 }
436 
ParseArrayElementValueInteger()437 bool Parser::ParseArrayElementValueInteger()
438 {
439     int64_t n;
440     if (!ParseInteger(&n)) {
441         context_.err =
442             GetError("Invalid value of array integer element.", Error::ErrorType::ERR_BAD_ARRAY_ELEMENT_VALUE_INTEGER);
443         return false;
444     }
445     if (currArrayElem_->IsBoolValue()) {
446         currArrayElem_->value = static_cast<bool>(n);
447     }
448     if (currArrayElem_->IsByteValue()) {
449         currArrayElem_->value = static_cast<uint8_t>(n);
450     }
451     if (currArrayElem_->IsShortValue()) {
452         currArrayElem_->value = static_cast<uint16_t>(n);
453     }
454     if (currArrayElem_->IsIntegerValue()) {
455         currArrayElem_->value = static_cast<uint32_t>(n);
456     }
457     if (currArrayElem_->IsLongValue()) {
458         currArrayElem_->value = static_cast<uint64_t>(n);
459     }
460     return true;
461 }
462 
ParseArrayElementValueFloat()463 bool Parser::ParseArrayElementValueFloat()
464 {
465     double n;
466     if (!ParseFloat(&n, !currArrayElem_->IsFloatValue())) {
467         context_.err =
468             GetError("Invalid value of array float element.", Error::ErrorType::ERR_BAD_ARRAY_ELEMENT_VALUE_FLOAT);
469         return false;
470     }
471     if (currArrayElem_->IsFloatValue()) {
472         currArrayElem_->value = static_cast<float>(n);
473     } else {
474         currArrayElem_->value = static_cast<double>(n);
475     }
476     return true;
477 }
478 
ParseArrayElementValueString()479 bool Parser::ParseArrayElementValueString()
480 {
481     if (context_.err.err != Error::ErrorType::ERR_NONE) {
482         return false;
483     }
484 
485     auto res = ParseStringLiteral();
486     if (!res) {
487         context_.err =
488             GetError("Invalid value of array string element.", Error::ErrorType::ERR_BAD_ARRAY_ELEMENT_VALUE_STRING);
489         return false;
490     }
491     currArrayElem_->value = res.value();
492     return true;
493 }
494 
ParseArrayElementValue()495 bool Parser::ParseArrayElementValue()
496 {
497     if (currArrayElem_->IsBoolValue() || currArrayElem_->IsByteValue() || currArrayElem_->IsShortValue() ||
498         currArrayElem_->IsIntegerValue() || currArrayElem_->IsLongValue()) {
499         if (!ParseArrayElementValueInteger()) {
500             return false;
501         }
502     }
503     if (currArrayElem_->IsFloatValue() || currArrayElem_->IsDoubleValue()) {
504         if (!ParseArrayElementValueFloat()) {
505             return false;
506         }
507     }
508     if (currArrayElem_->IsStringValue()) {
509         if (!ParseArrayElementValueString()) {
510             return false;
511         }
512     }
513 
514     ++context_;
515 
516     return true;
517 }
518 
ParseFunctionCode()519 bool Parser::ParseFunctionCode()
520 {
521     if (!open_ && *context_ == Token::Type::DEL_BRACE_L) {
522         open_ = true;
523         currFunc_->bodyLocation.begin = GetCurrentPosition(false);
524         ++context_;
525     }
526 
527     currFunc_->bodyPresence = true;
528 
529     if (!open_) {
530         context_.err = GetError("Expected keyword.", Error::ErrorType::ERR_BAD_KEYWORD);
531         return false;
532     }
533 
534     if (context_.Mask()) {
535         return true;
536     }
537 
538     if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
539         currFunc_->bodyLocation.end = GetCurrentPosition(true);
540         ++context_;
541         open_ = false;
542         return true;
543     }
544 
545     currIns_ = &currFunc_->ins.emplace_back();
546 
547     LOG(DEBUG, ASSEMBLER) << "parse line " << lineStric_
548                           << " as instruction ([label:] operation [operand,] [# comment])";
549 
550     ParseFunctionInstruction();
551 
552     if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
553         currFunc_->bodyLocation.end = GetCurrentPosition(true);
554         ++context_;
555         open_ = false;
556     }
557 
558     return true;
559 }
560 
ParseAsRecord(const std::vector<Token> & tokens)561 void Parser::ParseAsRecord(const std::vector<Token> &tokens)
562 {
563     LOG(DEBUG, ASSEMBLER) << "started parsing of record (line " << lineStric_ << "): " << tokens[0].wholeLine;
564     funcDef_ = false;
565     recordDef_ = true;
566     arrayDef_ = false;
567 
568     if (!open_) {
569         ++context_;
570     } else {
571         context_.err =
572             GetError("No one record can be defined inside another record.", Error::ErrorType::ERR_BAD_DEFINITION);
573         return;
574     }
575 
576     if (ParseRecordFullSign()) {
577         metadata_ = currRecord_->metadata.get();
578         if (ParseMetaDef()) {
579             if (!open_ && *context_ == Token::Type::DEL_BRACE_L) {
580                 currRecord_->bodyLocation.begin = GetCurrentPosition(false);
581                 ++context_;
582 
583                 LOG(DEBUG, ASSEMBLER) << "record body is open, line " << lineStric_ << ": " << tokens[0].wholeLine;
584 
585                 open_ = true;
586             }
587 
588             if (open_ && !context_.Mask() && *context_ != Token::Type::DEL_BRACE_R) {
589                 ParseRecordFields();
590             } else if (open_) {
591                 currRecord_->bodyPresence = true;
592             }
593 
594             if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
595                 LOG(DEBUG, ASSEMBLER) << "record body is closed, line " << lineStric_ << ": " << tokens[0].wholeLine;
596 
597                 currRecord_->bodyLocation.end = GetCurrentPosition(true);
598                 ++context_;
599 
600                 open_ = false;
601             }
602         }
603     }
604 }
605 
ParseAsFunction(const std::vector<Token> & tokens)606 void Parser::ParseAsFunction(const std::vector<Token> &tokens)
607 {
608     LOG(DEBUG, ASSEMBLER) << "started parsing of function (line " << lineStric_ << "): " << tokens[0].wholeLine;
609     recordDef_ = false;
610     funcDef_ = true;
611     arrayDef_ = false;
612 
613     if (!open_) {
614         ++context_;
615     } else {
616         context_.err =
617             GetError("No one function can be defined inside another function.", Error::ErrorType::ERR_BAD_DEFINITION);
618         return;
619     }
620 
621     if (ParseFunctionFullSign()) {
622         metadata_ = currFunc_->metadata.get();
623         if (ParseMetaDef()) {
624             if (!open_ && *context_ == Token::Type::DEL_BRACE_L) {
625                 currFunc_->bodyLocation.begin = GetCurrentPosition(false);
626                 ++context_;
627 
628                 LOG(DEBUG, ASSEMBLER) << "function body is open, line " << lineStric_ << ": " << tokens[0].wholeLine;
629 
630                 open_ = true;
631             }
632 
633             if (open_ && !context_.Mask() && *context_ != Token::Type::DEL_BRACE_R) {
634                 ParseFunctionCode();
635             } else if (open_) {
636                 currFunc_->bodyPresence = true;
637             }
638 
639             if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
640                 LOG(DEBUG, ASSEMBLER) << "function body is closed, line " << lineStric_ << ": " << tokens[0].wholeLine;
641 
642                 currFunc_->bodyLocation.end = GetCurrentPosition(true);
643                 ++context_;
644                 open_ = false;
645             }
646         }
647         if ((currFunc_->params.empty() ||
648              currFunc_->params[0].type.GetName() != pandasm::GetOwnerName(currFunc_->name) ||
649              currFunc_->metadata->IsCctor())) {
650             currFunc_->metadata->SetAccessFlags(currFunc_->metadata->GetAccessFlags() | ACC_STATIC);
651         }
652         const auto &it = ambiguousFunctionTable_.find({currFunc_->name, true});
653         if (it != ambiguousFunctionTable_.end()) {
654             ASSERT(ambiguousFunctionTable_.find({currFunc_->name, false}) != ambiguousFunctionTable_.end());
655             const auto &homonymFunc = ambiguousFunctionTable_.at({currFunc_->name, false});
656             if (homonymFunc.IsStatic() == it->second.IsStatic()) {
657                 context_.err = GetError("This function already exists.", Error::ErrorType::ERR_BAD_ID_FUNCTION);
658             }
659         }
660     }
661 }
662 
ParseAsBraceRight(const std::vector<Token> & tokens)663 void Parser::ParseAsBraceRight(const std::vector<Token> &tokens)
664 {
665     if (!open_) {
666         context_.err =
667             GetError("Delimiter '}' for the code area is outside a function.", Error::ErrorType::ERR_BAD_BOUND);
668         return;
669     }
670 
671     LOG(DEBUG, ASSEMBLER) << "body is closed (line " << lineStric_ << "): " << tokens[0].wholeLine;
672 
673     open_ = false;
674     if (funcDef_) {
675         currFunc_->bodyLocation.end = GetCurrentPosition(true);
676     } else if (recordDef_) {
677         currRecord_->bodyLocation.end = GetCurrentPosition(true);
678     } else if (arrayDef_) {
679         if (!ArrayElementsValidNumber()) {
680             context_.err =
681                 GetError("Constant array must contain at least one element.", Error::ErrorType::ERR_BAD_ARRAY_SIZE);
682             return;
683         }
684     } else {
685         LOG(FATAL, ASSEMBLER) << "Internal error: either function or record must be parsed here";
686     }
687     ++context_;
688 }
689 
ParseResetFunctionParams(bool isHomonym)690 void Parser::ParseResetFunctionParams(bool isHomonym)
691 {
692     for (const auto &t : context_.functionArgumentsLists) {
693         auto it = ambiguousFunctionTable_.find({t.first, isHomonym});
694         ASSERT(it != ambiguousFunctionTable_.end() || isHomonym);
695         if (it == ambiguousFunctionTable_.end()) {
696             continue;
697         }
698         currFunc_ = &(it->second);
699         currFunc_->regsNum = static_cast<size_t>(currFunc_->valueOfFirstParam + 1);
700 
701         for (const auto &v : t.second) {
702             if (currFunc_->ins.empty() && currFunc_->ins.size() < v.first && currFunc_->ins[v.first - 1].regs.empty()) {
703                 continue;
704             }
705             currFunc_->ins[v.first - 1].regs[v.second] += static_cast<uint16_t>(currFunc_->valueOfFirstParam + 1);
706             // NOLINTNEXTLINE(hicpp-signed-bitwise)
707             size_t maxRegNumber = (1 << currFunc_->ins[v.first - 1].MaxRegEncodingWidth());
708             if (currFunc_->ins[v.first - 1].regs[v.second] >= maxRegNumber) {
709                 const auto &debug = currFunc_->ins[v.first - 1].insDebug;
710                 context_.err = Error("Register width mismatch.", debug.lineNumber, Error::ErrorType::ERR_BAD_NAME_REG,
711                                      "", debug.boundLeft, debug.boundRight, debug.wholeLine);
712                 SetError();
713                 break;
714             }
715         }
716     }
717 }
718 
ParseResetFunctionLabelsAndParams()719 void Parser::ParseResetFunctionLabelsAndParams()
720 {
721     if (open_ || err_.err != Error::ErrorType::ERR_NONE) {
722         return;
723     }
724     for (const auto &f : ambiguousFunctionTable_) {
725         for (const auto &k : f.second.labelTable) {
726             if (!k.second.fileLocation->isDefined) {
727                 context_.err = Error("This label does not exist.", lineStric_, Error::ErrorType::ERR_BAD_LABEL_EXT, "",
728                                      k.second.fileLocation->boundLeft, k.second.fileLocation->boundRight,
729                                      k.second.fileLocation->wholeLine);
730                 SetError();
731             }
732         }
733     }
734 
735     ParseResetFunctionParams(false);
736     ParseResetFunctionParams(true);
737 }
738 
ParseInsFromFuncTable(ark::pandasm::Function & func)739 void Parser::ParseInsFromFuncTable(ark::pandasm::Function &func)
740 {
741     for (auto &insn : func.ins) {
742         if (!insn.HasFlag(InstFlags::METHOD_ID) && !insn.HasFlag(InstFlags::STATIC_METHOD_ID)) {
743             // we need to correct all method_id's
744             continue;
745         }
746 
747         bool isInitobj = insn.opcode == Opcode::INITOBJ || insn.opcode == Opcode::INITOBJ_SHORT ||
748                          insn.opcode == Opcode::INITOBJ_RANGE;
749         size_t diff = isInitobj ? 0 : 1;
750         auto funcName = insn.ids[0];
751 
752         if (!IsSignatureOrMangled(funcName)) {
753             const auto itSynonym = program_.functionSynonyms.find(funcName);
754             if (itSynonym == program_.functionSynonyms.end()) {
755                 continue;
756             }
757 
758             if (itSynonym->second.size() > 1) {
759                 const auto &debug = insn.insDebug;
760                 context_.err = Error("Unable to resolve ambiguous function call", debug.lineNumber,
761                                      Error::ErrorType::ERR_FUNCTION_MULTIPLE_ALTERNATIVES, "", debug.boundLeft,
762                                      debug.boundRight, debug.wholeLine);
763                 SetError();
764                 break;
765             }
766 
767             insn.ids[0] = program_.functionSynonyms.at(funcName)[0];
768         }
769 
770         auto foundFunc = ambiguousFunctionTable_.find({insn.ids[0], false});
771         ASSERT(foundFunc != ambiguousFunctionTable_.end());
772         if (insn.OperandListLength() - diff < foundFunc->second.GetParamsNum()) {
773             if (insn.IsCallRange() && (static_cast<int>(insn.regs.size()) - static_cast<int>(diff) >= 0)) {
774                 continue;
775             }
776 
777             const auto &debug = insn.insDebug;
778             context_.err =
779                 Error("Function argument mismatch.", debug.lineNumber, Error::ErrorType::ERR_FUNCTION_ARGUMENT_MISMATCH,
780                       "", debug.boundLeft, debug.boundRight, debug.wholeLine);
781             SetError();
782         }
783     }
784 }
785 
CheckVirtualCallInsn(const ark::pandasm::Ins & insn)786 bool Parser::CheckVirtualCallInsn(const ark::pandasm::Ins &insn)
787 {
788     switch (insn.opcode) {
789         case Opcode::CALL_VIRT:
790         case Opcode::CALL_VIRT_SHORT:
791         case Opcode::CALL_VIRT_RANGE:
792         case Opcode::CALL_VIRT_ACC:
793         case Opcode::CALL_VIRT_ACC_SHORT: {
794             if (program_.functionStaticTable.find(insn.ids[0]) != program_.functionStaticTable.cend()) {
795                 const auto &debug = insn.insDebug;
796                 context_.err =
797                     Error("Virtual instruction calls static method.", debug.lineNumber,
798                           Error::ErrorType::ERR_BAD_OPERAND, "", debug.boundLeft, debug.boundRight, debug.wholeLine);
799                 SetError();
800                 return false;
801             }
802             return true;
803         }
804         default:
805             return true;
806     }
807 }
808 
CheckVirtualCalls(const std::map<std::string,ark::pandasm::Function> & functionTable)809 void Parser::CheckVirtualCalls(const std::map<std::string, ark::pandasm::Function> &functionTable)
810 {
811     for (const auto &func : functionTable) {
812         for (const auto &insn : func.second.ins) {
813             if (!CheckVirtualCallInsn(insn)) {
814                 return;
815             }
816         }
817     }
818 }
819 
ParseResetFunctionTable()820 void Parser::ParseResetFunctionTable()
821 {
822     for (auto &[unusedKey, func] : ambiguousFunctionTable_) {
823         (void)unusedKey;
824         if (!func.fileLocation->isDefined) {
825             context_.err = Error("This function does not exist.", func.fileLocation->lineNumber,
826                                  Error::ErrorType::ERR_BAD_ID_FUNCTION, "", func.fileLocation->boundLeft,
827                                  func.fileLocation->boundRight, func.fileLocation->wholeLine);
828             SetError();
829         } else if (func.HasImplementation() != func.bodyPresence) {
830             context_.err =
831                 Error("Inconsistency of the definition of the function and its metadata.",
832                       func.fileLocation->lineNumber, Error::ErrorType::ERR_BAD_DEFINITION_FUNCTION, "",
833                       func.fileLocation->boundLeft, func.fileLocation->boundRight, func.fileLocation->wholeLine);
834             SetError();
835         } else {
836             ParseInsFromFuncTable(func);
837         }
838     }
839 }
840 
ParseResetRecords(const ark::pandasm::Record & record)841 void Parser::ParseResetRecords(const ark::pandasm::Record &record)
842 {
843     for (const auto &fld : record.fieldList) {
844         if (!record.HasImplementation() && !fld.metadata->IsForeign()) {
845             context_.err =
846                 Error("External record may have only external fields", fld.lineOfDef,
847                       Error::ErrorType::ERR_BAD_FIELD_METADATA, "", fld.boundLeft, fld.boundRight, fld.wholeLine);
848             SetError();
849         }
850         if (!fld.isDefined) {
851             context_.err = Error("This field does not exist.", fld.lineOfDef, Error::ErrorType::ERR_BAD_ID_FIELD, "",
852                                  fld.boundLeft, fld.boundRight, fld.wholeLine);
853             SetError();
854         }
855     }
856 }
857 
ParseResetRecordTable()858 void Parser::ParseResetRecordTable()
859 {
860     for (const auto &[unusedKey, record] : program_.recordTable) {
861         (void)unusedKey;
862         if (!record.fileLocation->isDefined) {
863             context_.err = Error("This record does not exist.", record.fileLocation->lineNumber,
864                                  Error::ErrorType::ERR_BAD_ID_RECORD, "", record.fileLocation->boundLeft,
865                                  record.fileLocation->boundRight, record.fileLocation->wholeLine);
866             SetError();
867         } else {
868             ParseResetRecords(record);
869         }
870     }
871 }
872 
ParseResetTables()873 void Parser::ParseResetTables()
874 {
875     if (err_.err != Error::ErrorType::ERR_NONE) {
876         return;
877     }
878 
879     ParseResetFunctionTable();
880 
881     if (err_.err != Error::ErrorType::ERR_NONE) {
882         return;
883     }
884 
885     ParseResetRecordTable();
886 }
887 
ParseAsLanguageDirective()888 void Parser::ParseAsLanguageDirective()
889 {
890     ++context_;
891 
892     if (context_.Mask()) {
893         context_.err = GetError("Incorrect .language directive: Expected language",
894                                 Error::ErrorType::ERR_BAD_DIRECTIVE_DECLARATION);
895         return;
896     }
897 
898     auto lang = context_.GiveToken();
899     auto res = ark::panda_file::LanguageFromString(lang);
900     if (!res) {
901         context_.err =
902             GetError("Incorrect .language directive: Unknown language", Error::ErrorType::ERR_UNKNOWN_LANGUAGE);
903         return;
904     }
905 
906     ++context_;
907 
908     if (!context_.Mask()) {
909         context_.err = GetError("Incorrect .language directive: Unexpected token",
910                                 Error::ErrorType::ERR_BAD_DIRECTIVE_DECLARATION);
911     }
912 
913     program_.lang = res.value();
914 }
915 
PrepareCatchBlock(bool isCatchall,size_t size,size_t catchallTokensNum,size_t catchTokensNum)916 Function::CatchBlock Parser::PrepareCatchBlock(bool isCatchall, size_t size, size_t catchallTokensNum,
917                                                size_t catchTokensNum)
918 {
919     constexpr size_t TRY_BEGIN = 0;
920     constexpr size_t TRY_END = 1;
921     constexpr size_t CATCH_BEGIN = 2;
922     constexpr size_t CATCH_END = 3;
923 
924     Function::CatchBlock catchBlock;
925     catchBlock.wholeLine = context_.tokens[0].wholeLine;
926     std::vector<std::string> labelNames {"try block begin", "try block end", "catch block begin"};
927     std::vector<std::string> labels;
928     bool fullCatchBlock = (isCatchall && size == catchallTokensNum) || (!isCatchall && size == catchTokensNum);
929     if (fullCatchBlock) {
930         labelNames.emplace_back("catch block end");
931     }
932     if (!isCatchall) {
933         catchBlock.exceptionRecord = context_.GiveToken();
934         ++context_;
935     }
936 
937     bool skipComma = isCatchall;
938     for (const auto &labelName : labelNames) {
939         if (!skipComma) {
940             if (*context_ != Token::Type::DEL_COMMA) {
941                 context_.err = GetError("Expected comma.", Error::ErrorType::ERR_BAD_DIRECTIVE_DECLARATION);
942                 return catchBlock;
943             }
944             ++context_;
945         }
946         skipComma = false;
947         if (!LabelValidName()) {
948             context_.err =
949                 GetError(std::string("Invalid name of the ") + labelName + " label.", Error::ErrorType::ERR_BAD_LABEL);
950             return catchBlock;
951         }
952         labels.emplace_back(context_.GiveToken());
953         AddObjectInTable(false, *labelTable_);
954         ++context_;
955     }
956 
957     ASSERT(context_.Mask());
958     catchBlock.tryBeginLabel = labels[TRY_BEGIN];
959     catchBlock.tryEndLabel = labels[TRY_END];
960     catchBlock.catchBeginLabel = labels[CATCH_BEGIN];
961     if (fullCatchBlock) {
962         catchBlock.catchEndLabel = labels[CATCH_END];
963     } else {
964         catchBlock.catchEndLabel = labels[CATCH_BEGIN];
965     }
966     return catchBlock;
967 }
968 
ParseAsCatchDirective()969 void Parser::ParseAsCatchDirective()
970 {
971     ASSERT(*context_ == Token::Type::ID_CATCH || *context_ == Token::Type::ID_CATCHALL);
972 
973     constexpr size_t CATCH_DIRECTIVE_TOKENS_NUM = 8;
974     constexpr size_t CATCHALL_DIRECTIVE_TOKENS_NUM = 6;
975     constexpr size_t CATCH_FULL_DIRECTIVE_TOKENS_NUM = 10;
976     constexpr size_t CATCHALL_FULL_DIRECTIVE_TOKENS_NUM = 8;
977 
978     bool isCatchall = *context_ == Token::Type::ID_CATCHALL;
979     size_t size = context_.tokens.size();
980     if (isCatchall && size != CATCHALL_DIRECTIVE_TOKENS_NUM && size != CATCHALL_FULL_DIRECTIVE_TOKENS_NUM) {
981         context_.err = GetError(
982             "Incorrect catch block declaration. Must be in the format: .catchall <try_begin_label>, <try_end_label>, "
983             "<catch_begin_label>[, <catch_end_label>]",
984             Error::ErrorType::ERR_BAD_DIRECTIVE_DECLARATION);
985         return;
986     }
987 
988     if (!isCatchall && size != CATCH_DIRECTIVE_TOKENS_NUM && size != CATCH_FULL_DIRECTIVE_TOKENS_NUM) {
989         context_.err = GetError(
990             "Incorrect catch block declaration. Must be in the format: .catch <exception_record>, <try_begin_label>, "
991             "<try_end_label>, <catch_begin_label>[, <catch_end_label>]",
992             Error::ErrorType::ERR_BAD_DIRECTIVE_DECLARATION);
993         return;
994     }
995 
996     ++context_;
997 
998     if (!isCatchall && !RecordValidName()) {
999         context_.err = GetError("Invalid name of the exception record.", Error::ErrorType::ERR_BAD_RECORD_NAME);
1000         return;
1001     }
1002 
1003     Function::CatchBlock catchBlock =
1004         PrepareCatchBlock(isCatchall, size, CATCHALL_FULL_DIRECTIVE_TOKENS_NUM, CATCH_FULL_DIRECTIVE_TOKENS_NUM);
1005 
1006     currFunc_->catchBlocks.push_back(catchBlock);
1007 }
1008 
ParseAsCatchall(const std::vector<Token> & tokens)1009 void Parser::ParseAsCatchall(const std::vector<Token> &tokens)
1010 {
1011     std::string directiveName = *context_ == Token::Type::ID_CATCH ? ".catch" : ".catchall";
1012     if (!funcDef_) {
1013         context_.err = GetError(directiveName + " directive is located outside of a function body.",
1014                                 Error::ErrorType::ERR_INCORRECT_DIRECTIVE_LOCATION);
1015         return;
1016     }
1017 
1018     LOG(DEBUG, ASSEMBLER) << "started parsing of " << directiveName << " directive (line " << lineStric_
1019                           << "): " << tokens[0].wholeLine;
1020 
1021     ParseAsCatchDirective();
1022 }
1023 
ParseAsLanguage(const std::vector<Token> & tokens,bool & isLangParsed,bool & isFirstStatement)1024 void Parser::ParseAsLanguage(const std::vector<Token> &tokens, bool &isLangParsed, bool &isFirstStatement)
1025 {
1026     if (isLangParsed) {
1027         context_.err = GetError("Multiple .language directives", Error::ErrorType::ERR_MULTIPLE_DIRECTIVES);
1028         return;
1029     }
1030 
1031     if (!isFirstStatement) {
1032         context_.err = GetError(".language directive must be specified before any other declarations",
1033                                 Error::ErrorType::ERR_INCORRECT_DIRECTIVE_LOCATION);
1034         return;
1035     }
1036 
1037     LOG(DEBUG, ASSEMBLER) << "started parsing of .language directive (line " << lineStric_
1038                           << "): " << tokens[0].wholeLine;
1039 
1040     ParseAsLanguageDirective();
1041 
1042     isLangParsed = true;
1043 }
1044 
ParseAfterLine(bool & isFirstStatement)1045 bool Parser::ParseAfterLine(bool &isFirstStatement)
1046 {
1047     SetError();
1048 
1049     if (!context_.Mask() && err_.err == Error::ErrorType::ERR_NONE) {
1050         context_.err = GetError("There can be nothing after.", Error::ErrorType::ERR_BAD_END);
1051     }
1052 
1053     if (err_.err != Error::ErrorType::ERR_NONE) {
1054         LOG(DEBUG, ASSEMBLER) << "processing aborted (error detected)";
1055         return false;
1056     }
1057 
1058     LOG(DEBUG, ASSEMBLER) << "parsing of line " << lineStric_ << " is successful";
1059 
1060     SetError();
1061 
1062     isFirstStatement = false;
1063 
1064     return true;
1065 }
1066 
ParseAfterMainLoop(const std::string & fileName)1067 Expected<Program, Error> Parser::ParseAfterMainLoop(const std::string &fileName)
1068 {
1069     ParseResetFunctionLabelsAndParams();
1070 
1071     if (open_ && err_.err == Error::ErrorType::ERR_NONE) {
1072         context_.err = Error("Code area is not closed.", currFunc_->fileLocation->lineNumber,
1073                              Error::ErrorType::ERR_BAD_CLOSE, "", 0, currFunc_->name.size(), currFunc_->name);
1074         SetError();
1075     }
1076 
1077     ParseResetTables();
1078 
1079     if (err_.err != Error::ErrorType::ERR_NONE) {
1080         return Unexpected(err_);
1081     }
1082 
1083     for (auto &[key, func] : ambiguousFunctionTable_) {
1084         if (func.metadata->HasImplementation()) {
1085             func.sourceFile = fileName;
1086         }
1087         if (func.IsStatic()) {
1088             program_.functionStaticTable.emplace(key.first, std::move(func));
1089         } else {
1090             program_.functionInstanceTable.emplace(key.first, std::move(func));
1091         }
1092     }
1093     ambiguousFunctionTable_.clear();
1094 
1095     CheckVirtualCalls(program_.functionStaticTable);
1096     CheckVirtualCalls(program_.functionInstanceTable);
1097     if (err_.err != Error::ErrorType::ERR_NONE) {
1098         return Unexpected(err_);
1099     }
1100 
1101     for (auto &rec : program_.recordTable) {
1102         if (rec.second.HasImplementation()) {
1103             rec.second.sourceFile = fileName;
1104         }
1105     }
1106 
1107     return std::move(program_);
1108 }
1109 
ParseContextByType(const std::vector<Token> & tokens,bool & isLangParsed,bool & isFirstStatement)1110 void Parser::ParseContextByType(const std::vector<Token> &tokens, bool &isLangParsed, bool &isFirstStatement)
1111 {
1112     switch (*context_) {
1113         case Token::Type::ID_CATCH:
1114         case Token::Type::ID_CATCHALL: {
1115             ParseAsCatchall(tokens);
1116             break;
1117         }
1118         case Token::Type::ID_LANG: {
1119             ParseAsLanguage(tokens, isLangParsed, isFirstStatement);
1120             break;
1121         }
1122         case Token::Type::ID_REC: {
1123             ParseAsRecord(tokens);
1124             break;
1125         }
1126         case Token::Type::ID_FUN: {
1127             ParseAsFunction(tokens);
1128             break;
1129         }
1130         case Token::Type::ID_ARR: {
1131             ParseAsArray(tokens);
1132             break;
1133         }
1134         case Token::Type::DEL_BRACE_R: {
1135             ParseAsBraceRight(tokens);
1136             break;
1137         }
1138         default: {
1139             if (funcDef_) {
1140                 ParseFunctionCode();
1141             } else if (recordDef_) {
1142                 ParseRecordFields();
1143             } else if (arrayDef_) {
1144                 ParseArrayElements();
1145             }
1146         }
1147     }
1148 }
1149 
Parse(TokenSet & vectorsTokens,const std::string & fileName)1150 Expected<Program, Error> Parser::Parse(TokenSet &vectorsTokens, const std::string &fileName)
1151 {
1152     bool isLangParsed = false;
1153     bool isFirstStatement = true;
1154     for (const auto &tokens : vectorsTokens) {
1155         ++lineStric_;
1156         if (tokens.empty()) {
1157             continue;
1158         }
1159         LOG(DEBUG, ASSEMBLER) << "started parsing of line " << lineStric_ << ": " << tokens[0].wholeLine;
1160         context_.Make(tokens);
1161 
1162         ParseContextByType(tokens, isLangParsed, isFirstStatement);
1163 
1164         if (!ParseAfterLine(isFirstStatement)) {
1165             break;
1166         }
1167     }
1168 
1169     return ParseAfterMainLoop(fileName);
1170 }
1171 
Parse(const std::string & source,const std::string & fileName)1172 Expected<Program, Error> Parser::Parse(const std::string &source, const std::string &fileName)
1173 {
1174     auto ss = std::stringstream(source);
1175     std::string line;
1176 
1177     Lexer l;
1178     std::vector<std::vector<Token>> v;
1179 
1180     while (std::getline(ss, line)) {
1181         auto [tokens, error] = l.TokenizeString(line);
1182         if (error.err != Error::ErrorType::ERR_NONE) {
1183             return Unexpected(error);
1184         }
1185 
1186         v.push_back(tokens);
1187     }
1188 
1189     return Parse(v, fileName);
1190 }
1191 
SetError()1192 void Parser::SetError()
1193 {
1194     err_ = context_.err;
1195 }
1196 
RegValidName()1197 bool Parser::RegValidName()
1198 {
1199     if (context_.err.err != Error::ErrorType::ERR_NONE) {
1200         return false;
1201     }
1202 
1203     if (currFunc_->GetParamsNum() > 0) {
1204         return context_.ValidateRegisterName('v') || context_.ValidateRegisterName('a', currFunc_->GetParamsNum() - 1);
1205     }
1206 
1207     return context_.ValidateRegisterName('v');
1208 }
1209 
ParamValidName()1210 bool Parser::ParamValidName()
1211 {
1212     return context_.ValidateParameterName(currFunc_->GetParamsNum());
1213 }
1214 
PrefixedValidName(BracketOptions options)1215 bool Parser::PrefixedValidName(BracketOptions options)
1216 {
1217     auto s = context_.GiveToken();
1218     if (!IsNonDigit(s[0])) {
1219         return false;
1220     }
1221     for (size_t i = 1; i < s.size(); ++i) {
1222         char const c = s[i];
1223         if (c == '.') {
1224             if (i + 1 >= s.size()) {
1225                 return false;
1226             }
1227             if (IsNonDigit(s[i + 1])) {
1228                 continue;
1229             }
1230             if (!IsAllowAngleBrackets(options) || s[i + 1] != '<') {
1231                 return false;
1232             }
1233             continue;
1234         }
1235         if (IsAlphaNumeric(c)) {
1236             continue;
1237         }
1238         if (IsAllowBrackets(options) && (c == '[' || c == ']')) {
1239             continue;
1240         }
1241         if (IsAllowAngleBrackets(options) && (c == '<' || c == '>')) {
1242             continue;
1243         }
1244         return false;
1245     }
1246     return true;
1247 }
1248 
RecordValidName()1249 bool Parser::RecordValidName()
1250 {
1251     return PrefixedValidName(BracketOptions::ALLOW_BRACKETS);
1252 }
1253 
FunctionValidName()1254 bool Parser::FunctionValidName()
1255 {
1256     return PrefixedValidName(BracketOptions::ALL_BRACKETS);
1257 }
1258 
ArrayValidName()1259 bool Parser::ArrayValidName()
1260 {
1261     return PrefixedValidName();
1262 }
1263 
LabelValidName()1264 bool Parser::LabelValidName()
1265 {
1266     auto token = context_.GiveToken();
1267     if (!IsNonDigit(token[0])) {
1268         return false;
1269     }
1270 
1271     token.remove_prefix(1);
1272 
1273     for (auto i : token) {
1274         if (!IsAlphaNumeric(i)) {
1275             return false;
1276         }
1277     }
1278 
1279     return true;
1280 }
1281 
ParseLabel()1282 bool Parser::ParseLabel()
1283 {
1284     LOG(DEBUG, ASSEMBLER) << "label search started (line " << lineStric_ << "): " << context_.tokens[0].wholeLine;
1285 
1286     context_++;
1287 
1288     if (*context_ == Token::Type::DEL_COLON) {
1289         context_--;
1290         if (LabelValidName()) {
1291             if (AddObjectInTable(true, *labelTable_)) {
1292                 currIns_->setLabel = true;
1293                 currIns_->label = context_.GiveToken();
1294 
1295                 LOG(DEBUG, ASSEMBLER) << "label detected (line " << lineStric_ << "): " << context_.GiveToken();
1296 
1297                 context_++;
1298                 context_++;
1299                 return !context_.Mask();
1300             }
1301 
1302             LOG(DEBUG, ASSEMBLER) << "label is detected (line " << lineStric_ << "): " << context_.GiveToken()
1303                                   << ", but this label already exists";
1304 
1305             context_.err = GetError("This label already exists.", Error::ErrorType::ERR_BAD_LABEL_EXT);
1306         } else {
1307             LOG(DEBUG, ASSEMBLER) << "label with non-standard character is detected, attempt to create a label is "
1308                                      "supposed, but this cannot be any label name (line "
1309                                   << lineStric_ << "): " << context_.GiveToken();
1310 
1311             context_.err = GetError(
1312                 "Invalid name of label. Label contains only characters: '_', '0' - '9', 'a' - 'z', 'A' - 'Z'; and "
1313                 "starts with any letter or with '_'.",
1314                 Error::ErrorType::ERR_BAD_LABEL);
1315         }
1316 
1317         return false;
1318     }
1319 
1320     context_--;
1321 
1322     LOG(DEBUG, ASSEMBLER) << "label is not detected (line " << lineStric_ << ")";
1323 
1324     return true;
1325 }
1326 
TokenToOpcode(Token::Type id)1327 static Opcode TokenToOpcode(Token::Type id)
1328 {
1329     ASSERT(id > Token::Type::OPERATION && id < Token::Type::KEYWORD);
1330     using Utype = std::underlying_type_t<Token::Type>;
1331     return static_cast<Opcode>(static_cast<Utype>(id) - static_cast<Utype>(Token::Type::OPERATION) - 1);
1332 }
1333 
ParseOperation()1334 bool Parser::ParseOperation()
1335 {
1336     if (context_.Mask()) {
1337         LOG(DEBUG, ASSEMBLER) << "no more tokens (line " << lineStric_ << "): " << context_.tokens[0].wholeLine;
1338 
1339         return false;
1340     }
1341 
1342     if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
1343         return false;
1344     }
1345 
1346     LOG(DEBUG, ASSEMBLER) << "operaion search started (line " << lineStric_ << "): " << context_.tokens[0].wholeLine;
1347 
1348     if (*context_ > Token::Type::OPERATION && *context_ < Token::Type::KEYWORD) {
1349         SetOperationInformation();
1350 
1351         context_.UpSignOperation();
1352         currIns_->opcode = TokenToOpcode(context_.id);
1353 
1354         LOG(DEBUG, ASSEMBLER) << "operatiuon is detected (line " << lineStric_ << "): " << context_.GiveToken()
1355                               << " (operand type: " << OperandTypePrint(currIns_->opcode) << ")";
1356 
1357         context_++;
1358         return true;
1359     }
1360 
1361     LOG(DEBUG, ASSEMBLER) << "founded " << context_.GiveToken() << ", it is not an operation (line " << lineStric_
1362                           << ")";
1363 
1364     context_.err = GetError("Invalid operation.", Error::ErrorType::ERR_BAD_OPERATION_NAME);
1365 
1366     return false;
1367 }
1368 
ParseOperandVreg()1369 bool Parser::ParseOperandVreg()
1370 {
1371     if (context_.err.err != Error::ErrorType::ERR_NONE) {
1372         return false;
1373     }
1374 
1375     if (*context_ != Token::Type::ID) {
1376         context_.err = GetError("Expected register.", Error::ErrorType::ERR_BAD_OPERAND, +1);
1377         return false;
1378     }
1379 
1380     std::string_view p = context_.GiveToken();
1381     if (p[0] == 'v') {
1382         p.remove_prefix(1);
1383         auto number = static_cast<int64_t>(ToNumber(p));
1384         if (number > *(context_.maxValueOfReg)) {
1385             *(context_.maxValueOfReg) = number;
1386         }
1387 
1388         currIns_->regs.push_back(static_cast<uint16_t>(number));
1389     } else if (p[0] == 'a') {
1390         p.remove_prefix(1);
1391         currIns_->regs.push_back(static_cast<uint16_t>(ToNumber(p)));
1392         context_.functionArgumentsList->emplace_back(context_.insNumber, currIns_->regs.size() - 1);
1393     }
1394 
1395     ++context_;
1396     return true;
1397 }
1398 
ParseOperandCall()1399 bool Parser::ParseOperandCall()
1400 {
1401     if (context_.err.err != Error::ErrorType::ERR_NONE) {
1402         return false;
1403     }
1404 
1405     if (!FunctionValidName()) {
1406         context_.err = GetError("Invalid name of function.", Error::ErrorType::ERR_BAD_NAME_REG);
1407         return false;
1408     }
1409 
1410     const auto p = std::string(context_.GiveToken().data(), context_.GiveToken().length());
1411     currIns_->ids.emplace_back(p);
1412 
1413     ++context_;
1414 
1415     std::string funcSignature {};
1416 
1417     if (!ParseOperandSignature(&funcSignature)) {
1418         return false;
1419     }
1420 
1421     if (funcSignature.empty()) {
1422         const auto itSynonym = program_.functionSynonyms.find(currIns_->ids.back());
1423         if (itSynonym == program_.functionSynonyms.end()) {
1424             [[maybe_unused]] auto it = ambiguousFunctionTable_.find({currIns_->ids.back(), false});
1425             ASSERT(it == ambiguousFunctionTable_.end() || !it->second.fileLocation->isDefined);
1426             AddObjectInTable(false, ambiguousFunctionTable_, currIns_->ids.back());
1427             return true;
1428         }
1429 
1430         if (itSynonym->second.size() > 1) {
1431             context_.err = GetError("Unable to resolve ambiguous function call",
1432                                     Error::ErrorType::ERR_FUNCTION_MULTIPLE_ALTERNATIVES);
1433             return false;
1434         }
1435     } else {
1436         currIns_->ids.back() += funcSignature;
1437         AddObjectInTable(false, ambiguousFunctionTable_, currIns_->ids.back());
1438     }
1439 
1440     return true;
1441 }
1442 
ParseOperandSignature(std::string * sign)1443 bool Parser::ParseOperandSignature(std::string *sign)
1444 {
1445     if (*context_ != Token::Type::DEL_COLON) {
1446         // no signature provided
1447         return true;
1448     }
1449 
1450     ++context_;
1451 
1452     if (*context_ != Token::Type::DEL_BRACKET_L) {
1453         context_.err = GetError("Expected \'(\' before signature", Error::ErrorType::ERR_BAD_SIGNATURE);
1454         return false;
1455     }
1456 
1457     ++context_;
1458 
1459     *sign += ":(";
1460 
1461     if (!ParseOperandSignatureTypesList(sign)) {
1462         return false;
1463     }
1464 
1465     if (*context_ != Token::Type::DEL_BRACKET_R) {
1466         context_.err = GetError("Expected \')\' at the end of the signature", Error::ErrorType::ERR_BAD_SIGNATURE);
1467         return false;
1468     }
1469 
1470     *sign += ")";
1471 
1472     ++context_;
1473 
1474     return true;
1475 }
1476 
ParseOperandSignatureTypesList(std::string * sign)1477 bool Parser::ParseOperandSignatureTypesList(std::string *sign)
1478 {
1479     bool comma = false;
1480 
1481     while (true) {
1482         if (context_.Mask()) {
1483             return true;
1484         }
1485 
1486         if (*context_ != Token::Type::DEL_COMMA && *context_ != Token::Type::ID) {
1487             break;
1488         }
1489 
1490         if (comma) {
1491             *sign += ",";
1492         }
1493 
1494         if (!ParseFunctionArgComma(comma)) {
1495             return false;
1496         }
1497 
1498         if (*context_ != Token::Type::ID) {
1499             context_.err = GetError("Expected signature arguments", Error::ErrorType::ERR_BAD_SIGNATURE_PARAMETERS);
1500             return false;
1501         }
1502 
1503         if (!TypeValidName()) {
1504             context_.err = GetError("Expected valid type", Error::ErrorType::ERR_BAD_TYPE);
1505             return false;
1506         }
1507 
1508         Type type;
1509         if (!ParseType(&type)) {
1510             return false;
1511         }
1512 
1513         *sign += type.GetName();
1514     }
1515 
1516     return true;
1517 }
1518 
IsOctal(char c)1519 static bool IsOctal(char c)
1520 {
1521     return c >= '0' && c <= '7';
1522 }
1523 
IsHex(char c)1524 static bool IsHex(char c)
1525 {
1526     return std::isxdigit(c) != 0;
1527 }
1528 
FromHex(char c)1529 static uint8_t FromHex(char c)
1530 {
1531     constexpr size_t DIGIT_NUM = 10;
1532 
1533     if (c >= '0' && c <= '9') {
1534         return c - '0';
1535     }
1536 
1537     if (c >= 'A' && c <= 'F') {
1538         return c - 'A' + DIGIT_NUM;
1539     }
1540 
1541     return c - 'a' + DIGIT_NUM;
1542 }
1543 
FromOctal(char c)1544 static uint8_t FromOctal(char c)
1545 {
1546     return c - '0';
1547 }
1548 
ParseOctalEscapeSequence(std::string_view s,size_t * i)1549 Expected<char, Error> Parser::ParseOctalEscapeSequence(std::string_view s, size_t *i)
1550 {
1551     constexpr size_t OCT_SHIFT = 3;
1552 
1553     size_t idx = *i;
1554     size_t n = 0;
1555     uint32_t r = 0;
1556 
1557     while (idx < s.length() && IsOctal(s[idx]) && n < OCT_SHIFT) {
1558         r |= FromOctal(s[idx++]);
1559         r <<= 3U;
1560         ++n;
1561     }
1562 
1563     r >>= 3U;
1564     *i += n;
1565 
1566     return r;
1567 }
1568 
ParseHexEscapeSequence(std::string_view s,size_t * i)1569 Expected<char, Error> Parser::ParseHexEscapeSequence(std::string_view s, size_t *i)
1570 {
1571     constexpr size_t HEX_SHIFT = 2;
1572 
1573     uint32_t r = 0;
1574     size_t idx = *i;
1575 
1576     for (size_t j = 0; j < HEX_SHIFT; j++) {
1577         char v = s[(*i)++];
1578 
1579         if (!IsHex(v)) {
1580             return Unexpected(GetError("Invalid \\x escape sequence",
1581                                        Error::ErrorType::ERR_BAD_STRING_INVALID_HEX_ESCAPE_SEQUENCE, idx - HEX_SHIFT));
1582         }
1583 
1584         r |= FromHex(v);
1585         r <<= 4U;
1586     }
1587 
1588     r >>= 4U;
1589 
1590     return r;
1591 }
1592 
ParseEscapeSequence(std::string_view s,size_t * i)1593 Expected<char, Error> Parser::ParseEscapeSequence(std::string_view s, size_t *i)
1594 {
1595     size_t idx = *i;
1596 
1597     char c = s[idx];
1598 
1599     if (IsOctal(c)) {
1600         return ParseOctalEscapeSequence(s, i);
1601     }
1602 
1603     ++(*i);
1604 
1605     switch (c) {
1606         case '\'':
1607         case '"':
1608         case '\\':
1609             return c;
1610         case 'a':
1611             return '\a';
1612         case 'b':
1613             return '\b';
1614         case 'f':
1615             return '\f';
1616         case 'n':
1617             return '\n';
1618         case 'r':
1619             return '\r';
1620         case 't':
1621             return '\t';
1622         case 'v':
1623             return '\v';
1624         default:
1625             break;
1626     }
1627 
1628     if (c == 'x') {
1629         return ParseHexEscapeSequence(s, i);
1630     }
1631 
1632     return Unexpected(
1633         GetError("Unknown escape sequence", Error::ErrorType::ERR_BAD_STRING_UNKNOWN_ESCAPE_SEQUENCE, idx - 1));
1634 }
1635 
ParseStringLiteral()1636 std::optional<std::string> Parser::ParseStringLiteral()
1637 {
1638     auto token = context_.GiveToken();
1639     if (*context_ != Token::Type::ID_STRING) {
1640         context_.err = GetError("Expected string literal", Error::ErrorType::ERR_BAD_OPERAND);
1641         return {};
1642     }
1643 
1644     size_t i = 1; /* skip leading quote */
1645     size_t len = token.length();
1646 
1647     std::string s;
1648 
1649     while (i < len - 1) {
1650         char c = token[i++];
1651 
1652         if (c != '\\') {
1653             s.append(1, c);
1654             continue;
1655         }
1656 
1657         auto res = ParseEscapeSequence(token, &i);
1658         if (!res) {
1659             context_.err = res.Error();
1660             return {};
1661         }
1662 
1663         s.append(1, res.Value());
1664     }
1665 
1666     program_.strings.insert(s);
1667 
1668     return s;
1669 }
1670 
ParseOperandString()1671 bool Parser::ParseOperandString()
1672 {
1673     if (context_.err.err != Error::ErrorType::ERR_NONE) {
1674         return false;
1675     }
1676 
1677     auto res = ParseStringLiteral();
1678     if (!res) {
1679         return false;
1680     }
1681 
1682     currIns_->ids.push_back(res.value());
1683 
1684     ++context_;
1685 
1686     return true;
1687 }
1688 
ParseOperandComma()1689 bool Parser::ParseOperandComma()
1690 {
1691     if (context_.err.err != Error::ErrorType::ERR_NONE) {
1692         return false;
1693     }
1694 
1695     if (context_++ != Token::Type::DEL_COMMA) {
1696         if (!context_.Mask() && *context_ != Token::Type::DEL_BRACKET_R) {
1697             --context_;
1698         }
1699 
1700         context_.err = GetError("Expected comma.", Error::ErrorType::ERR_BAD_NUMBER_OPERANDS);
1701         return false;
1702     }
1703 
1704     return true;
1705 }
1706 
ParseInteger(int64_t * value)1707 bool Parser::ParseInteger(int64_t *value)
1708 {
1709     if (context_.err.err != Error::ErrorType::ERR_NONE) {
1710         return false;
1711     }
1712 
1713     if (*context_ != Token::Type::ID) {
1714         if (*context_ == Token::Type::DEL_BRACE_R) {
1715             --context_;
1716         }
1717         context_.err = GetError("Expected immediate.", Error::ErrorType::ERR_BAD_OPERAND, +1);
1718         return false;
1719     }
1720 
1721     std::string_view p = context_.GiveToken();
1722     if (!ValidateInteger(p)) {
1723         context_.err = GetError("Expected integer.", Error::ErrorType::ERR_BAD_INTEGER_NAME);
1724         return false;
1725     }
1726 
1727     *value = IntegerNumber(p);
1728     if (errno == ERANGE) {
1729         context_.err =
1730             GetError("Too large immediate (length is more than 64 bit).", Error::ErrorType::ERR_BAD_INTEGER_WIDTH);
1731         return false;
1732     }
1733 
1734     return true;
1735 }
1736 
ParseFloat(double * value,bool is64bit)1737 bool Parser::ParseFloat(double *value, bool is64bit)
1738 {
1739     if (context_.err.err != Error::ErrorType::ERR_NONE) {
1740         return false;
1741     }
1742 
1743     if (*context_ != Token::Type::ID) {
1744         if (*context_ == Token::Type::DEL_BRACE_R) {
1745             --context_;
1746         }
1747         context_.err = GetError("Expected immediate.", Error::ErrorType::ERR_BAD_OPERAND, +1);
1748         return false;
1749     }
1750 
1751     std::string_view p = context_.GiveToken();
1752     if (!ValidateFloat(p)) {
1753         context_.err = GetError("Expected float.", Error::ErrorType::ERR_BAD_FLOAT_NAME);
1754         return false;
1755     }
1756 
1757     *value = FloatNumber(p, is64bit);
1758     if (errno == ERANGE) {
1759         context_.err =
1760             GetError("Too large immediate (length is more than 64 bit).", Error::ErrorType::ERR_BAD_FLOAT_WIDTH);
1761         return false;
1762     }
1763 
1764     return true;
1765 }
1766 
ParseOperandInteger()1767 bool Parser::ParseOperandInteger()
1768 {
1769     int64_t n;
1770     if (!ParseInteger(&n)) {
1771         return false;
1772     }
1773 
1774     currIns_->imms.emplace_back(n);
1775     ++context_;
1776     return true;
1777 }
1778 
ParseOperandFloat(bool is64bit)1779 bool Parser::ParseOperandFloat(bool is64bit)
1780 {
1781     double n;
1782     if (!ParseFloat(&n, is64bit)) {
1783         return false;
1784     }
1785 
1786     currIns_->imms.emplace_back(n);
1787     ++context_;
1788     return true;
1789 }
1790 
ParseOperandLabel()1791 bool Parser::ParseOperandLabel()
1792 {
1793     if (context_.err.err != Error::ErrorType::ERR_NONE) {
1794         return false;
1795     }
1796 
1797     if (!LabelValidName()) {
1798         context_.err = GetError("Invalid name of Label.", Error::ErrorType::ERR_BAD_NAME_ID);
1799         return false;
1800     }
1801 
1802     std::string_view p = context_.GiveToken();
1803     currIns_->ids.emplace_back(p.data(), p.length());
1804     AddObjectInTable(false, *labelTable_);
1805 
1806     ++context_;
1807 
1808     return true;
1809 }
1810 
ParseOperandId()1811 bool Parser::ParseOperandId()
1812 {
1813     if (context_.err.err != Error::ErrorType::ERR_NONE) {
1814         return false;
1815     }
1816 
1817     if (*context_ != Token::Type::ID) {
1818         context_.err = GetError("Expected Label.", Error::ErrorType::ERR_BAD_OPERAND);
1819         return false;
1820     }
1821     if (!LabelValidName()) {
1822         context_.err = GetError("Invalid name of Label.", Error::ErrorType::ERR_BAD_NAME_ID);
1823         return false;
1824     }
1825 
1826     std::string_view p = context_.GiveToken();
1827     currIns_->ids.emplace_back(p.data(), p.length());
1828     AddObjectInTable(false, *labelTable_);
1829 
1830     ++context_;
1831 
1832     return true;
1833 }
1834 
ParseOperandType(Type::VerificationType verType)1835 bool Parser::ParseOperandType(Type::VerificationType verType)
1836 {
1837     if (context_.err.err != Error::ErrorType::ERR_NONE) {
1838         return false;
1839     }
1840 
1841     if (*context_ != Token::Type::ID) {
1842         context_.err = GetError("Expected type.", Error::ErrorType::ERR_BAD_OPERAND);
1843         return false;
1844     }
1845     if (!TypeValidName()) {
1846         context_.err = GetError("Invalid name of type.", Error::ErrorType::ERR_BAD_NAME_ID);
1847         return false;
1848     }
1849 
1850     Type type;
1851     if (!ParseType(&type)) {
1852         return false;
1853     }
1854 
1855     bool isObject = context_.GiveToken() != "]";
1856     if (isObject) {
1857         AddObjectInTable(false, program_.recordTable);
1858 
1859         if (verType == Type::VerificationType::TYPE_ID_ARRAY) {
1860             GetWarning("Unexpected type_id recieved! Expected array, but object given",
1861                        Error::ErrorType::WAR_UNEXPECTED_TYPE_ID);
1862         }
1863     } else {
1864         if (!type.IsArrayContainsPrimTypes() &&
1865             program_.recordTable.find(type.GetComponentName()) == program_.recordTable.end()) {
1866             std::string componentName = type.GetComponentName();
1867             context_.token = componentName;
1868             AddObjectInTable(false, program_.recordTable);
1869         }
1870 
1871         if (verType == Type::VerificationType::TYPE_ID_OBJECT) {
1872             GetWarning("Unexpected type_id recieved! Expected object, but array given",
1873                        Error::ErrorType::WAR_UNEXPECTED_TYPE_ID);
1874         }
1875     }
1876 
1877     currIns_->ids.push_back(type.GetName());
1878 
1879     return true;
1880 }
1881 
ParseOperandLiteralArray()1882 bool Parser::ParseOperandLiteralArray()
1883 {
1884     if (context_.err.err != Error::ErrorType::ERR_NONE) {
1885         return false;
1886     }
1887     if (*context_ != Token::Type::ID) {
1888         context_.err = GetError("Expected array id.", Error::ErrorType::ERR_BAD_OPERAND);
1889         return false;
1890     }
1891     if (!ArrayValidName()) {
1892         context_.err = GetError("Invalid name of array.", Error::ErrorType::ERR_BAD_NAME_ID);
1893         return false;
1894     }
1895 
1896     std::string_view p = context_.GiveToken();
1897     auto arrayId = std::string(p.data(), p.length());
1898     if (program_.literalarrayTable.find(arrayId) == program_.literalarrayTable.end()) {
1899         context_.err = GetError("No array was found for this array id", Error::ErrorType::ERR_BAD_ID_ARRAY);
1900         return false;
1901     }
1902 
1903     currIns_->ids.emplace_back(p.data(), p.length());
1904 
1905     ++context_;
1906 
1907     return true;
1908 }
1909 
ParseOperandField()1910 bool Parser::ParseOperandField()
1911 {
1912     if (context_.err.err != Error::ErrorType::ERR_NONE) {
1913         return false;
1914     }
1915 
1916     if (*context_ != Token::Type::ID) {
1917         context_.err = GetError("Expected field.", Error::ErrorType::ERR_BAD_OPERAND);
1918         return false;
1919     }
1920     if (!PrefixedValidName()) {
1921         context_.err = GetError("Invalid name of field.", Error::ErrorType::ERR_BAD_NAME_ID);
1922         return false;
1923     }
1924 
1925     std::string_view p = context_.GiveToken();
1926     std::string recordFullName = std::string(p);
1927     // Some names of records in pandastdlib starts with 'panda.', therefore,
1928     // the record name is before the second dot, and the field name is after the second dot
1929     auto posPoint = recordFullName.find_last_of('.');
1930     std::string recordName = recordFullName.substr(0, posPoint);
1931     std::string fieldName = recordFullName.substr(posPoint + 1);
1932 
1933     auto itRecord = program_.recordTable.find(recordName);
1934     if (itRecord == program_.recordTable.end()) {
1935         context_.token = recordName;
1936         AddObjectInTable(false, program_.recordTable);
1937         itRecord = program_.recordTable.find(recordName);
1938     }
1939 
1940     auto isStatic = currIns_->HasFlag(InstFlags::STATIC_FIELD_ID);
1941     auto itField = std::find_if(
1942         itRecord->second.fieldList.begin(), itRecord->second.fieldList.end(),
1943         [&fieldName, &isStatic](const pandasm::Field &field) { return IsSameField(field, fieldName, isStatic); });
1944     if (!fieldName.empty() && itField == itRecord->second.fieldList.end()) {
1945         itRecord->second.fieldList.emplace_back(program_.lang);
1946         auto &field = itRecord->second.fieldList.back();
1947         field.name = fieldName;
1948         field.lineOfDef = lineStric_;
1949         field.wholeLine = context_.tokens[context_.number - 1].wholeLine;
1950         field.boundLeft = context_.tokens[context_.number - 1].boundLeft + recordName.length() + 1;
1951         field.boundRight = context_.tokens[context_.number - 1].boundRight;
1952         field.isDefined = false;
1953         if (isStatic) {
1954             field.metadata->SetAccessFlags(ACC_STATIC);
1955         }
1956     }
1957 
1958     currIns_->ids.emplace_back(p.data(), p.length());
1959 
1960     ++context_;
1961 
1962     return true;
1963 }
1964 
ParseOperandNone()1965 bool Parser::ParseOperandNone()
1966 {
1967     if (context_.err.err != Error::ErrorType::ERR_NONE) {
1968         return false;
1969     }
1970 
1971     if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
1972         return false;
1973     }
1974 
1975     if (!context_.Mask()) {
1976         context_.err = GetError("Invalid number of operands.", Error::ErrorType::ERR_BAD_NUMBER_OPERANDS);
1977         --context_;
1978         return false;
1979     }
1980     return true;
1981 }
1982 
ParseRecordFullSign()1983 bool Parser::ParseRecordFullSign()
1984 {
1985     return ParseRecordName();
1986 }
1987 
ParseFunctionFullSign()1988 bool Parser::ParseFunctionFullSign()
1989 {
1990     if (!ParseFunctionReturn()) {
1991         return false;
1992     }
1993 
1994     if (!ParseFunctionName()) {
1995         return false;
1996     }
1997 
1998     if (*context_ == Token::Type::DEL_BRACKET_L) {
1999         ++context_;
2000 
2001         if (ParseFunctionArgs()) {
2002             if (*context_ == Token::Type::DEL_BRACKET_R) {
2003                 ++context_;
2004                 return UpdateFunctionName();
2005             }
2006             context_.err = GetError("Expected ')'.", Error::ErrorType::ERR_BAD_ARGS_BOUND);
2007         }
2008     } else {
2009         context_.err = GetError("Expected '('.", Error::ErrorType::ERR_BAD_ARGS_BOUND);
2010     }
2011 
2012     return false;
2013 }
2014 
UpdateFunctionName()2015 bool Parser::UpdateFunctionName()
2016 {
2017     auto signature = GetFunctionSignatureFromName(currFunc_->name, currFunc_->params);
2018     auto iter = ambiguousFunctionTable_.find({signature, false});
2019     if (iter == ambiguousFunctionTable_.end()) {
2020         program_.functionSynonyms[currFunc_->name].push_back(signature);
2021 
2022         auto nodeHandle = ambiguousFunctionTable_.extract({currFunc_->name, false});
2023         nodeHandle.key() = {signature, false};
2024         ambiguousFunctionTable_.insert(std::move(nodeHandle));
2025     } else if (!iter->second.fileLocation->isDefined) {
2026         program_.functionSynonyms[currFunc_->name].push_back(signature);
2027 
2028         ambiguousFunctionTable_.erase({signature, false});
2029         auto nodeHandle = ambiguousFunctionTable_.extract({currFunc_->name, false});
2030         nodeHandle.key() = {signature, false};
2031         ambiguousFunctionTable_.insert(std::move(nodeHandle));
2032     } else {
2033         iter = ambiguousFunctionTable_.find({signature, true});
2034         if (iter == ambiguousFunctionTable_.end()) {
2035             auto nodeHandle = ambiguousFunctionTable_.extract({currFunc_->name, false});
2036             nodeHandle.key() = {signature, true};
2037             ambiguousFunctionTable_.insert(std::move(nodeHandle));
2038         } else {
2039             ASSERT(iter->second.fileLocation->isDefined);
2040             context_.err = GetError("This function already exists.", Error::ErrorType::ERR_BAD_ID_FUNCTION);
2041             return false;
2042         }
2043     }
2044 
2045     currFunc_->name = signature;
2046     context_.maxValueOfReg = &(currFunc_->valueOfFirstParam);
2047     context_.functionArgumentsList = &(context_.functionArgumentsLists[currFunc_->name]);
2048 
2049     return true;
2050 }
2051 
ParseArrayFullSign()2052 bool Parser::ParseArrayFullSign()
2053 {
2054     if (!ParseArrayName()) {
2055         return false;
2056     }
2057 
2058     if (*context_ == Token::Type::DEL_BRACE_L) {
2059         isConstArray_ = false;
2060         return true;
2061     }
2062 
2063     isConstArray_ = true;
2064 
2065     currArray_->literals.emplace_back();
2066     currArrayElem_ = &(currArray_->literals[currArray_->literals.size() - 1]);
2067 
2068     if (!ParseArrayElementType()) {
2069         context_.err = GetError("Invalid array type for static array.", Error::ErrorType::ERR_BAD_ARRAY_TYPE);
2070         return false;
2071     }
2072 
2073     currArrayElem_->value = static_cast<uint8_t>(currArrayElem_->tag);
2074     currArrayElem_->tag = panda_file::LiteralTag::TAGVALUE;
2075 
2076     if (*context_ == Token::Type::DEL_BRACE_L) {
2077         context_.err = GetError("No array size for static array.", Error::ErrorType::ERR_BAD_ARRAY_SIZE);
2078         return false;
2079     }
2080 
2081     currArray_->literals.emplace_back();
2082     currArrayElem_ = &(currArray_->literals[currArray_->literals.size() - 1]);
2083     currArrayElem_->tag = panda_file::LiteralTag::INTEGER;
2084 
2085     if (!ParseArrayElementValueInteger()) {
2086         context_.err =
2087             GetError("Invalid value for static array size value.", Error::ErrorType::ERR_BAD_ARRAY_SIZE_VALUE);
2088         return false;
2089     }
2090 
2091     ++context_;
2092 
2093     return true;
2094 }
2095 
ParseRecordName()2096 bool Parser::ParseRecordName()
2097 {
2098     LOG(DEBUG, ASSEMBLER) << "started searching for record name (line " << lineStric_
2099                           << "): " << context_.tokens[context_.number - 1].wholeLine;
2100 
2101     if (!RecordValidName()) {
2102         if (*context_ == Token::Type::DEL_BRACKET_L) {
2103             context_.err = GetError("No record name.", Error::ErrorType::ERR_BAD_RECORD_NAME);
2104             return false;
2105         }
2106         context_.err = GetError("Invalid name of the record.", Error::ErrorType::ERR_BAD_RECORD_NAME);
2107         return false;
2108     }
2109 
2110     auto recordName = std::string(context_.GiveToken());
2111     context_++;
2112     if (*context_ == Token::Type::DEL_SQUARE_BRACKET_L) {
2113         auto dim = ParseMultiArrayHallmark();
2114         if (context_.err.err != Error::ErrorType::ERR_NONE) {
2115             return false;
2116         }
2117         for (uint8_t i = 0; i < dim; i++) {
2118             recordName += "[]";
2119         }
2120     }
2121     if (!context_.Mask()) {
2122         context_--;
2123     }
2124 
2125     auto iter = program_.recordTable.find(recordName);
2126     if (iter == program_.recordTable.end() || !iter->second.fileLocation->isDefined) {
2127         SetRecordInformation(recordName);
2128     } else {
2129         context_.err = GetError("This record already exists.", Error::ErrorType::ERR_BAD_ID_RECORD);
2130         return false;
2131     }
2132 
2133     LOG(DEBUG, ASSEMBLER) << "record name found (line " << lineStric_ << "): " << context_.GiveToken();
2134 
2135     ++context_;
2136 
2137     return true;
2138 }
2139 
SetRecordInformation(const std::string & recordName)2140 void Parser::SetRecordInformation(const std::string &recordName)
2141 {
2142     AddObjectInTable(true, program_.recordTable, recordName);
2143     currRecord_ = &(program_.recordTable.at(recordName));
2144 }
2145 
ParseFunctionName()2146 bool Parser::ParseFunctionName()
2147 {
2148     LOG(DEBUG, ASSEMBLER) << "started searching for function name (line " << lineStric_
2149                           << "): " << context_.tokens[context_.number - 1].wholeLine;
2150 
2151     if (!FunctionValidName()) {
2152         if (*context_ == Token::Type::DEL_BRACKET_L) {
2153             context_.err = GetError("No function name.", Error::ErrorType::ERR_BAD_FUNCTION_NAME);
2154             return false;
2155         }
2156         context_.err = GetError("Invalid name of the function.", Error::ErrorType::ERR_BAD_FUNCTION_NAME);
2157         return false;
2158     }
2159 
2160     // names are mangled, so no need to check for same names here
2161     SetFunctionInformation();
2162     if (context_.err.err != Error::ErrorType::ERR_NONE) {
2163         return false;
2164     }
2165 
2166     LOG(DEBUG, ASSEMBLER) << "function name found (line " << lineStric_ << "): " << context_.GiveToken();
2167 
2168     ++context_;
2169 
2170     return true;
2171 }
2172 
SetFunctionInformation()2173 void Parser::SetFunctionInformation()
2174 {
2175     auto funcName = std::string(context_.GiveToken());
2176 
2177     context_++;
2178     if (*context_ == Token::Type::DEL_SQUARE_BRACKET_L || context_.Mask()) {
2179         auto dim = ParseMultiArrayHallmark();
2180         for (uint8_t i = 0; i < dim; i++) {
2181             funcName += "[]";
2182         }
2183         if (context_.GiveToken() == ".ctor") {
2184             funcName += ".ctor";
2185             AddObjectInTable(true, ambiguousFunctionTable_, funcName);
2186         }
2187     } else {
2188         context_--;
2189         AddObjectInTable(true, ambiguousFunctionTable_);
2190     }
2191     currFunc_ = &(ambiguousFunctionTable_.at({funcName, false}));
2192     labelTable_ = &(currFunc_->labelTable);
2193     currFunc_->returnType = context_.currFuncReturnType;
2194 }
2195 
ParseArrayName()2196 bool Parser::ParseArrayName()
2197 {
2198     LOG(DEBUG, ASSEMBLER) << "started searching for array name (line " << lineStric_
2199                           << "): " << context_.tokens[context_.number - 1].wholeLine;
2200 
2201     if (!ArrayValidName()) {
2202         if (*context_ == Token::Type::DEL_BRACKET_L) {
2203             context_.err = GetError("No array name.", Error::ErrorType::ERR_BAD_ARRAY_NAME);
2204             return false;
2205         }
2206         context_.err = GetError("Invalid name of the array.", Error::ErrorType::ERR_BAD_ARRAY_NAME);
2207         return false;
2208     }
2209 
2210     auto iter =
2211         program_.literalarrayTable.find(std::string(context_.GiveToken().data(), context_.GiveToken().length()));
2212     if (iter == program_.literalarrayTable.end()) {
2213         SetArrayInformation();
2214     } else {
2215         context_.err = GetError("This array already exists.", Error::ErrorType::ERR_BAD_ID_ARRAY);
2216         return false;
2217     }
2218 
2219     LOG(DEBUG, ASSEMBLER) << "array id found (line " << lineStric_ << "): " << context_.GiveToken();
2220 
2221     ++context_;
2222 
2223     return true;
2224 }
2225 
SetArrayInformation()2226 void Parser::SetArrayInformation()
2227 {
2228     program_.literalarrayTable.try_emplace(std::string(context_.GiveToken().data(), context_.GiveToken().length()),
2229                                            ark::pandasm::LiteralArray());
2230 
2231     currArray_ =
2232         &(program_.literalarrayTable.at(std::string(context_.GiveToken().data(), context_.GiveToken().length())));
2233 }
2234 
SetOperationInformation()2235 void Parser::SetOperationInformation()
2236 {
2237     context_.insNumber = currFunc_->ins.size();
2238     auto &currDebug = currFunc_->ins.back().insDebug;
2239     currDebug.lineNumber = lineStric_;
2240     currDebug.wholeLine = context_.tokens[context_.number - 1].wholeLine;
2241     currDebug.boundLeft = context_.tokens[context_.number - 1].boundLeft;
2242     currDebug.boundRight = context_.tokens[context_.number - 1].boundRight;
2243 }
2244 
ParseFunctionReturn()2245 bool Parser::ParseFunctionReturn()
2246 {
2247     LOG(DEBUG, ASSEMBLER) << "started searching for return function value (line " << lineStric_
2248                           << "): " << context_.tokens[context_.number - 1].wholeLine;
2249 
2250     if (!TypeValidName()) {
2251         if (*context_ == Token::Type::DEL_BRACKET_L) {
2252             context_.err = GetError("No return type.", Error::ErrorType::ERR_BAD_FUNCTION_RETURN_VALUE);
2253             return false;
2254         }
2255         context_.err = GetError("Not a return type.", Error::ErrorType::ERR_BAD_FUNCTION_RETURN_VALUE);
2256         return false;
2257     }
2258 
2259     if (!ParseType(&context_.currFuncReturnType)) {
2260         return false;
2261     }
2262 
2263     LOG(DEBUG, ASSEMBLER) << "return type found (line " << lineStric_ << "): " << context_.GiveToken();
2264 
2265     return true;
2266 }
2267 
TypeValidName()2268 bool Parser::TypeValidName()
2269 {
2270     if (Type::GetId(context_.GiveToken()) != panda_file::Type::TypeId::REFERENCE) {
2271         return true;
2272     }
2273 
2274     return PrefixedValidName(BracketOptions::ALLOW_BRACKETS);
2275 }
2276 
ParseFunctionArg()2277 bool Parser::ParseFunctionArg()
2278 {
2279     if (*context_ != Token::Type::ID) {
2280         context_.err = GetError("Expected identifier.", Error::ErrorType::ERR_BAD_FUNCTION_PARAMETERS);
2281         return false;
2282     }
2283 
2284     if (!TypeValidName()) {
2285         context_.err = GetError("Expected parameter type.", Error::ErrorType::ERR_BAD_TYPE);
2286         return false;
2287     }
2288 
2289     Type type;
2290     if (!ParseType(&type)) {
2291         return false;
2292     }
2293 
2294     if (context_.Mask()) {
2295         return false;
2296     }
2297 
2298     if (*context_ != Token::Type::ID) {
2299         context_.err = GetError("Expected identifier.", Error::ErrorType::ERR_BAD_FUNCTION_PARAMETERS);
2300         return false;
2301     }
2302 
2303     if (!ParamValidName()) {
2304         context_.err = GetError("Incorrect name of parameter.", Error::ErrorType::ERR_BAD_PARAM_NAME);
2305         return false;
2306     }
2307 
2308     ++context_;
2309 
2310     Function::Parameter parameter(type, program_.lang);
2311     metadata_ = &parameter.GetOrCreateMetadata();
2312 
2313     if (*context_ == Token::Type::DEL_LT && !ParseMetaDef()) {
2314         return false;
2315     }
2316 
2317     currFunc_->params.push_back(std::move(parameter));
2318 
2319     return true;
2320 }
2321 
ParseFunctionArgComma(bool & comma)2322 bool Parser::ParseFunctionArgComma(bool &comma)
2323 {
2324     if (comma && *context_ != Token::Type::DEL_COMMA) {
2325         context_.err = GetError("Expected comma.", Error::ErrorType::ERR_BAD_NUMBER_OPERANDS);
2326         return false;
2327     }
2328 
2329     if (comma) {
2330         ++context_;
2331     }
2332 
2333     comma = true;
2334 
2335     return true;
2336 }
2337 
ParseFunctionArgs()2338 bool Parser::ParseFunctionArgs()
2339 {
2340     LOG(DEBUG, ASSEMBLER) << "started searching for function parameters (line " << lineStric_
2341                           << "): " << context_.tokens[context_.number - 1].wholeLine;
2342 
2343     bool comma = false;
2344 
2345     while (true) {
2346         if (context_.Mask()) {
2347             return false;
2348         }
2349 
2350         if (context_.id != Token::Type::DEL_COMMA && context_.id != Token::Type::ID) {
2351             break;
2352         }
2353 
2354         if (!ParseFunctionArgComma(comma)) {
2355             return false;
2356         }
2357 
2358         if (!ParseFunctionArg()) {
2359             return false;
2360         }
2361     }
2362 
2363     LOG(DEBUG, ASSEMBLER) << "parameters found (line " << lineStric_ << "): ";
2364 
2365     return true;
2366 }
2367 
ParseMetaDef()2368 bool Parser::ParseMetaDef()
2369 {
2370     LOG(DEBUG, ASSEMBLER) << "started searching for meta information (line " << lineStric_
2371                           << "): " << context_.tokens[context_.number - 1].wholeLine;
2372 
2373     bool flag = false;
2374 
2375     if (context_.Mask()) {
2376         return false;
2377     }
2378 
2379     if (*context_ == Token::Type::DEL_LT) {
2380         flag = true;
2381         ++context_;
2382     }
2383 
2384     if (!ParseMetaList(flag)) {
2385         return false;
2386     }
2387 
2388     if (!flag && *context_ == Token::Type::DEL_GT) {
2389         context_.err = GetError("Expected '<'.", Error::ErrorType::ERR_BAD_METADATA_BOUND);
2390         ++context_;
2391         return false;
2392     }
2393 
2394     LOG(DEBUG, ASSEMBLER) << "searching for meta information (line " << lineStric_ << ") is successful";
2395 
2396     if (flag && context_.err.err == Error::ErrorType::ERR_NONE) {
2397         ++context_;
2398     }
2399 
2400     return true;
2401 }
2402 
SetMetadataContextError(const Metadata::Error & err,bool hasValue)2403 void Parser::SetMetadataContextError(const Metadata::Error &err, bool hasValue)
2404 {
2405     constexpr int64_t NO_VALUE_OFF = -1;
2406     constexpr int64_t SPECIAL_OFF = -2;
2407     constexpr int64_t STANDARD_OFF = -3;
2408 
2409     switch (err.GetType()) {
2410         case Metadata::Error::Type::UNKNOWN_ATTRIBUTE: {
2411             context_.err = GetError(err.GetMessage(), Error::ErrorType::ERR_BAD_METADATA_UNKNOWN_ATTRIBUTE, 0,
2412                                     hasValue ? STANDARD_OFF : NO_VALUE_OFF);
2413             break;
2414         }
2415         case Metadata::Error::Type::MISSING_ATTRIBUTE: {
2416             context_.err = GetError(err.GetMessage(), Error::ErrorType::ERR_BAD_METADATA_MISSING_ATTRIBUTE);
2417             break;
2418         }
2419         case Metadata::Error::Type::MISSING_VALUE: {
2420             context_.err = GetError(err.GetMessage(), Error::ErrorType::ERR_BAD_METADATA_MISSING_VALUE);
2421             break;
2422         }
2423         case Metadata::Error::Type::UNEXPECTED_ATTRIBUTE: {
2424             context_.err = GetError(err.GetMessage(), Error::ErrorType::ERR_BAD_METADATA_UNEXPECTED_ATTRIBUTE, 0,
2425                                     hasValue ? STANDARD_OFF : NO_VALUE_OFF);
2426             break;
2427         }
2428         case Metadata::Error::Type::UNEXPECTED_VALUE: {
2429             context_.err =
2430                 GetError(err.GetMessage(), Error::ErrorType::ERR_BAD_METADATA_UNEXPECTED_VALUE, 0, SPECIAL_OFF);
2431             break;
2432         }
2433         case Metadata::Error::Type::INVALID_VALUE: {
2434             context_.err = GetError(err.GetMessage(), Error::ErrorType::ERR_BAD_METADATA_INVALID_VALUE, 0, -1);
2435             break;
2436         }
2437         case Metadata::Error::Type::MULTIPLE_ATTRIBUTE: {
2438             context_.err = GetError(err.GetMessage(), Error::ErrorType::ERR_BAD_METADATA_MULTIPLE_ATTRIBUTE, 0,
2439                                     hasValue ? STANDARD_OFF : NO_VALUE_OFF);
2440             break;
2441         }
2442         default: {
2443             UNREACHABLE();
2444         }
2445     }
2446 }
2447 
ParseMetaListComma(bool & comma,bool eq)2448 bool Parser::ParseMetaListComma(bool &comma, bool eq)
2449 {
2450     if (!eq && comma && *context_ != Token::Type::DEL_COMMA) {
2451         context_.err = GetError("Expected comma.", Error::ErrorType::ERR_BAD_NUMBER_OPERANDS);
2452         return false;
2453     }
2454 
2455     if (!eq && comma) {
2456         ++context_;
2457     }
2458 
2459     comma = true;
2460 
2461     return true;
2462 }
2463 
MeetExpMetaList(bool eq)2464 bool Parser::MeetExpMetaList(bool eq)
2465 {
2466     if (!eq && *context_ != Token::Type::ID) {
2467         context_.err = GetError("Expected identifier.", Error::ErrorType::ERR_BAD_DEFINITION_METADATA, +1);
2468         return false;
2469     }
2470 
2471     if (eq && *context_ != Token::Type::ID && *context_ != Token::Type::ID_STRING) {
2472         context_.err =
2473             GetError("Expected identifier or string literal.", Error::ErrorType::ERR_BAD_DEFINITION_METADATA, +1);
2474         return false;
2475     }
2476 
2477     if (!eq && !PrefixedValidName()) {
2478         context_.err = GetError("Invalid attribute name.", Error::ErrorType::ERR_BAD_NAME_ID);
2479         return false;
2480     }
2481 
2482     return true;
2483 }
2484 
BuildMetaListAttr(bool & eq,std::string & attributeName,std::string & attributeValue)2485 bool Parser::BuildMetaListAttr(bool &eq, std::string &attributeName, std::string &attributeValue)
2486 {
2487     if (eq && *context_ == Token::Type::ID_STRING) {
2488         auto res = ParseStringLiteral();
2489         if (!res) {
2490             return false;
2491         }
2492 
2493         attributeValue = res.value();
2494     } else if (eq) {
2495         std::string sign {};
2496         attributeValue = context_.GiveToken();
2497         ++context_;
2498 
2499         if (!ParseOperandSignature(&sign)) {
2500             return false;
2501         }
2502 
2503         --context_;
2504         attributeValue += sign;
2505     } else {
2506         attributeName = context_.GiveToken();
2507     }
2508 
2509     ++context_;
2510 
2511     if (context_.Mask()) {
2512         return false;
2513     }
2514 
2515     if (*context_ == Token::Type::DEL_EQ) {
2516         if (eq) {
2517             context_.err = GetError("'=' was not expected.", Error::ErrorType::ERR_BAD_NOEXP_DELIM);
2518             return false;
2519         }
2520 
2521         ++context_;
2522         eq = true;
2523     } else {
2524         std::optional<Metadata::Error> res;
2525         bool hasValue = eq;
2526         if (hasValue) {
2527             res = metadata_->SetAttributeValue(attributeName, attributeValue);
2528         } else {
2529             res = metadata_->SetAttribute(attributeName);
2530         }
2531 
2532         eq = false;
2533 
2534         if (res) {
2535             auto err = res.value();
2536             SetMetadataContextError(err, hasValue);
2537             return false;
2538         }
2539     }
2540 
2541     return true;
2542 }
2543 
ParseMetaList(bool flag)2544 bool Parser::ParseMetaList(bool flag)
2545 {
2546     if (!flag && !context_.Mask() && *context_ != Token::Type::DEL_GT && *context_ != Token::Type::DEL_BRACE_L) {
2547         context_.err = GetError("No meta data expected.", Error::ErrorType::ERR_BAD_DEFINITION_METADATA);
2548         return false;
2549     }
2550 
2551     bool comma = false;
2552     bool eq = false;
2553 
2554     std::string attributeName;
2555     std::string attributeValue;
2556 
2557     while (true) {
2558         if (context_.Mask()) {
2559             context_.err = GetError("Expected '>'.", Error::ErrorType::ERR_BAD_METADATA_BOUND, +1);
2560             return false;
2561         }
2562 
2563         if (context_.id != Token::Type::DEL_COMMA && context_.id != Token::Type::ID &&
2564             context_.id != Token::Type::ID_STRING && context_.id != Token::Type::DEL_EQ) {
2565             break;
2566         }
2567 
2568         if (!ParseMetaListComma(comma, eq)) {
2569             return false;
2570         }
2571 
2572         if (!MeetExpMetaList(eq)) {
2573             return false;
2574         }
2575 
2576         if (!BuildMetaListAttr(eq, attributeName, attributeValue)) {
2577             return false;
2578         }
2579     }
2580 
2581     if (flag && *context_ != Token::Type::DEL_GT) {
2582         context_.err = GetError("Expected '>'.", Error::ErrorType::ERR_BAD_METADATA_BOUND);
2583         ++context_;
2584 
2585         return false;
2586     }
2587 
2588     auto res = metadata_->ValidateData();
2589     if (res) {
2590         auto err = res.value();
2591         SetMetadataContextError(err, false);
2592         return false;
2593     }
2594 
2595     return true;
2596 }
2597 
ParseFunctionInstruction()2598 bool Parser::ParseFunctionInstruction()
2599 {
2600     if (ParseLabel()) {
2601         if (ParseOperation()) {
2602             if (ParseOperands()) {
2603                 return true;
2604             }
2605         }
2606     }
2607 
2608     return context_.Mask();
2609 }
2610 
GetFuncNameWithoutArgs(const std::string & fullName)2611 static std::string GetFuncNameWithoutArgs(const std::string &fullName)
2612 {
2613     auto pos = fullName.find(':');
2614     return fullName.substr(0, pos);
2615 }
2616 
ParseOperandInitobj()2617 bool Parser::ParseOperandInitobj()
2618 {
2619     if (context_.err.err != Error::ErrorType::ERR_NONE) {
2620         return false;
2621     }
2622 
2623     if (!FunctionValidName()) {
2624         context_.err = GetError("Invalid name of function.", Error::ErrorType::ERR_BAD_FUNCTION_NAME);
2625         return false;
2626     }
2627 
2628     auto cid = std::string(context_.GiveToken().data(), context_.GiveToken().length());
2629 
2630     context_++;
2631     if (*context_ == Token::Type::DEL_COMMA || *context_ == Token::Type::DEL_COLON || context_.Mask()) {
2632         if (!context_.Mask()) {
2633             context_--;
2634         }
2635         return ParseOperandCall();
2636     }
2637     auto dim = ParseMultiArrayHallmark();
2638     if (context_.err.err != Error::ErrorType::ERR_NONE) {
2639         return false;
2640     }
2641     if (dim < 2U) {
2642         context_.err = GetError("Invalid name of function.", Error::ErrorType::ERR_BAD_FUNCTION_NAME);
2643         return false;
2644     }
2645 
2646     for (uint8_t i = 0; i < dim; i++) {
2647         cid += "[]";
2648     }
2649 
2650     if (context_.GiveToken() == ".ctor") {
2651         cid += ".ctor";
2652         currIns_->ids.emplace_back(cid);
2653         bool findFuncInTable = false;
2654         for (const auto &[key, func] : ambiguousFunctionTable_) {
2655             if (GetFuncNameWithoutArgs(key.first) == cid) {
2656                 findFuncInTable = true;
2657                 break;
2658             }
2659         }
2660         if (!findFuncInTable) {
2661             AddObjectInTable(false, ambiguousFunctionTable_, cid);
2662         }
2663         context_++;
2664         return true;
2665     }
2666     return false;
2667 }
2668 
ParseMultiArrayHallmark()2669 uint8_t Parser::ParseMultiArrayHallmark()
2670 {
2671     uint8_t counter = 0;
2672     do {
2673         if (*context_ == Token::Type::DEL_SQUARE_BRACKET_L) {
2674             context_++;
2675             if (*context_ == Token::Type::DEL_SQUARE_BRACKET_R) {
2676                 context_++;
2677                 counter++;
2678             } else {
2679                 context_.err = GetError("] expected.", Error::ErrorType::ERR_BAD_FUNCTION_NAME);
2680                 return counter;
2681             }
2682         } else {
2683             context_.err = GetError("[ expected.", Error::ErrorType::ERR_BAD_FUNCTION_NAME);
2684             return counter;
2685         }
2686     } while (!context_.Mask() &&
2687              (*context_ == Token::Type::DEL_SQUARE_BRACKET_L || *context_ == Token::Type::DEL_SQUARE_BRACKET_R));
2688     return counter;
2689 }
2690 
2691 }  // namespace ark::pandasm
2692