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