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