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