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> 27*bdd1243dSDimitry 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 } 1900b57cec5SDimitry Andric if (TokenLength == 4 && Code.startswith("true")) { 1910b57cec5SDimitry Andric Result.Kind = TokenInfo::TK_Literal; 1920b57cec5SDimitry Andric Result.Value = true; 1930b57cec5SDimitry Andric } else if (TokenLength == 5 && Code.startswith("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 Code = Code.drop_while([](char c) { 303480093f4SDimitry Andric // Don't trim newlines. 304480093f4SDimitry Andric return StringRef(" \t\v\f\r").contains(c); 305480093f4SDimitry Andric }); 3060b57cec5SDimitry Andric } 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric SourceLocation currentLocation() { 3090b57cec5SDimitry Andric SourceLocation Location; 3100b57cec5SDimitry Andric Location.Line = Line; 3110b57cec5SDimitry Andric Location.Column = Code.data() - StartOfLine.data() + 1; 3120b57cec5SDimitry Andric return Location; 3130b57cec5SDimitry Andric } 3140b57cec5SDimitry Andric 315480093f4SDimitry Andric StringRef &Code; 3160b57cec5SDimitry Andric StringRef StartOfLine; 3170b57cec5SDimitry Andric unsigned Line = 1; 3180b57cec5SDimitry Andric Diagnostics *Error; 3190b57cec5SDimitry Andric TokenInfo NextToken; 3200b57cec5SDimitry Andric const char *CodeCompletionLocation = nullptr; 3210b57cec5SDimitry Andric }; 3220b57cec5SDimitry Andric 3230b57cec5SDimitry Andric Parser::Sema::~Sema() = default; 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric std::vector<ArgKind> Parser::Sema::getAcceptedCompletionTypes( 3260b57cec5SDimitry Andric llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context) { 3270b57cec5SDimitry Andric return {}; 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric std::vector<MatcherCompletion> 3310b57cec5SDimitry Andric Parser::Sema::getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes) { 3320b57cec5SDimitry Andric return {}; 3330b57cec5SDimitry Andric } 3340b57cec5SDimitry Andric 3350b57cec5SDimitry Andric struct Parser::ScopedContextEntry { 3360b57cec5SDimitry Andric Parser *P; 3370b57cec5SDimitry Andric 3380b57cec5SDimitry Andric ScopedContextEntry(Parser *P, MatcherCtor C) : P(P) { 3390b57cec5SDimitry Andric P->ContextStack.push_back(std::make_pair(C, 0u)); 3400b57cec5SDimitry Andric } 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric ~ScopedContextEntry() { 3430b57cec5SDimitry Andric P->ContextStack.pop_back(); 3440b57cec5SDimitry Andric } 3450b57cec5SDimitry Andric 3460b57cec5SDimitry Andric void nextArg() { 3470b57cec5SDimitry Andric ++P->ContextStack.back().second; 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric }; 3500b57cec5SDimitry Andric 3510b57cec5SDimitry Andric /// Parse expressions that start with an identifier. 3520b57cec5SDimitry Andric /// 3530b57cec5SDimitry Andric /// This function can parse named values and matchers. 3540b57cec5SDimitry Andric /// In case of failure it will try to determine the user's intent to give 3550b57cec5SDimitry Andric /// an appropriate error message. 3560b57cec5SDimitry Andric bool Parser::parseIdentifierPrefixImpl(VariantValue *Value) { 3570b57cec5SDimitry Andric const TokenInfo NameToken = Tokenizer->consumeNextToken(); 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric if (Tokenizer->nextTokenKind() != TokenInfo::TK_OpenParen) { 3600b57cec5SDimitry Andric // Parse as a named value. 3610b57cec5SDimitry Andric if (const VariantValue NamedValue = 3620b57cec5SDimitry Andric NamedValues ? NamedValues->lookup(NameToken.Text) 3630b57cec5SDimitry Andric : VariantValue()) { 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric if (Tokenizer->nextTokenKind() != TokenInfo::TK_Period) { 3660b57cec5SDimitry Andric *Value = NamedValue; 3670b57cec5SDimitry Andric return true; 3680b57cec5SDimitry Andric } 3690b57cec5SDimitry Andric 3700b57cec5SDimitry Andric std::string BindID; 371fe6060f1SDimitry Andric Tokenizer->consumeNextToken(); 372fe6060f1SDimitry Andric TokenInfo ChainCallToken = Tokenizer->consumeNextToken(); 373fe6060f1SDimitry Andric if (ChainCallToken.Kind == TokenInfo::TK_CodeCompletion) { 374fe6060f1SDimitry Andric addCompletion(ChainCallToken, MatcherCompletion("bind(\"", "bind", 1)); 375fe6060f1SDimitry Andric return false; 376fe6060f1SDimitry Andric } 377fe6060f1SDimitry Andric 378fe6060f1SDimitry Andric if (ChainCallToken.Kind != TokenInfo::TK_Ident || 379fe6060f1SDimitry Andric (ChainCallToken.Text != TokenInfo::ID_Bind && 380fe6060f1SDimitry Andric ChainCallToken.Text != TokenInfo::ID_With)) { 381fe6060f1SDimitry Andric Error->addError(ChainCallToken.Range, 382fe6060f1SDimitry Andric Error->ET_ParserMalformedChainedExpr); 383fe6060f1SDimitry Andric return false; 384fe6060f1SDimitry Andric } 385fe6060f1SDimitry Andric if (ChainCallToken.Text == TokenInfo::ID_With) { 386fe6060f1SDimitry Andric 387fe6060f1SDimitry Andric Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error, 388fe6060f1SDimitry Andric NameToken.Text, NameToken.Range); 389fe6060f1SDimitry Andric 390fe6060f1SDimitry Andric Error->addError(ChainCallToken.Range, 391fe6060f1SDimitry Andric Error->ET_RegistryMatcherNoWithSupport); 392fe6060f1SDimitry Andric return false; 393fe6060f1SDimitry Andric } 3940b57cec5SDimitry Andric if (!parseBindID(BindID)) 3950b57cec5SDimitry Andric return false; 3960b57cec5SDimitry Andric 3970b57cec5SDimitry Andric assert(NamedValue.isMatcher()); 398*bdd1243dSDimitry Andric std::optional<DynTypedMatcher> Result = 3990b57cec5SDimitry Andric NamedValue.getMatcher().getSingleMatcher(); 40081ad6265SDimitry Andric if (Result) { 401*bdd1243dSDimitry Andric std::optional<DynTypedMatcher> Bound = Result->tryBind(BindID); 40281ad6265SDimitry Andric if (Bound) { 4030b57cec5SDimitry Andric *Value = VariantMatcher::SingleMatcher(*Bound); 4040b57cec5SDimitry Andric return true; 4050b57cec5SDimitry Andric } 4060b57cec5SDimitry Andric } 4070b57cec5SDimitry Andric return false; 4080b57cec5SDimitry Andric } 409480093f4SDimitry Andric 410480093f4SDimitry Andric if (Tokenizer->nextTokenKind() == TokenInfo::TK_NewLine) { 411480093f4SDimitry Andric Error->addError(Tokenizer->peekNextToken().Range, 412480093f4SDimitry Andric Error->ET_ParserNoOpenParen) 413480093f4SDimitry Andric << "NewLine"; 414480093f4SDimitry Andric return false; 415480093f4SDimitry Andric } 416480093f4SDimitry Andric 4170b57cec5SDimitry Andric // If the syntax is correct and the name is not a matcher either, report 4180b57cec5SDimitry Andric // unknown named value. 4190b57cec5SDimitry Andric if ((Tokenizer->nextTokenKind() == TokenInfo::TK_Comma || 4200b57cec5SDimitry Andric Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen || 421480093f4SDimitry Andric Tokenizer->nextTokenKind() == TokenInfo::TK_NewLine || 4220b57cec5SDimitry Andric Tokenizer->nextTokenKind() == TokenInfo::TK_Eof) && 4230b57cec5SDimitry Andric !S->lookupMatcherCtor(NameToken.Text)) { 4240b57cec5SDimitry Andric Error->addError(NameToken.Range, Error->ET_RegistryValueNotFound) 4250b57cec5SDimitry Andric << NameToken.Text; 4260b57cec5SDimitry Andric return false; 4270b57cec5SDimitry Andric } 4280b57cec5SDimitry Andric // Otherwise, fallback to the matcher parser. 4290b57cec5SDimitry Andric } 4300b57cec5SDimitry Andric 431480093f4SDimitry Andric Tokenizer->SkipNewlines(); 432480093f4SDimitry Andric 433fe6060f1SDimitry Andric assert(NameToken.Kind == TokenInfo::TK_Ident); 434fe6060f1SDimitry Andric TokenInfo OpenToken = Tokenizer->consumeNextToken(); 435fe6060f1SDimitry Andric if (OpenToken.Kind != TokenInfo::TK_OpenParen) { 436fe6060f1SDimitry Andric Error->addError(OpenToken.Range, Error->ET_ParserNoOpenParen) 437fe6060f1SDimitry Andric << OpenToken.Text; 4380b57cec5SDimitry Andric return false; 4390b57cec5SDimitry Andric } 4400b57cec5SDimitry Andric 441*bdd1243dSDimitry Andric std::optional<MatcherCtor> Ctor = S->lookupMatcherCtor(NameToken.Text); 442fe6060f1SDimitry Andric 443fe6060f1SDimitry Andric // Parse as a matcher expression. 444fe6060f1SDimitry Andric return parseMatcherExpressionImpl(NameToken, OpenToken, Ctor, Value); 445fe6060f1SDimitry Andric } 446fe6060f1SDimitry Andric 447fe6060f1SDimitry Andric bool Parser::parseBindID(std::string &BindID) { 448fe6060f1SDimitry Andric // Parse the parenthesized argument to .bind("foo") 4490b57cec5SDimitry Andric const TokenInfo OpenToken = Tokenizer->consumeNextToken(); 450480093f4SDimitry Andric const TokenInfo IDToken = Tokenizer->consumeNextTokenIgnoreNewlines(); 451480093f4SDimitry Andric const TokenInfo CloseToken = Tokenizer->consumeNextTokenIgnoreNewlines(); 4520b57cec5SDimitry Andric 4530b57cec5SDimitry Andric // TODO: We could use different error codes for each/some to be more 4540b57cec5SDimitry Andric // explicit about the syntax error. 4550b57cec5SDimitry Andric if (OpenToken.Kind != TokenInfo::TK_OpenParen) { 4560b57cec5SDimitry Andric Error->addError(OpenToken.Range, Error->ET_ParserMalformedBindExpr); 4570b57cec5SDimitry Andric return false; 4580b57cec5SDimitry Andric } 4590b57cec5SDimitry Andric if (IDToken.Kind != TokenInfo::TK_Literal || !IDToken.Value.isString()) { 4600b57cec5SDimitry Andric Error->addError(IDToken.Range, Error->ET_ParserMalformedBindExpr); 4610b57cec5SDimitry Andric return false; 4620b57cec5SDimitry Andric } 4630b57cec5SDimitry Andric if (CloseToken.Kind != TokenInfo::TK_CloseParen) { 4640b57cec5SDimitry Andric Error->addError(CloseToken.Range, Error->ET_ParserMalformedBindExpr); 4650b57cec5SDimitry Andric return false; 4660b57cec5SDimitry Andric } 4670b57cec5SDimitry Andric BindID = IDToken.Value.getString(); 4680b57cec5SDimitry Andric return true; 4690b57cec5SDimitry Andric } 4700b57cec5SDimitry Andric 471fe6060f1SDimitry Andric bool Parser::parseMatcherBuilder(MatcherCtor Ctor, const TokenInfo &NameToken, 472fe6060f1SDimitry Andric const TokenInfo &OpenToken, 473fe6060f1SDimitry Andric VariantValue *Value) { 474fe6060f1SDimitry Andric std::vector<ParserValue> Args; 475fe6060f1SDimitry Andric TokenInfo EndToken; 476fe6060f1SDimitry Andric 477fe6060f1SDimitry Andric Tokenizer->SkipNewlines(); 478fe6060f1SDimitry Andric 479fe6060f1SDimitry Andric { 480fe6060f1SDimitry Andric ScopedContextEntry SCE(this, Ctor); 481fe6060f1SDimitry Andric 482fe6060f1SDimitry Andric while (Tokenizer->nextTokenKind() != TokenInfo::TK_Eof) { 483fe6060f1SDimitry Andric if (Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen) { 484fe6060f1SDimitry Andric // End of args. 485fe6060f1SDimitry Andric EndToken = Tokenizer->consumeNextToken(); 486fe6060f1SDimitry Andric break; 487fe6060f1SDimitry Andric } 488fe6060f1SDimitry Andric if (!Args.empty()) { 489fe6060f1SDimitry Andric // We must find a , token to continue. 490fe6060f1SDimitry Andric TokenInfo CommaToken = Tokenizer->consumeNextToken(); 491fe6060f1SDimitry Andric if (CommaToken.Kind != TokenInfo::TK_Comma) { 492fe6060f1SDimitry Andric Error->addError(CommaToken.Range, Error->ET_ParserNoComma) 493fe6060f1SDimitry Andric << CommaToken.Text; 494fe6060f1SDimitry Andric return false; 495fe6060f1SDimitry Andric } 496fe6060f1SDimitry Andric } 497fe6060f1SDimitry Andric 498fe6060f1SDimitry Andric Diagnostics::Context Ctx(Diagnostics::Context::MatcherArg, Error, 499fe6060f1SDimitry Andric NameToken.Text, NameToken.Range, 500fe6060f1SDimitry Andric Args.size() + 1); 501fe6060f1SDimitry Andric ParserValue ArgValue; 502fe6060f1SDimitry Andric Tokenizer->SkipNewlines(); 503fe6060f1SDimitry Andric 504fe6060f1SDimitry Andric if (Tokenizer->peekNextToken().Kind == TokenInfo::TK_CodeCompletion) { 505fe6060f1SDimitry Andric addExpressionCompletions(); 506fe6060f1SDimitry Andric return false; 507fe6060f1SDimitry Andric } 508fe6060f1SDimitry Andric 509fe6060f1SDimitry Andric TokenInfo NodeMatcherToken = Tokenizer->consumeNextToken(); 510fe6060f1SDimitry Andric 511fe6060f1SDimitry Andric if (NodeMatcherToken.Kind != TokenInfo::TK_Ident) { 512fe6060f1SDimitry Andric Error->addError(NameToken.Range, Error->ET_ParserFailedToBuildMatcher) 513fe6060f1SDimitry Andric << NameToken.Text; 514fe6060f1SDimitry Andric return false; 515fe6060f1SDimitry Andric } 516fe6060f1SDimitry Andric 517fe6060f1SDimitry Andric ArgValue.Text = NodeMatcherToken.Text; 518fe6060f1SDimitry Andric ArgValue.Range = NodeMatcherToken.Range; 519fe6060f1SDimitry Andric 520*bdd1243dSDimitry Andric std::optional<MatcherCtor> MappedMatcher = 521fe6060f1SDimitry Andric S->lookupMatcherCtor(ArgValue.Text); 522fe6060f1SDimitry Andric 523fe6060f1SDimitry Andric if (!MappedMatcher) { 524fe6060f1SDimitry Andric Error->addError(NodeMatcherToken.Range, 525fe6060f1SDimitry Andric Error->ET_RegistryMatcherNotFound) 526fe6060f1SDimitry Andric << NodeMatcherToken.Text; 527fe6060f1SDimitry Andric return false; 528fe6060f1SDimitry Andric } 529fe6060f1SDimitry Andric 530fe6060f1SDimitry Andric ASTNodeKind NK = S->nodeMatcherType(*MappedMatcher); 531fe6060f1SDimitry Andric 532fe6060f1SDimitry Andric if (NK.isNone()) { 533fe6060f1SDimitry Andric Error->addError(NodeMatcherToken.Range, 534fe6060f1SDimitry Andric Error->ET_RegistryNonNodeMatcher) 535fe6060f1SDimitry Andric << NodeMatcherToken.Text; 536fe6060f1SDimitry Andric return false; 537fe6060f1SDimitry Andric } 538fe6060f1SDimitry Andric 539fe6060f1SDimitry Andric ArgValue.Value = NK; 540fe6060f1SDimitry Andric 541fe6060f1SDimitry Andric Tokenizer->SkipNewlines(); 542fe6060f1SDimitry Andric Args.push_back(ArgValue); 543fe6060f1SDimitry Andric 544fe6060f1SDimitry Andric SCE.nextArg(); 545fe6060f1SDimitry Andric } 546fe6060f1SDimitry Andric } 547fe6060f1SDimitry Andric 548fe6060f1SDimitry Andric if (EndToken.Kind == TokenInfo::TK_Eof) { 549fe6060f1SDimitry Andric Error->addError(OpenToken.Range, Error->ET_ParserNoCloseParen); 550fe6060f1SDimitry Andric return false; 551fe6060f1SDimitry Andric } 552fe6060f1SDimitry Andric 553fe6060f1SDimitry Andric internal::MatcherDescriptorPtr BuiltCtor = 554fe6060f1SDimitry Andric S->buildMatcherCtor(Ctor, NameToken.Range, Args, Error); 555fe6060f1SDimitry Andric 556fe6060f1SDimitry Andric if (!BuiltCtor.get()) { 557fe6060f1SDimitry Andric Error->addError(NameToken.Range, Error->ET_ParserFailedToBuildMatcher) 558fe6060f1SDimitry Andric << NameToken.Text; 559fe6060f1SDimitry Andric return false; 560fe6060f1SDimitry Andric } 561fe6060f1SDimitry Andric 562fe6060f1SDimitry Andric std::string BindID; 563fe6060f1SDimitry Andric if (Tokenizer->peekNextToken().Kind == TokenInfo::TK_Period) { 564fe6060f1SDimitry Andric Tokenizer->consumeNextToken(); 565fe6060f1SDimitry Andric TokenInfo ChainCallToken = Tokenizer->consumeNextToken(); 566fe6060f1SDimitry Andric if (ChainCallToken.Kind == TokenInfo::TK_CodeCompletion) { 567fe6060f1SDimitry Andric addCompletion(ChainCallToken, MatcherCompletion("bind(\"", "bind", 1)); 568fe6060f1SDimitry Andric addCompletion(ChainCallToken, MatcherCompletion("with(", "with", 1)); 569fe6060f1SDimitry Andric return false; 570fe6060f1SDimitry Andric } 571fe6060f1SDimitry Andric if (ChainCallToken.Kind != TokenInfo::TK_Ident || 572fe6060f1SDimitry Andric (ChainCallToken.Text != TokenInfo::ID_Bind && 573fe6060f1SDimitry Andric ChainCallToken.Text != TokenInfo::ID_With)) { 574fe6060f1SDimitry Andric Error->addError(ChainCallToken.Range, 575fe6060f1SDimitry Andric Error->ET_ParserMalformedChainedExpr); 576fe6060f1SDimitry Andric return false; 577fe6060f1SDimitry Andric } 578fe6060f1SDimitry Andric if (ChainCallToken.Text == TokenInfo::ID_Bind) { 579fe6060f1SDimitry Andric if (!parseBindID(BindID)) 580fe6060f1SDimitry Andric return false; 581fe6060f1SDimitry Andric Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error, 582fe6060f1SDimitry Andric NameToken.Text, NameToken.Range); 583fe6060f1SDimitry Andric SourceRange MatcherRange = NameToken.Range; 584fe6060f1SDimitry Andric MatcherRange.End = ChainCallToken.Range.End; 585fe6060f1SDimitry Andric VariantMatcher Result = S->actOnMatcherExpression( 586fe6060f1SDimitry Andric BuiltCtor.get(), MatcherRange, BindID, {}, Error); 587fe6060f1SDimitry Andric if (Result.isNull()) 588fe6060f1SDimitry Andric return false; 589fe6060f1SDimitry Andric 590fe6060f1SDimitry Andric *Value = Result; 591fe6060f1SDimitry Andric return true; 592fe6060f1SDimitry Andric } else if (ChainCallToken.Text == TokenInfo::ID_With) { 593fe6060f1SDimitry Andric Tokenizer->SkipNewlines(); 594fe6060f1SDimitry Andric 595fe6060f1SDimitry Andric if (Tokenizer->nextTokenKind() != TokenInfo::TK_OpenParen) { 596fe6060f1SDimitry Andric StringRef ErrTxt = Tokenizer->nextTokenKind() == TokenInfo::TK_Eof 597fe6060f1SDimitry Andric ? StringRef("EOF") 598fe6060f1SDimitry Andric : Tokenizer->peekNextToken().Text; 599fe6060f1SDimitry Andric Error->addError(Tokenizer->peekNextToken().Range, 600fe6060f1SDimitry Andric Error->ET_ParserNoOpenParen) 601fe6060f1SDimitry Andric << ErrTxt; 602fe6060f1SDimitry Andric return false; 603fe6060f1SDimitry Andric } 604fe6060f1SDimitry Andric 605fe6060f1SDimitry Andric TokenInfo WithOpenToken = Tokenizer->consumeNextToken(); 606fe6060f1SDimitry Andric 607fe6060f1SDimitry Andric return parseMatcherExpressionImpl(NameToken, WithOpenToken, 608fe6060f1SDimitry Andric BuiltCtor.get(), Value); 609fe6060f1SDimitry Andric } 610fe6060f1SDimitry Andric } 611fe6060f1SDimitry Andric 612fe6060f1SDimitry Andric Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error, 613fe6060f1SDimitry Andric NameToken.Text, NameToken.Range); 614fe6060f1SDimitry Andric SourceRange MatcherRange = NameToken.Range; 615fe6060f1SDimitry Andric MatcherRange.End = EndToken.Range.End; 616fe6060f1SDimitry Andric VariantMatcher Result = S->actOnMatcherExpression( 617fe6060f1SDimitry Andric BuiltCtor.get(), MatcherRange, BindID, {}, Error); 618fe6060f1SDimitry Andric if (Result.isNull()) 619fe6060f1SDimitry Andric return false; 620fe6060f1SDimitry Andric 621fe6060f1SDimitry Andric *Value = Result; 622fe6060f1SDimitry Andric return true; 623fe6060f1SDimitry Andric } 624fe6060f1SDimitry Andric 6250b57cec5SDimitry Andric /// Parse and validate a matcher expression. 6260b57cec5SDimitry Andric /// \return \c true on success, in which case \c Value has the matcher parsed. 6270b57cec5SDimitry Andric /// If the input is malformed, or some argument has an error, it 6280b57cec5SDimitry Andric /// returns \c false. 6290b57cec5SDimitry Andric bool Parser::parseMatcherExpressionImpl(const TokenInfo &NameToken, 630fe6060f1SDimitry Andric const TokenInfo &OpenToken, 631*bdd1243dSDimitry Andric std::optional<MatcherCtor> Ctor, 6320b57cec5SDimitry Andric VariantValue *Value) { 6330b57cec5SDimitry Andric if (!Ctor) { 6340b57cec5SDimitry Andric Error->addError(NameToken.Range, Error->ET_RegistryMatcherNotFound) 6350b57cec5SDimitry Andric << NameToken.Text; 6360b57cec5SDimitry Andric // Do not return here. We need to continue to give completion suggestions. 6370b57cec5SDimitry Andric } 6380b57cec5SDimitry Andric 639fe6060f1SDimitry Andric if (Ctor && *Ctor && S->isBuilderMatcher(*Ctor)) 640fe6060f1SDimitry Andric return parseMatcherBuilder(*Ctor, NameToken, OpenToken, Value); 641fe6060f1SDimitry Andric 6420b57cec5SDimitry Andric std::vector<ParserValue> Args; 6430b57cec5SDimitry Andric TokenInfo EndToken; 6440b57cec5SDimitry Andric 645480093f4SDimitry Andric Tokenizer->SkipNewlines(); 646480093f4SDimitry Andric 6470b57cec5SDimitry Andric { 64881ad6265SDimitry Andric ScopedContextEntry SCE(this, Ctor.value_or(nullptr)); 6490b57cec5SDimitry Andric 6500b57cec5SDimitry Andric while (Tokenizer->nextTokenKind() != TokenInfo::TK_Eof) { 6510b57cec5SDimitry Andric if (Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen) { 6520b57cec5SDimitry Andric // End of args. 6530b57cec5SDimitry Andric EndToken = Tokenizer->consumeNextToken(); 6540b57cec5SDimitry Andric break; 6550b57cec5SDimitry Andric } 6560b57cec5SDimitry Andric if (!Args.empty()) { 6570b57cec5SDimitry Andric // We must find a , token to continue. 6580b57cec5SDimitry Andric const TokenInfo CommaToken = Tokenizer->consumeNextToken(); 6590b57cec5SDimitry Andric if (CommaToken.Kind != TokenInfo::TK_Comma) { 6600b57cec5SDimitry Andric Error->addError(CommaToken.Range, Error->ET_ParserNoComma) 6610b57cec5SDimitry Andric << CommaToken.Text; 6620b57cec5SDimitry Andric return false; 6630b57cec5SDimitry Andric } 6640b57cec5SDimitry Andric } 6650b57cec5SDimitry Andric 6660b57cec5SDimitry Andric Diagnostics::Context Ctx(Diagnostics::Context::MatcherArg, Error, 6670b57cec5SDimitry Andric NameToken.Text, NameToken.Range, 6680b57cec5SDimitry Andric Args.size() + 1); 6690b57cec5SDimitry Andric ParserValue ArgValue; 670480093f4SDimitry Andric Tokenizer->SkipNewlines(); 6710b57cec5SDimitry Andric ArgValue.Text = Tokenizer->peekNextToken().Text; 6720b57cec5SDimitry Andric ArgValue.Range = Tokenizer->peekNextToken().Range; 6730b57cec5SDimitry Andric if (!parseExpressionImpl(&ArgValue.Value)) { 6740b57cec5SDimitry Andric return false; 6750b57cec5SDimitry Andric } 6760b57cec5SDimitry Andric 677480093f4SDimitry Andric Tokenizer->SkipNewlines(); 6780b57cec5SDimitry Andric Args.push_back(ArgValue); 6790b57cec5SDimitry Andric SCE.nextArg(); 6800b57cec5SDimitry Andric } 6810b57cec5SDimitry Andric } 6820b57cec5SDimitry Andric 6830b57cec5SDimitry Andric if (EndToken.Kind == TokenInfo::TK_Eof) { 6840b57cec5SDimitry Andric Error->addError(OpenToken.Range, Error->ET_ParserNoCloseParen); 6850b57cec5SDimitry Andric return false; 6860b57cec5SDimitry Andric } 6870b57cec5SDimitry Andric 6880b57cec5SDimitry Andric std::string BindID; 6890b57cec5SDimitry Andric if (Tokenizer->peekNextToken().Kind == TokenInfo::TK_Period) { 690fe6060f1SDimitry Andric Tokenizer->consumeNextToken(); 691fe6060f1SDimitry Andric TokenInfo ChainCallToken = Tokenizer->consumeNextToken(); 692fe6060f1SDimitry Andric if (ChainCallToken.Kind == TokenInfo::TK_CodeCompletion) { 693fe6060f1SDimitry Andric addCompletion(ChainCallToken, MatcherCompletion("bind(\"", "bind", 1)); 694fe6060f1SDimitry Andric return false; 695fe6060f1SDimitry Andric } 696fe6060f1SDimitry Andric 697fe6060f1SDimitry Andric if (ChainCallToken.Kind != TokenInfo::TK_Ident) { 698fe6060f1SDimitry Andric Error->addError(ChainCallToken.Range, 699fe6060f1SDimitry Andric Error->ET_ParserMalformedChainedExpr); 700fe6060f1SDimitry Andric return false; 701fe6060f1SDimitry Andric } 702fe6060f1SDimitry Andric if (ChainCallToken.Text == TokenInfo::ID_With) { 703fe6060f1SDimitry Andric 704fe6060f1SDimitry Andric Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error, 705fe6060f1SDimitry Andric NameToken.Text, NameToken.Range); 706fe6060f1SDimitry Andric 707fe6060f1SDimitry Andric Error->addError(ChainCallToken.Range, 708fe6060f1SDimitry Andric Error->ET_RegistryMatcherNoWithSupport); 709fe6060f1SDimitry Andric return false; 710fe6060f1SDimitry Andric } 711fe6060f1SDimitry Andric if (ChainCallToken.Text != TokenInfo::ID_Bind) { 712fe6060f1SDimitry Andric Error->addError(ChainCallToken.Range, 713fe6060f1SDimitry Andric Error->ET_ParserMalformedChainedExpr); 714fe6060f1SDimitry Andric return false; 715fe6060f1SDimitry Andric } 7160b57cec5SDimitry Andric if (!parseBindID(BindID)) 7170b57cec5SDimitry Andric return false; 7180b57cec5SDimitry Andric } 7190b57cec5SDimitry Andric 7200b57cec5SDimitry Andric if (!Ctor) 7210b57cec5SDimitry Andric return false; 7220b57cec5SDimitry Andric 7230b57cec5SDimitry Andric // Merge the start and end infos. 7240b57cec5SDimitry Andric Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error, 7250b57cec5SDimitry Andric NameToken.Text, NameToken.Range); 7260b57cec5SDimitry Andric SourceRange MatcherRange = NameToken.Range; 7270b57cec5SDimitry Andric MatcherRange.End = EndToken.Range.End; 7280b57cec5SDimitry Andric VariantMatcher Result = S->actOnMatcherExpression( 7290b57cec5SDimitry Andric *Ctor, MatcherRange, BindID, Args, Error); 7300b57cec5SDimitry Andric if (Result.isNull()) return false; 7310b57cec5SDimitry Andric 7320b57cec5SDimitry Andric *Value = Result; 7330b57cec5SDimitry Andric return true; 7340b57cec5SDimitry Andric } 7350b57cec5SDimitry Andric 7360b57cec5SDimitry Andric // If the prefix of this completion matches the completion token, add it to 7370b57cec5SDimitry Andric // Completions minus the prefix. 7380b57cec5SDimitry Andric void Parser::addCompletion(const TokenInfo &CompToken, 7390b57cec5SDimitry Andric const MatcherCompletion& Completion) { 7400b57cec5SDimitry Andric if (StringRef(Completion.TypedText).startswith(CompToken.Text) && 7410b57cec5SDimitry Andric Completion.Specificity > 0) { 7420b57cec5SDimitry Andric Completions.emplace_back(Completion.TypedText.substr(CompToken.Text.size()), 7430b57cec5SDimitry Andric Completion.MatcherDecl, Completion.Specificity); 7440b57cec5SDimitry Andric } 7450b57cec5SDimitry Andric } 7460b57cec5SDimitry Andric 7470b57cec5SDimitry Andric std::vector<MatcherCompletion> Parser::getNamedValueCompletions( 7480b57cec5SDimitry Andric ArrayRef<ArgKind> AcceptedTypes) { 7490b57cec5SDimitry Andric if (!NamedValues) return std::vector<MatcherCompletion>(); 7500b57cec5SDimitry Andric std::vector<MatcherCompletion> Result; 7510b57cec5SDimitry Andric for (const auto &Entry : *NamedValues) { 7520b57cec5SDimitry Andric unsigned Specificity; 7530b57cec5SDimitry Andric if (Entry.getValue().isConvertibleTo(AcceptedTypes, &Specificity)) { 7540b57cec5SDimitry Andric std::string Decl = 7550b57cec5SDimitry Andric (Entry.getValue().getTypeAsString() + " " + Entry.getKey()).str(); 7560b57cec5SDimitry Andric Result.emplace_back(Entry.getKey(), Decl, Specificity); 7570b57cec5SDimitry Andric } 7580b57cec5SDimitry Andric } 7590b57cec5SDimitry Andric return Result; 7600b57cec5SDimitry Andric } 7610b57cec5SDimitry Andric 7620b57cec5SDimitry Andric void Parser::addExpressionCompletions() { 763480093f4SDimitry Andric const TokenInfo CompToken = Tokenizer->consumeNextTokenIgnoreNewlines(); 7640b57cec5SDimitry Andric assert(CompToken.Kind == TokenInfo::TK_CodeCompletion); 7650b57cec5SDimitry Andric 7660b57cec5SDimitry Andric // We cannot complete code if there is an invalid element on the context 7670b57cec5SDimitry Andric // stack. 7680b57cec5SDimitry Andric for (ContextStackTy::iterator I = ContextStack.begin(), 7690b57cec5SDimitry Andric E = ContextStack.end(); 7700b57cec5SDimitry Andric I != E; ++I) { 7710b57cec5SDimitry Andric if (!I->first) 7720b57cec5SDimitry Andric return; 7730b57cec5SDimitry Andric } 7740b57cec5SDimitry Andric 7750b57cec5SDimitry Andric auto AcceptedTypes = S->getAcceptedCompletionTypes(ContextStack); 7760b57cec5SDimitry Andric for (const auto &Completion : S->getMatcherCompletions(AcceptedTypes)) { 7770b57cec5SDimitry Andric addCompletion(CompToken, Completion); 7780b57cec5SDimitry Andric } 7790b57cec5SDimitry Andric 7800b57cec5SDimitry Andric for (const auto &Completion : getNamedValueCompletions(AcceptedTypes)) { 7810b57cec5SDimitry Andric addCompletion(CompToken, Completion); 7820b57cec5SDimitry Andric } 7830b57cec5SDimitry Andric } 7840b57cec5SDimitry Andric 7850b57cec5SDimitry Andric /// Parse an <Expression> 7860b57cec5SDimitry Andric bool Parser::parseExpressionImpl(VariantValue *Value) { 7870b57cec5SDimitry Andric switch (Tokenizer->nextTokenKind()) { 7880b57cec5SDimitry Andric case TokenInfo::TK_Literal: 7890b57cec5SDimitry Andric *Value = Tokenizer->consumeNextToken().Value; 7900b57cec5SDimitry Andric return true; 7910b57cec5SDimitry Andric 7920b57cec5SDimitry Andric case TokenInfo::TK_Ident: 7930b57cec5SDimitry Andric return parseIdentifierPrefixImpl(Value); 7940b57cec5SDimitry Andric 7950b57cec5SDimitry Andric case TokenInfo::TK_CodeCompletion: 7960b57cec5SDimitry Andric addExpressionCompletions(); 7970b57cec5SDimitry Andric return false; 7980b57cec5SDimitry Andric 7990b57cec5SDimitry Andric case TokenInfo::TK_Eof: 8000b57cec5SDimitry Andric Error->addError(Tokenizer->consumeNextToken().Range, 8010b57cec5SDimitry Andric Error->ET_ParserNoCode); 8020b57cec5SDimitry Andric return false; 8030b57cec5SDimitry Andric 8040b57cec5SDimitry Andric case TokenInfo::TK_Error: 8050b57cec5SDimitry Andric // This error was already reported by the tokenizer. 8060b57cec5SDimitry Andric return false; 807480093f4SDimitry Andric case TokenInfo::TK_NewLine: 8080b57cec5SDimitry Andric case TokenInfo::TK_OpenParen: 8090b57cec5SDimitry Andric case TokenInfo::TK_CloseParen: 8100b57cec5SDimitry Andric case TokenInfo::TK_Comma: 8110b57cec5SDimitry Andric case TokenInfo::TK_Period: 8120b57cec5SDimitry Andric case TokenInfo::TK_InvalidChar: 8130b57cec5SDimitry Andric const TokenInfo Token = Tokenizer->consumeNextToken(); 814480093f4SDimitry Andric Error->addError(Token.Range, Error->ET_ParserInvalidToken) 815480093f4SDimitry Andric << (Token.Kind == TokenInfo::TK_NewLine ? "NewLine" : Token.Text); 8160b57cec5SDimitry Andric return false; 8170b57cec5SDimitry Andric } 8180b57cec5SDimitry Andric 8190b57cec5SDimitry Andric llvm_unreachable("Unknown token kind."); 8200b57cec5SDimitry Andric } 8210b57cec5SDimitry Andric 8220b57cec5SDimitry Andric static llvm::ManagedStatic<Parser::RegistrySema> DefaultRegistrySema; 8230b57cec5SDimitry Andric 8240b57cec5SDimitry Andric Parser::Parser(CodeTokenizer *Tokenizer, Sema *S, 8250b57cec5SDimitry Andric const NamedValueMap *NamedValues, Diagnostics *Error) 8260b57cec5SDimitry Andric : Tokenizer(Tokenizer), S(S ? S : &*DefaultRegistrySema), 8270b57cec5SDimitry Andric NamedValues(NamedValues), Error(Error) {} 8280b57cec5SDimitry Andric 8290b57cec5SDimitry Andric Parser::RegistrySema::~RegistrySema() = default; 8300b57cec5SDimitry Andric 831*bdd1243dSDimitry Andric std::optional<MatcherCtor> 8320b57cec5SDimitry Andric Parser::RegistrySema::lookupMatcherCtor(StringRef MatcherName) { 8330b57cec5SDimitry Andric return Registry::lookupMatcherCtor(MatcherName); 8340b57cec5SDimitry Andric } 8350b57cec5SDimitry Andric 8360b57cec5SDimitry Andric VariantMatcher Parser::RegistrySema::actOnMatcherExpression( 8370b57cec5SDimitry Andric MatcherCtor Ctor, SourceRange NameRange, StringRef BindID, 8380b57cec5SDimitry Andric ArrayRef<ParserValue> Args, Diagnostics *Error) { 8390b57cec5SDimitry Andric if (BindID.empty()) { 8400b57cec5SDimitry Andric return Registry::constructMatcher(Ctor, NameRange, Args, Error); 8410b57cec5SDimitry Andric } else { 8420b57cec5SDimitry Andric return Registry::constructBoundMatcher(Ctor, NameRange, BindID, Args, 8430b57cec5SDimitry Andric Error); 8440b57cec5SDimitry Andric } 8450b57cec5SDimitry Andric } 8460b57cec5SDimitry Andric 8470b57cec5SDimitry Andric std::vector<ArgKind> Parser::RegistrySema::getAcceptedCompletionTypes( 8480b57cec5SDimitry Andric ArrayRef<std::pair<MatcherCtor, unsigned>> Context) { 8490b57cec5SDimitry Andric return Registry::getAcceptedCompletionTypes(Context); 8500b57cec5SDimitry Andric } 8510b57cec5SDimitry Andric 8520b57cec5SDimitry Andric std::vector<MatcherCompletion> Parser::RegistrySema::getMatcherCompletions( 8530b57cec5SDimitry Andric ArrayRef<ArgKind> AcceptedTypes) { 8540b57cec5SDimitry Andric return Registry::getMatcherCompletions(AcceptedTypes); 8550b57cec5SDimitry Andric } 8560b57cec5SDimitry Andric 857fe6060f1SDimitry Andric bool Parser::RegistrySema::isBuilderMatcher(MatcherCtor Ctor) const { 858fe6060f1SDimitry Andric return Registry::isBuilderMatcher(Ctor); 859fe6060f1SDimitry Andric } 860fe6060f1SDimitry Andric 861fe6060f1SDimitry Andric ASTNodeKind Parser::RegistrySema::nodeMatcherType(MatcherCtor Ctor) const { 862fe6060f1SDimitry Andric return Registry::nodeMatcherType(Ctor); 863fe6060f1SDimitry Andric } 864fe6060f1SDimitry Andric 865fe6060f1SDimitry Andric internal::MatcherDescriptorPtr 866fe6060f1SDimitry Andric Parser::RegistrySema::buildMatcherCtor(MatcherCtor Ctor, SourceRange NameRange, 867fe6060f1SDimitry Andric ArrayRef<ParserValue> Args, 868fe6060f1SDimitry Andric Diagnostics *Error) const { 869fe6060f1SDimitry Andric return Registry::buildMatcherCtor(Ctor, NameRange, Args, Error); 870fe6060f1SDimitry Andric } 871fe6060f1SDimitry Andric 872480093f4SDimitry Andric bool Parser::parseExpression(StringRef &Code, Sema *S, 8730b57cec5SDimitry Andric const NamedValueMap *NamedValues, 8740b57cec5SDimitry Andric VariantValue *Value, Diagnostics *Error) { 8750b57cec5SDimitry Andric CodeTokenizer Tokenizer(Code, Error); 8760b57cec5SDimitry Andric if (!Parser(&Tokenizer, S, NamedValues, Error).parseExpressionImpl(Value)) 8770b57cec5SDimitry Andric return false; 878480093f4SDimitry Andric auto NT = Tokenizer.peekNextToken(); 879480093f4SDimitry Andric if (NT.Kind != TokenInfo::TK_Eof && NT.Kind != TokenInfo::TK_NewLine) { 8800b57cec5SDimitry Andric Error->addError(Tokenizer.peekNextToken().Range, 8810b57cec5SDimitry Andric Error->ET_ParserTrailingCode); 8820b57cec5SDimitry Andric return false; 8830b57cec5SDimitry Andric } 8840b57cec5SDimitry Andric return true; 8850b57cec5SDimitry Andric } 8860b57cec5SDimitry Andric 8870b57cec5SDimitry Andric std::vector<MatcherCompletion> 888480093f4SDimitry Andric Parser::completeExpression(StringRef &Code, unsigned CompletionOffset, Sema *S, 8890b57cec5SDimitry Andric const NamedValueMap *NamedValues) { 8900b57cec5SDimitry Andric Diagnostics Error; 8910b57cec5SDimitry Andric CodeTokenizer Tokenizer(Code, &Error, CompletionOffset); 8920b57cec5SDimitry Andric Parser P(&Tokenizer, S, NamedValues, &Error); 8930b57cec5SDimitry Andric VariantValue Dummy; 8940b57cec5SDimitry Andric P.parseExpressionImpl(&Dummy); 8950b57cec5SDimitry Andric 8960b57cec5SDimitry Andric // Sort by specificity, then by name. 8970b57cec5SDimitry Andric llvm::sort(P.Completions, 8980b57cec5SDimitry Andric [](const MatcherCompletion &A, const MatcherCompletion &B) { 8990b57cec5SDimitry Andric if (A.Specificity != B.Specificity) 9000b57cec5SDimitry Andric return A.Specificity > B.Specificity; 9010b57cec5SDimitry Andric return A.TypedText < B.TypedText; 9020b57cec5SDimitry Andric }); 9030b57cec5SDimitry Andric 9040b57cec5SDimitry Andric return P.Completions; 9050b57cec5SDimitry Andric } 9060b57cec5SDimitry Andric 907*bdd1243dSDimitry Andric std::optional<DynTypedMatcher> 908480093f4SDimitry Andric Parser::parseMatcherExpression(StringRef &Code, Sema *S, 9090b57cec5SDimitry Andric const NamedValueMap *NamedValues, 9100b57cec5SDimitry Andric Diagnostics *Error) { 9110b57cec5SDimitry Andric VariantValue Value; 9120b57cec5SDimitry Andric if (!parseExpression(Code, S, NamedValues, &Value, Error)) 913*bdd1243dSDimitry Andric return std::nullopt; 9140b57cec5SDimitry Andric if (!Value.isMatcher()) { 9150b57cec5SDimitry Andric Error->addError(SourceRange(), Error->ET_ParserNotAMatcher); 916*bdd1243dSDimitry Andric return std::nullopt; 9170b57cec5SDimitry Andric } 918*bdd1243dSDimitry Andric std::optional<DynTypedMatcher> Result = Value.getMatcher().getSingleMatcher(); 91981ad6265SDimitry Andric if (!Result) { 9200b57cec5SDimitry Andric Error->addError(SourceRange(), Error->ET_ParserOverloadedType) 9210b57cec5SDimitry Andric << Value.getTypeAsString(); 9220b57cec5SDimitry Andric } 9230b57cec5SDimitry Andric return Result; 9240b57cec5SDimitry Andric } 9250b57cec5SDimitry Andric 9260b57cec5SDimitry Andric } // namespace dynamic 9270b57cec5SDimitry Andric } // namespace ast_matchers 9280b57cec5SDimitry Andric } // namespace clang 929