1f4a2713aSLionel Sambuc //===--- Parser.cpp - Matcher expression parser -----*- C++ -*-===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc ///
10f4a2713aSLionel Sambuc /// \file
11f4a2713aSLionel Sambuc /// \brief Recursive parser implementation for the matcher expression grammar.
12f4a2713aSLionel Sambuc ///
13f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
14f4a2713aSLionel Sambuc
15f4a2713aSLionel Sambuc #include "clang/ASTMatchers/Dynamic/Parser.h"
16f4a2713aSLionel Sambuc #include "clang/ASTMatchers/Dynamic/Registry.h"
17f4a2713aSLionel Sambuc #include "clang/Basic/CharInfo.h"
18*0a6a1f1dSLionel Sambuc #include "llvm/ADT/Optional.h"
19f4a2713aSLionel Sambuc #include "llvm/ADT/Twine.h"
20*0a6a1f1dSLionel Sambuc #include "llvm/Support/ManagedStatic.h"
21*0a6a1f1dSLionel Sambuc #include <string>
22*0a6a1f1dSLionel Sambuc #include <vector>
23f4a2713aSLionel Sambuc
24f4a2713aSLionel Sambuc namespace clang {
25f4a2713aSLionel Sambuc namespace ast_matchers {
26f4a2713aSLionel Sambuc namespace dynamic {
27f4a2713aSLionel Sambuc
28f4a2713aSLionel Sambuc /// \brief Simple structure to hold information for one token from the parser.
29f4a2713aSLionel Sambuc struct Parser::TokenInfo {
30f4a2713aSLionel Sambuc /// \brief Different possible tokens.
31f4a2713aSLionel Sambuc enum TokenKind {
32*0a6a1f1dSLionel Sambuc TK_Eof,
33*0a6a1f1dSLionel Sambuc TK_OpenParen,
34*0a6a1f1dSLionel Sambuc TK_CloseParen,
35*0a6a1f1dSLionel Sambuc TK_Comma,
36*0a6a1f1dSLionel Sambuc TK_Period,
37*0a6a1f1dSLionel Sambuc TK_Literal,
38*0a6a1f1dSLionel Sambuc TK_Ident,
39*0a6a1f1dSLionel Sambuc TK_InvalidChar,
40*0a6a1f1dSLionel Sambuc TK_Error,
41*0a6a1f1dSLionel Sambuc TK_CodeCompletion
42f4a2713aSLionel Sambuc };
43f4a2713aSLionel Sambuc
44f4a2713aSLionel Sambuc /// \brief Some known identifiers.
45f4a2713aSLionel Sambuc static const char* const ID_Bind;
46f4a2713aSLionel Sambuc
TokenInfoclang::ast_matchers::dynamic::Parser::TokenInfo47f4a2713aSLionel Sambuc TokenInfo() : Text(), Kind(TK_Eof), Range(), Value() {}
48f4a2713aSLionel Sambuc
49f4a2713aSLionel Sambuc StringRef Text;
50f4a2713aSLionel Sambuc TokenKind Kind;
51f4a2713aSLionel Sambuc SourceRange Range;
52f4a2713aSLionel Sambuc VariantValue Value;
53f4a2713aSLionel Sambuc };
54f4a2713aSLionel Sambuc
55f4a2713aSLionel Sambuc const char* const Parser::TokenInfo::ID_Bind = "bind";
56f4a2713aSLionel Sambuc
57f4a2713aSLionel Sambuc /// \brief Simple tokenizer for the parser.
58f4a2713aSLionel Sambuc class Parser::CodeTokenizer {
59f4a2713aSLionel Sambuc public:
CodeTokenizer(StringRef MatcherCode,Diagnostics * Error)60f4a2713aSLionel Sambuc explicit CodeTokenizer(StringRef MatcherCode, Diagnostics *Error)
61*0a6a1f1dSLionel Sambuc : Code(MatcherCode), StartOfLine(MatcherCode), Line(1), Error(Error),
62*0a6a1f1dSLionel Sambuc CodeCompletionLocation(nullptr) {
63*0a6a1f1dSLionel Sambuc NextToken = getNextToken();
64*0a6a1f1dSLionel Sambuc }
65*0a6a1f1dSLionel Sambuc
CodeTokenizer(StringRef MatcherCode,Diagnostics * Error,unsigned CodeCompletionOffset)66*0a6a1f1dSLionel Sambuc CodeTokenizer(StringRef MatcherCode, Diagnostics *Error,
67*0a6a1f1dSLionel Sambuc unsigned CodeCompletionOffset)
68*0a6a1f1dSLionel Sambuc : Code(MatcherCode), StartOfLine(MatcherCode), Line(1), Error(Error),
69*0a6a1f1dSLionel Sambuc CodeCompletionLocation(MatcherCode.data() + CodeCompletionOffset) {
70f4a2713aSLionel Sambuc NextToken = getNextToken();
71f4a2713aSLionel Sambuc }
72f4a2713aSLionel Sambuc
73f4a2713aSLionel Sambuc /// \brief Returns but doesn't consume the next token.
peekNextToken() const74f4a2713aSLionel Sambuc const TokenInfo &peekNextToken() const { return NextToken; }
75f4a2713aSLionel Sambuc
76f4a2713aSLionel Sambuc /// \brief Consumes and returns the next token.
consumeNextToken()77f4a2713aSLionel Sambuc TokenInfo consumeNextToken() {
78f4a2713aSLionel Sambuc TokenInfo ThisToken = NextToken;
79f4a2713aSLionel Sambuc NextToken = getNextToken();
80f4a2713aSLionel Sambuc return ThisToken;
81f4a2713aSLionel Sambuc }
82f4a2713aSLionel Sambuc
nextTokenKind() const83f4a2713aSLionel Sambuc TokenInfo::TokenKind nextTokenKind() const { return NextToken.Kind; }
84f4a2713aSLionel Sambuc
85f4a2713aSLionel Sambuc private:
getNextToken()86f4a2713aSLionel Sambuc TokenInfo getNextToken() {
87f4a2713aSLionel Sambuc consumeWhitespace();
88f4a2713aSLionel Sambuc TokenInfo Result;
89f4a2713aSLionel Sambuc Result.Range.Start = currentLocation();
90f4a2713aSLionel Sambuc
91*0a6a1f1dSLionel Sambuc if (CodeCompletionLocation && CodeCompletionLocation <= Code.data()) {
92*0a6a1f1dSLionel Sambuc Result.Kind = TokenInfo::TK_CodeCompletion;
93*0a6a1f1dSLionel Sambuc Result.Text = StringRef(CodeCompletionLocation, 0);
94*0a6a1f1dSLionel Sambuc CodeCompletionLocation = nullptr;
95*0a6a1f1dSLionel Sambuc return Result;
96*0a6a1f1dSLionel Sambuc }
97*0a6a1f1dSLionel Sambuc
98f4a2713aSLionel Sambuc if (Code.empty()) {
99f4a2713aSLionel Sambuc Result.Kind = TokenInfo::TK_Eof;
100f4a2713aSLionel Sambuc Result.Text = "";
101f4a2713aSLionel Sambuc return Result;
102f4a2713aSLionel Sambuc }
103f4a2713aSLionel Sambuc
104f4a2713aSLionel Sambuc switch (Code[0]) {
105f4a2713aSLionel Sambuc case ',':
106f4a2713aSLionel Sambuc Result.Kind = TokenInfo::TK_Comma;
107f4a2713aSLionel Sambuc Result.Text = Code.substr(0, 1);
108f4a2713aSLionel Sambuc Code = Code.drop_front();
109f4a2713aSLionel Sambuc break;
110f4a2713aSLionel Sambuc case '.':
111f4a2713aSLionel Sambuc Result.Kind = TokenInfo::TK_Period;
112f4a2713aSLionel Sambuc Result.Text = Code.substr(0, 1);
113f4a2713aSLionel Sambuc Code = Code.drop_front();
114f4a2713aSLionel Sambuc break;
115f4a2713aSLionel Sambuc case '(':
116f4a2713aSLionel Sambuc Result.Kind = TokenInfo::TK_OpenParen;
117f4a2713aSLionel Sambuc Result.Text = Code.substr(0, 1);
118f4a2713aSLionel Sambuc Code = Code.drop_front();
119f4a2713aSLionel Sambuc break;
120f4a2713aSLionel Sambuc case ')':
121f4a2713aSLionel Sambuc Result.Kind = TokenInfo::TK_CloseParen;
122f4a2713aSLionel Sambuc Result.Text = Code.substr(0, 1);
123f4a2713aSLionel Sambuc Code = Code.drop_front();
124f4a2713aSLionel Sambuc break;
125f4a2713aSLionel Sambuc
126f4a2713aSLionel Sambuc case '"':
127f4a2713aSLionel Sambuc case '\'':
128f4a2713aSLionel Sambuc // Parse a string literal.
129f4a2713aSLionel Sambuc consumeStringLiteral(&Result);
130f4a2713aSLionel Sambuc break;
131f4a2713aSLionel Sambuc
132f4a2713aSLionel Sambuc case '0': case '1': case '2': case '3': case '4':
133f4a2713aSLionel Sambuc case '5': case '6': case '7': case '8': case '9':
134f4a2713aSLionel Sambuc // Parse an unsigned literal.
135f4a2713aSLionel Sambuc consumeUnsignedLiteral(&Result);
136f4a2713aSLionel Sambuc break;
137f4a2713aSLionel Sambuc
138f4a2713aSLionel Sambuc default:
139f4a2713aSLionel Sambuc if (isAlphanumeric(Code[0])) {
140f4a2713aSLionel Sambuc // Parse an identifier
141f4a2713aSLionel Sambuc size_t TokenLength = 1;
142*0a6a1f1dSLionel Sambuc while (1) {
143*0a6a1f1dSLionel Sambuc // A code completion location in/immediately after an identifier will
144*0a6a1f1dSLionel Sambuc // cause the portion of the identifier before the code completion
145*0a6a1f1dSLionel Sambuc // location to become a code completion token.
146*0a6a1f1dSLionel Sambuc if (CodeCompletionLocation == Code.data() + TokenLength) {
147*0a6a1f1dSLionel Sambuc CodeCompletionLocation = nullptr;
148*0a6a1f1dSLionel Sambuc Result.Kind = TokenInfo::TK_CodeCompletion;
149*0a6a1f1dSLionel Sambuc Result.Text = Code.substr(0, TokenLength);
150*0a6a1f1dSLionel Sambuc Code = Code.drop_front(TokenLength);
151*0a6a1f1dSLionel Sambuc return Result;
152*0a6a1f1dSLionel Sambuc }
153*0a6a1f1dSLionel Sambuc if (TokenLength == Code.size() || !isAlphanumeric(Code[TokenLength]))
154*0a6a1f1dSLionel Sambuc break;
155f4a2713aSLionel Sambuc ++TokenLength;
156*0a6a1f1dSLionel Sambuc }
157f4a2713aSLionel Sambuc Result.Kind = TokenInfo::TK_Ident;
158f4a2713aSLionel Sambuc Result.Text = Code.substr(0, TokenLength);
159f4a2713aSLionel Sambuc Code = Code.drop_front(TokenLength);
160f4a2713aSLionel Sambuc } else {
161f4a2713aSLionel Sambuc Result.Kind = TokenInfo::TK_InvalidChar;
162f4a2713aSLionel Sambuc Result.Text = Code.substr(0, 1);
163f4a2713aSLionel Sambuc Code = Code.drop_front(1);
164f4a2713aSLionel Sambuc }
165f4a2713aSLionel Sambuc break;
166f4a2713aSLionel Sambuc }
167f4a2713aSLionel Sambuc
168f4a2713aSLionel Sambuc Result.Range.End = currentLocation();
169f4a2713aSLionel Sambuc return Result;
170f4a2713aSLionel Sambuc }
171f4a2713aSLionel Sambuc
172f4a2713aSLionel Sambuc /// \brief Consume an unsigned literal.
consumeUnsignedLiteral(TokenInfo * Result)173f4a2713aSLionel Sambuc void consumeUnsignedLiteral(TokenInfo *Result) {
174f4a2713aSLionel Sambuc unsigned Length = 1;
175f4a2713aSLionel Sambuc if (Code.size() > 1) {
176f4a2713aSLionel Sambuc // Consume the 'x' or 'b' radix modifier, if present.
177f4a2713aSLionel Sambuc switch (toLowercase(Code[1])) {
178f4a2713aSLionel Sambuc case 'x': case 'b': Length = 2;
179f4a2713aSLionel Sambuc }
180f4a2713aSLionel Sambuc }
181f4a2713aSLionel Sambuc while (Length < Code.size() && isHexDigit(Code[Length]))
182f4a2713aSLionel Sambuc ++Length;
183f4a2713aSLionel Sambuc
184f4a2713aSLionel Sambuc Result->Text = Code.substr(0, Length);
185f4a2713aSLionel Sambuc Code = Code.drop_front(Length);
186f4a2713aSLionel Sambuc
187f4a2713aSLionel Sambuc unsigned Value;
188f4a2713aSLionel Sambuc if (!Result->Text.getAsInteger(0, Value)) {
189f4a2713aSLionel Sambuc Result->Kind = TokenInfo::TK_Literal;
190f4a2713aSLionel Sambuc Result->Value = Value;
191f4a2713aSLionel Sambuc } else {
192f4a2713aSLionel Sambuc SourceRange Range;
193f4a2713aSLionel Sambuc Range.Start = Result->Range.Start;
194f4a2713aSLionel Sambuc Range.End = currentLocation();
195f4a2713aSLionel Sambuc Error->addError(Range, Error->ET_ParserUnsignedError) << Result->Text;
196f4a2713aSLionel Sambuc Result->Kind = TokenInfo::TK_Error;
197f4a2713aSLionel Sambuc }
198f4a2713aSLionel Sambuc }
199f4a2713aSLionel Sambuc
200f4a2713aSLionel Sambuc /// \brief Consume a string literal.
201f4a2713aSLionel Sambuc ///
202f4a2713aSLionel Sambuc /// \c Code must be positioned at the start of the literal (the opening
203f4a2713aSLionel Sambuc /// quote). Consumed until it finds the same closing quote character.
consumeStringLiteral(TokenInfo * Result)204f4a2713aSLionel Sambuc void consumeStringLiteral(TokenInfo *Result) {
205f4a2713aSLionel Sambuc bool InEscape = false;
206f4a2713aSLionel Sambuc const char Marker = Code[0];
207f4a2713aSLionel Sambuc for (size_t Length = 1, Size = Code.size(); Length != Size; ++Length) {
208f4a2713aSLionel Sambuc if (InEscape) {
209f4a2713aSLionel Sambuc InEscape = false;
210f4a2713aSLionel Sambuc continue;
211f4a2713aSLionel Sambuc }
212f4a2713aSLionel Sambuc if (Code[Length] == '\\') {
213f4a2713aSLionel Sambuc InEscape = true;
214f4a2713aSLionel Sambuc continue;
215f4a2713aSLionel Sambuc }
216f4a2713aSLionel Sambuc if (Code[Length] == Marker) {
217f4a2713aSLionel Sambuc Result->Kind = TokenInfo::TK_Literal;
218f4a2713aSLionel Sambuc Result->Text = Code.substr(0, Length + 1);
219f4a2713aSLionel Sambuc Result->Value = Code.substr(1, Length - 1).str();
220f4a2713aSLionel Sambuc Code = Code.drop_front(Length + 1);
221f4a2713aSLionel Sambuc return;
222f4a2713aSLionel Sambuc }
223f4a2713aSLionel Sambuc }
224f4a2713aSLionel Sambuc
225f4a2713aSLionel Sambuc StringRef ErrorText = Code;
226f4a2713aSLionel Sambuc Code = Code.drop_front(Code.size());
227f4a2713aSLionel Sambuc SourceRange Range;
228f4a2713aSLionel Sambuc Range.Start = Result->Range.Start;
229f4a2713aSLionel Sambuc Range.End = currentLocation();
230f4a2713aSLionel Sambuc Error->addError(Range, Error->ET_ParserStringError) << ErrorText;
231f4a2713aSLionel Sambuc Result->Kind = TokenInfo::TK_Error;
232f4a2713aSLionel Sambuc }
233f4a2713aSLionel Sambuc
234f4a2713aSLionel Sambuc /// \brief Consume all leading whitespace from \c Code.
consumeWhitespace()235f4a2713aSLionel Sambuc void consumeWhitespace() {
236f4a2713aSLionel Sambuc while (!Code.empty() && isWhitespace(Code[0])) {
237f4a2713aSLionel Sambuc if (Code[0] == '\n') {
238f4a2713aSLionel Sambuc ++Line;
239f4a2713aSLionel Sambuc StartOfLine = Code.drop_front();
240f4a2713aSLionel Sambuc }
241f4a2713aSLionel Sambuc Code = Code.drop_front();
242f4a2713aSLionel Sambuc }
243f4a2713aSLionel Sambuc }
244f4a2713aSLionel Sambuc
currentLocation()245f4a2713aSLionel Sambuc SourceLocation currentLocation() {
246f4a2713aSLionel Sambuc SourceLocation Location;
247f4a2713aSLionel Sambuc Location.Line = Line;
248f4a2713aSLionel Sambuc Location.Column = Code.data() - StartOfLine.data() + 1;
249f4a2713aSLionel Sambuc return Location;
250f4a2713aSLionel Sambuc }
251f4a2713aSLionel Sambuc
252f4a2713aSLionel Sambuc StringRef Code;
253f4a2713aSLionel Sambuc StringRef StartOfLine;
254f4a2713aSLionel Sambuc unsigned Line;
255f4a2713aSLionel Sambuc Diagnostics *Error;
256f4a2713aSLionel Sambuc TokenInfo NextToken;
257*0a6a1f1dSLionel Sambuc const char *CodeCompletionLocation;
258f4a2713aSLionel Sambuc };
259f4a2713aSLionel Sambuc
~Sema()260f4a2713aSLionel Sambuc Parser::Sema::~Sema() {}
261f4a2713aSLionel Sambuc
getAcceptedCompletionTypes(llvm::ArrayRef<std::pair<MatcherCtor,unsigned>> Context)262*0a6a1f1dSLionel Sambuc std::vector<ArgKind> Parser::Sema::getAcceptedCompletionTypes(
263*0a6a1f1dSLionel Sambuc llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context) {
264*0a6a1f1dSLionel Sambuc return std::vector<ArgKind>();
265*0a6a1f1dSLionel Sambuc }
266*0a6a1f1dSLionel Sambuc
267*0a6a1f1dSLionel Sambuc std::vector<MatcherCompletion>
getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes)268*0a6a1f1dSLionel Sambuc Parser::Sema::getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes) {
269*0a6a1f1dSLionel Sambuc return std::vector<MatcherCompletion>();
270*0a6a1f1dSLionel Sambuc }
271*0a6a1f1dSLionel Sambuc
272*0a6a1f1dSLionel Sambuc struct Parser::ScopedContextEntry {
273*0a6a1f1dSLionel Sambuc Parser *P;
274*0a6a1f1dSLionel Sambuc
ScopedContextEntryclang::ast_matchers::dynamic::Parser::ScopedContextEntry275*0a6a1f1dSLionel Sambuc ScopedContextEntry(Parser *P, MatcherCtor C) : P(P) {
276*0a6a1f1dSLionel Sambuc P->ContextStack.push_back(std::make_pair(C, 0u));
277*0a6a1f1dSLionel Sambuc }
278*0a6a1f1dSLionel Sambuc
~ScopedContextEntryclang::ast_matchers::dynamic::Parser::ScopedContextEntry279*0a6a1f1dSLionel Sambuc ~ScopedContextEntry() {
280*0a6a1f1dSLionel Sambuc P->ContextStack.pop_back();
281*0a6a1f1dSLionel Sambuc }
282*0a6a1f1dSLionel Sambuc
nextArgclang::ast_matchers::dynamic::Parser::ScopedContextEntry283*0a6a1f1dSLionel Sambuc void nextArg() {
284*0a6a1f1dSLionel Sambuc ++P->ContextStack.back().second;
285*0a6a1f1dSLionel Sambuc }
286*0a6a1f1dSLionel Sambuc };
287*0a6a1f1dSLionel Sambuc
288*0a6a1f1dSLionel Sambuc /// \brief Parse expressions that start with an identifier.
289*0a6a1f1dSLionel Sambuc ///
290*0a6a1f1dSLionel Sambuc /// This function can parse named values and matchers.
291*0a6a1f1dSLionel Sambuc /// In case of failure it will try to determine the user's intent to give
292*0a6a1f1dSLionel Sambuc /// an appropriate error message.
parseIdentifierPrefixImpl(VariantValue * Value)293*0a6a1f1dSLionel Sambuc bool Parser::parseIdentifierPrefixImpl(VariantValue *Value) {
294*0a6a1f1dSLionel Sambuc const TokenInfo NameToken = Tokenizer->consumeNextToken();
295*0a6a1f1dSLionel Sambuc
296*0a6a1f1dSLionel Sambuc if (Tokenizer->nextTokenKind() != TokenInfo::TK_OpenParen) {
297*0a6a1f1dSLionel Sambuc // Parse as a named value.
298*0a6a1f1dSLionel Sambuc if (const VariantValue NamedValue =
299*0a6a1f1dSLionel Sambuc NamedValues ? NamedValues->lookup(NameToken.Text)
300*0a6a1f1dSLionel Sambuc : VariantValue()) {
301*0a6a1f1dSLionel Sambuc *Value = NamedValue;
302*0a6a1f1dSLionel Sambuc return true;
303*0a6a1f1dSLionel Sambuc }
304*0a6a1f1dSLionel Sambuc // If the syntax is correct and the name is not a matcher either, report
305*0a6a1f1dSLionel Sambuc // unknown named value.
306*0a6a1f1dSLionel Sambuc if ((Tokenizer->nextTokenKind() == TokenInfo::TK_Comma ||
307*0a6a1f1dSLionel Sambuc Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen ||
308*0a6a1f1dSLionel Sambuc Tokenizer->nextTokenKind() == TokenInfo::TK_Eof) &&
309*0a6a1f1dSLionel Sambuc !S->lookupMatcherCtor(NameToken.Text)) {
310*0a6a1f1dSLionel Sambuc Error->addError(NameToken.Range, Error->ET_RegistryValueNotFound)
311*0a6a1f1dSLionel Sambuc << NameToken.Text;
312*0a6a1f1dSLionel Sambuc return false;
313*0a6a1f1dSLionel Sambuc }
314*0a6a1f1dSLionel Sambuc // Otherwise, fallback to the matcher parser.
315*0a6a1f1dSLionel Sambuc }
316*0a6a1f1dSLionel Sambuc
317*0a6a1f1dSLionel Sambuc // Parse as a matcher expression.
318*0a6a1f1dSLionel Sambuc return parseMatcherExpressionImpl(NameToken, Value);
319*0a6a1f1dSLionel Sambuc }
320*0a6a1f1dSLionel Sambuc
321f4a2713aSLionel Sambuc /// \brief Parse and validate a matcher expression.
322f4a2713aSLionel Sambuc /// \return \c true on success, in which case \c Value has the matcher parsed.
323f4a2713aSLionel Sambuc /// If the input is malformed, or some argument has an error, it
324f4a2713aSLionel Sambuc /// returns \c false.
parseMatcherExpressionImpl(const TokenInfo & NameToken,VariantValue * Value)325*0a6a1f1dSLionel Sambuc bool Parser::parseMatcherExpressionImpl(const TokenInfo &NameToken,
326*0a6a1f1dSLionel Sambuc VariantValue *Value) {
327f4a2713aSLionel Sambuc assert(NameToken.Kind == TokenInfo::TK_Ident);
328f4a2713aSLionel Sambuc const TokenInfo OpenToken = Tokenizer->consumeNextToken();
329f4a2713aSLionel Sambuc if (OpenToken.Kind != TokenInfo::TK_OpenParen) {
330f4a2713aSLionel Sambuc Error->addError(OpenToken.Range, Error->ET_ParserNoOpenParen)
331f4a2713aSLionel Sambuc << OpenToken.Text;
332f4a2713aSLionel Sambuc return false;
333f4a2713aSLionel Sambuc }
334f4a2713aSLionel Sambuc
335*0a6a1f1dSLionel Sambuc llvm::Optional<MatcherCtor> Ctor = S->lookupMatcherCtor(NameToken.Text);
336*0a6a1f1dSLionel Sambuc
337*0a6a1f1dSLionel Sambuc if (!Ctor) {
338*0a6a1f1dSLionel Sambuc Error->addError(NameToken.Range, Error->ET_RegistryMatcherNotFound)
339*0a6a1f1dSLionel Sambuc << NameToken.Text;
340*0a6a1f1dSLionel Sambuc // Do not return here. We need to continue to give completion suggestions.
341*0a6a1f1dSLionel Sambuc }
342*0a6a1f1dSLionel Sambuc
343f4a2713aSLionel Sambuc std::vector<ParserValue> Args;
344f4a2713aSLionel Sambuc TokenInfo EndToken;
345*0a6a1f1dSLionel Sambuc
346*0a6a1f1dSLionel Sambuc {
347*0a6a1f1dSLionel Sambuc ScopedContextEntry SCE(this, Ctor ? *Ctor : nullptr);
348*0a6a1f1dSLionel Sambuc
349f4a2713aSLionel Sambuc while (Tokenizer->nextTokenKind() != TokenInfo::TK_Eof) {
350f4a2713aSLionel Sambuc if (Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen) {
351f4a2713aSLionel Sambuc // End of args.
352f4a2713aSLionel Sambuc EndToken = Tokenizer->consumeNextToken();
353f4a2713aSLionel Sambuc break;
354f4a2713aSLionel Sambuc }
355f4a2713aSLionel Sambuc if (Args.size() > 0) {
356f4a2713aSLionel Sambuc // We must find a , token to continue.
357f4a2713aSLionel Sambuc const TokenInfo CommaToken = Tokenizer->consumeNextToken();
358f4a2713aSLionel Sambuc if (CommaToken.Kind != TokenInfo::TK_Comma) {
359f4a2713aSLionel Sambuc Error->addError(CommaToken.Range, Error->ET_ParserNoComma)
360f4a2713aSLionel Sambuc << CommaToken.Text;
361f4a2713aSLionel Sambuc return false;
362f4a2713aSLionel Sambuc }
363f4a2713aSLionel Sambuc }
364f4a2713aSLionel Sambuc
365f4a2713aSLionel Sambuc Diagnostics::Context Ctx(Diagnostics::Context::MatcherArg, Error,
366*0a6a1f1dSLionel Sambuc NameToken.Text, NameToken.Range,
367*0a6a1f1dSLionel Sambuc Args.size() + 1);
368f4a2713aSLionel Sambuc ParserValue ArgValue;
369f4a2713aSLionel Sambuc ArgValue.Text = Tokenizer->peekNextToken().Text;
370f4a2713aSLionel Sambuc ArgValue.Range = Tokenizer->peekNextToken().Range;
371*0a6a1f1dSLionel Sambuc if (!parseExpressionImpl(&ArgValue.Value)) {
372*0a6a1f1dSLionel Sambuc return false;
373*0a6a1f1dSLionel Sambuc }
374f4a2713aSLionel Sambuc
375f4a2713aSLionel Sambuc Args.push_back(ArgValue);
376*0a6a1f1dSLionel Sambuc SCE.nextArg();
377*0a6a1f1dSLionel Sambuc }
378f4a2713aSLionel Sambuc }
379f4a2713aSLionel Sambuc
380f4a2713aSLionel Sambuc if (EndToken.Kind == TokenInfo::TK_Eof) {
381f4a2713aSLionel Sambuc Error->addError(OpenToken.Range, Error->ET_ParserNoCloseParen);
382f4a2713aSLionel Sambuc return false;
383f4a2713aSLionel Sambuc }
384f4a2713aSLionel Sambuc
385f4a2713aSLionel Sambuc std::string BindID;
386f4a2713aSLionel Sambuc if (Tokenizer->peekNextToken().Kind == TokenInfo::TK_Period) {
387f4a2713aSLionel Sambuc // Parse .bind("foo")
388f4a2713aSLionel Sambuc Tokenizer->consumeNextToken(); // consume the period.
389f4a2713aSLionel Sambuc const TokenInfo BindToken = Tokenizer->consumeNextToken();
390*0a6a1f1dSLionel Sambuc if (BindToken.Kind == TokenInfo::TK_CodeCompletion) {
391*0a6a1f1dSLionel Sambuc addCompletion(BindToken, MatcherCompletion("bind(\"", "bind", 1));
392*0a6a1f1dSLionel Sambuc return false;
393*0a6a1f1dSLionel Sambuc }
394*0a6a1f1dSLionel Sambuc
395f4a2713aSLionel Sambuc const TokenInfo OpenToken = Tokenizer->consumeNextToken();
396f4a2713aSLionel Sambuc const TokenInfo IDToken = Tokenizer->consumeNextToken();
397f4a2713aSLionel Sambuc const TokenInfo CloseToken = Tokenizer->consumeNextToken();
398f4a2713aSLionel Sambuc
399f4a2713aSLionel Sambuc // TODO: We could use different error codes for each/some to be more
400f4a2713aSLionel Sambuc // explicit about the syntax error.
401f4a2713aSLionel Sambuc if (BindToken.Kind != TokenInfo::TK_Ident ||
402f4a2713aSLionel Sambuc BindToken.Text != TokenInfo::ID_Bind) {
403f4a2713aSLionel Sambuc Error->addError(BindToken.Range, Error->ET_ParserMalformedBindExpr);
404f4a2713aSLionel Sambuc return false;
405f4a2713aSLionel Sambuc }
406f4a2713aSLionel Sambuc if (OpenToken.Kind != TokenInfo::TK_OpenParen) {
407f4a2713aSLionel Sambuc Error->addError(OpenToken.Range, Error->ET_ParserMalformedBindExpr);
408f4a2713aSLionel Sambuc return false;
409f4a2713aSLionel Sambuc }
410f4a2713aSLionel Sambuc if (IDToken.Kind != TokenInfo::TK_Literal || !IDToken.Value.isString()) {
411f4a2713aSLionel Sambuc Error->addError(IDToken.Range, Error->ET_ParserMalformedBindExpr);
412f4a2713aSLionel Sambuc return false;
413f4a2713aSLionel Sambuc }
414f4a2713aSLionel Sambuc if (CloseToken.Kind != TokenInfo::TK_CloseParen) {
415f4a2713aSLionel Sambuc Error->addError(CloseToken.Range, Error->ET_ParserMalformedBindExpr);
416f4a2713aSLionel Sambuc return false;
417f4a2713aSLionel Sambuc }
418f4a2713aSLionel Sambuc BindID = IDToken.Value.getString();
419f4a2713aSLionel Sambuc }
420f4a2713aSLionel Sambuc
421*0a6a1f1dSLionel Sambuc if (!Ctor)
422*0a6a1f1dSLionel Sambuc return false;
423*0a6a1f1dSLionel Sambuc
424f4a2713aSLionel Sambuc // Merge the start and end infos.
425f4a2713aSLionel Sambuc Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error,
426f4a2713aSLionel Sambuc NameToken.Text, NameToken.Range);
427f4a2713aSLionel Sambuc SourceRange MatcherRange = NameToken.Range;
428f4a2713aSLionel Sambuc MatcherRange.End = EndToken.Range.End;
429f4a2713aSLionel Sambuc VariantMatcher Result = S->actOnMatcherExpression(
430*0a6a1f1dSLionel Sambuc *Ctor, MatcherRange, BindID, Args, Error);
431f4a2713aSLionel Sambuc if (Result.isNull()) return false;
432f4a2713aSLionel Sambuc
433f4a2713aSLionel Sambuc *Value = Result;
434f4a2713aSLionel Sambuc return true;
435f4a2713aSLionel Sambuc }
436f4a2713aSLionel Sambuc
437*0a6a1f1dSLionel Sambuc // If the prefix of this completion matches the completion token, add it to
438*0a6a1f1dSLionel Sambuc // Completions minus the prefix.
addCompletion(const TokenInfo & CompToken,const MatcherCompletion & Completion)439*0a6a1f1dSLionel Sambuc void Parser::addCompletion(const TokenInfo &CompToken,
440*0a6a1f1dSLionel Sambuc const MatcherCompletion& Completion) {
441*0a6a1f1dSLionel Sambuc if (StringRef(Completion.TypedText).startswith(CompToken.Text) &&
442*0a6a1f1dSLionel Sambuc Completion.Specificity > 0) {
443*0a6a1f1dSLionel Sambuc Completions.emplace_back(Completion.TypedText.substr(CompToken.Text.size()),
444*0a6a1f1dSLionel Sambuc Completion.MatcherDecl, Completion.Specificity);
445*0a6a1f1dSLionel Sambuc }
446*0a6a1f1dSLionel Sambuc }
447*0a6a1f1dSLionel Sambuc
getNamedValueCompletions(ArrayRef<ArgKind> AcceptedTypes)448*0a6a1f1dSLionel Sambuc std::vector<MatcherCompletion> Parser::getNamedValueCompletions(
449*0a6a1f1dSLionel Sambuc ArrayRef<ArgKind> AcceptedTypes) {
450*0a6a1f1dSLionel Sambuc if (!NamedValues) return std::vector<MatcherCompletion>();
451*0a6a1f1dSLionel Sambuc std::vector<MatcherCompletion> Result;
452*0a6a1f1dSLionel Sambuc for (const auto &Entry : *NamedValues) {
453*0a6a1f1dSLionel Sambuc unsigned Specificity;
454*0a6a1f1dSLionel Sambuc if (Entry.getValue().isConvertibleTo(AcceptedTypes, &Specificity)) {
455*0a6a1f1dSLionel Sambuc std::string Decl =
456*0a6a1f1dSLionel Sambuc (Entry.getValue().getTypeAsString() + " " + Entry.getKey()).str();
457*0a6a1f1dSLionel Sambuc Result.emplace_back(Entry.getKey(), Decl, Specificity);
458*0a6a1f1dSLionel Sambuc }
459*0a6a1f1dSLionel Sambuc }
460*0a6a1f1dSLionel Sambuc return Result;
461*0a6a1f1dSLionel Sambuc }
462*0a6a1f1dSLionel Sambuc
addExpressionCompletions()463*0a6a1f1dSLionel Sambuc void Parser::addExpressionCompletions() {
464*0a6a1f1dSLionel Sambuc const TokenInfo CompToken = Tokenizer->consumeNextToken();
465*0a6a1f1dSLionel Sambuc assert(CompToken.Kind == TokenInfo::TK_CodeCompletion);
466*0a6a1f1dSLionel Sambuc
467*0a6a1f1dSLionel Sambuc // We cannot complete code if there is an invalid element on the context
468*0a6a1f1dSLionel Sambuc // stack.
469*0a6a1f1dSLionel Sambuc for (ContextStackTy::iterator I = ContextStack.begin(),
470*0a6a1f1dSLionel Sambuc E = ContextStack.end();
471*0a6a1f1dSLionel Sambuc I != E; ++I) {
472*0a6a1f1dSLionel Sambuc if (!I->first)
473*0a6a1f1dSLionel Sambuc return;
474*0a6a1f1dSLionel Sambuc }
475*0a6a1f1dSLionel Sambuc
476*0a6a1f1dSLionel Sambuc auto AcceptedTypes = S->getAcceptedCompletionTypes(ContextStack);
477*0a6a1f1dSLionel Sambuc for (const auto &Completion : S->getMatcherCompletions(AcceptedTypes)) {
478*0a6a1f1dSLionel Sambuc addCompletion(CompToken, Completion);
479*0a6a1f1dSLionel Sambuc }
480*0a6a1f1dSLionel Sambuc
481*0a6a1f1dSLionel Sambuc for (const auto &Completion : getNamedValueCompletions(AcceptedTypes)) {
482*0a6a1f1dSLionel Sambuc addCompletion(CompToken, Completion);
483*0a6a1f1dSLionel Sambuc }
484*0a6a1f1dSLionel Sambuc }
485*0a6a1f1dSLionel Sambuc
486f4a2713aSLionel Sambuc /// \brief Parse an <Expresssion>
parseExpressionImpl(VariantValue * Value)487f4a2713aSLionel Sambuc bool Parser::parseExpressionImpl(VariantValue *Value) {
488f4a2713aSLionel Sambuc switch (Tokenizer->nextTokenKind()) {
489f4a2713aSLionel Sambuc case TokenInfo::TK_Literal:
490f4a2713aSLionel Sambuc *Value = Tokenizer->consumeNextToken().Value;
491f4a2713aSLionel Sambuc return true;
492f4a2713aSLionel Sambuc
493f4a2713aSLionel Sambuc case TokenInfo::TK_Ident:
494*0a6a1f1dSLionel Sambuc return parseIdentifierPrefixImpl(Value);
495*0a6a1f1dSLionel Sambuc
496*0a6a1f1dSLionel Sambuc case TokenInfo::TK_CodeCompletion:
497*0a6a1f1dSLionel Sambuc addExpressionCompletions();
498*0a6a1f1dSLionel Sambuc return false;
499f4a2713aSLionel Sambuc
500f4a2713aSLionel Sambuc case TokenInfo::TK_Eof:
501f4a2713aSLionel Sambuc Error->addError(Tokenizer->consumeNextToken().Range,
502f4a2713aSLionel Sambuc Error->ET_ParserNoCode);
503f4a2713aSLionel Sambuc return false;
504f4a2713aSLionel Sambuc
505f4a2713aSLionel Sambuc case TokenInfo::TK_Error:
506f4a2713aSLionel Sambuc // This error was already reported by the tokenizer.
507f4a2713aSLionel Sambuc return false;
508f4a2713aSLionel Sambuc
509f4a2713aSLionel Sambuc case TokenInfo::TK_OpenParen:
510f4a2713aSLionel Sambuc case TokenInfo::TK_CloseParen:
511f4a2713aSLionel Sambuc case TokenInfo::TK_Comma:
512f4a2713aSLionel Sambuc case TokenInfo::TK_Period:
513f4a2713aSLionel Sambuc case TokenInfo::TK_InvalidChar:
514f4a2713aSLionel Sambuc const TokenInfo Token = Tokenizer->consumeNextToken();
515f4a2713aSLionel Sambuc Error->addError(Token.Range, Error->ET_ParserInvalidToken) << Token.Text;
516f4a2713aSLionel Sambuc return false;
517f4a2713aSLionel Sambuc }
518f4a2713aSLionel Sambuc
519f4a2713aSLionel Sambuc llvm_unreachable("Unknown token kind.");
520f4a2713aSLionel Sambuc }
521f4a2713aSLionel Sambuc
522*0a6a1f1dSLionel Sambuc static llvm::ManagedStatic<Parser::RegistrySema> DefaultRegistrySema;
523*0a6a1f1dSLionel Sambuc
Parser(CodeTokenizer * Tokenizer,Sema * S,const NamedValueMap * NamedValues,Diagnostics * Error)524f4a2713aSLionel Sambuc Parser::Parser(CodeTokenizer *Tokenizer, Sema *S,
525*0a6a1f1dSLionel Sambuc const NamedValueMap *NamedValues, Diagnostics *Error)
526*0a6a1f1dSLionel Sambuc : Tokenizer(Tokenizer), S(S ? S : &*DefaultRegistrySema),
527*0a6a1f1dSLionel Sambuc NamedValues(NamedValues), Error(Error) {}
528f4a2713aSLionel Sambuc
~RegistrySema()529*0a6a1f1dSLionel Sambuc Parser::RegistrySema::~RegistrySema() {}
530*0a6a1f1dSLionel Sambuc
531*0a6a1f1dSLionel Sambuc llvm::Optional<MatcherCtor>
lookupMatcherCtor(StringRef MatcherName)532*0a6a1f1dSLionel Sambuc Parser::RegistrySema::lookupMatcherCtor(StringRef MatcherName) {
533*0a6a1f1dSLionel Sambuc return Registry::lookupMatcherCtor(MatcherName);
534*0a6a1f1dSLionel Sambuc }
535*0a6a1f1dSLionel Sambuc
actOnMatcherExpression(MatcherCtor Ctor,const SourceRange & NameRange,StringRef BindID,ArrayRef<ParserValue> Args,Diagnostics * Error)536*0a6a1f1dSLionel Sambuc VariantMatcher Parser::RegistrySema::actOnMatcherExpression(
537*0a6a1f1dSLionel Sambuc MatcherCtor Ctor, const SourceRange &NameRange, StringRef BindID,
538*0a6a1f1dSLionel Sambuc ArrayRef<ParserValue> Args, Diagnostics *Error) {
539f4a2713aSLionel Sambuc if (BindID.empty()) {
540*0a6a1f1dSLionel Sambuc return Registry::constructMatcher(Ctor, NameRange, Args, Error);
541f4a2713aSLionel Sambuc } else {
542*0a6a1f1dSLionel Sambuc return Registry::constructBoundMatcher(Ctor, NameRange, BindID, Args,
543*0a6a1f1dSLionel Sambuc Error);
544f4a2713aSLionel Sambuc }
545f4a2713aSLionel Sambuc }
546f4a2713aSLionel Sambuc
getAcceptedCompletionTypes(ArrayRef<std::pair<MatcherCtor,unsigned>> Context)547*0a6a1f1dSLionel Sambuc std::vector<ArgKind> Parser::RegistrySema::getAcceptedCompletionTypes(
548*0a6a1f1dSLionel Sambuc ArrayRef<std::pair<MatcherCtor, unsigned>> Context) {
549*0a6a1f1dSLionel Sambuc return Registry::getAcceptedCompletionTypes(Context);
550*0a6a1f1dSLionel Sambuc }
551*0a6a1f1dSLionel Sambuc
getMatcherCompletions(ArrayRef<ArgKind> AcceptedTypes)552*0a6a1f1dSLionel Sambuc std::vector<MatcherCompletion> Parser::RegistrySema::getMatcherCompletions(
553*0a6a1f1dSLionel Sambuc ArrayRef<ArgKind> AcceptedTypes) {
554*0a6a1f1dSLionel Sambuc return Registry::getMatcherCompletions(AcceptedTypes);
555f4a2713aSLionel Sambuc }
556f4a2713aSLionel Sambuc
parseExpression(StringRef Code,Sema * S,const NamedValueMap * NamedValues,VariantValue * Value,Diagnostics * Error)557f4a2713aSLionel Sambuc bool Parser::parseExpression(StringRef Code, Sema *S,
558*0a6a1f1dSLionel Sambuc const NamedValueMap *NamedValues,
559f4a2713aSLionel Sambuc VariantValue *Value, Diagnostics *Error) {
560f4a2713aSLionel Sambuc CodeTokenizer Tokenizer(Code, Error);
561*0a6a1f1dSLionel Sambuc if (!Parser(&Tokenizer, S, NamedValues, Error).parseExpressionImpl(Value))
562*0a6a1f1dSLionel Sambuc return false;
563f4a2713aSLionel Sambuc if (Tokenizer.peekNextToken().Kind != TokenInfo::TK_Eof) {
564f4a2713aSLionel Sambuc Error->addError(Tokenizer.peekNextToken().Range,
565f4a2713aSLionel Sambuc Error->ET_ParserTrailingCode);
566f4a2713aSLionel Sambuc return false;
567f4a2713aSLionel Sambuc }
568f4a2713aSLionel Sambuc return true;
569f4a2713aSLionel Sambuc }
570f4a2713aSLionel Sambuc
571*0a6a1f1dSLionel Sambuc std::vector<MatcherCompletion>
completeExpression(StringRef Code,unsigned CompletionOffset,Sema * S,const NamedValueMap * NamedValues)572*0a6a1f1dSLionel Sambuc Parser::completeExpression(StringRef Code, unsigned CompletionOffset, Sema *S,
573*0a6a1f1dSLionel Sambuc const NamedValueMap *NamedValues) {
574*0a6a1f1dSLionel Sambuc Diagnostics Error;
575*0a6a1f1dSLionel Sambuc CodeTokenizer Tokenizer(Code, &Error, CompletionOffset);
576*0a6a1f1dSLionel Sambuc Parser P(&Tokenizer, S, NamedValues, &Error);
577*0a6a1f1dSLionel Sambuc VariantValue Dummy;
578*0a6a1f1dSLionel Sambuc P.parseExpressionImpl(&Dummy);
579*0a6a1f1dSLionel Sambuc
580*0a6a1f1dSLionel Sambuc // Sort by specificity, then by name.
581*0a6a1f1dSLionel Sambuc std::sort(P.Completions.begin(), P.Completions.end(),
582*0a6a1f1dSLionel Sambuc [](const MatcherCompletion &A, const MatcherCompletion &B) {
583*0a6a1f1dSLionel Sambuc if (A.Specificity != B.Specificity)
584*0a6a1f1dSLionel Sambuc return A.Specificity > B.Specificity;
585*0a6a1f1dSLionel Sambuc return A.TypedText < B.TypedText;
586*0a6a1f1dSLionel Sambuc });
587*0a6a1f1dSLionel Sambuc
588*0a6a1f1dSLionel Sambuc return P.Completions;
589f4a2713aSLionel Sambuc }
590f4a2713aSLionel Sambuc
591f4a2713aSLionel Sambuc llvm::Optional<DynTypedMatcher>
parseMatcherExpression(StringRef Code,Sema * S,const NamedValueMap * NamedValues,Diagnostics * Error)592*0a6a1f1dSLionel Sambuc Parser::parseMatcherExpression(StringRef Code, Sema *S,
593*0a6a1f1dSLionel Sambuc const NamedValueMap *NamedValues,
594f4a2713aSLionel Sambuc Diagnostics *Error) {
595f4a2713aSLionel Sambuc VariantValue Value;
596*0a6a1f1dSLionel Sambuc if (!parseExpression(Code, S, NamedValues, &Value, Error))
597f4a2713aSLionel Sambuc return llvm::Optional<DynTypedMatcher>();
598f4a2713aSLionel Sambuc if (!Value.isMatcher()) {
599f4a2713aSLionel Sambuc Error->addError(SourceRange(), Error->ET_ParserNotAMatcher);
600f4a2713aSLionel Sambuc return llvm::Optional<DynTypedMatcher>();
601f4a2713aSLionel Sambuc }
602f4a2713aSLionel Sambuc llvm::Optional<DynTypedMatcher> Result =
603f4a2713aSLionel Sambuc Value.getMatcher().getSingleMatcher();
604f4a2713aSLionel Sambuc if (!Result.hasValue()) {
605f4a2713aSLionel Sambuc Error->addError(SourceRange(), Error->ET_ParserOverloadedType)
606f4a2713aSLionel Sambuc << Value.getTypeAsString();
607f4a2713aSLionel Sambuc }
608f4a2713aSLionel Sambuc return Result;
609f4a2713aSLionel Sambuc }
610f4a2713aSLionel Sambuc
611f4a2713aSLionel Sambuc } // namespace dynamic
612f4a2713aSLionel Sambuc } // namespace ast_matchers
613f4a2713aSLionel Sambuc } // namespace clang
614