1b1994897Sopenharmony_ci/**
2b1994897Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3b1994897Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4b1994897Sopenharmony_ci * you may not use this file except in compliance with the License.
5b1994897Sopenharmony_ci * You may obtain a copy of the License at
6b1994897Sopenharmony_ci *
7b1994897Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8b1994897Sopenharmony_ci *
9b1994897Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10b1994897Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11b1994897Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12b1994897Sopenharmony_ci * See the License for the specific language governing permissions and
13b1994897Sopenharmony_ci * limitations under the License.
14b1994897Sopenharmony_ci */
15b1994897Sopenharmony_ci
16b1994897Sopenharmony_ci#ifndef ASSEMBLER_ASSEMBLY_PARSER_H
17b1994897Sopenharmony_ci#define ASSEMBLER_ASSEMBLY_PARSER_H
18b1994897Sopenharmony_ci
19b1994897Sopenharmony_ci#include <iostream>
20b1994897Sopenharmony_ci#include <memory>
21b1994897Sopenharmony_ci#include <string>
22b1994897Sopenharmony_ci#include <string_view>
23b1994897Sopenharmony_ci
24b1994897Sopenharmony_ci#include "assembly-context.h"
25b1994897Sopenharmony_ci#include "assembly-emitter.h"
26b1994897Sopenharmony_ci#include "assembly-field.h"
27b1994897Sopenharmony_ci#include "assembly-function.h"
28b1994897Sopenharmony_ci#include "assembly-ins.h"
29b1994897Sopenharmony_ci#include "assembly-label.h"
30b1994897Sopenharmony_ci#include "assembly-program.h"
31b1994897Sopenharmony_ci#include "assembly-record.h"
32b1994897Sopenharmony_ci#include "assembly-type.h"
33b1994897Sopenharmony_ci#include "define.h"
34b1994897Sopenharmony_ci#include "error.h"
35b1994897Sopenharmony_ci#include "ide_helpers.h"
36b1994897Sopenharmony_ci#include "lexer.h"
37b1994897Sopenharmony_ci#include "meta.h"
38b1994897Sopenharmony_ci#include "utils/expected.h"
39b1994897Sopenharmony_ci
40b1994897Sopenharmony_cinamespace panda::pandasm {
41b1994897Sopenharmony_ci
42b1994897Sopenharmony_ciusing Instructions = std::pair<std::vector<Ins>, Error>;
43b1994897Sopenharmony_ci
44b1994897Sopenharmony_ciusing Functions = std::pair<std::unordered_map<std::string, Function>, std::unordered_map<std::string, Record>>;
45b1994897Sopenharmony_ci
46b1994897Sopenharmony_ciclass Parser {
47b1994897Sopenharmony_cipublic:
48b1994897Sopenharmony_ci    Parser() = default;
49b1994897Sopenharmony_ci
50b1994897Sopenharmony_ci    NO_MOVE_SEMANTIC(Parser);
51b1994897Sopenharmony_ci    NO_COPY_SEMANTIC(Parser);
52b1994897Sopenharmony_ci
53b1994897Sopenharmony_ci    ~Parser() = default;
54b1994897Sopenharmony_ci
55b1994897Sopenharmony_ci    /*
56b1994897Sopenharmony_ci     * The main function of parsing, which takes a vector of token vectors and a name of the source file.
57b1994897Sopenharmony_ci     * Returns a program or an error value: Expected<Program, Error>
58b1994897Sopenharmony_ci     * This function analyzes code containing several functions:
59b1994897Sopenharmony_ci     *   - Each function used must be declared.
60b1994897Sopenharmony_ci     *   - The correct function declaration looks like this: .function ret_type fun_name([param_type aN,]) [<metadata>]
61b1994897Sopenharmony_ci     *     ([data] shows that this 'data' is optional).
62b1994897Sopenharmony_ci     *   - N in function parameters must increase when number of parameters increases
63b1994897Sopenharmony_ci     *     (Possible: a0, a1,..., aN. Impossible: a1, a10, a13).
64b1994897Sopenharmony_ci     *   - Each function has its own label table.
65b1994897Sopenharmony_ci     */
66b1994897Sopenharmony_ci    Expected<Program, Error> Parse(TokenSet &vectors_tokens, const std::string &file_name = "");
67b1994897Sopenharmony_ci
68b1994897Sopenharmony_ci    /*
69b1994897Sopenharmony_ci     * The main function of parsing, which takes a string with source and a name of the source file.
70b1994897Sopenharmony_ci     * Returns a program or an error value: Expected<Program, Error>
71b1994897Sopenharmony_ci     */
72b1994897Sopenharmony_ci    Expected<Program, Error> Parse(const std::string &source, const std::string &file_name = "");
73b1994897Sopenharmony_ci
74b1994897Sopenharmony_ci    /*
75b1994897Sopenharmony_ci     * Returns a set error
76b1994897Sopenharmony_ci     */
77b1994897Sopenharmony_ci    Error ShowError() const
78b1994897Sopenharmony_ci    {
79b1994897Sopenharmony_ci        return err_;
80b1994897Sopenharmony_ci    }
81b1994897Sopenharmony_ci
82b1994897Sopenharmony_ci    ErrorList ShowWarnings() const
83b1994897Sopenharmony_ci    {
84b1994897Sopenharmony_ci        return war_;
85b1994897Sopenharmony_ci    }
86b1994897Sopenharmony_ci
87b1994897Sopenharmony_ciprivate:
88b1994897Sopenharmony_ci    panda::pandasm::Program program_;
89b1994897Sopenharmony_ci    std::unordered_map<std::string, panda::pandasm::Label> *label_table_ = nullptr;
90b1994897Sopenharmony_ci    Metadata *metadata_ = nullptr;
91b1994897Sopenharmony_ci    Context context_; /* token iterator */
92b1994897Sopenharmony_ci    panda::pandasm::Record *curr_record_ = nullptr;
93b1994897Sopenharmony_ci    panda::pandasm::LiteralArray *curr_array_ = nullptr;
94b1994897Sopenharmony_ci    panda::pandasm::LiteralArray::Literal *curr_array_elem_ = nullptr;
95b1994897Sopenharmony_ci    panda::pandasm::Function *curr_func_ = nullptr;
96b1994897Sopenharmony_ci    panda::pandasm::Ins *curr_ins_ = nullptr;
97b1994897Sopenharmony_ci    panda::pandasm::Field *curr_fld_ = nullptr;
98b1994897Sopenharmony_ci    size_t line_stric_ = 0;
99b1994897Sopenharmony_ci    panda::pandasm::Error err_;
100b1994897Sopenharmony_ci    panda::pandasm::ErrorList war_;
101b1994897Sopenharmony_ci    bool open_ = false; /* flag of being in a code section */
102b1994897Sopenharmony_ci    bool record_def_ = false;
103b1994897Sopenharmony_ci    bool array_def_ = false;
104b1994897Sopenharmony_ci    bool func_def_ = false;
105b1994897Sopenharmony_ci    static constexpr uint32_t INTRO_CONST_ARRAY_LITERALS_NUMBER = 2;
106b1994897Sopenharmony_ci
107b1994897Sopenharmony_ci    inline Error GetError(const std::string &mess = "", Error::ErrorType err = Error::ErrorType::ERR_NONE,
108b1994897Sopenharmony_ci                          int8_t shift = 0, int token_shift = 0, const std::string &add_mess = "") const
109b1994897Sopenharmony_ci    {
110b1994897Sopenharmony_ci        return Error(mess, line_stric_, err, add_mess,
111b1994897Sopenharmony_ci                     context_.tokens[static_cast<int>(context_.number) + token_shift - 1].bound_left + shift,
112b1994897Sopenharmony_ci                     context_.tokens[static_cast<int>(context_.number) + token_shift - 1].bound_right,
113b1994897Sopenharmony_ci                     context_.tokens[static_cast<int>(context_.number) + token_shift - 1].whole_line);
114b1994897Sopenharmony_ci    }
115b1994897Sopenharmony_ci
116b1994897Sopenharmony_ci    inline void GetWarning(const std::string &mess = "", Error::ErrorType err = Error::ErrorType::ERR_NONE,
117b1994897Sopenharmony_ci                           int8_t shift = 0, const std::string &add_mess = "")
118b1994897Sopenharmony_ci    {
119b1994897Sopenharmony_ci        war_.emplace_back(mess, line_stric_, err, add_mess,
120b1994897Sopenharmony_ci                          context_.tokens[context_.number - 1].bound_left + static_cast<size_t>(shift),
121b1994897Sopenharmony_ci                          context_.tokens[context_.number - 1].bound_right,
122b1994897Sopenharmony_ci                          context_.tokens[context_.number - 1].whole_line, Error::ErrorClass::WARNING);
123b1994897Sopenharmony_ci    }
124b1994897Sopenharmony_ci
125b1994897Sopenharmony_ci    SourcePosition GetCurrentPosition(bool left_bound) const
126b1994897Sopenharmony_ci    {
127b1994897Sopenharmony_ci        if (left_bound) {
128b1994897Sopenharmony_ci            return SourcePosition {line_stric_, context_.tokens[context_.number - 1].bound_left};
129b1994897Sopenharmony_ci        }
130b1994897Sopenharmony_ci        return SourcePosition {line_stric_, context_.tokens[context_.number - 1].bound_right};
131b1994897Sopenharmony_ci    }
132b1994897Sopenharmony_ci
133b1994897Sopenharmony_ci    bool LabelValidName();
134b1994897Sopenharmony_ci    bool TypeValidName();
135b1994897Sopenharmony_ci    bool RegValidName();
136b1994897Sopenharmony_ci    bool ParamValidName();
137b1994897Sopenharmony_ci    bool FunctionValidName();
138b1994897Sopenharmony_ci    bool ParseFunctionName();
139b1994897Sopenharmony_ci    bool ParseLabel();
140b1994897Sopenharmony_ci    bool ParseOperation();
141b1994897Sopenharmony_ci    bool ParseOperands();
142b1994897Sopenharmony_ci    bool ParseFunctionCode();
143b1994897Sopenharmony_ci    bool ParseFunctionInstruction();
144b1994897Sopenharmony_ci    bool ParseFunctionFullSign();
145b1994897Sopenharmony_ci    bool UpdateFunctionName();
146b1994897Sopenharmony_ci    bool ParseFunctionReturn();
147b1994897Sopenharmony_ci    bool ParseFunctionArg();
148b1994897Sopenharmony_ci    bool ParseFunctionArgComma(bool &comma);
149b1994897Sopenharmony_ci    bool ParseFunctionArgs();
150b1994897Sopenharmony_ci    bool ParseType(Type *type);
151b1994897Sopenharmony_ci    bool PrefixedValidName();
152b1994897Sopenharmony_ci    bool ParseMetaListComma(bool &comma, bool eq);
153b1994897Sopenharmony_ci    bool MeetExpMetaList(bool eq);
154b1994897Sopenharmony_ci    bool BuildMetaListAttr(bool &eq, std::string &attribute_name, std::string &attribute_value);
155b1994897Sopenharmony_ci    bool ParseMetaList(bool flag);
156b1994897Sopenharmony_ci    bool ParseMetaDef();
157b1994897Sopenharmony_ci    bool ParseRecordFullSign();
158b1994897Sopenharmony_ci    bool ParseRecordFields();
159b1994897Sopenharmony_ci    bool ParseRecordField();
160b1994897Sopenharmony_ci    bool ParseRecordName();
161b1994897Sopenharmony_ci    bool RecordValidName();
162b1994897Sopenharmony_ci    bool ParseArrayFullSign();
163b1994897Sopenharmony_ci    bool IsConstArray();
164b1994897Sopenharmony_ci    bool ParseArrayName();
165b1994897Sopenharmony_ci    bool ArrayValidName();
166b1994897Sopenharmony_ci    bool ArrayElementsValidNumber();
167b1994897Sopenharmony_ci    bool ParseArrayElements();
168b1994897Sopenharmony_ci    bool ParseArrayElement();
169b1994897Sopenharmony_ci    bool ParseArrayElementType();
170b1994897Sopenharmony_ci    bool ParseArrayElementValue();
171b1994897Sopenharmony_ci    bool ParseArrayElementValueInteger();
172b1994897Sopenharmony_ci    bool ParseArrayElementValueFloat();
173b1994897Sopenharmony_ci    bool ParseArrayElementValueString();
174b1994897Sopenharmony_ci    bool ParseFieldName();
175b1994897Sopenharmony_ci    bool ParseFieldType();
176b1994897Sopenharmony_ci    std::optional<std::string> ParseStringLiteral();
177b1994897Sopenharmony_ci    int64_t MnemonicToBuiltinId();
178b1994897Sopenharmony_ci
179b1994897Sopenharmony_ci    bool ParseInteger(int64_t *value);
180b1994897Sopenharmony_ci    bool ParseFloat(double *value, bool is_64bit);
181b1994897Sopenharmony_ci    bool ParseOperandVreg();
182b1994897Sopenharmony_ci    bool ParseOperandComma();
183b1994897Sopenharmony_ci    bool ParseOperandInteger();
184b1994897Sopenharmony_ci    bool ParseOperandFloat(bool is_64bit);
185b1994897Sopenharmony_ci    bool ParseOperandId();
186b1994897Sopenharmony_ci    bool ParseOperandLabel();
187b1994897Sopenharmony_ci    bool ParseOperandField();
188b1994897Sopenharmony_ci    bool ParseOperandType(Type::VerificationType ver_type);
189b1994897Sopenharmony_ci    bool ParseOperandNone();
190b1994897Sopenharmony_ci    bool ParseOperandString();
191b1994897Sopenharmony_ci    bool ParseOperandLiteralArray();
192b1994897Sopenharmony_ci    bool ParseOperandCall();
193b1994897Sopenharmony_ci    bool ParseOperandSignature(std::string *sign);
194b1994897Sopenharmony_ci    bool ParseOperandSignatureTypesList(std::string *sign);
195b1994897Sopenharmony_ci    bool ParseOperandBuiltinMnemonic();
196b1994897Sopenharmony_ci
197b1994897Sopenharmony_ci    void SetFunctionInformation();
198b1994897Sopenharmony_ci    void SetRecordInformation();
199b1994897Sopenharmony_ci    void SetArrayInformation();
200b1994897Sopenharmony_ci    void SetOperationInformation();
201b1994897Sopenharmony_ci    void ParseAsCatchall(const std::vector<Token> &tokens);
202b1994897Sopenharmony_ci    void ParseAsLanguage(const std::vector<Token> &tokens, bool &is_lang_parsed, bool &is_first_statement);
203b1994897Sopenharmony_ci    void ParseAsRecord(const std::vector<Token> &tokens);
204b1994897Sopenharmony_ci    void ParseAsArray(const std::vector<Token> &tokens);
205b1994897Sopenharmony_ci    void ParseAsFunction(const std::vector<Token> &tokens);
206b1994897Sopenharmony_ci    void ParseAsBraceRight(const std::vector<Token> &tokens);
207b1994897Sopenharmony_ci    bool ParseAfterLine(bool &is_first_statement);
208b1994897Sopenharmony_ci    Expected<Program, Error> ParseAfterMainLoop(const std::string &file_name);
209b1994897Sopenharmony_ci    void ParseResetFunctionLabelsAndParams();
210b1994897Sopenharmony_ci    void ParseResetTables();
211b1994897Sopenharmony_ci    void ParseResetFunctionTable();
212b1994897Sopenharmony_ci    void ParseResetRecordTable();
213b1994897Sopenharmony_ci    void ParseResetArrayTable();
214b1994897Sopenharmony_ci    void ParseAsLanguageDirective();
215b1994897Sopenharmony_ci    Function::CatchBlock PrepareCatchBlock(bool is_catchall, size_t size, size_t catchall_tokens_num,
216b1994897Sopenharmony_ci                                           size_t catch_tokens_num);
217b1994897Sopenharmony_ci    void ParseAsCatchDirective();
218b1994897Sopenharmony_ci    void SetError();
219b1994897Sopenharmony_ci    void SetMetadataContextError(const Metadata::Error &err, bool has_value);
220b1994897Sopenharmony_ci
221b1994897Sopenharmony_ci    Expected<char, Error> ParseOctalEscapeSequence(std::string_view s, size_t *i);
222b1994897Sopenharmony_ci    Expected<char, Error> ParseHexEscapeSequence(std::string_view s, size_t *i);
223b1994897Sopenharmony_ci    Expected<char, Error> ParseEscapeSequence(std::string_view s, size_t *i);
224b1994897Sopenharmony_ci
225b1994897Sopenharmony_ci    template <class T>
226b1994897Sopenharmony_ci    auto TryEmplaceInTable(bool flag, T &item)
227b1994897Sopenharmony_ci    {
228b1994897Sopenharmony_ci        return item.try_emplace(std::string(context_.GiveToken().data(), context_.GiveToken().length()),
229b1994897Sopenharmony_ci                                std::string(context_.GiveToken().data(), context_.GiveToken().length()), program_.lang,
230b1994897Sopenharmony_ci                                context_.tokens[context_.number - 1].bound_left,
231b1994897Sopenharmony_ci                                context_.tokens[context_.number - 1].bound_right,
232b1994897Sopenharmony_ci                                context_.tokens[context_.number - 1].whole_line, flag, line_stric_);
233b1994897Sopenharmony_ci    }
234b1994897Sopenharmony_ci
235b1994897Sopenharmony_ci    template <class T>
236b1994897Sopenharmony_ci    bool AddObjectInTable(bool flag, T &item)
237b1994897Sopenharmony_ci    {
238b1994897Sopenharmony_ci        auto [iter, is_inserted] = TryEmplaceInTable(flag, item);
239b1994897Sopenharmony_ci
240b1994897Sopenharmony_ci        if (is_inserted) {
241b1994897Sopenharmony_ci            return true;
242b1994897Sopenharmony_ci        }
243b1994897Sopenharmony_ci
244b1994897Sopenharmony_ci        if (iter->second.file_location->is_defined && flag) {
245b1994897Sopenharmony_ci            return false;
246b1994897Sopenharmony_ci        }
247b1994897Sopenharmony_ci
248b1994897Sopenharmony_ci        if (!iter->second.file_location->is_defined && flag) {
249b1994897Sopenharmony_ci            iter->second.file_location->is_defined = true;
250b1994897Sopenharmony_ci            return true;
251b1994897Sopenharmony_ci        }
252b1994897Sopenharmony_ci
253b1994897Sopenharmony_ci        if (!iter->second.file_location->is_defined) {
254b1994897Sopenharmony_ci            iter->second.file_location->bound_left = context_.tokens[context_.number - 1].bound_left;
255b1994897Sopenharmony_ci            iter->second.file_location->bound_right = context_.tokens[context_.number - 1].bound_right;
256b1994897Sopenharmony_ci            iter->second.file_location->whole_line = context_.tokens[context_.number - 1].whole_line;
257b1994897Sopenharmony_ci            iter->second.file_location->line_number = line_stric_;
258b1994897Sopenharmony_ci        }
259b1994897Sopenharmony_ci
260b1994897Sopenharmony_ci        return true;
261b1994897Sopenharmony_ci    }
262b1994897Sopenharmony_ci};
263b1994897Sopenharmony_ci
264b1994897Sopenharmony_citemplate <>
265b1994897Sopenharmony_ciinline auto Parser::TryEmplaceInTable(bool flag, std::unordered_map<std::string, panda::pandasm::Label> &item)
266b1994897Sopenharmony_ci{
267b1994897Sopenharmony_ci    return item.try_emplace(std::string(context_.GiveToken().data(), context_.GiveToken().length()),
268b1994897Sopenharmony_ci                            std::string(context_.GiveToken().data(), context_.GiveToken().length()),
269b1994897Sopenharmony_ci                            context_.tokens[context_.number - 1].bound_left,
270b1994897Sopenharmony_ci                            context_.tokens[context_.number - 1].bound_right,
271b1994897Sopenharmony_ci                            context_.tokens[context_.number - 1].whole_line, flag, line_stric_);
272b1994897Sopenharmony_ci}
273b1994897Sopenharmony_ci
274b1994897Sopenharmony_ci}  // namespace panda::pandasm
275b1994897Sopenharmony_ci
276b1994897Sopenharmony_ci#endif  // ASSEMBLER_ASSEMBLY_PARSER_H
277