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