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