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