[mlir] Use StringRef::{starts,ends}_with (NFC)
[llvm-project.git] / mlir / lib / AsmParser / LocationParser.cpp
blobfed65c070121dd80c531547bec56db005bd20c75
1 //===- LocationParser.cpp - MLIR Location Parser -------------------------===//
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 //===----------------------------------------------------------------------===//
9 #include "Parser.h"
10 #include "Token.h"
11 #include "mlir/IR/Attributes.h"
12 #include "mlir/IR/BuiltinAttributes.h"
13 #include "mlir/IR/Location.h"
14 #include "mlir/Support/LLVM.h"
15 #include "mlir/Support/LogicalResult.h"
17 using namespace mlir;
18 using namespace mlir::detail;
20 /// Specific location instances.
21 ///
22 /// location-inst ::= filelinecol-location |
23 /// name-location |
24 /// callsite-location |
25 /// fused-location |
26 /// unknown-location
27 /// filelinecol-location ::= string-literal ':' integer-literal
28 /// ':' integer-literal
29 /// name-location ::= string-literal
30 /// callsite-location ::= 'callsite' '(' location-inst 'at' location-inst ')'
31 /// fused-location ::= fused ('<' attribute-value '>')?
32 /// '[' location-inst (location-inst ',')* ']'
33 /// unknown-location ::= 'unknown'
34 ///
35 ParseResult Parser::parseCallSiteLocation(LocationAttr &loc) {
36 consumeToken(Token::bare_identifier);
38 // Parse the '('.
39 if (parseToken(Token::l_paren, "expected '(' in callsite location"))
40 return failure();
42 // Parse the callee location.
43 LocationAttr calleeLoc;
44 if (parseLocationInstance(calleeLoc))
45 return failure();
47 // Parse the 'at'.
48 if (getToken().isNot(Token::bare_identifier) ||
49 getToken().getSpelling() != "at")
50 return emitWrongTokenError("expected 'at' in callsite location");
51 consumeToken(Token::bare_identifier);
53 // Parse the caller location.
54 LocationAttr callerLoc;
55 if (parseLocationInstance(callerLoc))
56 return failure();
58 // Parse the ')'.
59 if (parseToken(Token::r_paren, "expected ')' in callsite location"))
60 return failure();
62 // Return the callsite location.
63 loc = CallSiteLoc::get(calleeLoc, callerLoc);
64 return success();
67 ParseResult Parser::parseFusedLocation(LocationAttr &loc) {
68 consumeToken(Token::bare_identifier);
70 // Try to parse the optional metadata.
71 Attribute metadata;
72 if (consumeIf(Token::less)) {
73 metadata = parseAttribute();
74 if (!metadata)
75 return failure();
77 // Parse the '>' token.
78 if (parseToken(Token::greater,
79 "expected '>' after fused location metadata"))
80 return failure();
83 SmallVector<Location, 4> locations;
84 auto parseElt = [&] {
85 LocationAttr newLoc;
86 if (parseLocationInstance(newLoc))
87 return failure();
88 locations.push_back(newLoc);
89 return success();
92 if (parseCommaSeparatedList(Delimiter::Square, parseElt,
93 " in fused location"))
94 return failure();
96 // Return the fused location.
97 loc = FusedLoc::get(locations, metadata, getContext());
98 return success();
101 ParseResult Parser::parseNameOrFileLineColLocation(LocationAttr &loc) {
102 auto *ctx = getContext();
103 auto str = getToken().getStringValue();
104 consumeToken(Token::string);
106 // If the next token is ':' this is a filelinecol location.
107 if (consumeIf(Token::colon)) {
108 // Parse the line number.
109 if (getToken().isNot(Token::integer))
110 return emitWrongTokenError(
111 "expected integer line number in FileLineColLoc");
112 auto line = getToken().getUnsignedIntegerValue();
113 if (!line)
114 return emitWrongTokenError(
115 "expected integer line number in FileLineColLoc");
116 consumeToken(Token::integer);
118 // Parse the ':'.
119 if (parseToken(Token::colon, "expected ':' in FileLineColLoc"))
120 return failure();
122 // Parse the column number.
123 if (getToken().isNot(Token::integer))
124 return emitWrongTokenError(
125 "expected integer column number in FileLineColLoc");
126 auto column = getToken().getUnsignedIntegerValue();
127 if (!column.has_value())
128 return emitError("expected integer column number in FileLineColLoc");
129 consumeToken(Token::integer);
131 loc = FileLineColLoc::get(ctx, str, *line, *column);
132 return success();
135 // Otherwise, this is a NameLoc.
137 // Check for a child location.
138 if (consumeIf(Token::l_paren)) {
139 // Parse the child location.
140 LocationAttr childLoc;
141 if (parseLocationInstance(childLoc))
142 return failure();
144 loc = NameLoc::get(StringAttr::get(ctx, str), childLoc);
146 // Parse the closing ')'.
147 if (parseToken(Token::r_paren,
148 "expected ')' after child location of NameLoc"))
149 return failure();
150 } else {
151 loc = NameLoc::get(StringAttr::get(ctx, str));
154 return success();
157 ParseResult Parser::parseLocationInstance(LocationAttr &loc) {
158 // Handle aliases.
159 if (getToken().is(Token::hash_identifier)) {
160 Attribute locAttr = parseExtendedAttr(Type());
161 if (!locAttr)
162 return failure();
163 if (!(loc = dyn_cast<LocationAttr>(locAttr)))
164 return emitError("expected location attribute, but got") << locAttr;
165 return success();
168 // Handle either name or filelinecol locations.
169 if (getToken().is(Token::string))
170 return parseNameOrFileLineColLocation(loc);
172 // Bare tokens required for other cases.
173 if (!getToken().is(Token::bare_identifier))
174 return emitWrongTokenError("expected location instance");
176 // Check for the 'callsite' signifying a callsite location.
177 if (getToken().getSpelling() == "callsite")
178 return parseCallSiteLocation(loc);
180 // If the token is 'fused', then this is a fused location.
181 if (getToken().getSpelling() == "fused")
182 return parseFusedLocation(loc);
184 // Check for a 'unknown' for an unknown location.
185 if (getToken().getSpelling() == "unknown") {
186 consumeToken(Token::bare_identifier);
187 loc = UnknownLoc::get(getContext());
188 return success();
191 return emitWrongTokenError("expected location instance");