1 //===- Parser.h - MLIR Base Parser Class ------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef MLIR_LIB_PARSER_PARSER_H
10 #define MLIR_LIB_PARSER_PARSER_H
11 
12 #include "ParserState.h"
13 #include "mlir/IR/Builders.h"
14 #include "mlir/IR/OpImplementation.h"
15 
16 namespace mlir {
17 namespace detail {
18 //===----------------------------------------------------------------------===//
19 // Parser
20 //===----------------------------------------------------------------------===//
21 
22 /// This class implement support for parsing global entities like attributes and
23 /// types. It is intended to be subclassed by specialized subparsers that
24 /// include state.
25 class Parser {
26 public:
27   Builder builder;
28 
Parser(ParserState & state)29   Parser(ParserState &state) : builder(state.context), state(state) {}
30 
31   // Helper methods to get stuff from the parser-global state.
getState()32   ParserState &getState() const { return state; }
getContext()33   MLIRContext *getContext() const { return state.context; }
getSourceMgr()34   const llvm::SourceMgr &getSourceMgr() { return state.lex.getSourceMgr(); }
35 
36   /// Parse a comma-separated list of elements up until the specified end token.
37   ParseResult
38   parseCommaSeparatedListUntil(Token::Kind rightToken,
39                                function_ref<ParseResult()> parseElement,
40                                bool allowEmptyList = true);
41 
42   /// Parse a comma separated list of elements that must have at least one entry
43   /// in it.
44   ParseResult parseCommaSeparatedList(function_ref<ParseResult()> parseElement);
45 
46   ParseResult parsePrettyDialectSymbolName(StringRef &prettyName);
47 
48   // We have two forms of parsing methods - those that return a non-null
49   // pointer on success, and those that return a ParseResult to indicate whether
50   // they returned a failure.  The second class fills in by-reference arguments
51   // as the results of their action.
52 
53   //===--------------------------------------------------------------------===//
54   // Error Handling
55   //===--------------------------------------------------------------------===//
56 
57   /// Emit an error and return failure.
58   InFlightDiagnostic emitError(const Twine &message = {}) {
59     return emitError(state.curToken.getLoc(), message);
60   }
61   InFlightDiagnostic emitError(llvm::SMLoc loc, const Twine &message = {});
62 
63   /// Encode the specified source location information into an attribute for
64   /// attachment to the IR.
getEncodedSourceLocation(llvm::SMLoc loc)65   Location getEncodedSourceLocation(llvm::SMLoc loc) {
66     // If there are no active nested parsers, we can get the encoded source
67     // location directly.
68     if (state.parserDepth == 0)
69       return state.lex.getEncodedSourceLocation(loc);
70     // Otherwise, we need to re-encode it to point to the top level buffer.
71     return state.symbols.topLevelLexer->getEncodedSourceLocation(
72         remapLocationToTopLevelBuffer(loc));
73   }
74 
75   /// Remaps the given SMLoc to the top level lexer of the parser. This is used
76   /// to adjust locations of potentially nested parsers to ensure that they can
77   /// be emitted properly as diagnostics.
remapLocationToTopLevelBuffer(llvm::SMLoc loc)78   llvm::SMLoc remapLocationToTopLevelBuffer(llvm::SMLoc loc) {
79     // If there are no active nested parsers, we can return location directly.
80     SymbolState &symbols = state.symbols;
81     if (state.parserDepth == 0)
82       return loc;
83     assert(symbols.topLevelLexer && "expected valid top-level lexer");
84 
85     // Otherwise, we need to remap the location to the main parser. This is
86     // simply offseting the location onto the location of the last nested
87     // parser.
88     size_t offset = loc.getPointer() - state.lex.getBufferBegin();
89     auto *rawLoc =
90         symbols.nestedParserLocs[state.parserDepth - 1].getPointer() + offset;
91     return llvm::SMLoc::getFromPointer(rawLoc);
92   }
93 
94   //===--------------------------------------------------------------------===//
95   // Token Parsing
96   //===--------------------------------------------------------------------===//
97 
98   /// Return the current token the parser is inspecting.
getToken()99   const Token &getToken() const { return state.curToken; }
getTokenSpelling()100   StringRef getTokenSpelling() const { return state.curToken.getSpelling(); }
101 
102   /// If the current token has the specified kind, consume it and return true.
103   /// If not, return false.
consumeIf(Token::Kind kind)104   bool consumeIf(Token::Kind kind) {
105     if (state.curToken.isNot(kind))
106       return false;
107     consumeToken(kind);
108     return true;
109   }
110 
111   /// Advance the current lexer onto the next token.
consumeToken()112   void consumeToken() {
113     assert(state.curToken.isNot(Token::eof, Token::error) &&
114            "shouldn't advance past EOF or errors");
115     state.curToken = state.lex.lexToken();
116   }
117 
118   /// Advance the current lexer onto the next token, asserting what the expected
119   /// current token is.  This is preferred to the above method because it leads
120   /// to more self-documenting code with better checking.
consumeToken(Token::Kind kind)121   void consumeToken(Token::Kind kind) {
122     assert(state.curToken.is(kind) && "consumed an unexpected token");
123     consumeToken();
124   }
125 
126   /// Consume the specified token if present and return success.  On failure,
127   /// output a diagnostic and return failure.
128   ParseResult parseToken(Token::Kind expectedToken, const Twine &message);
129 
130   /// Parse an optional integer value from the stream.
131   OptionalParseResult parseOptionalInteger(APInt &result);
132 
133   /// Parse a floating point value from an integer literal token.
134   ParseResult parseFloatFromIntegerLiteral(Optional<APFloat> &result,
135                                            const Token &tok, bool isNegative,
136                                            const llvm::fltSemantics &semantics,
137                                            size_t typeSizeInBits);
138 
139   //===--------------------------------------------------------------------===//
140   // Type Parsing
141   //===--------------------------------------------------------------------===//
142 
143   ParseResult parseFunctionResultTypes(SmallVectorImpl<Type> &elements);
144   ParseResult parseTypeListNoParens(SmallVectorImpl<Type> &elements);
145   ParseResult parseTypeListParens(SmallVectorImpl<Type> &elements);
146 
147   /// Optionally parse a type.
148   OptionalParseResult parseOptionalType(Type &type);
149 
150   /// Parse an arbitrary type.
151   Type parseType();
152 
153   /// Parse a complex type.
154   Type parseComplexType();
155 
156   /// Parse an extended type.
157   Type parseExtendedType();
158 
159   /// Parse a function type.
160   Type parseFunctionType();
161 
162   /// Parse a memref type.
163   Type parseMemRefType();
164 
165   /// Parse a non function type.
166   Type parseNonFunctionType();
167 
168   /// Parse a tensor type.
169   Type parseTensorType();
170 
171   /// Parse a tuple type.
172   Type parseTupleType();
173 
174   /// Parse a vector type.
175   VectorType parseVectorType();
176   ParseResult parseDimensionListRanked(SmallVectorImpl<int64_t> &dimensions,
177                                        bool allowDynamic = true);
178   ParseResult parseXInDimensionList();
179 
180   /// Parse strided layout specification.
181   ParseResult parseStridedLayout(int64_t &offset,
182                                  SmallVectorImpl<int64_t> &strides);
183 
184   // Parse a brace-delimiter list of comma-separated integers with `?` as an
185   // unknown marker.
186   ParseResult parseStrideList(SmallVectorImpl<int64_t> &dimensions);
187 
188   //===--------------------------------------------------------------------===//
189   // Attribute Parsing
190   //===--------------------------------------------------------------------===//
191 
192   /// Parse an arbitrary attribute with an optional type.
193   Attribute parseAttribute(Type type = {});
194 
195   /// Parse an optional attribute with the provided type.
196   OptionalParseResult parseOptionalAttribute(Attribute &attribute,
197                                              Type type = {});
198   OptionalParseResult parseOptionalAttribute(ArrayAttr &attribute, Type type);
199   OptionalParseResult parseOptionalAttribute(StringAttr &attribute, Type type);
200 
201   /// Parse an optional attribute that is demarcated by a specific token.
202   template <typename AttributeT>
203   OptionalParseResult parseOptionalAttributeWithToken(Token::Kind kind,
204                                                       AttributeT &attr,
205                                                       Type type = {}) {
206     if (getToken().isNot(kind))
207       return llvm::None;
208 
209     if (Attribute parsedAttr = parseAttribute(type)) {
210       attr = parsedAttr.cast<AttributeT>();
211       return success();
212     }
213     return failure();
214   }
215 
216   /// Parse an attribute dictionary.
217   ParseResult parseAttributeDict(NamedAttrList &attributes);
218 
219   /// Parse an extended attribute.
220   Attribute parseExtendedAttr(Type type);
221 
222   /// Parse a float attribute.
223   Attribute parseFloatAttr(Type type, bool isNegative);
224 
225   /// Parse a decimal or a hexadecimal literal, which can be either an integer
226   /// or a float attribute.
227   Attribute parseDecOrHexAttr(Type type, bool isNegative);
228 
229   /// Parse an opaque elements attribute.
230   Attribute parseOpaqueElementsAttr(Type attrType);
231 
232   /// Parse a dense elements attribute.
233   Attribute parseDenseElementsAttr(Type attrType);
234   ShapedType parseElementsLiteralType(Type type);
235 
236   /// Parse a sparse elements attribute.
237   Attribute parseSparseElementsAttr(Type attrType);
238 
239   //===--------------------------------------------------------------------===//
240   // Location Parsing
241   //===--------------------------------------------------------------------===//
242 
243   /// Parse a raw location instance.
244   ParseResult parseLocationInstance(LocationAttr &loc);
245 
246   /// Parse a callsite location instance.
247   ParseResult parseCallSiteLocation(LocationAttr &loc);
248 
249   /// Parse a fused location instance.
250   ParseResult parseFusedLocation(LocationAttr &loc);
251 
252   /// Parse a name or FileLineCol location instance.
253   ParseResult parseNameOrFileLineColLocation(LocationAttr &loc);
254 
255   //===--------------------------------------------------------------------===//
256   // Affine Parsing
257   //===--------------------------------------------------------------------===//
258 
259   /// Parse a reference to either an affine map, or an integer set.
260   ParseResult parseAffineMapOrIntegerSetReference(AffineMap &map,
261                                                   IntegerSet &set);
262   ParseResult parseAffineMapReference(AffineMap &map);
263   ParseResult parseIntegerSetReference(IntegerSet &set);
264 
265   /// Parse an AffineMap where the dim and symbol identifiers are SSA ids.
266   ParseResult
267   parseAffineMapOfSSAIds(AffineMap &map,
268                          function_ref<ParseResult(bool)> parseElement,
269                          OpAsmParser::Delimiter delimiter);
270 
271   /// Parse an AffineExpr where dim and symbol identifiers are SSA ids.
272   ParseResult
273   parseAffineExprOfSSAIds(AffineExpr &expr,
274                           function_ref<ParseResult(bool)> parseElement);
275 
276 protected:
277   /// The Parser is subclassed and reinstantiated.  Do not add additional
278   /// non-trivial state here, add it to the ParserState class.
279   ParserState &state;
280 };
281 } // end namespace detail
282 } // end namespace mlir
283 
284 #endif // MLIR_LIB_PARSER_PARSER_H
285