1 /*
2 * Copyright (c) 2021-2024 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 PANDA_ASSEMBLER_ASSEMBLY_PARSER_H
17 #define PANDA_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 ark::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 PANDA_PUBLIC_API Expected<Program, Error> Parse(TokenSet &vectorsTokens, const std::string &fileName = "");
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 PANDA_PUBLIC_API Expected<Program, Error> Parse(const std::string &source, const std::string &fileName = "");
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 ark::pandasm::Program program_;
89 std::unordered_map<std::string, ark::pandasm::Label> *labelTable_ = nullptr;
90 Metadata *metadata_ = nullptr;
91 Context context_; /* token iterator */
92 ark::pandasm::Record *currRecord_ = nullptr;
93 ark::pandasm::LiteralArray *currArray_ = nullptr;
94 bool isConstArray_ = false;
95 ark::pandasm::LiteralArray::Literal *currArrayElem_ = nullptr;
96 ark::pandasm::Function *currFunc_ = nullptr;
97 ark::pandasm::Ins *currIns_ = nullptr;
98 ark::pandasm::Field *currFld_ = nullptr;
99 size_t lineStric_ = 0;
100 ark::pandasm::Error err_;
101 ark::pandasm::ErrorList war_;
102 bool open_ = false; /* flag of being in a code section */
103 bool recordDef_ = false;
104 bool arrayDef_ = false;
105 bool funcDef_ = false;
106 static constexpr uint32_t INTRO_CONST_ARRAY_LITERALS_NUMBER = 2;
107
108 inline Error GetError(const std::string &mess = "", Error::ErrorType err = Error::ErrorType::ERR_NONE,
109 int8_t shift = 0, int tokenShift = 0, const std::string &addMess = "") const
110 {
111 return Error(mess, lineStric_, err, addMess,
112 context_.tokens[static_cast<int>(context_.number) + tokenShift - 1].boundLeft + shift,
113 context_.tokens[static_cast<int>(context_.number) + tokenShift - 1].boundRight,
114 context_.tokens[static_cast<int>(context_.number) + tokenShift - 1].wholeLine);
115 }
116
117 inline void GetWarning(const std::string &mess = "", Error::ErrorType err = Error::ErrorType::ERR_NONE,
118 int8_t shift = 0, const std::string &addMess = "")
119 {
120 war_.emplace_back(mess, lineStric_, err, addMess,
121 context_.tokens[context_.number - 1].boundLeft + static_cast<size_t>(shift),
122 context_.tokens[context_.number - 1].boundRight,
123 context_.tokens[context_.number - 1].wholeLine, Error::ErrorClass::WARNING);
124 }
125
GetCurrentPosition(bool leftBound)126 SourcePosition GetCurrentPosition(bool leftBound) const
127 {
128 if (leftBound) {
129 return SourcePosition {lineStric_, context_.tokens[context_.number - 1].boundLeft};
130 }
131 return SourcePosition {lineStric_, context_.tokens[context_.number - 1].boundRight};
132 }
133
134 bool LabelValidName();
135 bool TypeValidName();
136 bool RegValidName();
137 bool ParamValidName();
138 bool FunctionValidName();
139 bool ParseFunctionName();
140 bool ParseLabel();
141 bool ParseOperation();
142 bool ParseOperands();
143 bool ParseFunctionCode();
144 bool ParseFunctionInstruction();
145 bool ParseFunctionFullSign();
146 bool UpdateFunctionName();
147 bool ParseFunctionReturn();
148 bool ParseFunctionArg();
149 bool ParseFunctionArgComma(bool &comma);
150 bool ParseFunctionArgs();
151 bool ParseType(Type *type);
152 bool PrefixedValidName(bool allowBrackets = false);
153 bool ParseMetaListComma(bool &comma, bool eq);
154 bool MeetExpMetaList(bool eq);
155 bool BuildMetaListAttr(bool &eq, std::string &attributeName, std::string &attributeValue);
156 bool ParseMetaList(bool flag);
157 bool ParseMetaDef();
158 bool ParseRecordFullSign();
159 bool ParseRecordFields();
160 bool ParseRecordField();
161 bool ParseRecordName();
162 bool RecordValidName();
163 bool ParseArrayFullSign();
164 bool IsConstArray();
165 bool ParseArrayName();
166 bool ArrayValidName();
167 bool ArrayElementsValidNumber();
168 bool ParseArrayElements();
169 bool ParseArrayElement();
170 bool ParseArrayElementType();
171 bool ParseArrayElementValue();
172 bool ParseArrayElementValueInteger();
173 bool ParseArrayElementValueFloat();
174 bool ParseArrayElementValueString();
175 bool ParseFieldName();
176 bool ParseFieldType();
177 std::optional<std::string> ParseStringLiteral();
178 int64_t MnemonicToBuiltinId();
179 uint8_t ParseMultiArrayHallmark();
180
181 bool ParseInteger(int64_t *value);
182 bool ParseFloat(double *value, bool is64bit);
183 bool ParseOperandVreg();
184 bool ParseOperandComma();
185 bool ParseOperandInteger();
186 bool ParseOperandFloat(bool is64bit);
187 bool ParseOperandId();
188 bool ParseOperandLabel();
189 bool ParseOperandField();
190 bool ParseOperandType(Type::VerificationType verType);
191 bool ParseOperandNone();
192 bool ParseOperandString();
193 bool ParseOperandLiteralArray();
194 bool ParseOperandCall();
195 bool ParseOperandSignature(std::string *sign);
196 bool ParseOperandSignatureTypesList(std::string *sign);
197 bool ParseOperandBuiltinMnemonic();
198 bool ParseOperandInitobj();
199
200 void SetFunctionInformation();
201 void SetRecordInformation(const std::string &recordName);
202 void SetArrayInformation();
203 void SetOperationInformation();
204 void ParseAsCatchall(const std::vector<Token> &tokens);
205 void ParseAsLanguage(const std::vector<Token> &tokens, bool &isLangParsed, bool &isFirstStatement);
206 void ParseAsRecord(const std::vector<Token> &tokens);
207 void ParseAsArray(const std::vector<Token> &tokens);
208 void ParseAsFunction(const std::vector<Token> &tokens);
209 void ParseAsUnionField(const std::vector<Token> &tokens);
210 void ParseAsBraceRight(const std::vector<Token> &tokens);
211 bool ParseAfterLine(bool &isFirstStatement);
212 void ParseContextByType(const std::vector<Token> &tokens, bool &isLangParsed, bool &isFirstStatement);
213 Expected<Program, Error> ParseAfterMainLoop(const std::string &fileName);
214 void ParseResetFunctionLabelsAndParams();
215 void ParseResetTables();
216 void ParseResetFunctionTable();
217 void ParseInsFromFuncTable(ark::pandasm::Function &func);
218 void ParseResetRecordTable();
219 void ParseResetRecords(const ark::pandasm::Record &record);
220 void ParseResetArrayTable();
221 void ParseAsLanguageDirective();
222 Function::CatchBlock PrepareCatchBlock(bool isCatchall, size_t size, size_t catchallTokensNum,
223 size_t catchTokensNum);
224 void ParseAsCatchDirective();
225 void SetError();
226 void SetMetadataContextError(const Metadata::Error &err, bool hasValue);
227
228 Expected<char, Error> ParseOctalEscapeSequence(std::string_view s, size_t *i);
229 Expected<char, Error> ParseHexEscapeSequence(std::string_view s, size_t *i);
230 Expected<char, Error> ParseEscapeSequence(std::string_view s, size_t *i);
231
232 template <class T>
TryEmplaceInTable(bool flag,T & item,const std::string & cid)233 auto TryEmplaceInTable(bool flag, T &item, const std::string &cid)
234 {
235 return item.try_emplace(cid, cid, program_.lang, context_.tokens[context_.number - 1].boundLeft,
236 context_.tokens[context_.number - 1].boundRight,
237 context_.tokens[context_.number - 1].wholeLine, flag, lineStric_);
238 }
239
240 template <class T>
241 bool AddObjectInTable(bool flag, T &item, const std::string &cid = "")
242 {
243 std::string elem = !cid.empty() ? cid : std::string(context_.GiveToken().data(), context_.GiveToken().length());
244 auto [iter, is_inserted] = TryEmplaceInTable(flag, item, elem);
245
246 if (is_inserted) {
247 return true;
248 }
249
250 if (iter->second.fileLocation->isDefined && flag) {
251 return false;
252 }
253
254 if (!iter->second.fileLocation->isDefined && flag) {
255 iter->second.fileLocation->isDefined = true;
256 return true;
257 }
258
259 if (!iter->second.fileLocation->isDefined) {
260 iter->second.fileLocation->boundLeft = context_.tokens[context_.number - 1].boundLeft;
261 iter->second.fileLocation->boundRight = context_.tokens[context_.number - 1].boundRight;
262 iter->second.fileLocation->wholeLine = context_.tokens[context_.number - 1].wholeLine;
263 iter->second.fileLocation->lineNumber = lineStric_;
264 }
265
266 return true;
267 }
268 };
269
270 template <>
TryEmplaceInTable(bool flag,std::unordered_map<std::string,ark::pandasm::Label> & item,const std::string & cid)271 inline auto Parser::TryEmplaceInTable(bool flag, std::unordered_map<std::string, ark::pandasm::Label> &item,
272 [[maybe_unused]] const std::string &cid)
273 {
274 return item.try_emplace(std::string(context_.GiveToken().data(), context_.GiveToken().length()),
275 std::string(context_.GiveToken().data(), context_.GiveToken().length()),
276 context_.tokens[context_.number - 1].boundLeft,
277 context_.tokens[context_.number - 1].boundRight,
278 context_.tokens[context_.number - 1].wholeLine, flag, lineStric_);
279 }
280
281 } // namespace ark::pandasm
282
283 #endif // PANDA_ASSEMBLER_ASSEMBLY_PARSER_H
284