1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <cctype>
17 #include <errno.h>
18
19 #include <iterator>
20
21 #include "assembly-type.h"
22 #include "ins_emit.h"
23 #include "modifiers.h"
24 #include "opcode_parsing.h"
25 #include "operand_types_print.h"
26 #include "utils/number-utils.h"
27
28 namespace panda::pandasm {
29
ParseRecordFields()30 bool Parser::ParseRecordFields()
31 {
32 if (!open_ && *context_ == Token::Type::DEL_BRACE_L) {
33 curr_record_->body_location.begin = GetCurrentPosition(false);
34 open_ = true;
35 ++context_;
36 }
37
38 curr_record_->body_presence = true;
39
40 if (!open_) {
41 context_.err = GetError("Expected keyword.", Error::ErrorType::ERR_BAD_KEYWORD);
42 return false;
43 }
44
45 if (context_.Mask()) {
46 return true;
47 }
48
49 if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
50 curr_record_->body_location.end = GetCurrentPosition(true);
51 ++context_;
52 open_ = false;
53 return true;
54 }
55
56 curr_record_->field_list.emplace_back(program_.lang);
57 curr_fld_ = &(curr_record_->field_list[curr_record_->field_list.size() - 1]);
58 curr_fld_->line_of_def = line_stric_;
59 context_.ins_number = curr_record_->field_list.size();
60
61 LOG(DEBUG, ASSEMBLER) << "parse line " << line_stric_ << " as field (.field name)";
62 if (!ParseRecordField()) {
63 if (context_.err.err != Error::ErrorType::ERR_NONE) {
64 return false;
65 }
66
67 if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
68 curr_record_->body_location.end = GetCurrentPosition(true);
69 ++context_;
70 open_ = false;
71 } else {
72 context_.err = GetError("Expected a new field on the next line.", Error::ErrorType::ERR_BAD_KEYWORD);
73 return false;
74 }
75 }
76
77 return true;
78 }
79
ParseFieldName()80 bool Parser::ParseFieldName()
81 {
82 if (PrefixedValidName()) {
83 std::string field_name = std::string(context_.GiveToken().data(), context_.GiveToken().length());
84
85 auto match_names = [&field_name](const pandasm::Field &f) { return field_name == f.name; };
86 const auto iter = std::find_if(curr_record_->field_list.begin(), curr_record_->field_list.end(), match_names);
87 if (iter != curr_record_->field_list.end()) {
88 if (iter->is_defined) {
89 context_.err =
90 GetError("Repeated field names in the same record.", Error::ErrorType::ERR_REPEATING_FIELD_NAME);
91 return false;
92 }
93
94 curr_record_->field_list.erase(iter);
95 }
96
97 curr_fld_ = &(curr_record_->field_list[curr_record_->field_list.size() - 1]);
98 curr_fld_->name = field_name;
99
100 ++context_;
101 return true;
102 }
103
104 context_.err = GetError("Invalid field name.", Error::ErrorType::ERR_BAD_OPERATION_NAME);
105
106 return false;
107 }
108
ParseType(Type * type)109 bool Parser::ParseType(Type *type)
110 {
111 ASSERT(TypeValidName());
112
113 std::string component_name(context_.GiveToken());
114 size_t rank = 0;
115
116 ++context_;
117
118 while (*context_ == Token::Type::DEL_SQUARE_BRACKET_L) {
119 ++context_;
120 if (*context_ != Token::Type::DEL_SQUARE_BRACKET_R) {
121 context_.err = GetError("Expected ']'.", Error::ErrorType::ERR_BAD_ARRAY_TYPE_BOUND);
122 return false;
123 }
124 ++context_;
125 ++rank;
126 }
127
128 *type = Type(component_name, rank);
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 for 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
ParseFunctionCode()185 bool Parser::ParseFunctionCode()
186 {
187 if (!open_ && *context_ == Token::Type::DEL_BRACE_L) {
188 open_ = true;
189 curr_func_->body_location.begin = GetCurrentPosition(false);
190 ++context_;
191 }
192
193 curr_func_->body_presence = true;
194
195 if (!open_) {
196 context_.err = GetError("Expected keyword.", Error::ErrorType::ERR_BAD_KEYWORD);
197 return false;
198 }
199
200 if (context_.Mask()) {
201 return true;
202 }
203
204 if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
205 curr_func_->body_location.end = GetCurrentPosition(true);
206 ++context_;
207 open_ = false;
208 return true;
209 }
210
211 curr_ins_ = &curr_func_->ins.emplace_back();
212
213 LOG(DEBUG, ASSEMBLER) << "parse line " << line_stric_
214 << " as instruction ([label:] operation [operand,] [# comment])";
215
216 ParseFunctionInstruction();
217
218 if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
219 curr_func_->body_location.end = GetCurrentPosition(true);
220 ++context_;
221 open_ = false;
222 }
223
224 return true;
225 }
226
ParseAsRecord(const std::vector<Token> & tokens)227 void Parser::ParseAsRecord(const std::vector<Token> &tokens)
228 {
229 LOG(DEBUG, ASSEMBLER) << "started parsing of record (line " << line_stric_ << "): " << tokens[0].whole_line;
230 func_def_ = false;
231 record_def_ = true;
232
233 if (!open_) {
234 ++context_;
235 } else {
236 context_.err =
237 GetError("No record can be defined inside another record.", Error::ErrorType::ERR_BAD_DEFINITION);
238 return;
239 }
240
241 if (ParseRecordFullSign()) {
242 metadata_ = curr_record_->metadata.get();
243 if (ParseMetaDef()) {
244 if (!open_ && *context_ == Token::Type::DEL_BRACE_L) {
245 curr_record_->body_location.begin = GetCurrentPosition(false);
246 ++context_;
247 open_ = true;
248
249 LOG(DEBUG, ASSEMBLER) << "record body is open, line " << line_stric_ << ": " << tokens[0].whole_line;
250 }
251
252 if (open_ && !context_.Mask() && *context_ != Token::Type::DEL_BRACE_R) {
253 ParseRecordFields();
254 } else if (open_) {
255 curr_record_->body_presence = true;
256 }
257
258 if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
259 LOG(DEBUG, ASSEMBLER) << "record body is closed, line " << line_stric_ << ": " << tokens[0].whole_line;
260
261 curr_record_->body_location.end = GetCurrentPosition(true);
262 ++context_;
263 open_ = false;
264 }
265 }
266 }
267 }
268
ParseAsFunction(const std::vector<Token> & tokens)269 void Parser::ParseAsFunction(const std::vector<Token> &tokens)
270 {
271 LOG(DEBUG, ASSEMBLER) << "started parsing of function (line " << line_stric_ << "): " << tokens[0].whole_line;
272 record_def_ = false;
273 func_def_ = true;
274
275 if (!open_) {
276 ++context_;
277 } else {
278 context_.err =
279 GetError("No one function can be defined inside another function.", Error::ErrorType::ERR_BAD_DEFINITION);
280 return;
281 }
282
283 if (ParseFunctionFullSign()) {
284 metadata_ = curr_func_->metadata.get();
285 if (ParseMetaDef()) {
286 if (!open_ && *context_ == Token::Type::DEL_BRACE_L) {
287 curr_func_->body_location.begin = GetCurrentPosition(false);
288 ++context_;
289 open_ = true;
290
291 LOG(DEBUG, ASSEMBLER) << "function body is open, line " << line_stric_ << ": " << tokens[0].whole_line;
292 }
293
294 if (open_ && !context_.Mask() && *context_ != Token::Type::DEL_BRACE_R) {
295 ParseFunctionCode();
296 } else if (open_) {
297 curr_func_->body_presence = true;
298 }
299
300 if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
301 LOG(DEBUG, ASSEMBLER) << "function body is closed, line " << line_stric_ << ": "
302 << tokens[0].whole_line;
303
304 curr_func_->body_location.end = GetCurrentPosition(true);
305 ++context_;
306 open_ = false;
307 }
308 }
309 }
310 }
311
ParseAsBraceRight(const std::vector<Token> & tokens)312 void Parser::ParseAsBraceRight(const std::vector<Token> &tokens)
313 {
314 if (!open_) {
315 context_.err =
316 GetError("Delimiter '}' for the code area is outside a function.", Error::ErrorType::ERR_BAD_BOUND);
317 return;
318 }
319
320 LOG(DEBUG, ASSEMBLER) << "body is closed (line " << line_stric_ << "): " << tokens[0].whole_line;
321
322 open_ = false;
323 if (func_def_) {
324 curr_func_->body_location.end = GetCurrentPosition(true);
325 } else if (record_def_) {
326 curr_record_->body_location.end = GetCurrentPosition(true);
327 } else {
328 LOG(FATAL, ASSEMBLER) << "Internal error: either function or record must be parsed here";
329 }
330 ++context_;
331 }
332
ParseResetFunctionLabelsAndParams()333 void Parser::ParseResetFunctionLabelsAndParams()
334 {
335 if (open_ || err_.err != Error::ErrorType::ERR_NONE) {
336 return;
337 }
338
339 for (const auto &f : program_.function_table) {
340 for (const auto &k : f.second.label_table) {
341 if (!k.second.file_location->is_defined) {
342 context_.err = Error("This label does not exist.", line_stric_, Error::ErrorType::ERR_BAD_LABEL_EXT, "",
343 k.second.file_location->bound_left, k.second.file_location->bound_right,
344 k.second.file_location->whole_line);
345 SetError();
346 }
347 }
348 }
349
350 for (const auto &t : context_.function_arguments_lists) {
351 curr_func_ = &(program_.function_table.at(t.first));
352 curr_func_->regs_num = static_cast<size_t>(curr_func_->value_of_first_param + 1);
353
354 for (const auto &v : t.second) {
355 if (!curr_func_->ins.empty() && curr_func_->ins.size() >= v.first &&
356 !curr_func_->ins[v.first - 1].regs.empty()) {
357 curr_func_->ins[v.first - 1].regs[v.second] +=
358 static_cast<uint16_t>(curr_func_->value_of_first_param + 1);
359 size_t max_reg_number = (1 << curr_func_->ins[v.first - 1].MaxRegEncodingWidth());
360 if (curr_func_->ins[v.first - 1].regs[v.second] >= max_reg_number) {
361 const auto &debug = curr_func_->ins[v.first - 1].ins_debug;
362 context_.err =
363 Error("Register width mismatch.", debug.line_number, Error::ErrorType::ERR_BAD_NAME_REG, "",
364 debug.bound_left, debug.bound_right, debug.whole_line);
365 SetError();
366 break;
367 }
368 }
369 }
370 }
371 }
372
ParseResetFunctionTable()373 void Parser::ParseResetFunctionTable()
374 {
375 for (const auto &k : program_.function_table) {
376 if (!k.second.file_location->is_defined) {
377 context_.err = Error("This function does not exist.", k.second.file_location->line_number,
378 Error::ErrorType::ERR_BAD_ID_FUNCTION, "", k.second.file_location->bound_left,
379 k.second.file_location->bound_right, k.second.file_location->whole_line);
380 SetError();
381 } else if (k.second.HasImplementation() != k.second.body_presence) {
382 context_.err =
383 Error("Inconsistent definition of the function and its metadata.", k.second.file_location->line_number,
384 Error::ErrorType::ERR_BAD_DEFINITION_FUNCTION, "", k.second.file_location->bound_left,
385 k.second.file_location->bound_right, k.second.file_location->whole_line);
386 SetError();
387 } else {
388 for (auto insn_it = k.second.ins.begin(); insn_it != k.second.ins.end(); ++insn_it) {
389 bool is_calli = insn_it->opcode == Opcode::CALLI_DYN || insn_it->opcode == Opcode::CALLI_DYN_SHORT ||
390 insn_it->opcode == Opcode::CALLI_DYN_RANGE;
391 if (is_calli || !insn_it->IsCall()) {
392 continue;
393 }
394
395 bool is_initobj = insn_it->opcode == Opcode::INITOBJ || insn_it->opcode == Opcode::INITOBJ_SHORT ||
396 insn_it->opcode == Opcode::INITOBJ_RANGE;
397 size_t diff = is_initobj ? 0 : 1;
398 if (insn_it->OperandListLength() - diff < program_.function_table.at(insn_it->ids[0]).GetParamsNum()) {
399 auto insn_idx = std::distance(k.second.ins.begin(), insn_it);
400 const auto &debug = curr_func_->ins[insn_idx].ins_debug;
401 context_.err = Error("Function argument mismatch.", debug.line_number,
402 Error::ErrorType::ERR_FUNCTION_ARGUMENT_MISMATCH, "", debug.bound_left,
403 debug.bound_right, debug.whole_line);
404 SetError();
405 }
406 }
407 }
408 }
409 }
410
ParseResetRecordTable()411 void Parser::ParseResetRecordTable()
412 {
413 for (const auto &k : program_.record_table) {
414 if (!k.second.file_location->is_defined) {
415 context_.err = Error("This record does not exist.", k.second.file_location->line_number,
416 Error::ErrorType::ERR_BAD_ID_RECORD, "", k.second.file_location->bound_left,
417 k.second.file_location->bound_right, k.second.file_location->whole_line);
418 SetError();
419 } else if (k.second.HasImplementation() != k.second.body_presence) {
420 context_.err = Error("Inconsistency of the definition of the record and its metadata.",
421 k.second.file_location->line_number, Error::ErrorType::ERR_BAD_DEFINITION_RECORD, "",
422 k.second.file_location->bound_left, k.second.file_location->bound_right,
423 k.second.file_location->whole_line);
424 SetError();
425 } else {
426 for (const auto &fld : k.second.field_list) {
427 if (!fld.is_defined) {
428 context_.err =
429 Error("This field does not exist.", fld.line_of_def, Error::ErrorType::ERR_BAD_ID_FIELD, "",
430 fld.bound_left, fld.bound_right, fld.whole_line);
431 SetError();
432 }
433 }
434 }
435 }
436 }
437
ParseResetTables()438 void Parser::ParseResetTables()
439 {
440 if (err_.err != Error::ErrorType::ERR_NONE) {
441 return;
442 }
443
444 ParseResetFunctionTable();
445
446 if (err_.err != Error::ErrorType::ERR_NONE) {
447 return;
448 }
449
450 ParseResetRecordTable();
451 }
452
ParseAsLanguageDirective()453 void Parser::ParseAsLanguageDirective()
454 {
455 ++context_;
456
457 if (context_.Mask()) {
458 context_.err = GetError("Incorrect .language directive: Expected language",
459 Error::ErrorType::ERR_BAD_DIRECTIVE_DECLARATION);
460 return;
461 }
462
463 auto lang = context_.GiveToken();
464 auto res = extensions::LanguageFromString(lang);
465 if (!res) {
466 context_.err =
467 GetError("Incorrect .language directive: Unknown language", Error::ErrorType::ERR_UNKNOWN_LANGUAGE);
468 return;
469 }
470
471 ++context_;
472
473 if (!context_.Mask()) {
474 context_.err = GetError("Incorrect .language directive: Unexpected token",
475 Error::ErrorType::ERR_BAD_DIRECTIVE_DECLARATION);
476 }
477
478 program_.lang = res.value();
479 }
480
PrepareCatchBlock(bool is_catchall,size_t size,size_t catchall_tokens_num,size_t catch_tokens_num)481 Function::CatchBlock Parser::PrepareCatchBlock(bool is_catchall, size_t size, size_t catchall_tokens_num,
482 size_t catch_tokens_num)
483 {
484 constexpr size_t TRY_BEGIN = 0;
485 constexpr size_t TRY_END = 1;
486 constexpr size_t CATCH_BEGIN = 2;
487 constexpr size_t CATCH_END = 3;
488
489 Function::CatchBlock catch_block;
490 catch_block.whole_line = context_.tokens[0].whole_line;
491 std::vector<std::string> label_names {"try block begin", "try block end", "catch block begin"};
492 std::vector<std::string> labels;
493 bool full_catch_block = (is_catchall && size == catchall_tokens_num) || (!is_catchall && size == catch_tokens_num);
494 if (full_catch_block) {
495 label_names.emplace_back("catch block end");
496 }
497 if (!is_catchall) {
498 catch_block.exception_record = context_.GiveToken();
499 ++context_;
500 }
501
502 bool skip_comma = is_catchall;
503 for (auto label_name : label_names) {
504 if (!skip_comma) {
505 if (*context_ != Token::Type::DEL_COMMA) {
506 context_.err = GetError("Expected comma.", Error::ErrorType::ERR_BAD_DIRECTIVE_DECLARATION);
507 return catch_block;
508 }
509 ++context_;
510 }
511 skip_comma = false;
512 if (!LabelValidName()) {
513 context_.err =
514 GetError(std::string("Invalid name of the ") + label_name + " label.", Error::ErrorType::ERR_BAD_LABEL);
515 return catch_block;
516 }
517 labels.emplace_back(context_.GiveToken());
518 AddObjectInTable(false, *label_table_);
519 ++context_;
520 }
521
522 ASSERT(context_.Mask());
523 catch_block.try_begin_label = labels[TRY_BEGIN];
524 catch_block.try_end_label = labels[TRY_END];
525 catch_block.catch_begin_label = labels[CATCH_BEGIN];
526 if (full_catch_block) {
527 catch_block.catch_end_label = labels[CATCH_END];
528 } else {
529 catch_block.catch_end_label = labels[CATCH_BEGIN];
530 }
531
532 return catch_block;
533 }
534
ParseAsCatchDirective()535 void Parser::ParseAsCatchDirective()
536 {
537 ASSERT(*context_ == Token::Type::ID_CATCH || *context_ == Token::Type::ID_CATCHALL);
538
539 constexpr size_t CATCH_DIRECTIVE_TOKENS_NUM = 8;
540 constexpr size_t CATCHALL_DIRECTIVE_TOKENS_NUM = 6;
541 constexpr size_t CATCH_FULL_DIRECTIVE_TOKENS_NUM = 10;
542 constexpr size_t CATCHALL_FULL_DIRECTIVE_TOKENS_NUM = 8;
543
544 bool is_catchall = *context_ == Token::Type::ID_CATCHALL;
545 size_t size = context_.tokens.size();
546 if (is_catchall && size != CATCHALL_DIRECTIVE_TOKENS_NUM && size != CATCHALL_FULL_DIRECTIVE_TOKENS_NUM) {
547 context_.err = GetError(
548 "Incorrect catch block declaration. Must be in the format: .catchall <try_begin_label>, <try_end_label>, "
549 "<catch_begin_label>[, <catch_end_label>]",
550 Error::ErrorType::ERR_BAD_DIRECTIVE_DECLARATION);
551 return;
552 }
553
554 if (!is_catchall && size != CATCH_DIRECTIVE_TOKENS_NUM && size != CATCH_FULL_DIRECTIVE_TOKENS_NUM) {
555 context_.err = GetError(
556 "Incorrect catch block declaration. Must be in the format: .catch <exception_record>, <try_begin_label>, "
557 "<try_end_label>, <catch_begin_label>[, <catch_end_label>]",
558 Error::ErrorType::ERR_BAD_DIRECTIVE_DECLARATION);
559 return;
560 }
561
562 ++context_;
563
564 if (!is_catchall && !RecordValidName()) {
565 context_.err = GetError("Invalid name of the exception record.", Error::ErrorType::ERR_BAD_RECORD_NAME);
566 return;
567 }
568
569 Function::CatchBlock catch_block =
570 PrepareCatchBlock(is_catchall, size, CATCHALL_FULL_DIRECTIVE_TOKENS_NUM, CATCH_FULL_DIRECTIVE_TOKENS_NUM);
571
572 curr_func_->catch_blocks.push_back(catch_block);
573 }
574
ParseAsCatchall(const std::vector<Token> & tokens)575 void Parser::ParseAsCatchall(const std::vector<Token> &tokens)
576 {
577 std::string directive_name = *context_ == Token::Type::ID_CATCH ? ".catch" : ".catchall";
578 if (!func_def_) {
579 context_.err = GetError(directive_name + " directive is outside a function body.",
580 Error::ErrorType::ERR_INCORRECT_DIRECTIVE_LOCATION);
581 return;
582 }
583
584 LOG(DEBUG, ASSEMBLER) << "started parsing of " << directive_name << " directive (line " << line_stric_
585 << "): " << tokens[0].whole_line;
586
587 ParseAsCatchDirective();
588 }
589
ParseAsLanguage(const std::vector<Token> & tokens,bool & is_lang_parsed,bool & is_first_statement)590 void Parser::ParseAsLanguage(const std::vector<Token> &tokens, bool &is_lang_parsed, bool &is_first_statement)
591 {
592 if (is_lang_parsed) {
593 context_.err = GetError("Multiple .language directives", Error::ErrorType::ERR_MULTIPLE_DIRECTIVES);
594 return;
595 }
596
597 if (!is_first_statement) {
598 context_.err = GetError(".language directive must be specified before any other declarations",
599 Error::ErrorType::ERR_INCORRECT_DIRECTIVE_LOCATION);
600 return;
601 }
602
603 LOG(DEBUG, ASSEMBLER) << "started parsing of .language directive (line " << line_stric_
604 << "): " << tokens[0].whole_line;
605
606 ParseAsLanguageDirective();
607
608 is_lang_parsed = true;
609 }
610
ParseAfterLine(bool & is_first_statement)611 bool Parser::ParseAfterLine(bool &is_first_statement)
612 {
613 SetError();
614
615 if (!context_.Mask() && err_.err == Error::ErrorType::ERR_NONE) {
616 context_.err = GetError("There should be nothing after.", Error::ErrorType::ERR_BAD_END);
617 }
618
619 if (err_.err != Error::ErrorType::ERR_NONE) {
620 LOG(DEBUG, ASSEMBLER) << "processing aborted (error detected)";
621 return false;
622 }
623
624 LOG(DEBUG, ASSEMBLER) << "parsing of line " << line_stric_ << " is successful";
625
626 SetError();
627
628 is_first_statement = false;
629
630 return true;
631 }
632
ParseAfterMainLoop(const std::string & file_name)633 Expected<Program, Error> Parser::ParseAfterMainLoop(const std::string &file_name)
634 {
635 ParseResetFunctionLabelsAndParams();
636
637 if (open_ && err_.err == Error::ErrorType::ERR_NONE) {
638 context_.err = Error("Code area is not closed.", curr_func_->file_location->line_number,
639 Error::ErrorType::ERR_BAD_CLOSE, "", 0, curr_func_->name.size(), curr_func_->name);
640 SetError();
641 }
642
643 ParseResetTables();
644
645 if (err_.err != Error::ErrorType::ERR_NONE) {
646 return Unexpected(err_);
647 }
648
649 for (auto &func : program_.function_table) {
650 if (func.second.metadata->HasImplementation()) {
651 func.second.source_file = file_name;
652 }
653 }
654
655 for (auto &rec : program_.record_table) {
656 if (rec.second.HasImplementation()) {
657 rec.second.source_file = file_name;
658 }
659 }
660
661 return std::move(program_);
662 }
663
Parse(TokenSet & vectors_tokens,const std::string & file_name)664 Expected<Program, Error> Parser::Parse(TokenSet &vectors_tokens, const std::string &file_name)
665 {
666 bool is_lang_parsed = false;
667 bool is_first_statement = true;
668
669 for (const auto &tokens : vectors_tokens) {
670 ++line_stric_;
671
672 if (tokens.empty()) {
673 continue;
674 }
675
676 LOG(DEBUG, ASSEMBLER) << "started parsing of line " << line_stric_ << ": " << tokens[0].whole_line;
677
678 context_.Make(tokens);
679 switch (*context_) {
680 case Token::Type::ID_CATCH:
681 case Token::Type::ID_CATCHALL: {
682 ParseAsCatchall(tokens);
683 break;
684 }
685 case Token::Type::ID_LANG: {
686 ParseAsLanguage(tokens, is_lang_parsed, is_first_statement);
687 break;
688 }
689 case Token::Type::ID_REC: {
690 ParseAsRecord(tokens);
691 break;
692 }
693 case Token::Type::ID_FUN: {
694 ParseAsFunction(tokens);
695 break;
696 }
697 case Token::Type::DEL_BRACE_R: {
698 ParseAsBraceRight(tokens);
699 break;
700 }
701 default: {
702 if (func_def_) {
703 ParseFunctionCode();
704 } else if (record_def_) {
705 ParseRecordFields();
706 }
707 }
708 }
709 if (!ParseAfterLine(is_first_statement)) {
710 break;
711 }
712 }
713
714 return ParseAfterMainLoop(file_name);
715 }
716
Parse(const std::string & source,const std::string & file_name)717 Expected<Program, Error> Parser::Parse(const std::string &source, const std::string &file_name)
718 {
719 auto ss = std::stringstream(source);
720 std::string line;
721
722 Lexer l;
723 std::vector<std::vector<Token>> v;
724
725 while (std::getline(ss, line)) {
726 auto [tokens, error] = l.TokenizeString(line);
727 if (error.err != Error::ErrorType::ERR_NONE) {
728 return Unexpected(error);
729 }
730
731 v.push_back(tokens);
732 }
733
734 return Parse(v, file_name);
735 }
736
SetError()737 void Parser::SetError()
738 {
739 err_ = context_.err;
740 }
741
RegValidName()742 bool Parser::RegValidName()
743 {
744 if (context_.err.err != Error::ErrorType::ERR_NONE) {
745 return false;
746 }
747
748 if (curr_func_->GetParamsNum() > 0) {
749 return context_.ValidateRegisterName('v') || context_.ValidateRegisterName('a', curr_func_->GetParamsNum() - 1);
750 }
751
752 return context_.ValidateRegisterName('v');
753 }
754
ParamValidName()755 bool Parser::ParamValidName()
756 {
757 return context_.ValidateParameterName(curr_func_->GetParamsNum());
758 }
759
IsAlphaNumeric(char c)760 bool IsAlphaNumeric(char c)
761 {
762 return std::isalnum(c) != 0 || c == '_';
763 }
764
IsNonDigit(char c)765 bool IsNonDigit(char c)
766 {
767 return std::isalpha(c) != 0 || c == '_';
768 }
769
PrefixedValidName()770 bool Parser::PrefixedValidName()
771 {
772 auto s = context_.GiveToken();
773 if (!IsNonDigit(s[0])) {
774 return false;
775 }
776
777 size_t i = 1;
778 while (i < s.size()) {
779 if (s[i] == '.') {
780 ++i;
781 if (i >= s.size() || !IsNonDigit(s[i])) {
782 return false;
783 }
784 } else if (!IsAlphaNumeric(s[i]) && s[i] != '$') {
785 return false;
786 }
787
788 ++i;
789 }
790
791 return true;
792 }
793
RecordValidName()794 bool Parser::RecordValidName()
795 {
796 return PrefixedValidName();
797 }
798
FunctionValidName()799 bool Parser::FunctionValidName()
800 {
801 return PrefixedValidName();
802 }
803
LabelValidName()804 bool Parser::LabelValidName()
805 {
806 auto token = context_.GiveToken();
807 if (!IsNonDigit(token[0])) {
808 return false;
809 }
810
811 token.remove_prefix(1);
812
813 for (auto i : token) {
814 if (!IsAlphaNumeric(i)) {
815 return false;
816 }
817 }
818
819 return true;
820 }
821
ParseLabel()822 bool Parser::ParseLabel()
823 {
824 LOG(DEBUG, ASSEMBLER) << "started searching for label (line " << line_stric_
825 << "): " << context_.tokens[0].whole_line;
826
827 context_++;
828
829 if (*context_ == Token::Type::DEL_COLON) {
830 context_--;
831 if (LabelValidName()) {
832 if (AddObjectInTable(true, *label_table_)) {
833 curr_ins_->set_label = true;
834 curr_ins_->label = context_.GiveToken();
835
836 LOG(DEBUG, ASSEMBLER) << "label detected (line " << line_stric_ << "): " << context_.GiveToken();
837
838 context_++;
839 context_++;
840 return !context_.Mask();
841 }
842
843 LOG(DEBUG, ASSEMBLER) << "label is detected (line " << line_stric_ << "): " << context_.GiveToken()
844 << ", but this label already exists";
845
846 context_.err = GetError("This label already exists.", Error::ErrorType::ERR_BAD_LABEL_EXT);
847
848 } else {
849 LOG(DEBUG, ASSEMBLER) << "label with non-standard character is detected, attempt to create a label is "
850 "supported, but this cannot be any label name (line "
851 << line_stric_ << "): " << context_.GiveToken();
852
853 context_.err = GetError(
854 "Invalid name of label. Label can only contain characters: '_', '0' - '9', 'a' - 'z', 'A' - 'Z'; and "
855 "starts with any letter or with '_'.",
856 Error::ErrorType::ERR_BAD_LABEL);
857 }
858
859 return false;
860 }
861
862 context_--;
863
864 LOG(DEBUG, ASSEMBLER) << "label is not detected (line " << line_stric_ << ")";
865
866 return true;
867 }
868
TokenToOpcode(Token::Type id)869 static Opcode TokenToOpcode(Token::Type id)
870 {
871 ASSERT(id > Token::Type::OPERATION);
872 ASSERT(id < Token::Type::KEYWORD);
873 using utype = std::underlying_type_t<Token::Type>;
874 return static_cast<Opcode>(static_cast<utype>(id) - static_cast<utype>(Token::Type::OPERATION) - 1);
875 }
876
ParseOperation()877 bool Parser::ParseOperation()
878 {
879 if (context_.Mask()) {
880 LOG(DEBUG, ASSEMBLER) << "no more tokens (line " << line_stric_ << "): " << context_.tokens[0].whole_line;
881
882 return false;
883 }
884
885 if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
886 return false;
887 }
888
889 LOG(DEBUG, ASSEMBLER) << "started searching for operation (line " << line_stric_
890 << "): " << context_.tokens[0].whole_line;
891
892 if (*context_ > Token::Type::OPERATION && *context_ < Token::Type::KEYWORD) {
893 SetOperationInformation();
894
895 context_.UpSignOperation();
896 curr_ins_->opcode = TokenToOpcode(context_.id);
897
898 LOG(DEBUG, ASSEMBLER) << "operation is detected (line " << line_stric_ << "): " << context_.GiveToken()
899 << " (operand type: " << OperandTypePrint(curr_ins_->opcode) << ")";
900
901 context_++;
902 return true;
903 }
904
905 LOG(DEBUG, ASSEMBLER) << "founded " << context_.GiveToken() << ", it is not an operation (line " << line_stric_
906 << ")";
907
908 context_.err = GetError("Invalid operation name.", Error::ErrorType::ERR_BAD_OPERATION_NAME);
909
910 return false;
911 }
912
ParseOperandVreg()913 bool Parser::ParseOperandVreg()
914 {
915 if (context_.err.err != Error::ErrorType::ERR_NONE) {
916 return false;
917 }
918
919 if (*context_ != Token::Type::ID) {
920 context_.err = GetError("Expected register.", Error::ErrorType::ERR_BAD_OPERAND, +1);
921 return false;
922 }
923
924 std::string_view p = context_.GiveToken();
925
926 if (p[0] == 'v') {
927 p.remove_prefix(1);
928 int64_t number = static_cast<int64_t>(ToNumber(p));
929
930 if (number > *(context_.max_value_of_reg)) {
931 *(context_.max_value_of_reg) = number;
932 }
933
934 curr_ins_->regs.push_back(static_cast<uint16_t>(number));
935 } else if (p[0] == 'a') {
936 p.remove_prefix(1);
937 curr_ins_->regs.push_back(static_cast<uint16_t>(ToNumber(p)));
938 context_.function_arguments_list->emplace_back(context_.ins_number, curr_ins_->regs.size() - 1);
939 }
940
941 ++context_;
942
943 return true;
944 }
945
ParseOperandCall()946 bool Parser::ParseOperandCall()
947 {
948 if (context_.err.err != Error::ErrorType::ERR_NONE) {
949 return false;
950 }
951
952 if (!FunctionValidName()) {
953 context_.err = GetError("Invalid name of function.", Error::ErrorType::ERR_BAD_NAME_REG);
954 return false;
955 }
956
957 std::string_view p = context_.GiveToken();
958 curr_ins_->ids.emplace_back(p.data(), p.length());
959 AddObjectInTable(false, program_.function_table);
960
961 ++context_;
962
963 return true;
964 }
965
IsOctal(char c)966 static bool IsOctal(char c)
967 {
968 return c >= '0' && c <= '7';
969 }
970
IsHex(char c)971 static bool IsHex(char c)
972 {
973 return std::isxdigit(c) != 0;
974 }
975
FromHex(char c)976 static uint8_t FromHex(char c)
977 {
978 constexpr size_t DIGIT_NUM = 10;
979
980 if (c >= '0' && c <= '9') {
981 return c - '0';
982 }
983
984 if (c >= 'A' && c <= 'F') {
985 return c - 'A' + DIGIT_NUM;
986 }
987
988 return c - 'a' + DIGIT_NUM;
989 }
990
FromOctal(char c)991 static uint8_t FromOctal(char c)
992 {
993 return c - '0';
994 }
995
ParseOctalEscapeSequence(std::string_view s,size_t * i)996 Expected<char, Error> Parser::ParseOctalEscapeSequence(std::string_view s, size_t *i)
997 {
998 constexpr size_t OCT_SHIFT = 3;
999
1000 size_t idx = *i;
1001 size_t n = 0;
1002 uint32_t r = 0;
1003
1004 while (idx < s.length() && IsOctal(s[idx]) && n < OCT_SHIFT) {
1005 r |= FromOctal(s[idx++]);
1006 r <<= 3U;
1007 ++n;
1008 }
1009
1010 r >>= 3U;
1011 *i += n;
1012
1013 return r;
1014 }
1015
ParseHexEscapeSequence(std::string_view s,size_t * i)1016 Expected<char, Error> Parser::ParseHexEscapeSequence(std::string_view s, size_t *i)
1017 {
1018 constexpr size_t HEX_SHIFT = 2;
1019
1020 uint32_t r = 0;
1021 size_t idx = *i;
1022
1023 for (size_t j = 0; j < HEX_SHIFT; j++) {
1024 char v = s[(*i)++];
1025 if (!IsHex(v)) {
1026 return Unexpected(GetError("Invalid hexadecimal escape sequence",
1027 Error::ErrorType::ERR_BAD_STRING_INVALID_HEX_ESCAPE_SEQUENCE, idx - HEX_SHIFT));
1028 }
1029
1030 r |= FromHex(v);
1031 r <<= 4U;
1032 }
1033
1034 r >>= 4U;
1035
1036 return r;
1037 }
1038
ParseEscapeSequence(std::string_view s,size_t * i)1039 Expected<char, Error> Parser::ParseEscapeSequence(std::string_view s, size_t *i)
1040 {
1041 size_t idx = *i;
1042 char c = s[idx];
1043 if (IsOctal(c)) {
1044 return ParseOctalEscapeSequence(s, i);
1045 }
1046
1047 ++(*i);
1048
1049 switch (c) {
1050 case '\'':
1051 case '"':
1052 case '\\':
1053 return c;
1054 case 'a':
1055 return '\a';
1056 case 'b':
1057 return '\b';
1058 case 'f':
1059 return '\f';
1060 case 'n':
1061 return '\n';
1062 case 'r':
1063 return '\r';
1064 case 't':
1065 return '\t';
1066 case 'v':
1067 return '\v';
1068 default:
1069 break;
1070 }
1071
1072 if (c == 'x') {
1073 return ParseHexEscapeSequence(s, i);
1074 }
1075
1076 return Unexpected(
1077 GetError("Unknown escape sequence", Error::ErrorType::ERR_BAD_STRING_UNKNOWN_ESCAPE_SEQUENCE, idx - 1));
1078 }
1079
ParseStringLiteral()1080 std::optional<std::string> Parser::ParseStringLiteral()
1081 {
1082 if (*context_ != Token::Type::ID_STRING) {
1083 context_.err = GetError("Expected string literal", Error::ErrorType::ERR_BAD_OPERAND);
1084 return {};
1085 }
1086
1087 auto token = context_.GiveToken();
1088
1089 size_t i = 1; /* skip leading quote */
1090 size_t len = token.length();
1091
1092 std::string s;
1093 while (i < len - 1) {
1094 char c = token[i++];
1095 if (c != '\\') {
1096 s.append(1, c);
1097 continue;
1098 }
1099
1100 auto res = ParseEscapeSequence(token, &i);
1101 if (!res) {
1102 context_.err = res.Error();
1103 return {};
1104 }
1105
1106 s.append(1, res.Value());
1107 }
1108
1109 program_.strings.insert(s);
1110
1111 return s;
1112 }
1113
ParseOperandString()1114 bool Parser::ParseOperandString()
1115 {
1116 if (context_.err.err != Error::ErrorType::ERR_NONE) {
1117 return false;
1118 }
1119
1120 auto res = ParseStringLiteral();
1121 if (!res) {
1122 return false;
1123 }
1124
1125 curr_ins_->ids.push_back(res.value());
1126 ++context_;
1127
1128 return true;
1129 }
1130
ParseOperandComma()1131 bool Parser::ParseOperandComma()
1132 {
1133 if (context_.err.err != Error::ErrorType::ERR_NONE) {
1134 return false;
1135 }
1136
1137 if (context_++ != Token::Type::DEL_COMMA) {
1138 if (!context_.Mask() && *context_ != Token::Type::DEL_BRACKET_R) {
1139 --context_;
1140 }
1141
1142 context_.err = GetError("Expected comma.", Error::ErrorType::ERR_BAD_NUMBER_OPERANDS);
1143 return false;
1144 }
1145
1146 return true;
1147 }
1148
ParseOperandInteger()1149 bool Parser::ParseOperandInteger()
1150 {
1151 if (context_.err.err != Error::ErrorType::ERR_NONE) {
1152 return false;
1153 }
1154
1155 if (*context_ != Token::Type::ID) {
1156 if (*context_ == Token::Type::DEL_BRACE_R) {
1157 --context_;
1158 }
1159 context_.err = GetError("Expected immediate.", Error::ErrorType::ERR_BAD_OPERAND, +1);
1160 return false;
1161 }
1162
1163 std::string_view p = context_.GiveToken();
1164 if (!ValidateInteger(p)) {
1165 context_.err = GetError("Expected integer.", Error::ErrorType::ERR_BAD_INTEGER_NAME);
1166 return false;
1167 }
1168
1169 int64_t n = IntegerNumber(p);
1170 if (errno == ERANGE) {
1171 context_.err =
1172 GetError("Too large immediate (length is more than 64 bit).", Error::ErrorType::ERR_BAD_INTEGER_WIDTH);
1173 return false;
1174 }
1175
1176 curr_ins_->imms.push_back(n);
1177 ++context_;
1178
1179 return true;
1180 }
1181
ParseOperandFloat(bool is_64bit)1182 bool Parser::ParseOperandFloat(bool is_64bit)
1183 {
1184 if (context_.err.err != Error::ErrorType::ERR_NONE) {
1185 return false;
1186 }
1187
1188 if (*context_ != Token::Type::ID) {
1189 if (*context_ == Token::Type::DEL_BRACE_R) {
1190 --context_;
1191 }
1192 context_.err = GetError("Expected immediate.", Error::ErrorType::ERR_BAD_OPERAND, +1);
1193 return false;
1194 }
1195
1196 std::string_view p = context_.GiveToken();
1197 if (!ValidateFloat(p)) {
1198 context_.err = GetError("Expected float.", Error::ErrorType::ERR_BAD_FLOAT_NAME);
1199 return false;
1200 }
1201
1202 double n = FloatNumber(p, is_64bit);
1203 if (errno == ERANGE) {
1204 context_.err =
1205 GetError("Too large immediate (length is more than 64 bit).", Error::ErrorType::ERR_BAD_FLOAT_WIDTH);
1206 return false;
1207 }
1208
1209 curr_ins_->imms.push_back(n);
1210 ++context_;
1211
1212 return true;
1213 }
1214
ParseOperandLabel()1215 bool Parser::ParseOperandLabel()
1216 {
1217 if (context_.err.err != Error::ErrorType::ERR_NONE) {
1218 return false;
1219 }
1220
1221 if (!LabelValidName()) {
1222 context_.err = GetError("Invalid name of label.", Error::ErrorType::ERR_BAD_NAME_ID);
1223 return false;
1224 }
1225
1226 std::string_view p = context_.GiveToken();
1227 curr_ins_->ids.emplace_back(p.data(), p.length());
1228 AddObjectInTable(false, *label_table_);
1229
1230 ++context_;
1231
1232 return true;
1233 }
1234
ParseOperandId()1235 bool Parser::ParseOperandId()
1236 {
1237 if (context_.err.err != Error::ErrorType::ERR_NONE) {
1238 return false;
1239 }
1240
1241 if (*context_ != Token::Type::ID) {
1242 context_.err = GetError("Expected label.", Error::ErrorType::ERR_BAD_OPERAND);
1243 return false;
1244 }
1245
1246 if (!LabelValidName()) {
1247 context_.err = GetError("Invalid name of label.", Error::ErrorType::ERR_BAD_NAME_ID);
1248 return false;
1249 }
1250
1251 std::string_view p = context_.GiveToken();
1252 curr_ins_->ids.emplace_back(p.data(), p.length());
1253 AddObjectInTable(false, *label_table_);
1254
1255 ++context_;
1256
1257 return true;
1258 }
1259
ParseOperandType(Type::VerificationType ver_type)1260 bool Parser::ParseOperandType(Type::VerificationType ver_type)
1261 {
1262 if (context_.err.err != Error::ErrorType::ERR_NONE) {
1263 return false;
1264 }
1265
1266 if (*context_ != Token::Type::ID) {
1267 context_.err = GetError("Expected type.", Error::ErrorType::ERR_BAD_OPERAND);
1268 return false;
1269 }
1270
1271 if (!TypeValidName()) {
1272 context_.err = GetError("Invalid name of type.", Error::ErrorType::ERR_BAD_NAME_ID);
1273 return false;
1274 }
1275
1276 Type type;
1277 if (!ParseType(&type)) {
1278 return false;
1279 }
1280
1281 bool is_object = (context_.GiveToken() == "]") ? (false) : (true);
1282 if (is_object) {
1283 AddObjectInTable(false, program_.record_table);
1284
1285 if (ver_type == Type::VerificationType::TYPE_ID_ARRAY) {
1286 GetWarning("Unexpected type_id received! Expected array, but object given",
1287 Error::ErrorType::WAR_UNEXPECTED_TYPE_ID);
1288 }
1289 } else {
1290 if (!type.IsArrayContainsPrimTypes() &&
1291 program_.record_table.find(type.GetComponentName()) == program_.record_table.end()) {
1292 std::string ComponentName = type.GetComponentName();
1293 context_.token = ComponentName;
1294 AddObjectInTable(false, program_.record_table);
1295 }
1296
1297 if (ver_type == Type::VerificationType::TYPE_ID_OBJECT) {
1298 GetWarning("Unexpected type_id received! Expected object, but array given",
1299 Error::ErrorType::WAR_UNEXPECTED_TYPE_ID);
1300 }
1301 }
1302
1303 curr_ins_->ids.push_back(type.GetName());
1304
1305 return true;
1306 }
1307
ParseOperandField()1308 bool Parser::ParseOperandField()
1309 {
1310 if (context_.err.err != Error::ErrorType::ERR_NONE) {
1311 return false;
1312 }
1313
1314 if (*context_ != Token::Type::ID) {
1315 context_.err = GetError("Expected field.", Error::ErrorType::ERR_BAD_OPERAND);
1316 return false;
1317 }
1318 if (!PrefixedValidName()) {
1319 context_.err = GetError("Invalid field name.", Error::ErrorType::ERR_BAD_NAME_ID);
1320 return false;
1321 }
1322
1323 std::string_view p = context_.GiveToken();
1324 std::string record_full_name = std::string(p);
1325 // Some names of records in pandastdlib starts with 'panda.', and therefore,
1326 // the record name is before the second dot, and the field name is after the second dot.
1327 auto pos_point = record_full_name.find_last_of('.');
1328 std::string record_name = record_full_name.substr(0, pos_point);
1329 std::string field_name = record_full_name.substr(pos_point + 1);
1330
1331 auto it_record = program_.record_table.find(record_name);
1332 if (it_record == program_.record_table.end()) {
1333 context_.token = record_name;
1334 AddObjectInTable(false, program_.record_table);
1335 it_record = program_.record_table.find(record_name);
1336 }
1337
1338 auto it_field = std::find_if(it_record->second.field_list.begin(), it_record->second.field_list.end(),
1339 [&field_name](pandasm::Field &field) { return field_name == field.name; });
1340
1341 if (!field_name.empty() && it_field == it_record->second.field_list.end()) {
1342 it_record->second.field_list.emplace_back(program_.lang);
1343 auto &field = it_record->second.field_list.back();
1344 field.name = field_name;
1345 field.line_of_def = line_stric_;
1346 field.whole_line = context_.tokens[context_.number - 1].whole_line;
1347 field.bound_left = context_.tokens[context_.number - 1].bound_left + record_name.length() + 1;
1348 field.bound_right = context_.tokens[context_.number - 1].bound_right;
1349 field.is_defined = false;
1350 }
1351
1352 curr_ins_->ids.emplace_back(p.data(), p.length());
1353 ++context_;
1354
1355 return true;
1356 }
1357
ParseOperandNone()1358 bool Parser::ParseOperandNone()
1359 {
1360 if (context_.err.err != Error::ErrorType::ERR_NONE) {
1361 return false;
1362 }
1363
1364 if (open_ && *context_ == Token::Type::DEL_BRACE_R) {
1365 return false;
1366 }
1367
1368 if (!context_.Mask()) {
1369 context_.err = GetError("Invalid number of operands.", Error::ErrorType::ERR_BAD_NUMBER_OPERANDS);
1370 --context_;
1371 return false;
1372 }
1373
1374 return true;
1375 }
1376
ParseRecordFullSign()1377 bool Parser::ParseRecordFullSign()
1378 {
1379 return ParseRecordName();
1380 }
1381
ParseFunctionFullSign()1382 bool Parser::ParseFunctionFullSign()
1383 {
1384 if (!ParseFunctionReturn()) {
1385 return false;
1386 }
1387
1388 if (!ParseFunctionName()) {
1389 return false;
1390 }
1391
1392 if (*context_ == Token::Type::DEL_BRACKET_L) {
1393 ++context_;
1394
1395 if (ParseFunctionArgs()) {
1396 if (*context_ == Token::Type::DEL_BRACKET_R) {
1397 ++context_;
1398 return true;
1399 }
1400 context_.err = GetError("Expected ')'.", Error::ErrorType::ERR_BAD_ARGS_BOUND);
1401 }
1402 } else {
1403 context_.err = GetError("Expected '('.", Error::ErrorType::ERR_BAD_ARGS_BOUND);
1404 }
1405
1406 return false;
1407 }
1408
ParseRecordName()1409 bool Parser::ParseRecordName()
1410 {
1411 LOG(DEBUG, ASSEMBLER) << "started searching for record name (line " << line_stric_
1412 << "): " << context_.tokens[context_.number - 1].whole_line;
1413
1414 if (!RecordValidName()) {
1415 if (*context_ == Token::Type::DEL_BRACKET_L) {
1416 context_.err = GetError("No record name.", Error::ErrorType::ERR_BAD_RECORD_NAME);
1417 return false;
1418 }
1419 context_.err = GetError("Invalid name of the record.", Error::ErrorType::ERR_BAD_RECORD_NAME);
1420 return false;
1421 }
1422
1423 auto iter = program_.record_table.find(std::string(context_.GiveToken().data(), context_.GiveToken().length()));
1424 if (iter == program_.record_table.end() || !iter->second.file_location->is_defined) {
1425 SetRecordInformation();
1426 } else {
1427 context_.err = GetError("This record already exists.", Error::ErrorType::ERR_BAD_ID_RECORD);
1428 return false;
1429 }
1430
1431 LOG(DEBUG, ASSEMBLER) << "record name found (line " << line_stric_ << "): " << context_.GiveToken();
1432
1433 ++context_;
1434
1435 return true;
1436 }
1437
SetRecordInformation()1438 void Parser::SetRecordInformation()
1439 {
1440 AddObjectInTable(true, program_.record_table);
1441 curr_record_ = &(program_.record_table.at(std::string(context_.GiveToken().data(), context_.GiveToken().length())));
1442 }
1443
ParseFunctionName()1444 bool Parser::ParseFunctionName()
1445 {
1446 LOG(DEBUG, ASSEMBLER) << "started searching for function name (line " << line_stric_
1447 << "): " << context_.tokens[context_.number - 1].whole_line;
1448
1449 if (!FunctionValidName()) {
1450 if (*context_ == Token::Type::DEL_BRACKET_L) {
1451 context_.err = GetError("No function name.", Error::ErrorType::ERR_BAD_FUNCTION_NAME);
1452 return false;
1453 }
1454 context_.err = GetError("Invalid name of the function.", Error::ErrorType::ERR_BAD_FUNCTION_NAME);
1455 return false;
1456 }
1457
1458 auto iter = program_.function_table.find(std::string(context_.GiveToken().data(), context_.GiveToken().length()));
1459
1460 if (iter == program_.function_table.end() || !iter->second.file_location->is_defined) {
1461 SetFunctionInformation();
1462 } else {
1463 context_.err = GetError("This function already exists.", Error::ErrorType::ERR_BAD_ID_FUNCTION);
1464 return false;
1465 }
1466
1467 LOG(DEBUG, ASSEMBLER) << "function name found (line " << line_stric_ << "): " << context_.GiveToken();
1468
1469 ++context_;
1470
1471 return true;
1472 }
1473
SetFunctionInformation()1474 void Parser::SetFunctionInformation()
1475 {
1476 std::string p = std::string(context_.GiveToken());
1477 AddObjectInTable(true, program_.function_table);
1478 curr_func_ = &(program_.function_table.at(p));
1479 label_table_ = &(curr_func_->label_table);
1480 curr_func_->return_type = context_.curr_func_return_type;
1481 context_.max_value_of_reg = &(curr_func_->value_of_first_param);
1482 context_.function_arguments_list = &(context_.function_arguments_lists[curr_func_->name]);
1483 }
1484
SetOperationInformation()1485 void Parser::SetOperationInformation()
1486 {
1487 context_.ins_number = curr_func_->ins.size();
1488 auto &curr_debug = curr_func_->ins.back().ins_debug;
1489 curr_debug.line_number = line_stric_;
1490 curr_debug.whole_line = context_.tokens[context_.number - 1].whole_line;
1491 curr_debug.bound_left = context_.tokens[context_.number - 1].bound_left;
1492 curr_debug.bound_right = context_.tokens[context_.number - 1].bound_right;
1493 }
1494
ParseFunctionReturn()1495 bool Parser::ParseFunctionReturn()
1496 {
1497 LOG(DEBUG, ASSEMBLER) << "started searching for return function value (line " << line_stric_
1498 << "): " << context_.tokens[context_.number - 1].whole_line;
1499
1500 if (!TypeValidName()) {
1501 if (*context_ == Token::Type::DEL_BRACKET_L) {
1502 context_.err = GetError("No return type.", Error::ErrorType::ERR_BAD_FUNCTION_RETURN_VALUE);
1503 return false;
1504 }
1505 context_.err = GetError("Invalid return type.", Error::ErrorType::ERR_BAD_FUNCTION_RETURN_VALUE);
1506 return false;
1507 }
1508
1509 if (!ParseType(&context_.curr_func_return_type)) {
1510 return false;
1511 }
1512
1513 LOG(DEBUG, ASSEMBLER) << "return type found (line " << line_stric_ << "): " << context_.GiveToken();
1514
1515 return true;
1516 }
1517
TypeValidName()1518 bool Parser::TypeValidName()
1519 {
1520 if (Type::GetId(context_.GiveToken()) != panda_file::Type::TypeId::REFERENCE) {
1521 return true;
1522 }
1523
1524 return PrefixedValidName();
1525 }
1526
ParseFunctionArg()1527 bool Parser::ParseFunctionArg()
1528 {
1529 if (*context_ != Token::Type::ID) {
1530 context_.err = GetError("Expected identifier.", Error::ErrorType::ERR_BAD_FUNCTION_PARAMETERS);
1531 return false;
1532 }
1533
1534 if (!TypeValidName()) {
1535 context_.err = GetError("Invalid parameter type.", Error::ErrorType::ERR_BAD_TYPE);
1536 return false;
1537 }
1538
1539 Type type;
1540 if (!ParseType(&type)) {
1541 return false;
1542 }
1543
1544 if (context_.Mask()) {
1545 return false;
1546 }
1547
1548 if (*context_ != Token::Type::ID) {
1549 context_.err = GetError("Expected identifier.", Error::ErrorType::ERR_BAD_FUNCTION_PARAMETERS);
1550 return false;
1551 }
1552
1553 if (!ParamValidName()) {
1554 context_.err = GetError("Invalid parameter name.", Error::ErrorType::ERR_BAD_PARAM_NAME);
1555 return false;
1556 }
1557
1558 ++context_;
1559
1560 Function::Parameter parameter(type, program_.lang);
1561 metadata_ = parameter.metadata.get();
1562
1563 if (*context_ == Token::Type::DEL_LT && !ParseMetaDef()) {
1564 return false;
1565 }
1566
1567 curr_func_->params.push_back(std::move(parameter));
1568
1569 return true;
1570 }
1571
ParseFunctionArgComma(bool & comma)1572 bool Parser::ParseFunctionArgComma(bool &comma)
1573 {
1574 if (comma && *context_ != Token::Type::DEL_COMMA) {
1575 context_.err = GetError("Expected comma.", Error::ErrorType::ERR_BAD_NUMBER_OPERANDS);
1576 return false;
1577 }
1578
1579 if (comma) {
1580 ++context_;
1581 }
1582
1583 comma = true;
1584
1585 return true;
1586 }
1587
ParseFunctionArgs()1588 bool Parser::ParseFunctionArgs()
1589 {
1590 LOG(DEBUG, ASSEMBLER) << "started searching for function parameters (line " << line_stric_
1591 << "): " << context_.tokens[context_.number - 1].whole_line;
1592
1593 bool comma = false;
1594
1595 while (true) {
1596 if (context_.Mask()) {
1597 return false;
1598 }
1599
1600 if (context_.id != Token::Type::DEL_COMMA && context_.id != Token::Type::ID) {
1601 break;
1602 }
1603
1604 if (!ParseFunctionArgComma(comma)) {
1605 return false;
1606 }
1607
1608 if (!ParseFunctionArg()) {
1609 return false;
1610 }
1611 }
1612
1613 LOG(DEBUG, ASSEMBLER) << "parameters found (line " << line_stric_ << "): ";
1614
1615 return true;
1616 }
1617
ParseMetaDef()1618 bool Parser::ParseMetaDef()
1619 {
1620 LOG(DEBUG, ASSEMBLER) << "started searching for meta information (line " << line_stric_
1621 << "): " << context_.tokens[context_.number - 1].whole_line;
1622
1623 if (context_.Mask()) {
1624 return false;
1625 }
1626
1627 bool flag = false;
1628
1629 if (*context_ == Token::Type::DEL_LT) {
1630 flag = true;
1631 ++context_;
1632 }
1633
1634 if (!ParseMetaList(flag)) {
1635 return false;
1636 }
1637
1638 if (!flag && *context_ == Token::Type::DEL_GT) {
1639 context_.err = GetError("Expected '<'.", Error::ErrorType::ERR_BAD_METADATA_BOUND);
1640 ++context_;
1641 return false;
1642 }
1643
1644 LOG(DEBUG, ASSEMBLER) << "searching for meta information (line " << line_stric_ << ") is successful";
1645
1646 if (flag && context_.err.err == Error::ErrorType::ERR_NONE) {
1647 ++context_;
1648 }
1649
1650 return true;
1651 }
1652
SetMetadataContextError(const Metadata::Error & err,bool has_value)1653 void Parser::SetMetadataContextError(const Metadata::Error &err, bool has_value)
1654 {
1655 constexpr int64_t NO_VALUE_OFF = -1;
1656 constexpr int64_t SPECIAL_OFF = -2;
1657 constexpr int64_t STANDARD_OFF = -3;
1658
1659 switch (err.GetType()) {
1660 case Metadata::Error::Type::UNKNOWN_ATTRIBUTE: {
1661 context_.err = GetError(err.GetMessage(), Error::ErrorType::ERR_BAD_METADATA_UNKNOWN_ATTRIBUTE, 0,
1662 has_value ? STANDARD_OFF : NO_VALUE_OFF);
1663 break;
1664 }
1665 case Metadata::Error::Type::MISSING_ATTRIBUTE: {
1666 context_.err = GetError(err.GetMessage(), Error::ErrorType::ERR_BAD_METADATA_MISSING_ATTRIBUTE);
1667 break;
1668 }
1669 case Metadata::Error::Type::MISSING_VALUE: {
1670 context_.err = GetError(err.GetMessage(), Error::ErrorType::ERR_BAD_METADATA_MISSING_VALUE);
1671 break;
1672 }
1673 case Metadata::Error::Type::UNEXPECTED_ATTRIBUTE: {
1674 context_.err = GetError(err.GetMessage(), Error::ErrorType::ERR_BAD_METADATA_UNEXPECTED_ATTRIBUTE, 0,
1675 has_value ? STANDARD_OFF : NO_VALUE_OFF);
1676 break;
1677 }
1678 case Metadata::Error::Type::UNEXPECTED_VALUE: {
1679 context_.err =
1680 GetError(err.GetMessage(), Error::ErrorType::ERR_BAD_METADATA_UNEXPECTED_VALUE, 0, SPECIAL_OFF);
1681 break;
1682 }
1683 case Metadata::Error::Type::INVALID_VALUE: {
1684 context_.err = GetError(err.GetMessage(), Error::ErrorType::ERR_BAD_METADATA_INVALID_VALUE, 0, -1);
1685 break;
1686 }
1687 case Metadata::Error::Type::MULTIPLE_ATTRIBUTE: {
1688 context_.err = GetError(err.GetMessage(), Error::ErrorType::ERR_BAD_METADATA_MULTIPLE_ATTRIBUTE, 0,
1689 has_value ? STANDARD_OFF : NO_VALUE_OFF);
1690 break;
1691 }
1692 default: {
1693 UNREACHABLE();
1694 }
1695 }
1696 }
1697
ParseMetaListComma(bool & comma,bool eq)1698 bool Parser::ParseMetaListComma(bool &comma, bool eq)
1699 {
1700 if (!eq && comma && *context_ != Token::Type::DEL_COMMA) {
1701 context_.err = GetError("Expected comma.", Error::ErrorType::ERR_BAD_NUMBER_OPERANDS);
1702 return false;
1703 }
1704
1705 if (!eq && comma) {
1706 ++context_;
1707 }
1708
1709 comma = true;
1710
1711 return true;
1712 }
1713
MeetExpMetaList(bool eq)1714 bool Parser::MeetExpMetaList(bool eq)
1715 {
1716 if (!eq && *context_ != Token::Type::ID) {
1717 context_.err = GetError("Expected identifier.", Error::ErrorType::ERR_BAD_DEFINITION_METADATA, +1);
1718 return false;
1719 }
1720
1721 if (eq && *context_ != Token::Type::ID && *context_ != Token::Type::ID_STRING) {
1722 context_.err =
1723 GetError("Expected identifier or string literal.", Error::ErrorType::ERR_BAD_DEFINITION_METADATA, +1);
1724 return false;
1725 }
1726
1727 if (!eq && !PrefixedValidName()) {
1728 context_.err = GetError("Invalid attribute name.", Error::ErrorType::ERR_BAD_NAME_ID);
1729 return false;
1730 }
1731
1732 return true;
1733 }
1734
BuildMetaListAttr(bool & eq,std::string & attribute_name,std::string & attribute_value)1735 bool Parser::BuildMetaListAttr(bool &eq, std::string &attribute_name, std::string &attribute_value)
1736 {
1737 if (eq && *context_ == Token::Type::ID_STRING) {
1738 auto res = ParseStringLiteral();
1739 if (!res) {
1740 return false;
1741 }
1742
1743 attribute_value = res.value();
1744 } else if (eq) {
1745 attribute_value = context_.GiveToken();
1746 } else {
1747 attribute_name = context_.GiveToken();
1748 }
1749
1750 ++context_;
1751
1752 if (context_.Mask()) {
1753 return false;
1754 }
1755
1756 if (*context_ == Token::Type::DEL_EQ) {
1757 if (eq) {
1758 context_.err = GetError("Unexpected '='.", Error::ErrorType::ERR_BAD_NOEXP_DELIM);
1759 return false;
1760 }
1761
1762 ++context_;
1763 eq = true;
1764 } else {
1765 std::optional<Metadata::Error> res;
1766 bool has_value = eq;
1767 if (has_value) {
1768 res = metadata_->SetAttributeValue(attribute_name, attribute_value);
1769 } else {
1770 res = metadata_->SetAttribute(attribute_name);
1771 }
1772
1773 eq = false;
1774
1775 if (res) {
1776 auto err = res.value();
1777 SetMetadataContextError(err, has_value);
1778 return false;
1779 }
1780 }
1781
1782 return true;
1783 }
1784
ParseMetaList(bool flag)1785 bool Parser::ParseMetaList(bool flag)
1786 {
1787 if (!flag && !context_.Mask() && *context_ != Token::Type::DEL_GT && *context_ != Token::Type::DEL_BRACE_L) {
1788 context_.err = GetError("No meta data expected.", Error::ErrorType::ERR_BAD_DEFINITION_METADATA);
1789 return false;
1790 }
1791
1792 bool comma = false;
1793 bool eq = false;
1794
1795 std::string attribute_name;
1796 std::string attribute_value;
1797
1798 while (true) {
1799 if (context_.Mask()) {
1800 context_.err = GetError("Expected '>'.", Error::ErrorType::ERR_BAD_METADATA_BOUND, +1);
1801 return false;
1802 }
1803
1804 if (context_.id != Token::Type::DEL_COMMA && context_.id != Token::Type::ID &&
1805 context_.id != Token::Type::ID_STRING && context_.id != Token::Type::DEL_EQ) {
1806 break;
1807 }
1808
1809 if (!ParseMetaListComma(comma, eq)) {
1810 return false;
1811 }
1812
1813 if (!MeetExpMetaList(eq)) {
1814 return false;
1815 }
1816
1817 if (!BuildMetaListAttr(eq, attribute_name, attribute_value)) {
1818 return false;
1819 }
1820 }
1821
1822 if (flag && *context_ != Token::Type::DEL_GT) {
1823 context_.err = GetError("Expected '>'.", Error::ErrorType::ERR_BAD_METADATA_BOUND);
1824 ++context_;
1825
1826 return false;
1827 }
1828
1829 auto res = metadata_->ValidateData();
1830 if (res) {
1831 auto err = res.value();
1832 SetMetadataContextError(err, false);
1833 return false;
1834 }
1835
1836 return true;
1837 }
1838
ParseFunctionInstruction()1839 bool Parser::ParseFunctionInstruction()
1840 {
1841 if (ParseLabel()) {
1842 if (ParseOperation()) {
1843 if (ParseOperands()) {
1844 return true;
1845 }
1846 }
1847 }
1848
1849 return context_.Mask();
1850 }
1851
1852 } // namespace panda::pandasm
1853