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