• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::Ins *curr_ins_ = nullptr;
97     panda::pandasm::Field *curr_fld_ = nullptr;
98     size_t line_stric_ = 0;
99     panda::pandasm::Error err_;
100     panda::pandasm::ErrorList war_;
101     bool open_ = false; /* flag of being in a code section */
102     bool record_def_ = false;
103     bool array_def_ = false;
104     bool func_def_ = false;
105     static constexpr uint32_t INTRO_CONST_ARRAY_LITERALS_NUMBER = 2;
106 
107     inline Error GetError(const std::string &mess = "", Error::ErrorType err = Error::ErrorType::ERR_NONE,
108                           int8_t shift = 0, int token_shift = 0, const std::string &add_mess = "") const
109     {
110         return Error(mess, line_stric_, err, add_mess,
111                      context_.tokens[static_cast<int>(context_.number) + token_shift - 1].bound_left + shift,
112                      context_.tokens[static_cast<int>(context_.number) + token_shift - 1].bound_right,
113                      context_.tokens[static_cast<int>(context_.number) + token_shift - 1].whole_line);
114     }
115 
116     inline void GetWarning(const std::string &mess = "", Error::ErrorType err = Error::ErrorType::ERR_NONE,
117                            int8_t shift = 0, const std::string &add_mess = "")
118     {
119         war_.emplace_back(mess, line_stric_, err, add_mess,
120                           context_.tokens[context_.number - 1].bound_left + static_cast<size_t>(shift),
121                           context_.tokens[context_.number - 1].bound_right,
122                           context_.tokens[context_.number - 1].whole_line, Error::ErrorClass::WARNING);
123     }
124 
GetCurrentPosition(bool left_bound)125     SourcePosition GetCurrentPosition(bool left_bound) const
126     {
127         if (left_bound) {
128             return SourcePosition {line_stric_, context_.tokens[context_.number - 1].bound_left};
129         }
130         return SourcePosition {line_stric_, context_.tokens[context_.number - 1].bound_right};
131     }
132 
133     bool LabelValidName();
134     bool TypeValidName();
135     bool RegValidName();
136     bool ParamValidName();
137     bool FunctionValidName();
138     bool ParseFunctionName();
139     bool ParseLabel();
140     bool ParseOperation();
141     bool ParseOperands();
142     bool ParseFunctionCode();
143     bool ParseFunctionInstruction();
144     bool ParseFunctionFullSign();
145     bool UpdateFunctionName();
146     bool ParseFunctionReturn();
147     bool ParseFunctionArg();
148     bool ParseFunctionArgComma(bool &comma);
149     bool ParseFunctionArgs();
150     bool ParseType(Type *type);
151     bool PrefixedValidName();
152     bool ParseMetaListComma(bool &comma, bool eq);
153     bool MeetExpMetaList(bool eq);
154     bool BuildMetaListAttr(bool &eq, std::string &attribute_name, std::string &attribute_value);
155     bool ParseMetaList(bool flag);
156     bool ParseMetaDef();
157     bool ParseRecordFullSign();
158     bool ParseRecordFields();
159     bool ParseRecordField();
160     bool ParseRecordName();
161     bool RecordValidName();
162     bool ParseArrayFullSign();
163     bool IsConstArray();
164     bool ParseArrayName();
165     bool ArrayValidName();
166     bool ArrayElementsValidNumber();
167     bool ParseArrayElements();
168     bool ParseArrayElement();
169     bool ParseArrayElementType();
170     bool ParseArrayElementValue();
171     bool ParseArrayElementValueInteger();
172     bool ParseArrayElementValueFloat();
173     bool ParseArrayElementValueString();
174     bool ParseFieldName();
175     bool ParseFieldType();
176     std::optional<std::string> ParseStringLiteral();
177     int64_t MnemonicToBuiltinId();
178 
179     bool ParseInteger(int64_t *value);
180     bool ParseFloat(double *value, bool is_64bit);
181     bool ParseOperandVreg();
182     bool ParseOperandComma();
183     bool ParseOperandInteger();
184     bool ParseOperandFloat(bool is_64bit);
185     bool ParseOperandId();
186     bool ParseOperandLabel();
187     bool ParseOperandField();
188     bool ParseOperandType(Type::VerificationType ver_type);
189     bool ParseOperandNone();
190     bool ParseOperandString();
191     bool ParseOperandLiteralArray();
192     bool ParseOperandCall();
193     bool ParseOperandSignature(std::string *sign);
194     bool ParseOperandSignatureTypesList(std::string *sign);
195     bool ParseOperandBuiltinMnemonic();
196 
197     void SetFunctionInformation();
198     void SetRecordInformation();
199     void SetArrayInformation();
200     void SetOperationInformation();
201     void ParseAsCatchall(const std::vector<Token> &tokens);
202     void ParseAsLanguage(const std::vector<Token> &tokens, bool &is_lang_parsed, bool &is_first_statement);
203     void ParseAsRecord(const std::vector<Token> &tokens);
204     void ParseAsArray(const std::vector<Token> &tokens);
205     void ParseAsFunction(const std::vector<Token> &tokens);
206     void ParseAsBraceRight(const std::vector<Token> &tokens);
207     bool ParseAfterLine(bool &is_first_statement);
208     Expected<Program, Error> ParseAfterMainLoop(const std::string &file_name);
209     void ParseResetFunctionLabelsAndParams();
210     void ParseResetTables();
211     void ParseResetFunctionTable();
212     void ParseResetRecordTable();
213     void ParseResetArrayTable();
214     void ParseAsLanguageDirective();
215     Function::CatchBlock PrepareCatchBlock(bool is_catchall, size_t size, size_t catchall_tokens_num,
216                                            size_t catch_tokens_num);
217     void ParseAsCatchDirective();
218     void SetError();
219     void SetMetadataContextError(const Metadata::Error &err, bool has_value);
220 
221     Expected<char, Error> ParseOctalEscapeSequence(std::string_view s, size_t *i);
222     Expected<char, Error> ParseHexEscapeSequence(std::string_view s, size_t *i);
223     Expected<char, Error> ParseEscapeSequence(std::string_view s, size_t *i);
224 
225     template <class T>
TryEmplaceInTable(bool flag,T & item)226     auto TryEmplaceInTable(bool flag, T &item)
227     {
228         return item.try_emplace(std::string(context_.GiveToken().data(), context_.GiveToken().length()),
229                                 std::string(context_.GiveToken().data(), context_.GiveToken().length()), program_.lang,
230                                 context_.tokens[context_.number - 1].bound_left,
231                                 context_.tokens[context_.number - 1].bound_right,
232                                 context_.tokens[context_.number - 1].whole_line, flag, line_stric_);
233     }
234 
235     template <class T>
AddObjectInTable(bool flag,T & item)236     bool AddObjectInTable(bool flag, T &item)
237     {
238         auto [iter, is_inserted] = TryEmplaceInTable(flag, item);
239 
240         if (is_inserted) {
241             return true;
242         }
243 
244         if (iter->second.file_location->is_defined && flag) {
245             return false;
246         }
247 
248         if (!iter->second.file_location->is_defined && flag) {
249             iter->second.file_location->is_defined = true;
250             return true;
251         }
252 
253         if (!iter->second.file_location->is_defined) {
254             iter->second.file_location->bound_left = context_.tokens[context_.number - 1].bound_left;
255             iter->second.file_location->bound_right = context_.tokens[context_.number - 1].bound_right;
256             iter->second.file_location->whole_line = context_.tokens[context_.number - 1].whole_line;
257             iter->second.file_location->line_number = line_stric_;
258         }
259 
260         return true;
261     }
262 };
263 
264 template <>
TryEmplaceInTable(bool flag,std::unordered_map<std::string,panda::pandasm::Label> & item)265 inline auto Parser::TryEmplaceInTable(bool flag, std::unordered_map<std::string, panda::pandasm::Label> &item)
266 {
267     return item.try_emplace(std::string(context_.GiveToken().data(), context_.GiveToken().length()),
268                             std::string(context_.GiveToken().data(), context_.GiveToken().length()),
269                             context_.tokens[context_.number - 1].bound_left,
270                             context_.tokens[context_.number - 1].bound_right,
271                             context_.tokens[context_.number - 1].whole_line, flag, line_stric_);
272 }
273 
274 }  // namespace panda::pandasm
275 
276 #endif  // ASSEMBLER_ASSEMBLY_PARSER_H
277