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:
CodeTokenizer(StringRef & MatcherCode,Diagnostics * Error)71480093f4SDimitry Andric explicit CodeTokenizer(StringRef &MatcherCode, Diagnostics *Error)
720b57cec5SDimitry Andric : Code(MatcherCode), StartOfLine(MatcherCode), Error(Error) {
730b57cec5SDimitry Andric NextToken = getNextToken();
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric
CodeTokenizer(StringRef & MatcherCode,Diagnostics * Error,unsigned CodeCompletionOffset)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.
peekNextToken() const840b57cec5SDimitry Andric const TokenInfo &peekNextToken() const { return NextToken; }
850b57cec5SDimitry Andric
860b57cec5SDimitry Andric /// Consumes and returns the next token.
consumeNextToken()870b57cec5SDimitry Andric TokenInfo consumeNextToken() {
880b57cec5SDimitry Andric TokenInfo ThisToken = NextToken;
890b57cec5SDimitry Andric NextToken = getNextToken();
900b57cec5SDimitry Andric return ThisToken;
910b57cec5SDimitry Andric }
920b57cec5SDimitry Andric
SkipNewlines()93480093f4SDimitry Andric TokenInfo SkipNewlines() {
94480093f4SDimitry Andric while (NextToken.Kind == TokenInfo::TK_NewLine)
95480093f4SDimitry Andric NextToken = getNextToken();
96480093f4SDimitry Andric return NextToken;
97480093f4SDimitry Andric }
98480093f4SDimitry Andric
consumeNextTokenIgnoreNewlines()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
nextTokenKind() const1060b57cec5SDimitry Andric TokenInfo::TokenKind nextTokenKind() const { return NextToken.Kind; }
1070b57cec5SDimitry Andric
1080b57cec5SDimitry Andric private:
getNextToken()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.
consumeNumberLiteral(TokenInfo * Result)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.
consumeStringLiteral(TokenInfo * Result)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.
consumeWhitespace()3010b57cec5SDimitry Andric void consumeWhitespace() {
302480093f4SDimitry Andric // Don't trim newlines.
303*647cbc5dSDimitry Andric Code = Code.ltrim(" \t\v\f\r");
3040b57cec5SDimitry Andric }
3050b57cec5SDimitry Andric
currentLocation()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
getAcceptedCompletionTypes(llvm::ArrayRef<std::pair<MatcherCtor,unsigned>> Context)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>
getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes)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
ScopedContextEntryclang::ast_matchers::dynamic::Parser::ScopedContextEntry3360b57cec5SDimitry Andric ScopedContextEntry(Parser *P, MatcherCtor C) : P(P) {
3370b57cec5SDimitry Andric P->ContextStack.push_back(std::make_pair(C, 0u));
3380b57cec5SDimitry Andric }
3390b57cec5SDimitry Andric
~ScopedContextEntryclang::ast_matchers::dynamic::Parser::ScopedContextEntry3400b57cec5SDimitry Andric ~ScopedContextEntry() {
3410b57cec5SDimitry Andric P->ContextStack.pop_back();
3420b57cec5SDimitry Andric }
3430b57cec5SDimitry Andric
nextArgclang::ast_matchers::dynamic::Parser::ScopedContextEntry3440b57cec5SDimitry 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.
parseIdentifierPrefixImpl(VariantValue * Value)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
parseBindID(std::string & BindID)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
parseMatcherBuilder(MatcherCtor Ctor,const TokenInfo & NameToken,const TokenInfo & OpenToken,VariantValue * Value)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.
parseMatcherExpressionImpl(const TokenInfo & NameToken,const TokenInfo & OpenToken,std::optional<MatcherCtor> Ctor,VariantValue * Value)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.
addCompletion(const TokenInfo & CompToken,const MatcherCompletion & Completion)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
getNamedValueCompletions(ArrayRef<ArgKind> AcceptedTypes)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
addExpressionCompletions()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>
parseExpressionImpl(VariantValue * Value)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
Parser(CodeTokenizer * Tokenizer,Sema * S,const NamedValueMap * NamedValues,Diagnostics * Error)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>
lookupMatcherCtor(StringRef MatcherName)8300b57cec5SDimitry Andric Parser::RegistrySema::lookupMatcherCtor(StringRef MatcherName) {
8310b57cec5SDimitry Andric return Registry::lookupMatcherCtor(MatcherName);
8320b57cec5SDimitry Andric }
8330b57cec5SDimitry Andric
actOnMatcherExpression(MatcherCtor Ctor,SourceRange NameRange,StringRef BindID,ArrayRef<ParserValue> Args,Diagnostics * Error)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
getAcceptedCompletionTypes(ArrayRef<std::pair<MatcherCtor,unsigned>> Context)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
getMatcherCompletions(ArrayRef<ArgKind> AcceptedTypes)8500b57cec5SDimitry Andric std::vector<MatcherCompletion> Parser::RegistrySema::getMatcherCompletions(
8510b57cec5SDimitry Andric ArrayRef<ArgKind> AcceptedTypes) {
8520b57cec5SDimitry Andric return Registry::getMatcherCompletions(AcceptedTypes);
8530b57cec5SDimitry Andric }
8540b57cec5SDimitry Andric
isBuilderMatcher(MatcherCtor Ctor) const855fe6060f1SDimitry Andric bool Parser::RegistrySema::isBuilderMatcher(MatcherCtor Ctor) const {
856fe6060f1SDimitry Andric return Registry::isBuilderMatcher(Ctor);
857fe6060f1SDimitry Andric }
858fe6060f1SDimitry Andric
nodeMatcherType(MatcherCtor Ctor) const859fe6060f1SDimitry Andric ASTNodeKind Parser::RegistrySema::nodeMatcherType(MatcherCtor Ctor) const {
860fe6060f1SDimitry Andric return Registry::nodeMatcherType(Ctor);
861fe6060f1SDimitry Andric }
862fe6060f1SDimitry Andric
863fe6060f1SDimitry Andric internal::MatcherDescriptorPtr
buildMatcherCtor(MatcherCtor Ctor,SourceRange NameRange,ArrayRef<ParserValue> Args,Diagnostics * Error) const864fe6060f1SDimitry 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
parseExpression(StringRef & Code,Sema * S,const NamedValueMap * NamedValues,VariantValue * Value,Diagnostics * Error)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>
completeExpression(StringRef & Code,unsigned CompletionOffset,Sema * S,const NamedValueMap * NamedValues)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>
parseMatcherExpression(StringRef & Code,Sema * S,const NamedValueMap * NamedValues,Diagnostics * Error)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