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