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   //===--------------------------------------------------------------------===//
131   // Type Parsing
132   //===--------------------------------------------------------------------===//
133 
134   ParseResult parseFunctionResultTypes(SmallVectorImpl<Type> &elements);
135   ParseResult parseTypeListNoParens(SmallVectorImpl<Type> &elements);
136   ParseResult parseTypeListParens(SmallVectorImpl<Type> &elements);
137 
138   /// Optionally parse a type.
139   OptionalParseResult parseOptionalType(Type &type);
140 
141   /// Parse an arbitrary type.
142   Type parseType();
143 
144   /// Parse a complex type.
145   Type parseComplexType();
146 
147   /// Parse an extended type.
148   Type parseExtendedType();
149 
150   /// Parse a function type.
151   Type parseFunctionType();
152 
153   /// Parse a memref type.
154   Type parseMemRefType();
155 
156   /// Parse a non function type.
157   Type parseNonFunctionType();
158 
159   /// Parse a tensor type.
160   Type parseTensorType();
161 
162   /// Parse a tuple type.
163   Type parseTupleType();
164 
165   /// Parse a vector type.
166   VectorType parseVectorType();
167   ParseResult parseDimensionListRanked(SmallVectorImpl<int64_t> &dimensions,
168                                        bool allowDynamic = true);
169   ParseResult parseXInDimensionList();
170 
171   /// Parse strided layout specification.
172   ParseResult parseStridedLayout(int64_t &offset,
173                                  SmallVectorImpl<int64_t> &strides);
174 
175   // Parse a brace-delimiter list of comma-separated integers with `?` as an
176   // unknown marker.
177   ParseResult parseStrideList(SmallVectorImpl<int64_t> &dimensions);
178 
179   //===--------------------------------------------------------------------===//
180   // Attribute Parsing
181   //===--------------------------------------------------------------------===//
182 
183   /// Parse an arbitrary attribute with an optional type.
184   Attribute parseAttribute(Type type = {});
185 
186   /// Parse an optional attribute with the provided type.
187   OptionalParseResult parseOptionalAttribute(Attribute &attribute,
188                                              Type type = {});
189   OptionalParseResult parseOptionalAttribute(ArrayAttr &attribute, Type type);
190   OptionalParseResult parseOptionalAttribute(StringAttr &attribute, Type type);
191 
192   /// Parse an optional attribute that is demarcated by a specific token.
193   template <typename AttributeT>
194   OptionalParseResult parseOptionalAttributeWithToken(Token::Kind kind,
195                                                       AttributeT &attr,
196                                                       Type type = {}) {
197     if (getToken().isNot(kind))
198       return llvm::None;
199 
200     if (Attribute parsedAttr = parseAttribute(type)) {
201       attr = parsedAttr.cast<AttributeT>();
202       return success();
203     }
204     return failure();
205   }
206 
207   /// Parse an attribute dictionary.
208   ParseResult parseAttributeDict(NamedAttrList &attributes);
209 
210   /// Parse an extended attribute.
211   Attribute parseExtendedAttr(Type type);
212 
213   /// Parse a float attribute.
214   Attribute parseFloatAttr(Type type, bool isNegative);
215 
216   /// Parse a decimal or a hexadecimal literal, which can be either an integer
217   /// or a float attribute.
218   Attribute parseDecOrHexAttr(Type type, bool isNegative);
219 
220   /// Parse an opaque elements attribute.
221   Attribute parseOpaqueElementsAttr(Type attrType);
222 
223   /// Parse a dense elements attribute.
224   Attribute parseDenseElementsAttr(Type attrType);
225   ShapedType parseElementsLiteralType(Type type);
226 
227   /// Parse a sparse elements attribute.
228   Attribute parseSparseElementsAttr(Type attrType);
229 
230   //===--------------------------------------------------------------------===//
231   // Location Parsing
232   //===--------------------------------------------------------------------===//
233 
234   /// Parse a raw location instance.
235   ParseResult parseLocationInstance(LocationAttr &loc);
236 
237   /// Parse a callsite location instance.
238   ParseResult parseCallSiteLocation(LocationAttr &loc);
239 
240   /// Parse a fused location instance.
241   ParseResult parseFusedLocation(LocationAttr &loc);
242 
243   /// Parse a name or FileLineCol location instance.
244   ParseResult parseNameOrFileLineColLocation(LocationAttr &loc);
245 
246   /// Parse an optional trailing location.
247   ///
248   ///   trailing-location ::= (`loc` (`(` location `)` | attribute-alias))?
249   ///
250   ParseResult parseOptionalTrailingLocation(Location &loc);
251 
252   //===--------------------------------------------------------------------===//
253   // Affine Parsing
254   //===--------------------------------------------------------------------===//
255 
256   /// Parse a reference to either an affine map, or an integer set.
257   ParseResult parseAffineMapOrIntegerSetReference(AffineMap &map,
258                                                   IntegerSet &set);
259   ParseResult parseAffineMapReference(AffineMap &map);
260   ParseResult parseIntegerSetReference(IntegerSet &set);
261 
262   /// Parse an AffineMap where the dim and symbol identifiers are SSA ids.
263   ParseResult
264   parseAffineMapOfSSAIds(AffineMap &map,
265                          function_ref<ParseResult(bool)> parseElement,
266                          OpAsmParser::Delimiter delimiter);
267 
268 private:
269   /// The Parser is subclassed and reinstantiated.  Do not add additional
270   /// non-trivial state here, add it to the ParserState class.
271   ParserState &state;
272 };
273 } // end namespace detail
274 } // end namespace mlir
275 
276 #endif // MLIR_LIB_PARSER_PARSER_H
277