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