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