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