clang: lib/Tooling/Transformer/Parsing.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

17#include "llvm/ADT/StringMap.h"

18#include "llvm/ADT/StringRef.h"

19#include "llvm/Support/Errc.h"

20#include "llvm/Support/Error.h"

21#include

22#include

23#include

24#include

25

26using namespace clang;

27using namespace transformer;

28

29

30

31

32

33

34

35namespace {

37

38template <typename... Ts> using RangeSelectorOp = RangeSelector (*)(Ts...);

39

40struct ParseState {

41

42 StringRef Input;

43

44

45 StringRef OriginalInput;

46};

47

48

49

50template struct ParseProgress {

51 ParseState State;

52

54};

55

57template using ParseFunction = ExpectedProgress (*)(ParseState);

58

59class ParseError : public llvm::ErrorInfo {

60public:

61

62 static char ID;

63

64 ParseError(size_t Pos, std::string ErrorMsg, std::string InputExcerpt)

65 : Pos(Pos), ErrorMsg(std::move(ErrorMsg)),

66 Excerpt(std::move(InputExcerpt)) {}

67

68 void log(llvm::raw_ostream &OS) const override {

69 OS << "parse error at position (" << Pos << "): " << ErrorMsg

70 << ": " + Excerpt;

71 }

72

73 std::error_code convertToErrorCode() const override {

74 return llvm::inconvertibleErrorCode();

75 }

76

77

78 size_t Pos;

79 std::string ErrorMsg;

80

81 std::string Excerpt;

82};

83

84char ParseError::ID;

85}

86

87static const llvm::StringMap<RangeSelectorOpstd::string> &

89 static const llvm::StringMap<RangeSelectorOpstd::string> M = {

90 {"name", name},

91 {"node", node},

98 return M;

99}

100

101static const llvm::StringMap<RangeSelectorOp> &

103 static const llvm::StringMap<RangeSelectorOp> M = {

105 return M;

106}

107

108static const llvm::StringMap<RangeSelectorOp<std::string, std::string>> &

110 static const llvm::StringMap<RangeSelectorOp<std::string, std::string>> M = {

112 return M;

113}

114

115static const llvm::StringMap<RangeSelectorOp<RangeSelector, RangeSelector>> &

117 static const llvm::StringMap<RangeSelectorOp<RangeSelector, RangeSelector>>

119 return M;

120}

121

122template

123std::optional findOptional(const llvm::StringMap &Map,

124 llvm::StringRef Key) {

125 auto it = Map.find(Key);

126 if (it == Map.end())

127 return std::nullopt;

128 return it->second;

129}

130

131template

133 ResultType Result) {

134 return ParseProgress{State, std::move(Result)};

135}

136

137static llvm::Error makeParseError(const ParseState &S, std::string ErrorMsg) {

138 size_t Pos = S.OriginalInput.size() - S.Input.size();

139 return llvm::make_error(Pos, std::move(ErrorMsg),

140 S.OriginalInput.substr(Pos, 20).str());

141}

142

143

144static ParseState advance(ParseState S, size_t N) {

145 S.Input = S.Input.drop_front(N);

146 return S;

147}

148

151}

152

153

154

155static ExpectedProgressstd::nullopt\_t parseChar(char c, ParseState State) {

157 if (State.Input.empty() || State.Input.front() != c)

159 ("expected char not found: " + llvm::Twine(c)).str());

161}

162

163

164static ExpectedProgressstd::string parseId(ParseState State) {

166 auto Id = State.Input.take_while(

168 if (Id.empty())

169 return makeParseError(State, "failed to parse name");

171}

172

173

174

175static ExpectedProgressstd::string parseStringId(ParseState State) {

177 if (State.Input.empty())

178 return makeParseError(State, "unexpected end of input");

179 if (!State.Input.consume_front("\""))

181 State,

182 "expecting string, but encountered other character or end of input");

183

184 StringRef Id = State.Input.take_until([](char c) { return c == '"'; });

185 if (State.Input.size() == Id.size())

187

189}

190

191

192

193template

194ExpectedProgress parseSingle(ParseFunction ParseElement,

195 RangeSelectorOp Op,

196 ParseState State) {

198 if (P)

199 return P.takeError();

200

201 auto E = ParseElement(P->State);

202 if (E)

203 return E.takeError();

204

206 if (P)

207 return P.takeError();

208

210}

211

212

213

214template

215ExpectedProgress parsePair(ParseFunction ParseElement,

216 RangeSelectorOp<T, T> Op,

217 ParseState State) {

219 if (P)

220 return P.takeError();

221

222 auto Left = ParseElement(P->State);

223 if (!Left)

224 return Left.takeError();

225

227 if (P)

228 return P.takeError();

229

230 auto Right = ParseElement(P->State);

231 if (!Right)

232 return Right.takeError();

233

235 if (P)

236 return P.takeError();

237

239 Op(std::move(Left->Value), std::move(Right->Value)));

240}

241

242

243

244

245static ExpectedProgress

248 if (Id)

249 return Id.takeError();

250

251 std::string OpName = std::move(Id->Value);

254

257

260

263

264 return makeParseError(State, "unknown selector name: " + OpName);

265}

266

268 ParseState State = {Input, Input};

270 if (!Result)

271 return Result.takeError();

272 State = Result->State;

273

275 if (State.Input.empty())

276 return Result->Value;

277 return makeParseError(State, "unexpected input after selector");

278}

static ExpectedProgress< std::string > parseStringId(ParseState State)

static ExpectedProgress< std::nullopt_t > parseChar(char c, ParseState State)

ParseProgress< ResultType > makeParseProgress(ParseState State, ResultType Result)

static StringRef consumeWhitespace(StringRef S)

ExpectedProgress< RangeSelector > parseSingle(ParseFunction< T > ParseElement, RangeSelectorOp< T > Op, ParseState State)

ExpectedProgress< RangeSelector > parsePair(ParseFunction< T > ParseElement, RangeSelectorOp< T, T > Op, ParseState State)

std::optional< Element > findOptional(const llvm::StringMap< Element > &Map, llvm::StringRef Key)

static llvm::Error makeParseError(const ParseState &S, std::string ErrorMsg)

static const llvm::StringMap< RangeSelectorOp< RangeSelector > > & getUnaryRangeSelectors()

static ExpectedProgress< RangeSelector > parseRangeSelectorImpl(ParseState State)

static ExpectedProgress< std::string > parseId(ParseState State)

static ParseState advance(ParseState S, size_t N)

static const llvm::StringMap< RangeSelectorOp< RangeSelector, RangeSelector > > & getBinaryRangeSelectors()

static const llvm::StringMap< RangeSelectorOp< std::string, std::string > > & getBinaryStringSelectors()

static const llvm::StringMap< RangeSelectorOp< std::string > > & getUnaryStringSelectors()

Defines parsing functions for Transformer types.

Defines a combinator library supporting the definition of selectors, which select source ranges based...

Defines the clang::SourceLocation class and associated facilities.

__device__ __2f16 float c

RangeSelector initListElements(std::string ID)

RangeSelector enclose(RangeSelector Begin, RangeSelector End)

Selects from the start of Begin and to the end of End.

RangeSelector member(std::string ID)

Given a MemberExpr, selects the member token.

RangeSelector between(RangeSelector R1, RangeSelector R2)

Selects the range between R1 and `R2.

RangeSelector elseBranch(std::string ID)

Given an \IfStmt (bound to ID), selects the range of the else branch, starting from the else keyword.

RangeSelector node(std::string ID)

Selects a node, including trailing semicolon, if any (for declarations and non-expression statements)...

MatchConsumer< CharSourceRange > RangeSelector

RangeSelector encloseNodes(std::string BeginID, std::string EndID)

Convenience version of range where end-points are bound nodes.

RangeSelector after(RangeSelector Selector)

Selects the point immediately following Selector.

RangeSelector callArgs(std::string ID)

RangeSelector before(RangeSelector Selector)

Selects the (empty) range [B,B) when Selector selects the range [B,E).

llvm::Expected< RangeSelector > parseRangeSelector(llvm::StringRef Input)

Parses a string representation of a RangeSelector.

RangeSelector statement(std::string ID)

Selects a node, including trailing semicolon (always).

RangeSelector expansion(RangeSelector S)

Selects the range from which S was expanded (possibly along with other source), if S is an expansion,...

RangeSelector statements(std::string ID)

RangeSelector name(std::string ID)

Given a node with a "name", (like NamedDecl, DeclRefExpr, CxxCtorInitializer, and TypeLoc) selects th...

The JSON file list parser is used to communicate input to InstallAPI.

LLVM_READNONE bool isASCII(char c)

Returns true if a byte is an ASCII character.

LLVM_READONLY bool isAsciiIdentifierContinue(unsigned char c)

LLVM_READONLY bool isWhitespace(unsigned char c)

Return true if this character is horizontal or vertical ASCII whitespace: ' ', '\t',...