27 #include "llvm/Support/MemoryBuffer.h"
28 #include "llvm/Support/SourceMgr.h"
35 using llvm::MemoryBuffer;
36 using llvm::SourceMgr;
42 class CustomDialectAsmParser :
public AsmParserImpl<DialectAsmParser> {
44 CustomDialectAsmParser(StringRef fullSpec,
Parser &parser)
47 ~CustomDialectAsmParser()
override =
default;
51 StringRef getFullSymbolSpec()
const override {
return fullSpec; }
68 bool &isCodeCompletion) {
77 assert(*curPtr ==
'<');
82 auto emitPunctError = [&] {
83 return emitError() <<
"unbalanced '" << nestedPunctuation.back()
84 <<
"' character in pretty dialect name";
87 auto checkNestedPunctuation = [&](
char expectedToken) ->
ParseResult {
88 if (nestedPunctuation.back() != expectedToken)
89 return emitPunctError();
90 nestedPunctuation.pop_back();
96 if (curPtr == codeCompleteLoc) {
97 isCodeCompletion =
true;
98 nestedPunctuation.clear();
106 if (!nestedPunctuation.empty())
107 return emitPunctError();
108 return emitError(
"unexpected nul or EOF in pretty dialect name");
113 nestedPunctuation.push_back(c);
123 if (
failed(checkNestedPunctuation(
'<')))
127 if (
failed(checkNestedPunctuation(
'[')))
131 if (
failed(checkNestedPunctuation(
'(')))
135 if (
failed(checkNestedPunctuation(
'{')))
146 isCodeCompletion =
true;
147 nestedPunctuation.clear();
160 }
while (!nestedPunctuation.empty());
166 unsigned length = curPtr - body.begin();
167 body = StringRef(body.data(), length);
172 template <
typename Symbol,
typename SymbolAliasMap,
typename CreateFn>
174 SymbolAliasMap &aliases,
175 CreateFn &&createSymbol) {
179 StringRef identifier = tok.
getSpelling().drop_front();
189 auto [dialectName, symbolData] = identifier.split(
'.');
190 bool isPrettyName = !symbolData.empty() || identifier.back() ==
'.';
194 bool hasTrailingData =
200 if (!hasTrailingData && !isPrettyName) {
202 auto aliasIt = aliases.find(identifier);
203 if (aliasIt == aliases.end())
208 if constexpr (std::is_same_v<Symbol, Type>)
213 return aliasIt->second;
221 symbolData = StringRef(dialectName.end(), 0);
224 bool isCodeCompletion =
false;
227 symbolData = symbolData.drop_front();
231 if (!isCodeCompletion)
232 symbolData = symbolData.drop_back();
234 loc = SMLoc::getFromPointer(symbolData.data());
242 return createSymbol(dialectName, symbolData, loc);
255 Attribute attr = parseExtendedSymbol<Attribute>(
257 [&](StringRef dialectName, StringRef symbolData, SMLoc loc) ->
Attribute {
259 Type attrType = type;
260 if (consumeIf(Token::colon) && !(attrType = parseType()))
264 if (Dialect *dialect =
265 builder.getContext()->getOrLoadDialect(dialectName)) {
267 const char *curLexerPos = getToken().getLoc().getPointer();
268 resetToken(symbolData.data());
271 CustomDialectAsmParser customParser(symbolData, *this);
272 Attribute attr = dialect->parseAttribute(customParser, attrType);
273 resetToken(curLexerPos);
278 return OpaqueAttr::getChecked(
284 auto typedAttr = dyn_cast_or_null<TypedAttr>(attr);
285 if (type && typedAttr && typedAttr.getType() != type) {
286 emitError(
"attribute type different than expected: expected ")
287 << type <<
", but got " << typedAttr.getType();
300 Type Parser::parseExtendedType() {
302 return parseExtendedSymbol<Type>(
303 *
this, state.asmState, state.symbols.typeAliasDefinitions,
304 [&](StringRef dialectName, StringRef symbolData, SMLoc loc) ->
Type {
306 if (auto *dialect = ctx->getOrLoadDialect(dialectName)) {
308 const char *curLexerPos = getToken().getLoc().getPointer();
309 resetToken(symbolData.data());
312 CustomDialectAsmParser customParser(symbolData, *this);
313 Type type = dialect->parseType(customParser);
314 resetToken(curLexerPos);
319 return OpaqueType::getChecked([&] { return emitError(loc); },
331 template <
typename T,
typename ParserFn>
333 size_t *numReadOut,
bool isKnownNullTerminated,
334 ParserFn &&parserFn) {
338 isKnownNullTerminated
339 ? MemoryBuffer::getMemBuffer(inputStr,
341 : MemoryBuffer::getMemBufferCopy(inputStr, inputStr);
343 sourceMgr.AddNewSourceBuffer(std::move(memBuffer), SMLoc());
346 ParserState state(sourceMgr, config, aliasState,
nullptr,
351 T symbol = parserFn(parser);
358 endTok.
getLoc().getPointer() - startTok.
getLoc().getPointer();
360 *numReadOut = numRead;
361 }
else if (numRead != inputStr.size()) {
363 << inputStr.drop_front(numRead) <<
"'";
370 Type type,
size_t *numRead,
371 bool isKnownNullTerminated) {
372 return parseSymbol<Attribute>(
373 attrStr, context, numRead, isKnownNullTerminated,
377 bool isKnownNullTerminated) {
378 return parseSymbol<Type>(typeStr, context, numRead, isKnownNullTerminated,
static Symbol parseExtendedSymbol(Parser &p, AsmParserState *asmState, SymbolAliasMap &aliases, CreateFn &&createSymbol)
Parse an extended dialect symbol.
static T parseSymbol(StringRef inputStr, MLIRContext *context, size_t *numReadOut, bool isKnownNullTerminated, ParserFn &&parserFn)
Parses a symbol, of type 'T', and returns it if parsing was successful.
static MLIRContext * getContext(OpFoldResult val)
This class represents state from a parsed MLIR textual format string.
void addTypeAliasUses(StringRef name, SMRange locations)
void addAttrAliasUses(StringRef name, SMRange locations)
Attributes are known-constant values of operations.
The DialectAsmParser has methods for interacting with the asm parser when parsing attributes and type...
const char * getCodeCompleteLoc() const
Return the code completion location of the lexer, or nullptr if there is none.
MLIRContext is the top-level object for a collection of MLIR operations.
This class represents success/failure for parsing-like operations that find it important to chain tog...
This class represents a configuration for the MLIR assembly parser.
This represents a token in the MLIR syntax.
SMRange getLocRange() const
bool isCodeCompletion() const
Returns true if the current token represents a code completion.
StringRef getSpelling() const
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class provides the implementation of the generic parser methods within AsmParser.
This class implement support for parsing global entities like attributes and types.
Type parseType()
Parse an arbitrary type.
InFlightDiagnostic emitError(const Twine &message={})
Emit an error and return failure.
ParserState & state
The Parser is subclassed and reinstantiated.
Attribute parseAttribute(Type type={})
Parse an arbitrary attribute with an optional type.
StringRef getTokenSpelling() const
void consumeToken()
Advance the current lexer onto the next token.
ParseResult parseDialectSymbolBody(StringRef &body, bool &isCodeCompletion)
Parse the body of a dialect symbol, which starts and ends with <>'s, and may be recursive.
MLIRContext * getContext() const
InFlightDiagnostic emitWrongTokenError(const Twine &message={})
Emit an error about a "wrong token".
void resetToken(const char *tokPos)
Reset the parser to the given lexer position.
Attribute parseExtendedAttr(Type type)
Parse an extended attribute.
const Token & getToken() const
Return the current token the parser is inspecting.
Attribute codeCompleteDialectSymbol(const llvm::StringMap< Attribute > &aliases)
Detect if any of the given parameter types has a sub-element handler.
Include the generated interface declarations.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Attribute parseAttribute(llvm::StringRef attrStr, MLIRContext *context, Type type={}, size_t *numRead=nullptr, bool isKnownNullTerminated=false)
This parses a single MLIR attribute to an MLIR context if it was valid.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
Type parseType(llvm::StringRef typeStr, MLIRContext *context, size_t *numRead=nullptr, bool isKnownNullTerminated=false)
This parses a single MLIR type to an MLIR context if it was valid.
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
This class refers to all of the state maintained globally by the parser, such as the current lexer po...
SymbolState & symbols
The current state for symbol parsing.
Lexer lex
The lexer for the source file we're parsing.
Token curToken
This is the next token that hasn't been consumed yet.
AsmParserState * asmState
An optional pointer to a struct containing high level parser state to be populated during parsing.
This class contains record of any parsed top-level symbols.
llvm::StringMap< Attribute > attributeAliasDefinitions
A map from attribute alias identifier to Attribute.