xref: /freebsd/contrib/llvm-project/clang/lib/ASTMatchers/Dynamic/Parser.cpp (revision 647cbc5de815c5651677bf8582797f716ec7b48d)
10b57cec5SDimitry Andric //===- Parser.cpp - Matcher expression parser -----------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric ///
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// Recursive parser implementation for the matcher expression grammar.
110b57cec5SDimitry Andric ///
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "clang/ASTMatchers/Dynamic/Parser.h"
150b57cec5SDimitry Andric #include "clang/ASTMatchers/ASTMatchersInternal.h"
160b57cec5SDimitry Andric #include "clang/ASTMatchers/Dynamic/Diagnostics.h"
170b57cec5SDimitry Andric #include "clang/ASTMatchers/Dynamic/Registry.h"
180b57cec5SDimitry Andric #include "clang/Basic/CharInfo.h"
190b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
200b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
210b57cec5SDimitry Andric #include "llvm/Support/ManagedStatic.h"
220b57cec5SDimitry Andric #include <algorithm>
230b57cec5SDimitry Andric #include <cassert>
240b57cec5SDimitry Andric #include <cerrno>
250b57cec5SDimitry Andric #include <cstddef>
260b57cec5SDimitry Andric #include <cstdlib>
27bdd1243dSDimitry Andric #include <optional>
280b57cec5SDimitry Andric #include <string>
290b57cec5SDimitry Andric #include <utility>
300b57cec5SDimitry Andric #include <vector>
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric namespace clang {
330b57cec5SDimitry Andric namespace ast_matchers {
340b57cec5SDimitry Andric namespace dynamic {
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric /// Simple structure to hold information for one token from the parser.
370b57cec5SDimitry Andric struct Parser::TokenInfo {
380b57cec5SDimitry Andric   /// Different possible tokens.
390b57cec5SDimitry Andric   enum TokenKind {
400b57cec5SDimitry Andric     TK_Eof,
41480093f4SDimitry Andric     TK_NewLine,
420b57cec5SDimitry Andric     TK_OpenParen,
430b57cec5SDimitry Andric     TK_CloseParen,
440b57cec5SDimitry Andric     TK_Comma,
450b57cec5SDimitry Andric     TK_Period,
460b57cec5SDimitry Andric     TK_Literal,
470b57cec5SDimitry Andric     TK_Ident,
480b57cec5SDimitry Andric     TK_InvalidChar,
490b57cec5SDimitry Andric     TK_Error,
500b57cec5SDimitry Andric     TK_CodeCompletion
510b57cec5SDimitry Andric   };
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   /// Some known identifiers.
540b57cec5SDimitry Andric   static const char* const ID_Bind;
55fe6060f1SDimitry Andric   static const char *const ID_With;
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric   TokenInfo() = default;
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric   StringRef Text;
600b57cec5SDimitry Andric   TokenKind Kind = TK_Eof;
610b57cec5SDimitry Andric   SourceRange Range;
620b57cec5SDimitry Andric   VariantValue Value;
630b57cec5SDimitry Andric };
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric const char* const Parser::TokenInfo::ID_Bind = "bind";
66fe6060f1SDimitry Andric const char *const Parser::TokenInfo::ID_With = "with";
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric /// Simple tokenizer for the parser.
690b57cec5SDimitry Andric class Parser::CodeTokenizer {
700b57cec5SDimitry Andric public:
71480093f4SDimitry Andric   explicit CodeTokenizer(StringRef &MatcherCode, Diagnostics *Error)
720b57cec5SDimitry Andric       : Code(MatcherCode), StartOfLine(MatcherCode), Error(Error) {
730b57cec5SDimitry Andric     NextToken = getNextToken();
740b57cec5SDimitry Andric   }
750b57cec5SDimitry Andric 
76480093f4SDimitry Andric   CodeTokenizer(StringRef &MatcherCode, Diagnostics *Error,
770b57cec5SDimitry Andric                 unsigned CodeCompletionOffset)
780b57cec5SDimitry Andric       : Code(MatcherCode), StartOfLine(MatcherCode), Error(Error),
790b57cec5SDimitry Andric         CodeCompletionLocation(MatcherCode.data() + CodeCompletionOffset) {
800b57cec5SDimitry Andric     NextToken = getNextToken();
810b57cec5SDimitry Andric   }
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   /// Returns but doesn't consume the next token.
840b57cec5SDimitry Andric   const TokenInfo &peekNextToken() const { return NextToken; }
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   /// Consumes and returns the next token.
870b57cec5SDimitry Andric   TokenInfo consumeNextToken() {
880b57cec5SDimitry Andric     TokenInfo ThisToken = NextToken;
890b57cec5SDimitry Andric     NextToken = getNextToken();
900b57cec5SDimitry Andric     return ThisToken;
910b57cec5SDimitry Andric   }
920b57cec5SDimitry Andric 
93480093f4SDimitry Andric   TokenInfo SkipNewlines() {
94480093f4SDimitry Andric     while (NextToken.Kind == TokenInfo::TK_NewLine)
95480093f4SDimitry Andric       NextToken = getNextToken();
96480093f4SDimitry Andric     return NextToken;
97480093f4SDimitry Andric   }
98480093f4SDimitry Andric 
99480093f4SDimitry Andric   TokenInfo consumeNextTokenIgnoreNewlines() {
100480093f4SDimitry Andric     SkipNewlines();
101480093f4SDimitry Andric     if (NextToken.Kind == TokenInfo::TK_Eof)
102480093f4SDimitry Andric       return NextToken;
103480093f4SDimitry Andric     return consumeNextToken();
104480093f4SDimitry Andric   }
105480093f4SDimitry Andric 
1060b57cec5SDimitry Andric   TokenInfo::TokenKind nextTokenKind() const { return NextToken.Kind; }
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric private:
1090b57cec5SDimitry Andric   TokenInfo getNextToken() {
1100b57cec5SDimitry Andric     consumeWhitespace();
1110b57cec5SDimitry Andric     TokenInfo Result;
1120b57cec5SDimitry Andric     Result.Range.Start = currentLocation();
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric     if (CodeCompletionLocation && CodeCompletionLocation <= Code.data()) {
1150b57cec5SDimitry Andric       Result.Kind = TokenInfo::TK_CodeCompletion;
1160b57cec5SDimitry Andric       Result.Text = StringRef(CodeCompletionLocation, 0);
1170b57cec5SDimitry Andric       CodeCompletionLocation = nullptr;
1180b57cec5SDimitry Andric       return Result;
1190b57cec5SDimitry Andric     }
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric     if (Code.empty()) {
1220b57cec5SDimitry Andric       Result.Kind = TokenInfo::TK_Eof;
1230b57cec5SDimitry Andric       Result.Text = "";
1240b57cec5SDimitry Andric       return Result;
1250b57cec5SDimitry Andric     }
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric     switch (Code[0]) {
1280b57cec5SDimitry Andric     case '#':
129480093f4SDimitry Andric       Code = Code.drop_until([](char c) { return c == '\n'; });
130480093f4SDimitry Andric       return getNextToken();
1310b57cec5SDimitry Andric     case ',':
1320b57cec5SDimitry Andric       Result.Kind = TokenInfo::TK_Comma;
1330b57cec5SDimitry Andric       Result.Text = Code.substr(0, 1);
1340b57cec5SDimitry Andric       Code = Code.drop_front();
1350b57cec5SDimitry Andric       break;
1360b57cec5SDimitry Andric     case '.':
1370b57cec5SDimitry Andric       Result.Kind = TokenInfo::TK_Period;
1380b57cec5SDimitry Andric       Result.Text = Code.substr(0, 1);
1390b57cec5SDimitry Andric       Code = Code.drop_front();
1400b57cec5SDimitry Andric       break;
141480093f4SDimitry Andric     case '\n':
142480093f4SDimitry Andric       ++Line;
143480093f4SDimitry Andric       StartOfLine = Code.drop_front();
144480093f4SDimitry Andric       Result.Kind = TokenInfo::TK_NewLine;
145480093f4SDimitry Andric       Result.Text = Code.substr(0, 1);
146480093f4SDimitry Andric       Code = Code.drop_front();
147480093f4SDimitry Andric       break;
1480b57cec5SDimitry Andric     case '(':
1490b57cec5SDimitry Andric       Result.Kind = TokenInfo::TK_OpenParen;
1500b57cec5SDimitry Andric       Result.Text = Code.substr(0, 1);
1510b57cec5SDimitry Andric       Code = Code.drop_front();
1520b57cec5SDimitry Andric       break;
1530b57cec5SDimitry Andric     case ')':
1540b57cec5SDimitry Andric       Result.Kind = TokenInfo::TK_CloseParen;
1550b57cec5SDimitry Andric       Result.Text = Code.substr(0, 1);
1560b57cec5SDimitry Andric       Code = Code.drop_front();
1570b57cec5SDimitry Andric       break;
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric     case '"':
1600b57cec5SDimitry Andric     case '\'':
1610b57cec5SDimitry Andric       // Parse a string literal.
1620b57cec5SDimitry Andric       consumeStringLiteral(&Result);
1630b57cec5SDimitry Andric       break;
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric     case '0': case '1': case '2': case '3': case '4':
1660b57cec5SDimitry Andric     case '5': case '6': case '7': case '8': case '9':
1670b57cec5SDimitry Andric       // Parse an unsigned and float literal.
1680b57cec5SDimitry Andric       consumeNumberLiteral(&Result);
1690b57cec5SDimitry Andric       break;
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric     default:
1720b57cec5SDimitry Andric       if (isAlphanumeric(Code[0])) {
1730b57cec5SDimitry Andric         // Parse an identifier
1740b57cec5SDimitry Andric         size_t TokenLength = 1;
1750b57cec5SDimitry Andric         while (true) {
1760b57cec5SDimitry Andric           // A code completion location in/immediately after an identifier will
1770b57cec5SDimitry Andric           // cause the portion of the identifier before the code completion
1780b57cec5SDimitry Andric           // location to become a code completion token.
1790b57cec5SDimitry Andric           if (CodeCompletionLocation == Code.data() + TokenLength) {
1800b57cec5SDimitry Andric             CodeCompletionLocation = nullptr;
1810b57cec5SDimitry Andric             Result.Kind = TokenInfo::TK_CodeCompletion;
1820b57cec5SDimitry Andric             Result.Text = Code.substr(0, TokenLength);
1830b57cec5SDimitry Andric             Code = Code.drop_front(TokenLength);
1840b57cec5SDimitry Andric             return Result;
1850b57cec5SDimitry Andric           }
1860b57cec5SDimitry Andric           if (TokenLength == Code.size() || !isAlphanumeric(Code[TokenLength]))
1870b57cec5SDimitry Andric             break;
1880b57cec5SDimitry Andric           ++TokenLength;
1890b57cec5SDimitry Andric         }
1905f757f3fSDimitry Andric         if (TokenLength == 4 && Code.starts_with("true")) {
1910b57cec5SDimitry Andric           Result.Kind = TokenInfo::TK_Literal;
1920b57cec5SDimitry Andric           Result.Value = true;
1935f757f3fSDimitry Andric         } else if (TokenLength == 5 && Code.starts_with("false")) {
1940b57cec5SDimitry Andric           Result.Kind = TokenInfo::TK_Literal;
1950b57cec5SDimitry Andric           Result.Value = false;
1960b57cec5SDimitry Andric         } else {
1970b57cec5SDimitry Andric           Result.Kind = TokenInfo::TK_Ident;
1980b57cec5SDimitry Andric           Result.Text = Code.substr(0, TokenLength);
1990b57cec5SDimitry Andric         }
2000b57cec5SDimitry Andric         Code = Code.drop_front(TokenLength);
2010b57cec5SDimitry Andric       } else {
2020b57cec5SDimitry Andric         Result.Kind = TokenInfo::TK_InvalidChar;
2030b57cec5SDimitry Andric         Result.Text = Code.substr(0, 1);
2040b57cec5SDimitry Andric         Code = Code.drop_front(1);
2050b57cec5SDimitry Andric       }
2060b57cec5SDimitry Andric       break;
2070b57cec5SDimitry Andric     }
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric     Result.Range.End = currentLocation();
2100b57cec5SDimitry Andric     return Result;
2110b57cec5SDimitry Andric   }
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   /// Consume an unsigned and float literal.
2140b57cec5SDimitry Andric   void consumeNumberLiteral(TokenInfo *Result) {
2150b57cec5SDimitry Andric     bool isFloatingLiteral = false;
2160b57cec5SDimitry Andric     unsigned Length = 1;
2170b57cec5SDimitry Andric     if (Code.size() > 1) {
2180b57cec5SDimitry Andric       // Consume the 'x' or 'b' radix modifier, if present.
2190b57cec5SDimitry Andric       switch (toLowercase(Code[1])) {
2200b57cec5SDimitry Andric       case 'x': case 'b': Length = 2;
2210b57cec5SDimitry Andric       }
2220b57cec5SDimitry Andric     }
2230b57cec5SDimitry Andric     while (Length < Code.size() && isHexDigit(Code[Length]))
2240b57cec5SDimitry Andric       ++Length;
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric     // Try to recognize a floating point literal.
2270b57cec5SDimitry Andric     while (Length < Code.size()) {
2280b57cec5SDimitry Andric       char c = Code[Length];
2290b57cec5SDimitry Andric       if (c == '-' || c == '+' || c == '.' || isHexDigit(c)) {
2300b57cec5SDimitry Andric         isFloatingLiteral = true;
2310b57cec5SDimitry Andric         Length++;
2320b57cec5SDimitry Andric       } else {
2330b57cec5SDimitry Andric         break;
2340b57cec5SDimitry Andric       }
2350b57cec5SDimitry Andric     }
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric     Result->Text = Code.substr(0, Length);
2380b57cec5SDimitry Andric     Code = Code.drop_front(Length);
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric     if (isFloatingLiteral) {
2410b57cec5SDimitry Andric       char *end;
2420b57cec5SDimitry Andric       errno = 0;
2430b57cec5SDimitry Andric       std::string Text = Result->Text.str();
2440b57cec5SDimitry Andric       double doubleValue = strtod(Text.c_str(), &end);
2450b57cec5SDimitry Andric       if (*end == 0 && errno == 0) {
2460b57cec5SDimitry Andric         Result->Kind = TokenInfo::TK_Literal;
2470b57cec5SDimitry Andric         Result->Value = doubleValue;
2480b57cec5SDimitry Andric         return;
2490b57cec5SDimitry Andric       }
2500b57cec5SDimitry Andric     } else {
2510b57cec5SDimitry Andric       unsigned Value;
2520b57cec5SDimitry Andric       if (!Result->Text.getAsInteger(0, Value)) {
2530b57cec5SDimitry Andric         Result->Kind = TokenInfo::TK_Literal;
2540b57cec5SDimitry Andric         Result->Value = Value;
2550b57cec5SDimitry Andric         return;
2560b57cec5SDimitry Andric       }
2570b57cec5SDimitry Andric     }
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric     SourceRange Range;
2600b57cec5SDimitry Andric     Range.Start = Result->Range.Start;
2610b57cec5SDimitry Andric     Range.End = currentLocation();
2620b57cec5SDimitry Andric     Error->addError(Range, Error->ET_ParserNumberError) << Result->Text;
2630b57cec5SDimitry Andric     Result->Kind = TokenInfo::TK_Error;
2640b57cec5SDimitry Andric   }
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric   /// Consume a string literal.
2670b57cec5SDimitry Andric   ///
2680b57cec5SDimitry Andric   /// \c Code must be positioned at the start of the literal (the opening
2690b57cec5SDimitry Andric   /// quote). Consumed until it finds the same closing quote character.
2700b57cec5SDimitry Andric   void consumeStringLiteral(TokenInfo *Result) {
2710b57cec5SDimitry Andric     bool InEscape = false;
2720b57cec5SDimitry Andric     const char Marker = Code[0];
2730b57cec5SDimitry Andric     for (size_t Length = 1, Size = Code.size(); Length != Size; ++Length) {
2740b57cec5SDimitry Andric       if (InEscape) {
2750b57cec5SDimitry Andric         InEscape = false;
2760b57cec5SDimitry Andric         continue;
2770b57cec5SDimitry Andric       }
2780b57cec5SDimitry Andric       if (Code[Length] == '\\') {
2790b57cec5SDimitry Andric         InEscape = true;
2800b57cec5SDimitry Andric         continue;
2810b57cec5SDimitry Andric       }
2820b57cec5SDimitry Andric       if (Code[Length] == Marker) {
2830b57cec5SDimitry Andric         Result->Kind = TokenInfo::TK_Literal;
2840b57cec5SDimitry Andric         Result->Text = Code.substr(0, Length + 1);
2850b57cec5SDimitry Andric         Result->Value = Code.substr(1, Length - 1);
2860b57cec5SDimitry Andric         Code = Code.drop_front(Length + 1);
2870b57cec5SDimitry Andric         return;
2880b57cec5SDimitry Andric       }
2890b57cec5SDimitry Andric     }
2900b57cec5SDimitry Andric 
2910b57cec5SDimitry Andric     StringRef ErrorText = Code;
2920b57cec5SDimitry Andric     Code = Code.drop_front(Code.size());
2930b57cec5SDimitry Andric     SourceRange Range;
2940b57cec5SDimitry Andric     Range.Start = Result->Range.Start;
2950b57cec5SDimitry Andric     Range.End = currentLocation();
2960b57cec5SDimitry Andric     Error->addError(Range, Error->ET_ParserStringError) << ErrorText;
2970b57cec5SDimitry Andric     Result->Kind = TokenInfo::TK_Error;
2980b57cec5SDimitry Andric   }
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric   /// Consume all leading whitespace from \c Code.
3010b57cec5SDimitry Andric   void consumeWhitespace() {
302480093f4SDimitry Andric     // Don't trim newlines.
303*647cbc5dSDimitry Andric     Code = Code.ltrim(" \t\v\f\r");
3040b57cec5SDimitry Andric   }
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric   SourceLocation currentLocation() {
3070b57cec5SDimitry Andric     SourceLocation Location;
3080b57cec5SDimitry Andric     Location.Line = Line;
3090b57cec5SDimitry Andric     Location.Column = Code.data() - StartOfLine.data() + 1;
3100b57cec5SDimitry Andric     return Location;
3110b57cec5SDimitry Andric   }
3120b57cec5SDimitry Andric 
313480093f4SDimitry Andric   StringRef &Code;
3140b57cec5SDimitry Andric   StringRef StartOfLine;
3150b57cec5SDimitry Andric   unsigned Line = 1;
3160b57cec5SDimitry Andric   Diagnostics *Error;
3170b57cec5SDimitry Andric   TokenInfo NextToken;
3180b57cec5SDimitry Andric   const char *CodeCompletionLocation = nullptr;
3190b57cec5SDimitry Andric };
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric Parser::Sema::~Sema() = default;
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric std::vector<ArgKind> Parser::Sema::getAcceptedCompletionTypes(
3240b57cec5SDimitry Andric     llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context) {
3250b57cec5SDimitry Andric   return {};
3260b57cec5SDimitry Andric }
3270b57cec5SDimitry Andric 
3280b57cec5SDimitry Andric std::vector<MatcherCompletion>
3290b57cec5SDimitry Andric Parser::Sema::getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes) {
3300b57cec5SDimitry Andric   return {};
3310b57cec5SDimitry Andric }
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric struct Parser::ScopedContextEntry {
3340b57cec5SDimitry Andric   Parser *P;
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric   ScopedContextEntry(Parser *P, MatcherCtor C) : P(P) {
3370b57cec5SDimitry Andric     P->ContextStack.push_back(std::make_pair(C, 0u));
3380b57cec5SDimitry Andric   }
3390b57cec5SDimitry Andric 
3400b57cec5SDimitry Andric   ~ScopedContextEntry() {
3410b57cec5SDimitry Andric     P->ContextStack.pop_back();
3420b57cec5SDimitry Andric   }
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric   void nextArg() {
3450b57cec5SDimitry Andric     ++P->ContextStack.back().second;
3460b57cec5SDimitry Andric   }
3470b57cec5SDimitry Andric };
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric /// Parse expressions that start with an identifier.
3500b57cec5SDimitry Andric ///
3510b57cec5SDimitry Andric /// This function can parse named values and matchers.
3520b57cec5SDimitry Andric /// In case of failure it will try to determine the user's intent to give
3530b57cec5SDimitry Andric /// an appropriate error message.
3540b57cec5SDimitry Andric bool Parser::parseIdentifierPrefixImpl(VariantValue *Value) {
3550b57cec5SDimitry Andric   const TokenInfo NameToken = Tokenizer->consumeNextToken();
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric   if (Tokenizer->nextTokenKind() != TokenInfo::TK_OpenParen) {
3580b57cec5SDimitry Andric     // Parse as a named value.
3590b57cec5SDimitry Andric     if (const VariantValue NamedValue =
3600b57cec5SDimitry Andric             NamedValues ? NamedValues->lookup(NameToken.Text)
3610b57cec5SDimitry Andric                         : VariantValue()) {
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric       if (Tokenizer->nextTokenKind() != TokenInfo::TK_Period) {
3640b57cec5SDimitry Andric         *Value = NamedValue;
3650b57cec5SDimitry Andric         return true;
3660b57cec5SDimitry Andric       }
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric       std::string BindID;
369fe6060f1SDimitry Andric       Tokenizer->consumeNextToken();
370fe6060f1SDimitry Andric       TokenInfo ChainCallToken = Tokenizer->consumeNextToken();
371fe6060f1SDimitry Andric       if (ChainCallToken.Kind == TokenInfo::TK_CodeCompletion) {
372fe6060f1SDimitry Andric         addCompletion(ChainCallToken, MatcherCompletion("bind(\"", "bind", 1));
373fe6060f1SDimitry Andric         return false;
374fe6060f1SDimitry Andric       }
375fe6060f1SDimitry Andric 
376fe6060f1SDimitry Andric       if (ChainCallToken.Kind != TokenInfo::TK_Ident ||
377fe6060f1SDimitry Andric           (ChainCallToken.Text != TokenInfo::ID_Bind &&
378fe6060f1SDimitry Andric            ChainCallToken.Text != TokenInfo::ID_With)) {
379fe6060f1SDimitry Andric         Error->addError(ChainCallToken.Range,
380fe6060f1SDimitry Andric                         Error->ET_ParserMalformedChainedExpr);
381fe6060f1SDimitry Andric         return false;
382fe6060f1SDimitry Andric       }
383fe6060f1SDimitry Andric       if (ChainCallToken.Text == TokenInfo::ID_With) {
384fe6060f1SDimitry Andric 
385fe6060f1SDimitry Andric         Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error,
386fe6060f1SDimitry Andric                                  NameToken.Text, NameToken.Range);
387fe6060f1SDimitry Andric 
388fe6060f1SDimitry Andric         Error->addError(ChainCallToken.Range,
389fe6060f1SDimitry Andric                         Error->ET_RegistryMatcherNoWithSupport);
390fe6060f1SDimitry Andric         return false;
391fe6060f1SDimitry Andric       }
3920b57cec5SDimitry Andric       if (!parseBindID(BindID))
3930b57cec5SDimitry Andric         return false;
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric       assert(NamedValue.isMatcher());
396bdd1243dSDimitry Andric       std::optional<DynTypedMatcher> Result =
3970b57cec5SDimitry Andric           NamedValue.getMatcher().getSingleMatcher();
39881ad6265SDimitry Andric       if (Result) {
399bdd1243dSDimitry Andric         std::optional<DynTypedMatcher> Bound = Result->tryBind(BindID);
40081ad6265SDimitry Andric         if (Bound) {
4010b57cec5SDimitry Andric           *Value = VariantMatcher::SingleMatcher(*Bound);
4020b57cec5SDimitry Andric           return true;
4030b57cec5SDimitry Andric         }
4040b57cec5SDimitry Andric       }
4050b57cec5SDimitry Andric       return false;
4060b57cec5SDimitry Andric     }
407480093f4SDimitry Andric 
408480093f4SDimitry Andric     if (Tokenizer->nextTokenKind() == TokenInfo::TK_NewLine) {
409480093f4SDimitry Andric       Error->addError(Tokenizer->peekNextToken().Range,
410480093f4SDimitry Andric                       Error->ET_ParserNoOpenParen)
411480093f4SDimitry Andric           << "NewLine";
412480093f4SDimitry Andric       return false;
413480093f4SDimitry Andric     }
414480093f4SDimitry Andric 
4150b57cec5SDimitry Andric     // If the syntax is correct and the name is not a matcher either, report
4160b57cec5SDimitry Andric     // unknown named value.
4170b57cec5SDimitry Andric     if ((Tokenizer->nextTokenKind() == TokenInfo::TK_Comma ||
4180b57cec5SDimitry Andric          Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen ||
419480093f4SDimitry Andric          Tokenizer->nextTokenKind() == TokenInfo::TK_NewLine ||
4200b57cec5SDimitry Andric          Tokenizer->nextTokenKind() == TokenInfo::TK_Eof) &&
4210b57cec5SDimitry Andric         !S->lookupMatcherCtor(NameToken.Text)) {
4220b57cec5SDimitry Andric       Error->addError(NameToken.Range, Error->ET_RegistryValueNotFound)
4230b57cec5SDimitry Andric           << NameToken.Text;
4240b57cec5SDimitry Andric       return false;
4250b57cec5SDimitry Andric     }
4260b57cec5SDimitry Andric     // Otherwise, fallback to the matcher parser.
4270b57cec5SDimitry Andric   }
4280b57cec5SDimitry Andric 
429480093f4SDimitry Andric   Tokenizer->SkipNewlines();
430480093f4SDimitry Andric 
431fe6060f1SDimitry Andric   assert(NameToken.Kind == TokenInfo::TK_Ident);
432fe6060f1SDimitry Andric   TokenInfo OpenToken = Tokenizer->consumeNextToken();
433fe6060f1SDimitry Andric   if (OpenToken.Kind != TokenInfo::TK_OpenParen) {
434fe6060f1SDimitry Andric     Error->addError(OpenToken.Range, Error->ET_ParserNoOpenParen)
435fe6060f1SDimitry Andric         << OpenToken.Text;
4360b57cec5SDimitry Andric     return false;
4370b57cec5SDimitry Andric   }
4380b57cec5SDimitry Andric 
439bdd1243dSDimitry Andric   std::optional<MatcherCtor> Ctor = S->lookupMatcherCtor(NameToken.Text);
440fe6060f1SDimitry Andric 
441fe6060f1SDimitry Andric   // Parse as a matcher expression.
442fe6060f1SDimitry Andric   return parseMatcherExpressionImpl(NameToken, OpenToken, Ctor, Value);
443fe6060f1SDimitry Andric }
444fe6060f1SDimitry Andric 
445fe6060f1SDimitry Andric bool Parser::parseBindID(std::string &BindID) {
446fe6060f1SDimitry Andric   // Parse the parenthesized argument to .bind("foo")
4470b57cec5SDimitry Andric   const TokenInfo OpenToken = Tokenizer->consumeNextToken();
448480093f4SDimitry Andric   const TokenInfo IDToken = Tokenizer->consumeNextTokenIgnoreNewlines();
449480093f4SDimitry Andric   const TokenInfo CloseToken = Tokenizer->consumeNextTokenIgnoreNewlines();
4500b57cec5SDimitry Andric 
4510b57cec5SDimitry Andric   // TODO: We could use different error codes for each/some to be more
4520b57cec5SDimitry Andric   //       explicit about the syntax error.
4530b57cec5SDimitry Andric   if (OpenToken.Kind != TokenInfo::TK_OpenParen) {
4540b57cec5SDimitry Andric     Error->addError(OpenToken.Range, Error->ET_ParserMalformedBindExpr);
4550b57cec5SDimitry Andric     return false;
4560b57cec5SDimitry Andric   }
4570b57cec5SDimitry Andric   if (IDToken.Kind != TokenInfo::TK_Literal || !IDToken.Value.isString()) {
4580b57cec5SDimitry Andric     Error->addError(IDToken.Range, Error->ET_ParserMalformedBindExpr);
4590b57cec5SDimitry Andric     return false;
4600b57cec5SDimitry Andric   }
4610b57cec5SDimitry Andric   if (CloseToken.Kind != TokenInfo::TK_CloseParen) {
4620b57cec5SDimitry Andric     Error->addError(CloseToken.Range, Error->ET_ParserMalformedBindExpr);
4630b57cec5SDimitry Andric     return false;
4640b57cec5SDimitry Andric   }
4650b57cec5SDimitry Andric   BindID = IDToken.Value.getString();
4660b57cec5SDimitry Andric   return true;
4670b57cec5SDimitry Andric }
4680b57cec5SDimitry Andric 
469fe6060f1SDimitry Andric bool Parser::parseMatcherBuilder(MatcherCtor Ctor, const TokenInfo &NameToken,
470fe6060f1SDimitry Andric                                  const TokenInfo &OpenToken,
471fe6060f1SDimitry Andric                                  VariantValue *Value) {
472fe6060f1SDimitry Andric   std::vector<ParserValue> Args;
473fe6060f1SDimitry Andric   TokenInfo EndToken;
474fe6060f1SDimitry Andric 
475fe6060f1SDimitry Andric   Tokenizer->SkipNewlines();
476fe6060f1SDimitry Andric 
477fe6060f1SDimitry Andric   {
478fe6060f1SDimitry Andric     ScopedContextEntry SCE(this, Ctor);
479fe6060f1SDimitry Andric 
480fe6060f1SDimitry Andric     while (Tokenizer->nextTokenKind() != TokenInfo::TK_Eof) {
481fe6060f1SDimitry Andric       if (Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen) {
482fe6060f1SDimitry Andric         // End of args.
483fe6060f1SDimitry Andric         EndToken = Tokenizer->consumeNextToken();
484fe6060f1SDimitry Andric         break;
485fe6060f1SDimitry Andric       }
486fe6060f1SDimitry Andric       if (!Args.empty()) {
487fe6060f1SDimitry Andric         // We must find a , token to continue.
488fe6060f1SDimitry Andric         TokenInfo CommaToken = Tokenizer->consumeNextToken();
489fe6060f1SDimitry Andric         if (CommaToken.Kind != TokenInfo::TK_Comma) {
490fe6060f1SDimitry Andric           Error->addError(CommaToken.Range, Error->ET_ParserNoComma)
491fe6060f1SDimitry Andric               << CommaToken.Text;
492fe6060f1SDimitry Andric           return false;
493fe6060f1SDimitry Andric         }
494fe6060f1SDimitry Andric       }
495fe6060f1SDimitry Andric 
496fe6060f1SDimitry Andric       Diagnostics::Context Ctx(Diagnostics::Context::MatcherArg, Error,
497fe6060f1SDimitry Andric                                NameToken.Text, NameToken.Range,
498fe6060f1SDimitry Andric                                Args.size() + 1);
499fe6060f1SDimitry Andric       ParserValue ArgValue;
500fe6060f1SDimitry Andric       Tokenizer->SkipNewlines();
501fe6060f1SDimitry Andric 
502fe6060f1SDimitry Andric       if (Tokenizer->peekNextToken().Kind == TokenInfo::TK_CodeCompletion) {
503fe6060f1SDimitry Andric         addExpressionCompletions();
504fe6060f1SDimitry Andric         return false;
505fe6060f1SDimitry Andric       }
506fe6060f1SDimitry Andric 
507fe6060f1SDimitry Andric       TokenInfo NodeMatcherToken = Tokenizer->consumeNextToken();
508fe6060f1SDimitry Andric 
509fe6060f1SDimitry Andric       if (NodeMatcherToken.Kind != TokenInfo::TK_Ident) {
510fe6060f1SDimitry Andric         Error->addError(NameToken.Range, Error->ET_ParserFailedToBuildMatcher)
511fe6060f1SDimitry Andric             << NameToken.Text;
512fe6060f1SDimitry Andric         return false;
513fe6060f1SDimitry Andric       }
514fe6060f1SDimitry Andric 
515fe6060f1SDimitry Andric       ArgValue.Text = NodeMatcherToken.Text;
516fe6060f1SDimitry Andric       ArgValue.Range = NodeMatcherToken.Range;
517fe6060f1SDimitry Andric 
518bdd1243dSDimitry Andric       std::optional<MatcherCtor> MappedMatcher =
519fe6060f1SDimitry Andric           S->lookupMatcherCtor(ArgValue.Text);
520fe6060f1SDimitry Andric 
521fe6060f1SDimitry Andric       if (!MappedMatcher) {
522fe6060f1SDimitry Andric         Error->addError(NodeMatcherToken.Range,
523fe6060f1SDimitry Andric                         Error->ET_RegistryMatcherNotFound)
524fe6060f1SDimitry Andric             << NodeMatcherToken.Text;
525fe6060f1SDimitry Andric         return false;
526fe6060f1SDimitry Andric       }
527fe6060f1SDimitry Andric 
528fe6060f1SDimitry Andric       ASTNodeKind NK = S->nodeMatcherType(*MappedMatcher);
529fe6060f1SDimitry Andric 
530fe6060f1SDimitry Andric       if (NK.isNone()) {
531fe6060f1SDimitry Andric         Error->addError(NodeMatcherToken.Range,
532fe6060f1SDimitry Andric                         Error->ET_RegistryNonNodeMatcher)
533fe6060f1SDimitry Andric             << NodeMatcherToken.Text;
534fe6060f1SDimitry Andric         return false;
535fe6060f1SDimitry Andric       }
536fe6060f1SDimitry Andric 
537fe6060f1SDimitry Andric       ArgValue.Value = NK;
538fe6060f1SDimitry Andric 
539fe6060f1SDimitry Andric       Tokenizer->SkipNewlines();
540fe6060f1SDimitry Andric       Args.push_back(ArgValue);
541fe6060f1SDimitry Andric 
542fe6060f1SDimitry Andric       SCE.nextArg();
543fe6060f1SDimitry Andric     }
544fe6060f1SDimitry Andric   }
545fe6060f1SDimitry Andric 
546fe6060f1SDimitry Andric   if (EndToken.Kind == TokenInfo::TK_Eof) {
547fe6060f1SDimitry Andric     Error->addError(OpenToken.Range, Error->ET_ParserNoCloseParen);
548fe6060f1SDimitry Andric     return false;
549fe6060f1SDimitry Andric   }
550fe6060f1SDimitry Andric 
551fe6060f1SDimitry Andric   internal::MatcherDescriptorPtr BuiltCtor =
552fe6060f1SDimitry Andric       S->buildMatcherCtor(Ctor, NameToken.Range, Args, Error);
553fe6060f1SDimitry Andric 
554fe6060f1SDimitry Andric   if (!BuiltCtor.get()) {
555fe6060f1SDimitry Andric     Error->addError(NameToken.Range, Error->ET_ParserFailedToBuildMatcher)
556fe6060f1SDimitry Andric         << NameToken.Text;
557fe6060f1SDimitry Andric     return false;
558fe6060f1SDimitry Andric   }
559fe6060f1SDimitry Andric 
560fe6060f1SDimitry Andric   std::string BindID;
561fe6060f1SDimitry Andric   if (Tokenizer->peekNextToken().Kind == TokenInfo::TK_Period) {
562fe6060f1SDimitry Andric     Tokenizer->consumeNextToken();
563fe6060f1SDimitry Andric     TokenInfo ChainCallToken = Tokenizer->consumeNextToken();
564fe6060f1SDimitry Andric     if (ChainCallToken.Kind == TokenInfo::TK_CodeCompletion) {
565fe6060f1SDimitry Andric       addCompletion(ChainCallToken, MatcherCompletion("bind(\"", "bind", 1));
566fe6060f1SDimitry Andric       addCompletion(ChainCallToken, MatcherCompletion("with(", "with", 1));
567fe6060f1SDimitry Andric       return false;
568fe6060f1SDimitry Andric     }
569fe6060f1SDimitry Andric     if (ChainCallToken.Kind != TokenInfo::TK_Ident ||
570fe6060f1SDimitry Andric         (ChainCallToken.Text != TokenInfo::ID_Bind &&
571fe6060f1SDimitry Andric          ChainCallToken.Text != TokenInfo::ID_With)) {
572fe6060f1SDimitry Andric       Error->addError(ChainCallToken.Range,
573fe6060f1SDimitry Andric                       Error->ET_ParserMalformedChainedExpr);
574fe6060f1SDimitry Andric       return false;
575fe6060f1SDimitry Andric     }
576fe6060f1SDimitry Andric     if (ChainCallToken.Text == TokenInfo::ID_Bind) {
577fe6060f1SDimitry Andric       if (!parseBindID(BindID))
578fe6060f1SDimitry Andric         return false;
579fe6060f1SDimitry Andric       Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error,
580fe6060f1SDimitry Andric                                NameToken.Text, NameToken.Range);
581fe6060f1SDimitry Andric       SourceRange MatcherRange = NameToken.Range;
582fe6060f1SDimitry Andric       MatcherRange.End = ChainCallToken.Range.End;
583fe6060f1SDimitry Andric       VariantMatcher Result = S->actOnMatcherExpression(
584fe6060f1SDimitry Andric           BuiltCtor.get(), MatcherRange, BindID, {}, Error);
585fe6060f1SDimitry Andric       if (Result.isNull())
586fe6060f1SDimitry Andric         return false;
587fe6060f1SDimitry Andric 
588fe6060f1SDimitry Andric       *Value = Result;
589fe6060f1SDimitry Andric       return true;
590fe6060f1SDimitry Andric     } else if (ChainCallToken.Text == TokenInfo::ID_With) {
591fe6060f1SDimitry Andric       Tokenizer->SkipNewlines();
592fe6060f1SDimitry Andric 
593fe6060f1SDimitry Andric       if (Tokenizer->nextTokenKind() != TokenInfo::TK_OpenParen) {
594fe6060f1SDimitry Andric         StringRef ErrTxt = Tokenizer->nextTokenKind() == TokenInfo::TK_Eof
595fe6060f1SDimitry Andric                                ? StringRef("EOF")
596fe6060f1SDimitry Andric                                : Tokenizer->peekNextToken().Text;
597fe6060f1SDimitry Andric         Error->addError(Tokenizer->peekNextToken().Range,
598fe6060f1SDimitry Andric                         Error->ET_ParserNoOpenParen)
599fe6060f1SDimitry Andric             << ErrTxt;
600fe6060f1SDimitry Andric         return false;
601fe6060f1SDimitry Andric       }
602fe6060f1SDimitry Andric 
603fe6060f1SDimitry Andric       TokenInfo WithOpenToken = Tokenizer->consumeNextToken();
604fe6060f1SDimitry Andric 
605fe6060f1SDimitry Andric       return parseMatcherExpressionImpl(NameToken, WithOpenToken,
606fe6060f1SDimitry Andric                                         BuiltCtor.get(), Value);
607fe6060f1SDimitry Andric     }
608fe6060f1SDimitry Andric   }
609fe6060f1SDimitry Andric 
610fe6060f1SDimitry Andric   Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error,
611fe6060f1SDimitry Andric                            NameToken.Text, NameToken.Range);
612fe6060f1SDimitry Andric   SourceRange MatcherRange = NameToken.Range;
613fe6060f1SDimitry Andric   MatcherRange.End = EndToken.Range.End;
614fe6060f1SDimitry Andric   VariantMatcher Result = S->actOnMatcherExpression(
615fe6060f1SDimitry Andric       BuiltCtor.get(), MatcherRange, BindID, {}, Error);
616fe6060f1SDimitry Andric   if (Result.isNull())
617fe6060f1SDimitry Andric     return false;
618fe6060f1SDimitry Andric 
619fe6060f1SDimitry Andric   *Value = Result;
620fe6060f1SDimitry Andric   return true;
621fe6060f1SDimitry Andric }
622fe6060f1SDimitry Andric 
6230b57cec5SDimitry Andric /// Parse and validate a matcher expression.
6240b57cec5SDimitry Andric /// \return \c true on success, in which case \c Value has the matcher parsed.
6250b57cec5SDimitry Andric ///   If the input is malformed, or some argument has an error, it
6260b57cec5SDimitry Andric ///   returns \c false.
6270b57cec5SDimitry Andric bool Parser::parseMatcherExpressionImpl(const TokenInfo &NameToken,
628fe6060f1SDimitry Andric                                         const TokenInfo &OpenToken,
629bdd1243dSDimitry Andric                                         std::optional<MatcherCtor> Ctor,
6300b57cec5SDimitry Andric                                         VariantValue *Value) {
6310b57cec5SDimitry Andric   if (!Ctor) {
6320b57cec5SDimitry Andric     Error->addError(NameToken.Range, Error->ET_RegistryMatcherNotFound)
6330b57cec5SDimitry Andric         << NameToken.Text;
6340b57cec5SDimitry Andric     // Do not return here. We need to continue to give completion suggestions.
6350b57cec5SDimitry Andric   }
6360b57cec5SDimitry Andric 
637fe6060f1SDimitry Andric   if (Ctor && *Ctor && S->isBuilderMatcher(*Ctor))
638fe6060f1SDimitry Andric     return parseMatcherBuilder(*Ctor, NameToken, OpenToken, Value);
639fe6060f1SDimitry Andric 
6400b57cec5SDimitry Andric   std::vector<ParserValue> Args;
6410b57cec5SDimitry Andric   TokenInfo EndToken;
6420b57cec5SDimitry Andric 
643480093f4SDimitry Andric   Tokenizer->SkipNewlines();
644480093f4SDimitry Andric 
6450b57cec5SDimitry Andric   {
64681ad6265SDimitry Andric     ScopedContextEntry SCE(this, Ctor.value_or(nullptr));
6470b57cec5SDimitry Andric 
6480b57cec5SDimitry Andric     while (Tokenizer->nextTokenKind() != TokenInfo::TK_Eof) {
6490b57cec5SDimitry Andric       if (Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen) {
6500b57cec5SDimitry Andric         // End of args.
6510b57cec5SDimitry Andric         EndToken = Tokenizer->consumeNextToken();
6520b57cec5SDimitry Andric         break;
6530b57cec5SDimitry Andric       }
6540b57cec5SDimitry Andric       if (!Args.empty()) {
6550b57cec5SDimitry Andric         // We must find a , token to continue.
6560b57cec5SDimitry Andric         const TokenInfo CommaToken = Tokenizer->consumeNextToken();
6570b57cec5SDimitry Andric         if (CommaToken.Kind != TokenInfo::TK_Comma) {
6580b57cec5SDimitry Andric           Error->addError(CommaToken.Range, Error->ET_ParserNoComma)
6590b57cec5SDimitry Andric               << CommaToken.Text;
6600b57cec5SDimitry Andric           return false;
6610b57cec5SDimitry Andric         }
6620b57cec5SDimitry Andric       }
6630b57cec5SDimitry Andric 
6640b57cec5SDimitry Andric       Diagnostics::Context Ctx(Diagnostics::Context::MatcherArg, Error,
6650b57cec5SDimitry Andric                                NameToken.Text, NameToken.Range,
6660b57cec5SDimitry Andric                                Args.size() + 1);
6670b57cec5SDimitry Andric       ParserValue ArgValue;
668480093f4SDimitry Andric       Tokenizer->SkipNewlines();
6690b57cec5SDimitry Andric       ArgValue.Text = Tokenizer->peekNextToken().Text;
6700b57cec5SDimitry Andric       ArgValue.Range = Tokenizer->peekNextToken().Range;
6710b57cec5SDimitry Andric       if (!parseExpressionImpl(&ArgValue.Value)) {
6720b57cec5SDimitry Andric         return false;
6730b57cec5SDimitry Andric       }
6740b57cec5SDimitry Andric 
675480093f4SDimitry Andric       Tokenizer->SkipNewlines();
6760b57cec5SDimitry Andric       Args.push_back(ArgValue);
6770b57cec5SDimitry Andric       SCE.nextArg();
6780b57cec5SDimitry Andric     }
6790b57cec5SDimitry Andric   }
6800b57cec5SDimitry Andric 
6810b57cec5SDimitry Andric   if (EndToken.Kind == TokenInfo::TK_Eof) {
6820b57cec5SDimitry Andric     Error->addError(OpenToken.Range, Error->ET_ParserNoCloseParen);
6830b57cec5SDimitry Andric     return false;
6840b57cec5SDimitry Andric   }
6850b57cec5SDimitry Andric 
6860b57cec5SDimitry Andric   std::string BindID;
6870b57cec5SDimitry Andric   if (Tokenizer->peekNextToken().Kind == TokenInfo::TK_Period) {
688fe6060f1SDimitry Andric     Tokenizer->consumeNextToken();
689fe6060f1SDimitry Andric     TokenInfo ChainCallToken = Tokenizer->consumeNextToken();
690fe6060f1SDimitry Andric     if (ChainCallToken.Kind == TokenInfo::TK_CodeCompletion) {
691fe6060f1SDimitry Andric       addCompletion(ChainCallToken, MatcherCompletion("bind(\"", "bind", 1));
692fe6060f1SDimitry Andric       return false;
693fe6060f1SDimitry Andric     }
694fe6060f1SDimitry Andric 
695fe6060f1SDimitry Andric     if (ChainCallToken.Kind != TokenInfo::TK_Ident) {
696fe6060f1SDimitry Andric       Error->addError(ChainCallToken.Range,
697fe6060f1SDimitry Andric                       Error->ET_ParserMalformedChainedExpr);
698fe6060f1SDimitry Andric       return false;
699fe6060f1SDimitry Andric     }
700fe6060f1SDimitry Andric     if (ChainCallToken.Text == TokenInfo::ID_With) {
701fe6060f1SDimitry Andric 
702fe6060f1SDimitry Andric       Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error,
703fe6060f1SDimitry Andric                                NameToken.Text, NameToken.Range);
704fe6060f1SDimitry Andric 
705fe6060f1SDimitry Andric       Error->addError(ChainCallToken.Range,
706fe6060f1SDimitry Andric                       Error->ET_RegistryMatcherNoWithSupport);
707fe6060f1SDimitry Andric       return false;
708fe6060f1SDimitry Andric     }
709fe6060f1SDimitry Andric     if (ChainCallToken.Text != TokenInfo::ID_Bind) {
710fe6060f1SDimitry Andric       Error->addError(ChainCallToken.Range,
711fe6060f1SDimitry Andric                       Error->ET_ParserMalformedChainedExpr);
712fe6060f1SDimitry Andric       return false;
713fe6060f1SDimitry Andric     }
7140b57cec5SDimitry Andric     if (!parseBindID(BindID))
7150b57cec5SDimitry Andric       return false;
7160b57cec5SDimitry Andric   }
7170b57cec5SDimitry Andric 
7180b57cec5SDimitry Andric   if (!Ctor)
7190b57cec5SDimitry Andric     return false;
7200b57cec5SDimitry Andric 
7210b57cec5SDimitry Andric   // Merge the start and end infos.
7220b57cec5SDimitry Andric   Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error,
7230b57cec5SDimitry Andric                            NameToken.Text, NameToken.Range);
7240b57cec5SDimitry Andric   SourceRange MatcherRange = NameToken.Range;
7250b57cec5SDimitry Andric   MatcherRange.End = EndToken.Range.End;
7260b57cec5SDimitry Andric   VariantMatcher Result = S->actOnMatcherExpression(
7270b57cec5SDimitry Andric       *Ctor, MatcherRange, BindID, Args, Error);
7280b57cec5SDimitry Andric   if (Result.isNull()) return false;
7290b57cec5SDimitry Andric 
7300b57cec5SDimitry Andric   *Value = Result;
7310b57cec5SDimitry Andric   return true;
7320b57cec5SDimitry Andric }
7330b57cec5SDimitry Andric 
7340b57cec5SDimitry Andric // If the prefix of this completion matches the completion token, add it to
7350b57cec5SDimitry Andric // Completions minus the prefix.
7360b57cec5SDimitry Andric void Parser::addCompletion(const TokenInfo &CompToken,
7370b57cec5SDimitry Andric                            const MatcherCompletion& Completion) {
7385f757f3fSDimitry Andric   if (StringRef(Completion.TypedText).starts_with(CompToken.Text) &&
7390b57cec5SDimitry Andric       Completion.Specificity > 0) {
7400b57cec5SDimitry Andric     Completions.emplace_back(Completion.TypedText.substr(CompToken.Text.size()),
7410b57cec5SDimitry Andric                              Completion.MatcherDecl, Completion.Specificity);
7420b57cec5SDimitry Andric   }
7430b57cec5SDimitry Andric }
7440b57cec5SDimitry Andric 
7450b57cec5SDimitry Andric std::vector<MatcherCompletion> Parser::getNamedValueCompletions(
7460b57cec5SDimitry Andric     ArrayRef<ArgKind> AcceptedTypes) {
7470b57cec5SDimitry Andric   if (!NamedValues) return std::vector<MatcherCompletion>();
7480b57cec5SDimitry Andric   std::vector<MatcherCompletion> Result;
7490b57cec5SDimitry Andric   for (const auto &Entry : *NamedValues) {
7500b57cec5SDimitry Andric     unsigned Specificity;
7510b57cec5SDimitry Andric     if (Entry.getValue().isConvertibleTo(AcceptedTypes, &Specificity)) {
7520b57cec5SDimitry Andric       std::string Decl =
7530b57cec5SDimitry Andric           (Entry.getValue().getTypeAsString() + " " + Entry.getKey()).str();
7540b57cec5SDimitry Andric       Result.emplace_back(Entry.getKey(), Decl, Specificity);
7550b57cec5SDimitry Andric     }
7560b57cec5SDimitry Andric   }
7570b57cec5SDimitry Andric   return Result;
7580b57cec5SDimitry Andric }
7590b57cec5SDimitry Andric 
7600b57cec5SDimitry Andric void Parser::addExpressionCompletions() {
761480093f4SDimitry Andric   const TokenInfo CompToken = Tokenizer->consumeNextTokenIgnoreNewlines();
7620b57cec5SDimitry Andric   assert(CompToken.Kind == TokenInfo::TK_CodeCompletion);
7630b57cec5SDimitry Andric 
7640b57cec5SDimitry Andric   // We cannot complete code if there is an invalid element on the context
7650b57cec5SDimitry Andric   // stack.
7660b57cec5SDimitry Andric   for (ContextStackTy::iterator I = ContextStack.begin(),
7670b57cec5SDimitry Andric                                 E = ContextStack.end();
7680b57cec5SDimitry Andric        I != E; ++I) {
7690b57cec5SDimitry Andric     if (!I->first)
7700b57cec5SDimitry Andric       return;
7710b57cec5SDimitry Andric   }
7720b57cec5SDimitry Andric 
7730b57cec5SDimitry Andric   auto AcceptedTypes = S->getAcceptedCompletionTypes(ContextStack);
7740b57cec5SDimitry Andric   for (const auto &Completion : S->getMatcherCompletions(AcceptedTypes)) {
7750b57cec5SDimitry Andric     addCompletion(CompToken, Completion);
7760b57cec5SDimitry Andric   }
7770b57cec5SDimitry Andric 
7780b57cec5SDimitry Andric   for (const auto &Completion : getNamedValueCompletions(AcceptedTypes)) {
7790b57cec5SDimitry Andric     addCompletion(CompToken, Completion);
7800b57cec5SDimitry Andric   }
7810b57cec5SDimitry Andric }
7820b57cec5SDimitry Andric 
7830b57cec5SDimitry Andric /// Parse an <Expression>
7840b57cec5SDimitry Andric bool Parser::parseExpressionImpl(VariantValue *Value) {
7850b57cec5SDimitry Andric   switch (Tokenizer->nextTokenKind()) {
7860b57cec5SDimitry Andric   case TokenInfo::TK_Literal:
7870b57cec5SDimitry Andric     *Value = Tokenizer->consumeNextToken().Value;
7880b57cec5SDimitry Andric     return true;
7890b57cec5SDimitry Andric 
7900b57cec5SDimitry Andric   case TokenInfo::TK_Ident:
7910b57cec5SDimitry Andric     return parseIdentifierPrefixImpl(Value);
7920b57cec5SDimitry Andric 
7930b57cec5SDimitry Andric   case TokenInfo::TK_CodeCompletion:
7940b57cec5SDimitry Andric     addExpressionCompletions();
7950b57cec5SDimitry Andric     return false;
7960b57cec5SDimitry Andric 
7970b57cec5SDimitry Andric   case TokenInfo::TK_Eof:
7980b57cec5SDimitry Andric     Error->addError(Tokenizer->consumeNextToken().Range,
7990b57cec5SDimitry Andric                     Error->ET_ParserNoCode);
8000b57cec5SDimitry Andric     return false;
8010b57cec5SDimitry Andric 
8020b57cec5SDimitry Andric   case TokenInfo::TK_Error:
8030b57cec5SDimitry Andric     // This error was already reported by the tokenizer.
8040b57cec5SDimitry Andric     return false;
805480093f4SDimitry Andric   case TokenInfo::TK_NewLine:
8060b57cec5SDimitry Andric   case TokenInfo::TK_OpenParen:
8070b57cec5SDimitry Andric   case TokenInfo::TK_CloseParen:
8080b57cec5SDimitry Andric   case TokenInfo::TK_Comma:
8090b57cec5SDimitry Andric   case TokenInfo::TK_Period:
8100b57cec5SDimitry Andric   case TokenInfo::TK_InvalidChar:
8110b57cec5SDimitry Andric     const TokenInfo Token = Tokenizer->consumeNextToken();
812480093f4SDimitry Andric     Error->addError(Token.Range, Error->ET_ParserInvalidToken)
813480093f4SDimitry Andric         << (Token.Kind == TokenInfo::TK_NewLine ? "NewLine" : Token.Text);
8140b57cec5SDimitry Andric     return false;
8150b57cec5SDimitry Andric   }
8160b57cec5SDimitry Andric 
8170b57cec5SDimitry Andric   llvm_unreachable("Unknown token kind.");
8180b57cec5SDimitry Andric }
8190b57cec5SDimitry Andric 
8200b57cec5SDimitry Andric static llvm::ManagedStatic<Parser::RegistrySema> DefaultRegistrySema;
8210b57cec5SDimitry Andric 
8220b57cec5SDimitry Andric Parser::Parser(CodeTokenizer *Tokenizer, Sema *S,
8230b57cec5SDimitry Andric                const NamedValueMap *NamedValues, Diagnostics *Error)
8240b57cec5SDimitry Andric     : Tokenizer(Tokenizer), S(S ? S : &*DefaultRegistrySema),
8250b57cec5SDimitry Andric       NamedValues(NamedValues), Error(Error) {}
8260b57cec5SDimitry Andric 
8270b57cec5SDimitry Andric Parser::RegistrySema::~RegistrySema() = default;
8280b57cec5SDimitry Andric 
829bdd1243dSDimitry Andric std::optional<MatcherCtor>
8300b57cec5SDimitry Andric Parser::RegistrySema::lookupMatcherCtor(StringRef MatcherName) {
8310b57cec5SDimitry Andric   return Registry::lookupMatcherCtor(MatcherName);
8320b57cec5SDimitry Andric }
8330b57cec5SDimitry Andric 
8340b57cec5SDimitry Andric VariantMatcher Parser::RegistrySema::actOnMatcherExpression(
8350b57cec5SDimitry Andric     MatcherCtor Ctor, SourceRange NameRange, StringRef BindID,
8360b57cec5SDimitry Andric     ArrayRef<ParserValue> Args, Diagnostics *Error) {
8370b57cec5SDimitry Andric   if (BindID.empty()) {
8380b57cec5SDimitry Andric     return Registry::constructMatcher(Ctor, NameRange, Args, Error);
8390b57cec5SDimitry Andric   } else {
8400b57cec5SDimitry Andric     return Registry::constructBoundMatcher(Ctor, NameRange, BindID, Args,
8410b57cec5SDimitry Andric                                            Error);
8420b57cec5SDimitry Andric   }
8430b57cec5SDimitry Andric }
8440b57cec5SDimitry Andric 
8450b57cec5SDimitry Andric std::vector<ArgKind> Parser::RegistrySema::getAcceptedCompletionTypes(
8460b57cec5SDimitry Andric     ArrayRef<std::pair<MatcherCtor, unsigned>> Context) {
8470b57cec5SDimitry Andric   return Registry::getAcceptedCompletionTypes(Context);
8480b57cec5SDimitry Andric }
8490b57cec5SDimitry Andric 
8500b57cec5SDimitry Andric std::vector<MatcherCompletion> Parser::RegistrySema::getMatcherCompletions(
8510b57cec5SDimitry Andric     ArrayRef<ArgKind> AcceptedTypes) {
8520b57cec5SDimitry Andric   return Registry::getMatcherCompletions(AcceptedTypes);
8530b57cec5SDimitry Andric }
8540b57cec5SDimitry Andric 
855fe6060f1SDimitry Andric bool Parser::RegistrySema::isBuilderMatcher(MatcherCtor Ctor) const {
856fe6060f1SDimitry Andric   return Registry::isBuilderMatcher(Ctor);
857fe6060f1SDimitry Andric }
858fe6060f1SDimitry Andric 
859fe6060f1SDimitry Andric ASTNodeKind Parser::RegistrySema::nodeMatcherType(MatcherCtor Ctor) const {
860fe6060f1SDimitry Andric   return Registry::nodeMatcherType(Ctor);
861fe6060f1SDimitry Andric }
862fe6060f1SDimitry Andric 
863fe6060f1SDimitry Andric internal::MatcherDescriptorPtr
864fe6060f1SDimitry Andric Parser::RegistrySema::buildMatcherCtor(MatcherCtor Ctor, SourceRange NameRange,
865fe6060f1SDimitry Andric                                        ArrayRef<ParserValue> Args,
866fe6060f1SDimitry Andric                                        Diagnostics *Error) const {
867fe6060f1SDimitry Andric   return Registry::buildMatcherCtor(Ctor, NameRange, Args, Error);
868fe6060f1SDimitry Andric }
869fe6060f1SDimitry Andric 
870480093f4SDimitry Andric bool Parser::parseExpression(StringRef &Code, Sema *S,
8710b57cec5SDimitry Andric                              const NamedValueMap *NamedValues,
8720b57cec5SDimitry Andric                              VariantValue *Value, Diagnostics *Error) {
8730b57cec5SDimitry Andric   CodeTokenizer Tokenizer(Code, Error);
8740b57cec5SDimitry Andric   if (!Parser(&Tokenizer, S, NamedValues, Error).parseExpressionImpl(Value))
8750b57cec5SDimitry Andric     return false;
876480093f4SDimitry Andric   auto NT = Tokenizer.peekNextToken();
877480093f4SDimitry Andric   if (NT.Kind != TokenInfo::TK_Eof && NT.Kind != TokenInfo::TK_NewLine) {
8780b57cec5SDimitry Andric     Error->addError(Tokenizer.peekNextToken().Range,
8790b57cec5SDimitry Andric                     Error->ET_ParserTrailingCode);
8800b57cec5SDimitry Andric     return false;
8810b57cec5SDimitry Andric   }
8820b57cec5SDimitry Andric   return true;
8830b57cec5SDimitry Andric }
8840b57cec5SDimitry Andric 
8850b57cec5SDimitry Andric std::vector<MatcherCompletion>
886480093f4SDimitry Andric Parser::completeExpression(StringRef &Code, unsigned CompletionOffset, Sema *S,
8870b57cec5SDimitry Andric                            const NamedValueMap *NamedValues) {
8880b57cec5SDimitry Andric   Diagnostics Error;
8890b57cec5SDimitry Andric   CodeTokenizer Tokenizer(Code, &Error, CompletionOffset);
8900b57cec5SDimitry Andric   Parser P(&Tokenizer, S, NamedValues, &Error);
8910b57cec5SDimitry Andric   VariantValue Dummy;
8920b57cec5SDimitry Andric   P.parseExpressionImpl(&Dummy);
8930b57cec5SDimitry Andric 
8940b57cec5SDimitry Andric   // Sort by specificity, then by name.
8950b57cec5SDimitry Andric   llvm::sort(P.Completions,
8960b57cec5SDimitry Andric              [](const MatcherCompletion &A, const MatcherCompletion &B) {
8970b57cec5SDimitry Andric                if (A.Specificity != B.Specificity)
8980b57cec5SDimitry Andric                  return A.Specificity > B.Specificity;
8990b57cec5SDimitry Andric                return A.TypedText < B.TypedText;
9000b57cec5SDimitry Andric              });
9010b57cec5SDimitry Andric 
9020b57cec5SDimitry Andric   return P.Completions;
9030b57cec5SDimitry Andric }
9040b57cec5SDimitry Andric 
905bdd1243dSDimitry Andric std::optional<DynTypedMatcher>
906480093f4SDimitry Andric Parser::parseMatcherExpression(StringRef &Code, Sema *S,
9070b57cec5SDimitry Andric                                const NamedValueMap *NamedValues,
9080b57cec5SDimitry Andric                                Diagnostics *Error) {
9090b57cec5SDimitry Andric   VariantValue Value;
9100b57cec5SDimitry Andric   if (!parseExpression(Code, S, NamedValues, &Value, Error))
911bdd1243dSDimitry Andric     return std::nullopt;
9120b57cec5SDimitry Andric   if (!Value.isMatcher()) {
9130b57cec5SDimitry Andric     Error->addError(SourceRange(), Error->ET_ParserNotAMatcher);
914bdd1243dSDimitry Andric     return std::nullopt;
9150b57cec5SDimitry Andric   }
916bdd1243dSDimitry Andric   std::optional<DynTypedMatcher> Result = Value.getMatcher().getSingleMatcher();
91781ad6265SDimitry Andric   if (!Result) {
9180b57cec5SDimitry Andric     Error->addError(SourceRange(), Error->ET_ParserOverloadedType)
9190b57cec5SDimitry Andric         << Value.getTypeAsString();
9200b57cec5SDimitry Andric   }
9210b57cec5SDimitry Andric   return Result;
9220b57cec5SDimitry Andric }
9230b57cec5SDimitry Andric 
9240b57cec5SDimitry Andric } // namespace dynamic
9250b57cec5SDimitry Andric } // namespace ast_matchers
9260b57cec5SDimitry Andric } // namespace clang
927