xref: /openbsd-src/gnu/llvm/clang/lib/ASTMatchers/Dynamic/Parser.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrick //===- Parser.cpp - Matcher expression parser -----------------------------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick ///
9e5dd7070Spatrick /// \file
10e5dd7070Spatrick /// Recursive parser implementation for the matcher expression grammar.
11e5dd7070Spatrick ///
12e5dd7070Spatrick //===----------------------------------------------------------------------===//
13e5dd7070Spatrick 
14e5dd7070Spatrick #include "clang/ASTMatchers/Dynamic/Parser.h"
15e5dd7070Spatrick #include "clang/ASTMatchers/ASTMatchersInternal.h"
16e5dd7070Spatrick #include "clang/ASTMatchers/Dynamic/Diagnostics.h"
17e5dd7070Spatrick #include "clang/ASTMatchers/Dynamic/Registry.h"
18e5dd7070Spatrick #include "clang/Basic/CharInfo.h"
19e5dd7070Spatrick #include "llvm/ADT/StringRef.h"
20e5dd7070Spatrick #include "llvm/Support/ErrorHandling.h"
21e5dd7070Spatrick #include "llvm/Support/ManagedStatic.h"
22e5dd7070Spatrick #include <algorithm>
23e5dd7070Spatrick #include <cassert>
24e5dd7070Spatrick #include <cerrno>
25e5dd7070Spatrick #include <cstddef>
26e5dd7070Spatrick #include <cstdlib>
27*12c85518Srobert #include <optional>
28e5dd7070Spatrick #include <string>
29e5dd7070Spatrick #include <utility>
30e5dd7070Spatrick #include <vector>
31e5dd7070Spatrick 
32e5dd7070Spatrick namespace clang {
33e5dd7070Spatrick namespace ast_matchers {
34e5dd7070Spatrick namespace dynamic {
35e5dd7070Spatrick 
36e5dd7070Spatrick /// Simple structure to hold information for one token from the parser.
37e5dd7070Spatrick struct Parser::TokenInfo {
38e5dd7070Spatrick   /// Different possible tokens.
39e5dd7070Spatrick   enum TokenKind {
40e5dd7070Spatrick     TK_Eof,
41e5dd7070Spatrick     TK_NewLine,
42e5dd7070Spatrick     TK_OpenParen,
43e5dd7070Spatrick     TK_CloseParen,
44e5dd7070Spatrick     TK_Comma,
45e5dd7070Spatrick     TK_Period,
46e5dd7070Spatrick     TK_Literal,
47e5dd7070Spatrick     TK_Ident,
48e5dd7070Spatrick     TK_InvalidChar,
49e5dd7070Spatrick     TK_Error,
50e5dd7070Spatrick     TK_CodeCompletion
51e5dd7070Spatrick   };
52e5dd7070Spatrick 
53e5dd7070Spatrick   /// Some known identifiers.
54e5dd7070Spatrick   static const char* const ID_Bind;
55a9ac8606Spatrick   static const char *const ID_With;
56e5dd7070Spatrick 
57e5dd7070Spatrick   TokenInfo() = default;
58e5dd7070Spatrick 
59e5dd7070Spatrick   StringRef Text;
60e5dd7070Spatrick   TokenKind Kind = TK_Eof;
61e5dd7070Spatrick   SourceRange Range;
62e5dd7070Spatrick   VariantValue Value;
63e5dd7070Spatrick };
64e5dd7070Spatrick 
65e5dd7070Spatrick const char* const Parser::TokenInfo::ID_Bind = "bind";
66a9ac8606Spatrick const char *const Parser::TokenInfo::ID_With = "with";
67e5dd7070Spatrick 
68e5dd7070Spatrick /// Simple tokenizer for the parser.
69e5dd7070Spatrick class Parser::CodeTokenizer {
70e5dd7070Spatrick public:
CodeTokenizer(StringRef & MatcherCode,Diagnostics * Error)71e5dd7070Spatrick   explicit CodeTokenizer(StringRef &MatcherCode, Diagnostics *Error)
72e5dd7070Spatrick       : Code(MatcherCode), StartOfLine(MatcherCode), Error(Error) {
73e5dd7070Spatrick     NextToken = getNextToken();
74e5dd7070Spatrick   }
75e5dd7070Spatrick 
CodeTokenizer(StringRef & MatcherCode,Diagnostics * Error,unsigned CodeCompletionOffset)76e5dd7070Spatrick   CodeTokenizer(StringRef &MatcherCode, Diagnostics *Error,
77e5dd7070Spatrick                 unsigned CodeCompletionOffset)
78e5dd7070Spatrick       : Code(MatcherCode), StartOfLine(MatcherCode), Error(Error),
79e5dd7070Spatrick         CodeCompletionLocation(MatcherCode.data() + CodeCompletionOffset) {
80e5dd7070Spatrick     NextToken = getNextToken();
81e5dd7070Spatrick   }
82e5dd7070Spatrick 
83e5dd7070Spatrick   /// Returns but doesn't consume the next token.
peekNextToken() const84e5dd7070Spatrick   const TokenInfo &peekNextToken() const { return NextToken; }
85e5dd7070Spatrick 
86e5dd7070Spatrick   /// Consumes and returns the next token.
consumeNextToken()87e5dd7070Spatrick   TokenInfo consumeNextToken() {
88e5dd7070Spatrick     TokenInfo ThisToken = NextToken;
89e5dd7070Spatrick     NextToken = getNextToken();
90e5dd7070Spatrick     return ThisToken;
91e5dd7070Spatrick   }
92e5dd7070Spatrick 
SkipNewlines()93e5dd7070Spatrick   TokenInfo SkipNewlines() {
94e5dd7070Spatrick     while (NextToken.Kind == TokenInfo::TK_NewLine)
95e5dd7070Spatrick       NextToken = getNextToken();
96e5dd7070Spatrick     return NextToken;
97e5dd7070Spatrick   }
98e5dd7070Spatrick 
consumeNextTokenIgnoreNewlines()99e5dd7070Spatrick   TokenInfo consumeNextTokenIgnoreNewlines() {
100e5dd7070Spatrick     SkipNewlines();
101e5dd7070Spatrick     if (NextToken.Kind == TokenInfo::TK_Eof)
102e5dd7070Spatrick       return NextToken;
103e5dd7070Spatrick     return consumeNextToken();
104e5dd7070Spatrick   }
105e5dd7070Spatrick 
nextTokenKind() const106e5dd7070Spatrick   TokenInfo::TokenKind nextTokenKind() const { return NextToken.Kind; }
107e5dd7070Spatrick 
108e5dd7070Spatrick private:
getNextToken()109e5dd7070Spatrick   TokenInfo getNextToken() {
110e5dd7070Spatrick     consumeWhitespace();
111e5dd7070Spatrick     TokenInfo Result;
112e5dd7070Spatrick     Result.Range.Start = currentLocation();
113e5dd7070Spatrick 
114e5dd7070Spatrick     if (CodeCompletionLocation && CodeCompletionLocation <= Code.data()) {
115e5dd7070Spatrick       Result.Kind = TokenInfo::TK_CodeCompletion;
116e5dd7070Spatrick       Result.Text = StringRef(CodeCompletionLocation, 0);
117e5dd7070Spatrick       CodeCompletionLocation = nullptr;
118e5dd7070Spatrick       return Result;
119e5dd7070Spatrick     }
120e5dd7070Spatrick 
121e5dd7070Spatrick     if (Code.empty()) {
122e5dd7070Spatrick       Result.Kind = TokenInfo::TK_Eof;
123e5dd7070Spatrick       Result.Text = "";
124e5dd7070Spatrick       return Result;
125e5dd7070Spatrick     }
126e5dd7070Spatrick 
127e5dd7070Spatrick     switch (Code[0]) {
128e5dd7070Spatrick     case '#':
129e5dd7070Spatrick       Code = Code.drop_until([](char c) { return c == '\n'; });
130e5dd7070Spatrick       return getNextToken();
131e5dd7070Spatrick     case ',':
132e5dd7070Spatrick       Result.Kind = TokenInfo::TK_Comma;
133e5dd7070Spatrick       Result.Text = Code.substr(0, 1);
134e5dd7070Spatrick       Code = Code.drop_front();
135e5dd7070Spatrick       break;
136e5dd7070Spatrick     case '.':
137e5dd7070Spatrick       Result.Kind = TokenInfo::TK_Period;
138e5dd7070Spatrick       Result.Text = Code.substr(0, 1);
139e5dd7070Spatrick       Code = Code.drop_front();
140e5dd7070Spatrick       break;
141e5dd7070Spatrick     case '\n':
142e5dd7070Spatrick       ++Line;
143e5dd7070Spatrick       StartOfLine = Code.drop_front();
144e5dd7070Spatrick       Result.Kind = TokenInfo::TK_NewLine;
145e5dd7070Spatrick       Result.Text = Code.substr(0, 1);
146e5dd7070Spatrick       Code = Code.drop_front();
147e5dd7070Spatrick       break;
148e5dd7070Spatrick     case '(':
149e5dd7070Spatrick       Result.Kind = TokenInfo::TK_OpenParen;
150e5dd7070Spatrick       Result.Text = Code.substr(0, 1);
151e5dd7070Spatrick       Code = Code.drop_front();
152e5dd7070Spatrick       break;
153e5dd7070Spatrick     case ')':
154e5dd7070Spatrick       Result.Kind = TokenInfo::TK_CloseParen;
155e5dd7070Spatrick       Result.Text = Code.substr(0, 1);
156e5dd7070Spatrick       Code = Code.drop_front();
157e5dd7070Spatrick       break;
158e5dd7070Spatrick 
159e5dd7070Spatrick     case '"':
160e5dd7070Spatrick     case '\'':
161e5dd7070Spatrick       // Parse a string literal.
162e5dd7070Spatrick       consumeStringLiteral(&Result);
163e5dd7070Spatrick       break;
164e5dd7070Spatrick 
165e5dd7070Spatrick     case '0': case '1': case '2': case '3': case '4':
166e5dd7070Spatrick     case '5': case '6': case '7': case '8': case '9':
167e5dd7070Spatrick       // Parse an unsigned and float literal.
168e5dd7070Spatrick       consumeNumberLiteral(&Result);
169e5dd7070Spatrick       break;
170e5dd7070Spatrick 
171e5dd7070Spatrick     default:
172e5dd7070Spatrick       if (isAlphanumeric(Code[0])) {
173e5dd7070Spatrick         // Parse an identifier
174e5dd7070Spatrick         size_t TokenLength = 1;
175e5dd7070Spatrick         while (true) {
176e5dd7070Spatrick           // A code completion location in/immediately after an identifier will
177e5dd7070Spatrick           // cause the portion of the identifier before the code completion
178e5dd7070Spatrick           // location to become a code completion token.
179e5dd7070Spatrick           if (CodeCompletionLocation == Code.data() + TokenLength) {
180e5dd7070Spatrick             CodeCompletionLocation = nullptr;
181e5dd7070Spatrick             Result.Kind = TokenInfo::TK_CodeCompletion;
182e5dd7070Spatrick             Result.Text = Code.substr(0, TokenLength);
183e5dd7070Spatrick             Code = Code.drop_front(TokenLength);
184e5dd7070Spatrick             return Result;
185e5dd7070Spatrick           }
186e5dd7070Spatrick           if (TokenLength == Code.size() || !isAlphanumeric(Code[TokenLength]))
187e5dd7070Spatrick             break;
188e5dd7070Spatrick           ++TokenLength;
189e5dd7070Spatrick         }
190e5dd7070Spatrick         if (TokenLength == 4 && Code.startswith("true")) {
191e5dd7070Spatrick           Result.Kind = TokenInfo::TK_Literal;
192e5dd7070Spatrick           Result.Value = true;
193e5dd7070Spatrick         } else if (TokenLength == 5 && Code.startswith("false")) {
194e5dd7070Spatrick           Result.Kind = TokenInfo::TK_Literal;
195e5dd7070Spatrick           Result.Value = false;
196e5dd7070Spatrick         } else {
197e5dd7070Spatrick           Result.Kind = TokenInfo::TK_Ident;
198e5dd7070Spatrick           Result.Text = Code.substr(0, TokenLength);
199e5dd7070Spatrick         }
200e5dd7070Spatrick         Code = Code.drop_front(TokenLength);
201e5dd7070Spatrick       } else {
202e5dd7070Spatrick         Result.Kind = TokenInfo::TK_InvalidChar;
203e5dd7070Spatrick         Result.Text = Code.substr(0, 1);
204e5dd7070Spatrick         Code = Code.drop_front(1);
205e5dd7070Spatrick       }
206e5dd7070Spatrick       break;
207e5dd7070Spatrick     }
208e5dd7070Spatrick 
209e5dd7070Spatrick     Result.Range.End = currentLocation();
210e5dd7070Spatrick     return Result;
211e5dd7070Spatrick   }
212e5dd7070Spatrick 
213e5dd7070Spatrick   /// Consume an unsigned and float literal.
consumeNumberLiteral(TokenInfo * Result)214e5dd7070Spatrick   void consumeNumberLiteral(TokenInfo *Result) {
215e5dd7070Spatrick     bool isFloatingLiteral = false;
216e5dd7070Spatrick     unsigned Length = 1;
217e5dd7070Spatrick     if (Code.size() > 1) {
218e5dd7070Spatrick       // Consume the 'x' or 'b' radix modifier, if present.
219e5dd7070Spatrick       switch (toLowercase(Code[1])) {
220e5dd7070Spatrick       case 'x': case 'b': Length = 2;
221e5dd7070Spatrick       }
222e5dd7070Spatrick     }
223e5dd7070Spatrick     while (Length < Code.size() && isHexDigit(Code[Length]))
224e5dd7070Spatrick       ++Length;
225e5dd7070Spatrick 
226e5dd7070Spatrick     // Try to recognize a floating point literal.
227e5dd7070Spatrick     while (Length < Code.size()) {
228e5dd7070Spatrick       char c = Code[Length];
229e5dd7070Spatrick       if (c == '-' || c == '+' || c == '.' || isHexDigit(c)) {
230e5dd7070Spatrick         isFloatingLiteral = true;
231e5dd7070Spatrick         Length++;
232e5dd7070Spatrick       } else {
233e5dd7070Spatrick         break;
234e5dd7070Spatrick       }
235e5dd7070Spatrick     }
236e5dd7070Spatrick 
237e5dd7070Spatrick     Result->Text = Code.substr(0, Length);
238e5dd7070Spatrick     Code = Code.drop_front(Length);
239e5dd7070Spatrick 
240e5dd7070Spatrick     if (isFloatingLiteral) {
241e5dd7070Spatrick       char *end;
242e5dd7070Spatrick       errno = 0;
243e5dd7070Spatrick       std::string Text = Result->Text.str();
244e5dd7070Spatrick       double doubleValue = strtod(Text.c_str(), &end);
245e5dd7070Spatrick       if (*end == 0 && errno == 0) {
246e5dd7070Spatrick         Result->Kind = TokenInfo::TK_Literal;
247e5dd7070Spatrick         Result->Value = doubleValue;
248e5dd7070Spatrick         return;
249e5dd7070Spatrick       }
250e5dd7070Spatrick     } else {
251e5dd7070Spatrick       unsigned Value;
252e5dd7070Spatrick       if (!Result->Text.getAsInteger(0, Value)) {
253e5dd7070Spatrick         Result->Kind = TokenInfo::TK_Literal;
254e5dd7070Spatrick         Result->Value = Value;
255e5dd7070Spatrick         return;
256e5dd7070Spatrick       }
257e5dd7070Spatrick     }
258e5dd7070Spatrick 
259e5dd7070Spatrick     SourceRange Range;
260e5dd7070Spatrick     Range.Start = Result->Range.Start;
261e5dd7070Spatrick     Range.End = currentLocation();
262e5dd7070Spatrick     Error->addError(Range, Error->ET_ParserNumberError) << Result->Text;
263e5dd7070Spatrick     Result->Kind = TokenInfo::TK_Error;
264e5dd7070Spatrick   }
265e5dd7070Spatrick 
266e5dd7070Spatrick   /// Consume a string literal.
267e5dd7070Spatrick   ///
268e5dd7070Spatrick   /// \c Code must be positioned at the start of the literal (the opening
269e5dd7070Spatrick   /// quote). Consumed until it finds the same closing quote character.
consumeStringLiteral(TokenInfo * Result)270e5dd7070Spatrick   void consumeStringLiteral(TokenInfo *Result) {
271e5dd7070Spatrick     bool InEscape = false;
272e5dd7070Spatrick     const char Marker = Code[0];
273e5dd7070Spatrick     for (size_t Length = 1, Size = Code.size(); Length != Size; ++Length) {
274e5dd7070Spatrick       if (InEscape) {
275e5dd7070Spatrick         InEscape = false;
276e5dd7070Spatrick         continue;
277e5dd7070Spatrick       }
278e5dd7070Spatrick       if (Code[Length] == '\\') {
279e5dd7070Spatrick         InEscape = true;
280e5dd7070Spatrick         continue;
281e5dd7070Spatrick       }
282e5dd7070Spatrick       if (Code[Length] == Marker) {
283e5dd7070Spatrick         Result->Kind = TokenInfo::TK_Literal;
284e5dd7070Spatrick         Result->Text = Code.substr(0, Length + 1);
285e5dd7070Spatrick         Result->Value = Code.substr(1, Length - 1);
286e5dd7070Spatrick         Code = Code.drop_front(Length + 1);
287e5dd7070Spatrick         return;
288e5dd7070Spatrick       }
289e5dd7070Spatrick     }
290e5dd7070Spatrick 
291e5dd7070Spatrick     StringRef ErrorText = Code;
292e5dd7070Spatrick     Code = Code.drop_front(Code.size());
293e5dd7070Spatrick     SourceRange Range;
294e5dd7070Spatrick     Range.Start = Result->Range.Start;
295e5dd7070Spatrick     Range.End = currentLocation();
296e5dd7070Spatrick     Error->addError(Range, Error->ET_ParserStringError) << ErrorText;
297e5dd7070Spatrick     Result->Kind = TokenInfo::TK_Error;
298e5dd7070Spatrick   }
299e5dd7070Spatrick 
300e5dd7070Spatrick   /// Consume all leading whitespace from \c Code.
consumeWhitespace()301e5dd7070Spatrick   void consumeWhitespace() {
302e5dd7070Spatrick     Code = Code.drop_while([](char c) {
303e5dd7070Spatrick       // Don't trim newlines.
304e5dd7070Spatrick       return StringRef(" \t\v\f\r").contains(c);
305e5dd7070Spatrick     });
306e5dd7070Spatrick   }
307e5dd7070Spatrick 
currentLocation()308e5dd7070Spatrick   SourceLocation currentLocation() {
309e5dd7070Spatrick     SourceLocation Location;
310e5dd7070Spatrick     Location.Line = Line;
311e5dd7070Spatrick     Location.Column = Code.data() - StartOfLine.data() + 1;
312e5dd7070Spatrick     return Location;
313e5dd7070Spatrick   }
314e5dd7070Spatrick 
315e5dd7070Spatrick   StringRef &Code;
316e5dd7070Spatrick   StringRef StartOfLine;
317e5dd7070Spatrick   unsigned Line = 1;
318e5dd7070Spatrick   Diagnostics *Error;
319e5dd7070Spatrick   TokenInfo NextToken;
320e5dd7070Spatrick   const char *CodeCompletionLocation = nullptr;
321e5dd7070Spatrick };
322e5dd7070Spatrick 
323e5dd7070Spatrick Parser::Sema::~Sema() = default;
324e5dd7070Spatrick 
getAcceptedCompletionTypes(llvm::ArrayRef<std::pair<MatcherCtor,unsigned>> Context)325e5dd7070Spatrick std::vector<ArgKind> Parser::Sema::getAcceptedCompletionTypes(
326e5dd7070Spatrick     llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context) {
327e5dd7070Spatrick   return {};
328e5dd7070Spatrick }
329e5dd7070Spatrick 
330e5dd7070Spatrick std::vector<MatcherCompletion>
getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes)331e5dd7070Spatrick Parser::Sema::getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes) {
332e5dd7070Spatrick   return {};
333e5dd7070Spatrick }
334e5dd7070Spatrick 
335e5dd7070Spatrick struct Parser::ScopedContextEntry {
336e5dd7070Spatrick   Parser *P;
337e5dd7070Spatrick 
ScopedContextEntryclang::ast_matchers::dynamic::Parser::ScopedContextEntry338e5dd7070Spatrick   ScopedContextEntry(Parser *P, MatcherCtor C) : P(P) {
339e5dd7070Spatrick     P->ContextStack.push_back(std::make_pair(C, 0u));
340e5dd7070Spatrick   }
341e5dd7070Spatrick 
~ScopedContextEntryclang::ast_matchers::dynamic::Parser::ScopedContextEntry342e5dd7070Spatrick   ~ScopedContextEntry() {
343e5dd7070Spatrick     P->ContextStack.pop_back();
344e5dd7070Spatrick   }
345e5dd7070Spatrick 
nextArgclang::ast_matchers::dynamic::Parser::ScopedContextEntry346e5dd7070Spatrick   void nextArg() {
347e5dd7070Spatrick     ++P->ContextStack.back().second;
348e5dd7070Spatrick   }
349e5dd7070Spatrick };
350e5dd7070Spatrick 
351e5dd7070Spatrick /// Parse expressions that start with an identifier.
352e5dd7070Spatrick ///
353e5dd7070Spatrick /// This function can parse named values and matchers.
354e5dd7070Spatrick /// In case of failure it will try to determine the user's intent to give
355e5dd7070Spatrick /// an appropriate error message.
parseIdentifierPrefixImpl(VariantValue * Value)356e5dd7070Spatrick bool Parser::parseIdentifierPrefixImpl(VariantValue *Value) {
357e5dd7070Spatrick   const TokenInfo NameToken = Tokenizer->consumeNextToken();
358e5dd7070Spatrick 
359e5dd7070Spatrick   if (Tokenizer->nextTokenKind() != TokenInfo::TK_OpenParen) {
360e5dd7070Spatrick     // Parse as a named value.
361e5dd7070Spatrick     if (const VariantValue NamedValue =
362e5dd7070Spatrick             NamedValues ? NamedValues->lookup(NameToken.Text)
363e5dd7070Spatrick                         : VariantValue()) {
364e5dd7070Spatrick 
365e5dd7070Spatrick       if (Tokenizer->nextTokenKind() != TokenInfo::TK_Period) {
366e5dd7070Spatrick         *Value = NamedValue;
367e5dd7070Spatrick         return true;
368e5dd7070Spatrick       }
369e5dd7070Spatrick 
370e5dd7070Spatrick       std::string BindID;
371a9ac8606Spatrick       Tokenizer->consumeNextToken();
372a9ac8606Spatrick       TokenInfo ChainCallToken = Tokenizer->consumeNextToken();
373a9ac8606Spatrick       if (ChainCallToken.Kind == TokenInfo::TK_CodeCompletion) {
374a9ac8606Spatrick         addCompletion(ChainCallToken, MatcherCompletion("bind(\"", "bind", 1));
375a9ac8606Spatrick         return false;
376a9ac8606Spatrick       }
377a9ac8606Spatrick 
378a9ac8606Spatrick       if (ChainCallToken.Kind != TokenInfo::TK_Ident ||
379a9ac8606Spatrick           (ChainCallToken.Text != TokenInfo::ID_Bind &&
380a9ac8606Spatrick            ChainCallToken.Text != TokenInfo::ID_With)) {
381a9ac8606Spatrick         Error->addError(ChainCallToken.Range,
382a9ac8606Spatrick                         Error->ET_ParserMalformedChainedExpr);
383a9ac8606Spatrick         return false;
384a9ac8606Spatrick       }
385a9ac8606Spatrick       if (ChainCallToken.Text == TokenInfo::ID_With) {
386a9ac8606Spatrick 
387a9ac8606Spatrick         Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error,
388a9ac8606Spatrick                                  NameToken.Text, NameToken.Range);
389a9ac8606Spatrick 
390a9ac8606Spatrick         Error->addError(ChainCallToken.Range,
391a9ac8606Spatrick                         Error->ET_RegistryMatcherNoWithSupport);
392a9ac8606Spatrick         return false;
393a9ac8606Spatrick       }
394e5dd7070Spatrick       if (!parseBindID(BindID))
395e5dd7070Spatrick         return false;
396e5dd7070Spatrick 
397e5dd7070Spatrick       assert(NamedValue.isMatcher());
398*12c85518Srobert       std::optional<DynTypedMatcher> Result =
399e5dd7070Spatrick           NamedValue.getMatcher().getSingleMatcher();
400*12c85518Srobert       if (Result) {
401*12c85518Srobert         std::optional<DynTypedMatcher> Bound = Result->tryBind(BindID);
402*12c85518Srobert         if (Bound) {
403e5dd7070Spatrick           *Value = VariantMatcher::SingleMatcher(*Bound);
404e5dd7070Spatrick           return true;
405e5dd7070Spatrick         }
406e5dd7070Spatrick       }
407e5dd7070Spatrick       return false;
408e5dd7070Spatrick     }
409e5dd7070Spatrick 
410e5dd7070Spatrick     if (Tokenizer->nextTokenKind() == TokenInfo::TK_NewLine) {
411e5dd7070Spatrick       Error->addError(Tokenizer->peekNextToken().Range,
412e5dd7070Spatrick                       Error->ET_ParserNoOpenParen)
413e5dd7070Spatrick           << "NewLine";
414e5dd7070Spatrick       return false;
415e5dd7070Spatrick     }
416e5dd7070Spatrick 
417e5dd7070Spatrick     // If the syntax is correct and the name is not a matcher either, report
418e5dd7070Spatrick     // unknown named value.
419e5dd7070Spatrick     if ((Tokenizer->nextTokenKind() == TokenInfo::TK_Comma ||
420e5dd7070Spatrick          Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen ||
421e5dd7070Spatrick          Tokenizer->nextTokenKind() == TokenInfo::TK_NewLine ||
422e5dd7070Spatrick          Tokenizer->nextTokenKind() == TokenInfo::TK_Eof) &&
423e5dd7070Spatrick         !S->lookupMatcherCtor(NameToken.Text)) {
424e5dd7070Spatrick       Error->addError(NameToken.Range, Error->ET_RegistryValueNotFound)
425e5dd7070Spatrick           << NameToken.Text;
426e5dd7070Spatrick       return false;
427e5dd7070Spatrick     }
428e5dd7070Spatrick     // Otherwise, fallback to the matcher parser.
429e5dd7070Spatrick   }
430e5dd7070Spatrick 
431e5dd7070Spatrick   Tokenizer->SkipNewlines();
432e5dd7070Spatrick 
433a9ac8606Spatrick   assert(NameToken.Kind == TokenInfo::TK_Ident);
434a9ac8606Spatrick   TokenInfo OpenToken = Tokenizer->consumeNextToken();
435a9ac8606Spatrick   if (OpenToken.Kind != TokenInfo::TK_OpenParen) {
436a9ac8606Spatrick     Error->addError(OpenToken.Range, Error->ET_ParserNoOpenParen)
437a9ac8606Spatrick         << OpenToken.Text;
438e5dd7070Spatrick     return false;
439e5dd7070Spatrick   }
440e5dd7070Spatrick 
441*12c85518Srobert   std::optional<MatcherCtor> Ctor = S->lookupMatcherCtor(NameToken.Text);
442a9ac8606Spatrick 
443a9ac8606Spatrick   // Parse as a matcher expression.
444a9ac8606Spatrick   return parseMatcherExpressionImpl(NameToken, OpenToken, Ctor, Value);
445a9ac8606Spatrick }
446a9ac8606Spatrick 
parseBindID(std::string & BindID)447a9ac8606Spatrick bool Parser::parseBindID(std::string &BindID) {
448a9ac8606Spatrick   // Parse the parenthesized argument to .bind("foo")
449e5dd7070Spatrick   const TokenInfo OpenToken = Tokenizer->consumeNextToken();
450e5dd7070Spatrick   const TokenInfo IDToken = Tokenizer->consumeNextTokenIgnoreNewlines();
451e5dd7070Spatrick   const TokenInfo CloseToken = Tokenizer->consumeNextTokenIgnoreNewlines();
452e5dd7070Spatrick 
453e5dd7070Spatrick   // TODO: We could use different error codes for each/some to be more
454e5dd7070Spatrick   //       explicit about the syntax error.
455e5dd7070Spatrick   if (OpenToken.Kind != TokenInfo::TK_OpenParen) {
456e5dd7070Spatrick     Error->addError(OpenToken.Range, Error->ET_ParserMalformedBindExpr);
457e5dd7070Spatrick     return false;
458e5dd7070Spatrick   }
459e5dd7070Spatrick   if (IDToken.Kind != TokenInfo::TK_Literal || !IDToken.Value.isString()) {
460e5dd7070Spatrick     Error->addError(IDToken.Range, Error->ET_ParserMalformedBindExpr);
461e5dd7070Spatrick     return false;
462e5dd7070Spatrick   }
463e5dd7070Spatrick   if (CloseToken.Kind != TokenInfo::TK_CloseParen) {
464e5dd7070Spatrick     Error->addError(CloseToken.Range, Error->ET_ParserMalformedBindExpr);
465e5dd7070Spatrick     return false;
466e5dd7070Spatrick   }
467e5dd7070Spatrick   BindID = IDToken.Value.getString();
468e5dd7070Spatrick   return true;
469e5dd7070Spatrick }
470e5dd7070Spatrick 
parseMatcherBuilder(MatcherCtor Ctor,const TokenInfo & NameToken,const TokenInfo & OpenToken,VariantValue * Value)471a9ac8606Spatrick bool Parser::parseMatcherBuilder(MatcherCtor Ctor, const TokenInfo &NameToken,
472a9ac8606Spatrick                                  const TokenInfo &OpenToken,
473a9ac8606Spatrick                                  VariantValue *Value) {
474a9ac8606Spatrick   std::vector<ParserValue> Args;
475a9ac8606Spatrick   TokenInfo EndToken;
476a9ac8606Spatrick 
477a9ac8606Spatrick   Tokenizer->SkipNewlines();
478a9ac8606Spatrick 
479a9ac8606Spatrick   {
480a9ac8606Spatrick     ScopedContextEntry SCE(this, Ctor);
481a9ac8606Spatrick 
482a9ac8606Spatrick     while (Tokenizer->nextTokenKind() != TokenInfo::TK_Eof) {
483a9ac8606Spatrick       if (Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen) {
484a9ac8606Spatrick         // End of args.
485a9ac8606Spatrick         EndToken = Tokenizer->consumeNextToken();
486a9ac8606Spatrick         break;
487a9ac8606Spatrick       }
488a9ac8606Spatrick       if (!Args.empty()) {
489a9ac8606Spatrick         // We must find a , token to continue.
490a9ac8606Spatrick         TokenInfo CommaToken = Tokenizer->consumeNextToken();
491a9ac8606Spatrick         if (CommaToken.Kind != TokenInfo::TK_Comma) {
492a9ac8606Spatrick           Error->addError(CommaToken.Range, Error->ET_ParserNoComma)
493a9ac8606Spatrick               << CommaToken.Text;
494a9ac8606Spatrick           return false;
495a9ac8606Spatrick         }
496a9ac8606Spatrick       }
497a9ac8606Spatrick 
498a9ac8606Spatrick       Diagnostics::Context Ctx(Diagnostics::Context::MatcherArg, Error,
499a9ac8606Spatrick                                NameToken.Text, NameToken.Range,
500a9ac8606Spatrick                                Args.size() + 1);
501a9ac8606Spatrick       ParserValue ArgValue;
502a9ac8606Spatrick       Tokenizer->SkipNewlines();
503a9ac8606Spatrick 
504a9ac8606Spatrick       if (Tokenizer->peekNextToken().Kind == TokenInfo::TK_CodeCompletion) {
505a9ac8606Spatrick         addExpressionCompletions();
506a9ac8606Spatrick         return false;
507a9ac8606Spatrick       }
508a9ac8606Spatrick 
509a9ac8606Spatrick       TokenInfo NodeMatcherToken = Tokenizer->consumeNextToken();
510a9ac8606Spatrick 
511a9ac8606Spatrick       if (NodeMatcherToken.Kind != TokenInfo::TK_Ident) {
512a9ac8606Spatrick         Error->addError(NameToken.Range, Error->ET_ParserFailedToBuildMatcher)
513a9ac8606Spatrick             << NameToken.Text;
514a9ac8606Spatrick         return false;
515a9ac8606Spatrick       }
516a9ac8606Spatrick 
517a9ac8606Spatrick       ArgValue.Text = NodeMatcherToken.Text;
518a9ac8606Spatrick       ArgValue.Range = NodeMatcherToken.Range;
519a9ac8606Spatrick 
520*12c85518Srobert       std::optional<MatcherCtor> MappedMatcher =
521a9ac8606Spatrick           S->lookupMatcherCtor(ArgValue.Text);
522a9ac8606Spatrick 
523a9ac8606Spatrick       if (!MappedMatcher) {
524a9ac8606Spatrick         Error->addError(NodeMatcherToken.Range,
525a9ac8606Spatrick                         Error->ET_RegistryMatcherNotFound)
526a9ac8606Spatrick             << NodeMatcherToken.Text;
527a9ac8606Spatrick         return false;
528a9ac8606Spatrick       }
529a9ac8606Spatrick 
530a9ac8606Spatrick       ASTNodeKind NK = S->nodeMatcherType(*MappedMatcher);
531a9ac8606Spatrick 
532a9ac8606Spatrick       if (NK.isNone()) {
533a9ac8606Spatrick         Error->addError(NodeMatcherToken.Range,
534a9ac8606Spatrick                         Error->ET_RegistryNonNodeMatcher)
535a9ac8606Spatrick             << NodeMatcherToken.Text;
536a9ac8606Spatrick         return false;
537a9ac8606Spatrick       }
538a9ac8606Spatrick 
539a9ac8606Spatrick       ArgValue.Value = NK;
540a9ac8606Spatrick 
541a9ac8606Spatrick       Tokenizer->SkipNewlines();
542a9ac8606Spatrick       Args.push_back(ArgValue);
543a9ac8606Spatrick 
544a9ac8606Spatrick       SCE.nextArg();
545a9ac8606Spatrick     }
546a9ac8606Spatrick   }
547a9ac8606Spatrick 
548a9ac8606Spatrick   if (EndToken.Kind == TokenInfo::TK_Eof) {
549a9ac8606Spatrick     Error->addError(OpenToken.Range, Error->ET_ParserNoCloseParen);
550a9ac8606Spatrick     return false;
551a9ac8606Spatrick   }
552a9ac8606Spatrick 
553a9ac8606Spatrick   internal::MatcherDescriptorPtr BuiltCtor =
554a9ac8606Spatrick       S->buildMatcherCtor(Ctor, NameToken.Range, Args, Error);
555a9ac8606Spatrick 
556a9ac8606Spatrick   if (!BuiltCtor.get()) {
557a9ac8606Spatrick     Error->addError(NameToken.Range, Error->ET_ParserFailedToBuildMatcher)
558a9ac8606Spatrick         << NameToken.Text;
559a9ac8606Spatrick     return false;
560a9ac8606Spatrick   }
561a9ac8606Spatrick 
562a9ac8606Spatrick   std::string BindID;
563a9ac8606Spatrick   if (Tokenizer->peekNextToken().Kind == TokenInfo::TK_Period) {
564a9ac8606Spatrick     Tokenizer->consumeNextToken();
565a9ac8606Spatrick     TokenInfo ChainCallToken = Tokenizer->consumeNextToken();
566a9ac8606Spatrick     if (ChainCallToken.Kind == TokenInfo::TK_CodeCompletion) {
567a9ac8606Spatrick       addCompletion(ChainCallToken, MatcherCompletion("bind(\"", "bind", 1));
568a9ac8606Spatrick       addCompletion(ChainCallToken, MatcherCompletion("with(", "with", 1));
569a9ac8606Spatrick       return false;
570a9ac8606Spatrick     }
571a9ac8606Spatrick     if (ChainCallToken.Kind != TokenInfo::TK_Ident ||
572a9ac8606Spatrick         (ChainCallToken.Text != TokenInfo::ID_Bind &&
573a9ac8606Spatrick          ChainCallToken.Text != TokenInfo::ID_With)) {
574a9ac8606Spatrick       Error->addError(ChainCallToken.Range,
575a9ac8606Spatrick                       Error->ET_ParserMalformedChainedExpr);
576a9ac8606Spatrick       return false;
577a9ac8606Spatrick     }
578a9ac8606Spatrick     if (ChainCallToken.Text == TokenInfo::ID_Bind) {
579a9ac8606Spatrick       if (!parseBindID(BindID))
580a9ac8606Spatrick         return false;
581a9ac8606Spatrick       Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error,
582a9ac8606Spatrick                                NameToken.Text, NameToken.Range);
583a9ac8606Spatrick       SourceRange MatcherRange = NameToken.Range;
584a9ac8606Spatrick       MatcherRange.End = ChainCallToken.Range.End;
585a9ac8606Spatrick       VariantMatcher Result = S->actOnMatcherExpression(
586a9ac8606Spatrick           BuiltCtor.get(), MatcherRange, BindID, {}, Error);
587a9ac8606Spatrick       if (Result.isNull())
588a9ac8606Spatrick         return false;
589a9ac8606Spatrick 
590a9ac8606Spatrick       *Value = Result;
591a9ac8606Spatrick       return true;
592a9ac8606Spatrick     } else if (ChainCallToken.Text == TokenInfo::ID_With) {
593a9ac8606Spatrick       Tokenizer->SkipNewlines();
594a9ac8606Spatrick 
595a9ac8606Spatrick       if (Tokenizer->nextTokenKind() != TokenInfo::TK_OpenParen) {
596a9ac8606Spatrick         StringRef ErrTxt = Tokenizer->nextTokenKind() == TokenInfo::TK_Eof
597a9ac8606Spatrick                                ? StringRef("EOF")
598a9ac8606Spatrick                                : Tokenizer->peekNextToken().Text;
599a9ac8606Spatrick         Error->addError(Tokenizer->peekNextToken().Range,
600a9ac8606Spatrick                         Error->ET_ParserNoOpenParen)
601a9ac8606Spatrick             << ErrTxt;
602a9ac8606Spatrick         return false;
603a9ac8606Spatrick       }
604a9ac8606Spatrick 
605a9ac8606Spatrick       TokenInfo WithOpenToken = Tokenizer->consumeNextToken();
606a9ac8606Spatrick 
607a9ac8606Spatrick       return parseMatcherExpressionImpl(NameToken, WithOpenToken,
608a9ac8606Spatrick                                         BuiltCtor.get(), Value);
609a9ac8606Spatrick     }
610a9ac8606Spatrick   }
611a9ac8606Spatrick 
612a9ac8606Spatrick   Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error,
613a9ac8606Spatrick                            NameToken.Text, NameToken.Range);
614a9ac8606Spatrick   SourceRange MatcherRange = NameToken.Range;
615a9ac8606Spatrick   MatcherRange.End = EndToken.Range.End;
616a9ac8606Spatrick   VariantMatcher Result = S->actOnMatcherExpression(
617a9ac8606Spatrick       BuiltCtor.get(), MatcherRange, BindID, {}, Error);
618a9ac8606Spatrick   if (Result.isNull())
619a9ac8606Spatrick     return false;
620a9ac8606Spatrick 
621a9ac8606Spatrick   *Value = Result;
622a9ac8606Spatrick   return true;
623a9ac8606Spatrick }
624a9ac8606Spatrick 
625e5dd7070Spatrick /// Parse and validate a matcher expression.
626e5dd7070Spatrick /// \return \c true on success, in which case \c Value has the matcher parsed.
627e5dd7070Spatrick ///   If the input is malformed, or some argument has an error, it
628e5dd7070Spatrick ///   returns \c false.
parseMatcherExpressionImpl(const TokenInfo & NameToken,const TokenInfo & OpenToken,std::optional<MatcherCtor> Ctor,VariantValue * Value)629e5dd7070Spatrick bool Parser::parseMatcherExpressionImpl(const TokenInfo &NameToken,
630a9ac8606Spatrick                                         const TokenInfo &OpenToken,
631*12c85518Srobert                                         std::optional<MatcherCtor> Ctor,
632e5dd7070Spatrick                                         VariantValue *Value) {
633e5dd7070Spatrick   if (!Ctor) {
634e5dd7070Spatrick     Error->addError(NameToken.Range, Error->ET_RegistryMatcherNotFound)
635e5dd7070Spatrick         << NameToken.Text;
636e5dd7070Spatrick     // Do not return here. We need to continue to give completion suggestions.
637e5dd7070Spatrick   }
638e5dd7070Spatrick 
639a9ac8606Spatrick   if (Ctor && *Ctor && S->isBuilderMatcher(*Ctor))
640a9ac8606Spatrick     return parseMatcherBuilder(*Ctor, NameToken, OpenToken, Value);
641a9ac8606Spatrick 
642e5dd7070Spatrick   std::vector<ParserValue> Args;
643e5dd7070Spatrick   TokenInfo EndToken;
644e5dd7070Spatrick 
645e5dd7070Spatrick   Tokenizer->SkipNewlines();
646e5dd7070Spatrick 
647e5dd7070Spatrick   {
648*12c85518Srobert     ScopedContextEntry SCE(this, Ctor.value_or(nullptr));
649e5dd7070Spatrick 
650e5dd7070Spatrick     while (Tokenizer->nextTokenKind() != TokenInfo::TK_Eof) {
651e5dd7070Spatrick       if (Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen) {
652e5dd7070Spatrick         // End of args.
653e5dd7070Spatrick         EndToken = Tokenizer->consumeNextToken();
654e5dd7070Spatrick         break;
655e5dd7070Spatrick       }
656e5dd7070Spatrick       if (!Args.empty()) {
657e5dd7070Spatrick         // We must find a , token to continue.
658e5dd7070Spatrick         const TokenInfo CommaToken = Tokenizer->consumeNextToken();
659e5dd7070Spatrick         if (CommaToken.Kind != TokenInfo::TK_Comma) {
660e5dd7070Spatrick           Error->addError(CommaToken.Range, Error->ET_ParserNoComma)
661e5dd7070Spatrick               << CommaToken.Text;
662e5dd7070Spatrick           return false;
663e5dd7070Spatrick         }
664e5dd7070Spatrick       }
665e5dd7070Spatrick 
666e5dd7070Spatrick       Diagnostics::Context Ctx(Diagnostics::Context::MatcherArg, Error,
667e5dd7070Spatrick                                NameToken.Text, NameToken.Range,
668e5dd7070Spatrick                                Args.size() + 1);
669e5dd7070Spatrick       ParserValue ArgValue;
670e5dd7070Spatrick       Tokenizer->SkipNewlines();
671e5dd7070Spatrick       ArgValue.Text = Tokenizer->peekNextToken().Text;
672e5dd7070Spatrick       ArgValue.Range = Tokenizer->peekNextToken().Range;
673e5dd7070Spatrick       if (!parseExpressionImpl(&ArgValue.Value)) {
674e5dd7070Spatrick         return false;
675e5dd7070Spatrick       }
676e5dd7070Spatrick 
677e5dd7070Spatrick       Tokenizer->SkipNewlines();
678e5dd7070Spatrick       Args.push_back(ArgValue);
679e5dd7070Spatrick       SCE.nextArg();
680e5dd7070Spatrick     }
681e5dd7070Spatrick   }
682e5dd7070Spatrick 
683e5dd7070Spatrick   if (EndToken.Kind == TokenInfo::TK_Eof) {
684e5dd7070Spatrick     Error->addError(OpenToken.Range, Error->ET_ParserNoCloseParen);
685e5dd7070Spatrick     return false;
686e5dd7070Spatrick   }
687e5dd7070Spatrick 
688e5dd7070Spatrick   std::string BindID;
689e5dd7070Spatrick   if (Tokenizer->peekNextToken().Kind == TokenInfo::TK_Period) {
690a9ac8606Spatrick     Tokenizer->consumeNextToken();
691a9ac8606Spatrick     TokenInfo ChainCallToken = Tokenizer->consumeNextToken();
692a9ac8606Spatrick     if (ChainCallToken.Kind == TokenInfo::TK_CodeCompletion) {
693a9ac8606Spatrick       addCompletion(ChainCallToken, MatcherCompletion("bind(\"", "bind", 1));
694a9ac8606Spatrick       return false;
695a9ac8606Spatrick     }
696a9ac8606Spatrick 
697a9ac8606Spatrick     if (ChainCallToken.Kind != TokenInfo::TK_Ident) {
698a9ac8606Spatrick       Error->addError(ChainCallToken.Range,
699a9ac8606Spatrick                       Error->ET_ParserMalformedChainedExpr);
700a9ac8606Spatrick       return false;
701a9ac8606Spatrick     }
702a9ac8606Spatrick     if (ChainCallToken.Text == TokenInfo::ID_With) {
703a9ac8606Spatrick 
704a9ac8606Spatrick       Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error,
705a9ac8606Spatrick                                NameToken.Text, NameToken.Range);
706a9ac8606Spatrick 
707a9ac8606Spatrick       Error->addError(ChainCallToken.Range,
708a9ac8606Spatrick                       Error->ET_RegistryMatcherNoWithSupport);
709a9ac8606Spatrick       return false;
710a9ac8606Spatrick     }
711a9ac8606Spatrick     if (ChainCallToken.Text != TokenInfo::ID_Bind) {
712a9ac8606Spatrick       Error->addError(ChainCallToken.Range,
713a9ac8606Spatrick                       Error->ET_ParserMalformedChainedExpr);
714a9ac8606Spatrick       return false;
715a9ac8606Spatrick     }
716e5dd7070Spatrick     if (!parseBindID(BindID))
717e5dd7070Spatrick       return false;
718e5dd7070Spatrick   }
719e5dd7070Spatrick 
720e5dd7070Spatrick   if (!Ctor)
721e5dd7070Spatrick     return false;
722e5dd7070Spatrick 
723e5dd7070Spatrick   // Merge the start and end infos.
724e5dd7070Spatrick   Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error,
725e5dd7070Spatrick                            NameToken.Text, NameToken.Range);
726e5dd7070Spatrick   SourceRange MatcherRange = NameToken.Range;
727e5dd7070Spatrick   MatcherRange.End = EndToken.Range.End;
728e5dd7070Spatrick   VariantMatcher Result = S->actOnMatcherExpression(
729e5dd7070Spatrick       *Ctor, MatcherRange, BindID, Args, Error);
730e5dd7070Spatrick   if (Result.isNull()) return false;
731e5dd7070Spatrick 
732e5dd7070Spatrick   *Value = Result;
733e5dd7070Spatrick   return true;
734e5dd7070Spatrick }
735e5dd7070Spatrick 
736e5dd7070Spatrick // If the prefix of this completion matches the completion token, add it to
737e5dd7070Spatrick // Completions minus the prefix.
addCompletion(const TokenInfo & CompToken,const MatcherCompletion & Completion)738e5dd7070Spatrick void Parser::addCompletion(const TokenInfo &CompToken,
739e5dd7070Spatrick                            const MatcherCompletion& Completion) {
740e5dd7070Spatrick   if (StringRef(Completion.TypedText).startswith(CompToken.Text) &&
741e5dd7070Spatrick       Completion.Specificity > 0) {
742e5dd7070Spatrick     Completions.emplace_back(Completion.TypedText.substr(CompToken.Text.size()),
743e5dd7070Spatrick                              Completion.MatcherDecl, Completion.Specificity);
744e5dd7070Spatrick   }
745e5dd7070Spatrick }
746e5dd7070Spatrick 
getNamedValueCompletions(ArrayRef<ArgKind> AcceptedTypes)747e5dd7070Spatrick std::vector<MatcherCompletion> Parser::getNamedValueCompletions(
748e5dd7070Spatrick     ArrayRef<ArgKind> AcceptedTypes) {
749e5dd7070Spatrick   if (!NamedValues) return std::vector<MatcherCompletion>();
750e5dd7070Spatrick   std::vector<MatcherCompletion> Result;
751e5dd7070Spatrick   for (const auto &Entry : *NamedValues) {
752e5dd7070Spatrick     unsigned Specificity;
753e5dd7070Spatrick     if (Entry.getValue().isConvertibleTo(AcceptedTypes, &Specificity)) {
754e5dd7070Spatrick       std::string Decl =
755e5dd7070Spatrick           (Entry.getValue().getTypeAsString() + " " + Entry.getKey()).str();
756e5dd7070Spatrick       Result.emplace_back(Entry.getKey(), Decl, Specificity);
757e5dd7070Spatrick     }
758e5dd7070Spatrick   }
759e5dd7070Spatrick   return Result;
760e5dd7070Spatrick }
761e5dd7070Spatrick 
addExpressionCompletions()762e5dd7070Spatrick void Parser::addExpressionCompletions() {
763e5dd7070Spatrick   const TokenInfo CompToken = Tokenizer->consumeNextTokenIgnoreNewlines();
764e5dd7070Spatrick   assert(CompToken.Kind == TokenInfo::TK_CodeCompletion);
765e5dd7070Spatrick 
766e5dd7070Spatrick   // We cannot complete code if there is an invalid element on the context
767e5dd7070Spatrick   // stack.
768e5dd7070Spatrick   for (ContextStackTy::iterator I = ContextStack.begin(),
769e5dd7070Spatrick                                 E = ContextStack.end();
770e5dd7070Spatrick        I != E; ++I) {
771e5dd7070Spatrick     if (!I->first)
772e5dd7070Spatrick       return;
773e5dd7070Spatrick   }
774e5dd7070Spatrick 
775e5dd7070Spatrick   auto AcceptedTypes = S->getAcceptedCompletionTypes(ContextStack);
776e5dd7070Spatrick   for (const auto &Completion : S->getMatcherCompletions(AcceptedTypes)) {
777e5dd7070Spatrick     addCompletion(CompToken, Completion);
778e5dd7070Spatrick   }
779e5dd7070Spatrick 
780e5dd7070Spatrick   for (const auto &Completion : getNamedValueCompletions(AcceptedTypes)) {
781e5dd7070Spatrick     addCompletion(CompToken, Completion);
782e5dd7070Spatrick   }
783e5dd7070Spatrick }
784e5dd7070Spatrick 
785e5dd7070Spatrick /// Parse an <Expression>
parseExpressionImpl(VariantValue * Value)786e5dd7070Spatrick bool Parser::parseExpressionImpl(VariantValue *Value) {
787e5dd7070Spatrick   switch (Tokenizer->nextTokenKind()) {
788e5dd7070Spatrick   case TokenInfo::TK_Literal:
789e5dd7070Spatrick     *Value = Tokenizer->consumeNextToken().Value;
790e5dd7070Spatrick     return true;
791e5dd7070Spatrick 
792e5dd7070Spatrick   case TokenInfo::TK_Ident:
793e5dd7070Spatrick     return parseIdentifierPrefixImpl(Value);
794e5dd7070Spatrick 
795e5dd7070Spatrick   case TokenInfo::TK_CodeCompletion:
796e5dd7070Spatrick     addExpressionCompletions();
797e5dd7070Spatrick     return false;
798e5dd7070Spatrick 
799e5dd7070Spatrick   case TokenInfo::TK_Eof:
800e5dd7070Spatrick     Error->addError(Tokenizer->consumeNextToken().Range,
801e5dd7070Spatrick                     Error->ET_ParserNoCode);
802e5dd7070Spatrick     return false;
803e5dd7070Spatrick 
804e5dd7070Spatrick   case TokenInfo::TK_Error:
805e5dd7070Spatrick     // This error was already reported by the tokenizer.
806e5dd7070Spatrick     return false;
807e5dd7070Spatrick   case TokenInfo::TK_NewLine:
808e5dd7070Spatrick   case TokenInfo::TK_OpenParen:
809e5dd7070Spatrick   case TokenInfo::TK_CloseParen:
810e5dd7070Spatrick   case TokenInfo::TK_Comma:
811e5dd7070Spatrick   case TokenInfo::TK_Period:
812e5dd7070Spatrick   case TokenInfo::TK_InvalidChar:
813e5dd7070Spatrick     const TokenInfo Token = Tokenizer->consumeNextToken();
814e5dd7070Spatrick     Error->addError(Token.Range, Error->ET_ParserInvalidToken)
815e5dd7070Spatrick         << (Token.Kind == TokenInfo::TK_NewLine ? "NewLine" : Token.Text);
816e5dd7070Spatrick     return false;
817e5dd7070Spatrick   }
818e5dd7070Spatrick 
819e5dd7070Spatrick   llvm_unreachable("Unknown token kind.");
820e5dd7070Spatrick }
821e5dd7070Spatrick 
822e5dd7070Spatrick static llvm::ManagedStatic<Parser::RegistrySema> DefaultRegistrySema;
823e5dd7070Spatrick 
Parser(CodeTokenizer * Tokenizer,Sema * S,const NamedValueMap * NamedValues,Diagnostics * Error)824e5dd7070Spatrick Parser::Parser(CodeTokenizer *Tokenizer, Sema *S,
825e5dd7070Spatrick                const NamedValueMap *NamedValues, Diagnostics *Error)
826e5dd7070Spatrick     : Tokenizer(Tokenizer), S(S ? S : &*DefaultRegistrySema),
827e5dd7070Spatrick       NamedValues(NamedValues), Error(Error) {}
828e5dd7070Spatrick 
829e5dd7070Spatrick Parser::RegistrySema::~RegistrySema() = default;
830e5dd7070Spatrick 
831*12c85518Srobert std::optional<MatcherCtor>
lookupMatcherCtor(StringRef MatcherName)832e5dd7070Spatrick Parser::RegistrySema::lookupMatcherCtor(StringRef MatcherName) {
833e5dd7070Spatrick   return Registry::lookupMatcherCtor(MatcherName);
834e5dd7070Spatrick }
835e5dd7070Spatrick 
actOnMatcherExpression(MatcherCtor Ctor,SourceRange NameRange,StringRef BindID,ArrayRef<ParserValue> Args,Diagnostics * Error)836e5dd7070Spatrick VariantMatcher Parser::RegistrySema::actOnMatcherExpression(
837e5dd7070Spatrick     MatcherCtor Ctor, SourceRange NameRange, StringRef BindID,
838e5dd7070Spatrick     ArrayRef<ParserValue> Args, Diagnostics *Error) {
839e5dd7070Spatrick   if (BindID.empty()) {
840e5dd7070Spatrick     return Registry::constructMatcher(Ctor, NameRange, Args, Error);
841e5dd7070Spatrick   } else {
842e5dd7070Spatrick     return Registry::constructBoundMatcher(Ctor, NameRange, BindID, Args,
843e5dd7070Spatrick                                            Error);
844e5dd7070Spatrick   }
845e5dd7070Spatrick }
846e5dd7070Spatrick 
getAcceptedCompletionTypes(ArrayRef<std::pair<MatcherCtor,unsigned>> Context)847e5dd7070Spatrick std::vector<ArgKind> Parser::RegistrySema::getAcceptedCompletionTypes(
848e5dd7070Spatrick     ArrayRef<std::pair<MatcherCtor, unsigned>> Context) {
849e5dd7070Spatrick   return Registry::getAcceptedCompletionTypes(Context);
850e5dd7070Spatrick }
851e5dd7070Spatrick 
getMatcherCompletions(ArrayRef<ArgKind> AcceptedTypes)852e5dd7070Spatrick std::vector<MatcherCompletion> Parser::RegistrySema::getMatcherCompletions(
853e5dd7070Spatrick     ArrayRef<ArgKind> AcceptedTypes) {
854e5dd7070Spatrick   return Registry::getMatcherCompletions(AcceptedTypes);
855e5dd7070Spatrick }
856e5dd7070Spatrick 
isBuilderMatcher(MatcherCtor Ctor) const857a9ac8606Spatrick bool Parser::RegistrySema::isBuilderMatcher(MatcherCtor Ctor) const {
858a9ac8606Spatrick   return Registry::isBuilderMatcher(Ctor);
859a9ac8606Spatrick }
860a9ac8606Spatrick 
nodeMatcherType(MatcherCtor Ctor) const861a9ac8606Spatrick ASTNodeKind Parser::RegistrySema::nodeMatcherType(MatcherCtor Ctor) const {
862a9ac8606Spatrick   return Registry::nodeMatcherType(Ctor);
863a9ac8606Spatrick }
864a9ac8606Spatrick 
865a9ac8606Spatrick internal::MatcherDescriptorPtr
buildMatcherCtor(MatcherCtor Ctor,SourceRange NameRange,ArrayRef<ParserValue> Args,Diagnostics * Error) const866a9ac8606Spatrick Parser::RegistrySema::buildMatcherCtor(MatcherCtor Ctor, SourceRange NameRange,
867a9ac8606Spatrick                                        ArrayRef<ParserValue> Args,
868a9ac8606Spatrick                                        Diagnostics *Error) const {
869a9ac8606Spatrick   return Registry::buildMatcherCtor(Ctor, NameRange, Args, Error);
870a9ac8606Spatrick }
871a9ac8606Spatrick 
parseExpression(StringRef & Code,Sema * S,const NamedValueMap * NamedValues,VariantValue * Value,Diagnostics * Error)872e5dd7070Spatrick bool Parser::parseExpression(StringRef &Code, Sema *S,
873e5dd7070Spatrick                              const NamedValueMap *NamedValues,
874e5dd7070Spatrick                              VariantValue *Value, Diagnostics *Error) {
875e5dd7070Spatrick   CodeTokenizer Tokenizer(Code, Error);
876e5dd7070Spatrick   if (!Parser(&Tokenizer, S, NamedValues, Error).parseExpressionImpl(Value))
877e5dd7070Spatrick     return false;
878e5dd7070Spatrick   auto NT = Tokenizer.peekNextToken();
879e5dd7070Spatrick   if (NT.Kind != TokenInfo::TK_Eof && NT.Kind != TokenInfo::TK_NewLine) {
880e5dd7070Spatrick     Error->addError(Tokenizer.peekNextToken().Range,
881e5dd7070Spatrick                     Error->ET_ParserTrailingCode);
882e5dd7070Spatrick     return false;
883e5dd7070Spatrick   }
884e5dd7070Spatrick   return true;
885e5dd7070Spatrick }
886e5dd7070Spatrick 
887e5dd7070Spatrick std::vector<MatcherCompletion>
completeExpression(StringRef & Code,unsigned CompletionOffset,Sema * S,const NamedValueMap * NamedValues)888e5dd7070Spatrick Parser::completeExpression(StringRef &Code, unsigned CompletionOffset, Sema *S,
889e5dd7070Spatrick                            const NamedValueMap *NamedValues) {
890e5dd7070Spatrick   Diagnostics Error;
891e5dd7070Spatrick   CodeTokenizer Tokenizer(Code, &Error, CompletionOffset);
892e5dd7070Spatrick   Parser P(&Tokenizer, S, NamedValues, &Error);
893e5dd7070Spatrick   VariantValue Dummy;
894e5dd7070Spatrick   P.parseExpressionImpl(&Dummy);
895e5dd7070Spatrick 
896e5dd7070Spatrick   // Sort by specificity, then by name.
897e5dd7070Spatrick   llvm::sort(P.Completions,
898e5dd7070Spatrick              [](const MatcherCompletion &A, const MatcherCompletion &B) {
899e5dd7070Spatrick                if (A.Specificity != B.Specificity)
900e5dd7070Spatrick                  return A.Specificity > B.Specificity;
901e5dd7070Spatrick                return A.TypedText < B.TypedText;
902e5dd7070Spatrick              });
903e5dd7070Spatrick 
904e5dd7070Spatrick   return P.Completions;
905e5dd7070Spatrick }
906e5dd7070Spatrick 
907*12c85518Srobert std::optional<DynTypedMatcher>
parseMatcherExpression(StringRef & Code,Sema * S,const NamedValueMap * NamedValues,Diagnostics * Error)908e5dd7070Spatrick Parser::parseMatcherExpression(StringRef &Code, Sema *S,
909e5dd7070Spatrick                                const NamedValueMap *NamedValues,
910e5dd7070Spatrick                                Diagnostics *Error) {
911e5dd7070Spatrick   VariantValue Value;
912e5dd7070Spatrick   if (!parseExpression(Code, S, NamedValues, &Value, Error))
913*12c85518Srobert     return std::nullopt;
914e5dd7070Spatrick   if (!Value.isMatcher()) {
915e5dd7070Spatrick     Error->addError(SourceRange(), Error->ET_ParserNotAMatcher);
916*12c85518Srobert     return std::nullopt;
917e5dd7070Spatrick   }
918*12c85518Srobert   std::optional<DynTypedMatcher> Result = Value.getMatcher().getSingleMatcher();
919*12c85518Srobert   if (!Result) {
920e5dd7070Spatrick     Error->addError(SourceRange(), Error->ET_ParserOverloadedType)
921e5dd7070Spatrick         << Value.getTypeAsString();
922e5dd7070Spatrick   }
923e5dd7070Spatrick   return Result;
924e5dd7070Spatrick }
925e5dd7070Spatrick 
926e5dd7070Spatrick } // namespace dynamic
927e5dd7070Spatrick } // namespace ast_matchers
928e5dd7070Spatrick } // namespace clang
929