• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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