Parser.cpp revision 276479
1259701Sdim//===--- Parser.cpp - Matcher expression parser -----*- C++ -*-===// 2259701Sdim// 3259701Sdim// The LLVM Compiler Infrastructure 4259701Sdim// 5259701Sdim// This file is distributed under the University of Illinois Open Source 6259701Sdim// License. See LICENSE.TXT for details. 7259701Sdim// 8259701Sdim//===----------------------------------------------------------------------===// 9259701Sdim/// 10259701Sdim/// \file 11259701Sdim/// \brief Recursive parser implementation for the matcher expression grammar. 12259701Sdim/// 13259701Sdim//===----------------------------------------------------------------------===// 14259701Sdim 15259701Sdim#include "clang/ASTMatchers/Dynamic/Parser.h" 16259701Sdim#include "clang/ASTMatchers/Dynamic/Registry.h" 17259701Sdim#include "clang/Basic/CharInfo.h" 18276479Sdim#include "llvm/ADT/Optional.h" 19259701Sdim#include "llvm/ADT/Twine.h" 20276479Sdim#include <string> 21276479Sdim#include <vector> 22259701Sdim 23259701Sdimnamespace clang { 24259701Sdimnamespace ast_matchers { 25259701Sdimnamespace dynamic { 26259701Sdim 27259701Sdim/// \brief Simple structure to hold information for one token from the parser. 28259701Sdimstruct Parser::TokenInfo { 29259701Sdim /// \brief Different possible tokens. 30259701Sdim enum TokenKind { 31276479Sdim TK_Eof, 32276479Sdim TK_OpenParen, 33276479Sdim TK_CloseParen, 34276479Sdim TK_Comma, 35276479Sdim TK_Period, 36276479Sdim TK_Literal, 37276479Sdim TK_Ident, 38276479Sdim TK_InvalidChar, 39276479Sdim TK_Error, 40276479Sdim TK_CodeCompletion 41259701Sdim }; 42259701Sdim 43259701Sdim /// \brief Some known identifiers. 44259701Sdim static const char* const ID_Bind; 45259701Sdim 46259701Sdim TokenInfo() : Text(), Kind(TK_Eof), Range(), Value() {} 47259701Sdim 48259701Sdim StringRef Text; 49259701Sdim TokenKind Kind; 50259701Sdim SourceRange Range; 51259701Sdim VariantValue Value; 52259701Sdim}; 53259701Sdim 54259701Sdimconst char* const Parser::TokenInfo::ID_Bind = "bind"; 55259701Sdim 56259701Sdim/// \brief Simple tokenizer for the parser. 57259701Sdimclass Parser::CodeTokenizer { 58259701Sdimpublic: 59259701Sdim explicit CodeTokenizer(StringRef MatcherCode, Diagnostics *Error) 60276479Sdim : Code(MatcherCode), StartOfLine(MatcherCode), Line(1), Error(Error), 61276479Sdim CodeCompletionLocation(nullptr) { 62259701Sdim NextToken = getNextToken(); 63259701Sdim } 64259701Sdim 65276479Sdim CodeTokenizer(StringRef MatcherCode, Diagnostics *Error, 66276479Sdim unsigned CodeCompletionOffset) 67276479Sdim : Code(MatcherCode), StartOfLine(MatcherCode), Line(1), Error(Error), 68276479Sdim CodeCompletionLocation(MatcherCode.data() + CodeCompletionOffset) { 69276479Sdim NextToken = getNextToken(); 70276479Sdim } 71276479Sdim 72259701Sdim /// \brief Returns but doesn't consume the next token. 73259701Sdim const TokenInfo &peekNextToken() const { return NextToken; } 74259701Sdim 75259701Sdim /// \brief Consumes and returns the next token. 76259701Sdim TokenInfo consumeNextToken() { 77259701Sdim TokenInfo ThisToken = NextToken; 78259701Sdim NextToken = getNextToken(); 79259701Sdim return ThisToken; 80259701Sdim } 81259701Sdim 82259701Sdim TokenInfo::TokenKind nextTokenKind() const { return NextToken.Kind; } 83259701Sdim 84259701Sdimprivate: 85259701Sdim TokenInfo getNextToken() { 86259701Sdim consumeWhitespace(); 87259701Sdim TokenInfo Result; 88259701Sdim Result.Range.Start = currentLocation(); 89259701Sdim 90276479Sdim if (CodeCompletionLocation && CodeCompletionLocation <= Code.data()) { 91276479Sdim Result.Kind = TokenInfo::TK_CodeCompletion; 92276479Sdim Result.Text = StringRef(CodeCompletionLocation, 0); 93276479Sdim CodeCompletionLocation = nullptr; 94276479Sdim return Result; 95276479Sdim } 96276479Sdim 97259701Sdim if (Code.empty()) { 98259701Sdim Result.Kind = TokenInfo::TK_Eof; 99259701Sdim Result.Text = ""; 100259701Sdim return Result; 101259701Sdim } 102259701Sdim 103259701Sdim switch (Code[0]) { 104259701Sdim case ',': 105259701Sdim Result.Kind = TokenInfo::TK_Comma; 106259701Sdim Result.Text = Code.substr(0, 1); 107259701Sdim Code = Code.drop_front(); 108259701Sdim break; 109259701Sdim case '.': 110259701Sdim Result.Kind = TokenInfo::TK_Period; 111259701Sdim Result.Text = Code.substr(0, 1); 112259701Sdim Code = Code.drop_front(); 113259701Sdim break; 114259701Sdim case '(': 115259701Sdim Result.Kind = TokenInfo::TK_OpenParen; 116259701Sdim Result.Text = Code.substr(0, 1); 117259701Sdim Code = Code.drop_front(); 118259701Sdim break; 119259701Sdim case ')': 120259701Sdim Result.Kind = TokenInfo::TK_CloseParen; 121259701Sdim Result.Text = Code.substr(0, 1); 122259701Sdim Code = Code.drop_front(); 123259701Sdim break; 124259701Sdim 125259701Sdim case '"': 126259701Sdim case '\'': 127259701Sdim // Parse a string literal. 128259701Sdim consumeStringLiteral(&Result); 129259701Sdim break; 130259701Sdim 131259701Sdim case '0': case '1': case '2': case '3': case '4': 132259701Sdim case '5': case '6': case '7': case '8': case '9': 133259701Sdim // Parse an unsigned literal. 134259701Sdim consumeUnsignedLiteral(&Result); 135259701Sdim break; 136259701Sdim 137259701Sdim default: 138259701Sdim if (isAlphanumeric(Code[0])) { 139259701Sdim // Parse an identifier 140259701Sdim size_t TokenLength = 1; 141276479Sdim while (1) { 142276479Sdim // A code completion location in/immediately after an identifier will 143276479Sdim // cause the portion of the identifier before the code completion 144276479Sdim // location to become a code completion token. 145276479Sdim if (CodeCompletionLocation == Code.data() + TokenLength) { 146276479Sdim CodeCompletionLocation = nullptr; 147276479Sdim Result.Kind = TokenInfo::TK_CodeCompletion; 148276479Sdim Result.Text = Code.substr(0, TokenLength); 149276479Sdim Code = Code.drop_front(TokenLength); 150276479Sdim return Result; 151276479Sdim } 152276479Sdim if (TokenLength == Code.size() || !isAlphanumeric(Code[TokenLength])) 153276479Sdim break; 154259701Sdim ++TokenLength; 155276479Sdim } 156259701Sdim Result.Kind = TokenInfo::TK_Ident; 157259701Sdim Result.Text = Code.substr(0, TokenLength); 158259701Sdim Code = Code.drop_front(TokenLength); 159259701Sdim } else { 160259701Sdim Result.Kind = TokenInfo::TK_InvalidChar; 161259701Sdim Result.Text = Code.substr(0, 1); 162259701Sdim Code = Code.drop_front(1); 163259701Sdim } 164259701Sdim break; 165259701Sdim } 166259701Sdim 167259701Sdim Result.Range.End = currentLocation(); 168259701Sdim return Result; 169259701Sdim } 170259701Sdim 171259701Sdim /// \brief Consume an unsigned literal. 172259701Sdim void consumeUnsignedLiteral(TokenInfo *Result) { 173259701Sdim unsigned Length = 1; 174259701Sdim if (Code.size() > 1) { 175259701Sdim // Consume the 'x' or 'b' radix modifier, if present. 176259701Sdim switch (toLowercase(Code[1])) { 177259701Sdim case 'x': case 'b': Length = 2; 178259701Sdim } 179259701Sdim } 180259701Sdim while (Length < Code.size() && isHexDigit(Code[Length])) 181259701Sdim ++Length; 182259701Sdim 183259701Sdim Result->Text = Code.substr(0, Length); 184259701Sdim Code = Code.drop_front(Length); 185259701Sdim 186259701Sdim unsigned Value; 187259701Sdim if (!Result->Text.getAsInteger(0, Value)) { 188259701Sdim Result->Kind = TokenInfo::TK_Literal; 189259701Sdim Result->Value = Value; 190259701Sdim } else { 191259701Sdim SourceRange Range; 192259701Sdim Range.Start = Result->Range.Start; 193259701Sdim Range.End = currentLocation(); 194259701Sdim Error->addError(Range, Error->ET_ParserUnsignedError) << Result->Text; 195259701Sdim Result->Kind = TokenInfo::TK_Error; 196259701Sdim } 197259701Sdim } 198259701Sdim 199259701Sdim /// \brief Consume a string literal. 200259701Sdim /// 201259701Sdim /// \c Code must be positioned at the start of the literal (the opening 202259701Sdim /// quote). Consumed until it finds the same closing quote character. 203259701Sdim void consumeStringLiteral(TokenInfo *Result) { 204259701Sdim bool InEscape = false; 205259701Sdim const char Marker = Code[0]; 206259701Sdim for (size_t Length = 1, Size = Code.size(); Length != Size; ++Length) { 207259701Sdim if (InEscape) { 208259701Sdim InEscape = false; 209259701Sdim continue; 210259701Sdim } 211259701Sdim if (Code[Length] == '\\') { 212259701Sdim InEscape = true; 213259701Sdim continue; 214259701Sdim } 215259701Sdim if (Code[Length] == Marker) { 216259701Sdim Result->Kind = TokenInfo::TK_Literal; 217259701Sdim Result->Text = Code.substr(0, Length + 1); 218259701Sdim Result->Value = Code.substr(1, Length - 1).str(); 219259701Sdim Code = Code.drop_front(Length + 1); 220259701Sdim return; 221259701Sdim } 222259701Sdim } 223259701Sdim 224259701Sdim StringRef ErrorText = Code; 225259701Sdim Code = Code.drop_front(Code.size()); 226259701Sdim SourceRange Range; 227259701Sdim Range.Start = Result->Range.Start; 228259701Sdim Range.End = currentLocation(); 229259701Sdim Error->addError(Range, Error->ET_ParserStringError) << ErrorText; 230259701Sdim Result->Kind = TokenInfo::TK_Error; 231259701Sdim } 232259701Sdim 233259701Sdim /// \brief Consume all leading whitespace from \c Code. 234259701Sdim void consumeWhitespace() { 235259701Sdim while (!Code.empty() && isWhitespace(Code[0])) { 236259701Sdim if (Code[0] == '\n') { 237259701Sdim ++Line; 238259701Sdim StartOfLine = Code.drop_front(); 239259701Sdim } 240259701Sdim Code = Code.drop_front(); 241259701Sdim } 242259701Sdim } 243259701Sdim 244259701Sdim SourceLocation currentLocation() { 245259701Sdim SourceLocation Location; 246259701Sdim Location.Line = Line; 247259701Sdim Location.Column = Code.data() - StartOfLine.data() + 1; 248259701Sdim return Location; 249259701Sdim } 250259701Sdim 251259701Sdim StringRef Code; 252259701Sdim StringRef StartOfLine; 253259701Sdim unsigned Line; 254259701Sdim Diagnostics *Error; 255259701Sdim TokenInfo NextToken; 256276479Sdim const char *CodeCompletionLocation; 257259701Sdim}; 258259701Sdim 259259701SdimParser::Sema::~Sema() {} 260259701Sdim 261276479SdimVariantValue Parser::Sema::getNamedValue(StringRef Name) { 262276479Sdim return VariantValue(); 263276479Sdim} 264276479Sdim 265276479Sdimstruct Parser::ScopedContextEntry { 266276479Sdim Parser *P; 267276479Sdim 268276479Sdim ScopedContextEntry(Parser *P, MatcherCtor C) : P(P) { 269276479Sdim P->ContextStack.push_back(std::make_pair(C, 0u)); 270276479Sdim } 271276479Sdim 272276479Sdim ~ScopedContextEntry() { 273276479Sdim P->ContextStack.pop_back(); 274276479Sdim } 275276479Sdim 276276479Sdim void nextArg() { 277276479Sdim ++P->ContextStack.back().second; 278276479Sdim } 279276479Sdim}; 280276479Sdim 281276479Sdim/// \brief Parse expressions that start with an identifier. 282276479Sdim/// 283276479Sdim/// This function can parse named values and matchers. 284276479Sdim/// In case of failure it will try to determine the user's intent to give 285276479Sdim/// an appropriate error message. 286276479Sdimbool Parser::parseIdentifierPrefixImpl(VariantValue *Value) { 287276479Sdim const TokenInfo NameToken = Tokenizer->consumeNextToken(); 288276479Sdim 289276479Sdim if (Tokenizer->nextTokenKind() != TokenInfo::TK_OpenParen) { 290276479Sdim // Parse as a named value. 291276479Sdim if (const VariantValue NamedValue = S->getNamedValue(NameToken.Text)) { 292276479Sdim *Value = NamedValue; 293276479Sdim return true; 294276479Sdim } 295276479Sdim // If the syntax is correct and the name is not a matcher either, report 296276479Sdim // unknown named value. 297276479Sdim if ((Tokenizer->nextTokenKind() == TokenInfo::TK_Comma || 298276479Sdim Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen || 299276479Sdim Tokenizer->nextTokenKind() == TokenInfo::TK_Eof) && 300276479Sdim !S->lookupMatcherCtor(NameToken.Text)) { 301276479Sdim Error->addError(NameToken.Range, Error->ET_RegistryValueNotFound) 302276479Sdim << NameToken.Text; 303276479Sdim return false; 304276479Sdim } 305276479Sdim // Otherwise, fallback to the matcher parser. 306276479Sdim } 307276479Sdim 308276479Sdim // Parse as a matcher expression. 309276479Sdim return parseMatcherExpressionImpl(NameToken, Value); 310276479Sdim} 311276479Sdim 312259701Sdim/// \brief Parse and validate a matcher expression. 313259701Sdim/// \return \c true on success, in which case \c Value has the matcher parsed. 314259701Sdim/// If the input is malformed, or some argument has an error, it 315259701Sdim/// returns \c false. 316276479Sdimbool Parser::parseMatcherExpressionImpl(const TokenInfo &NameToken, 317276479Sdim VariantValue *Value) { 318259701Sdim assert(NameToken.Kind == TokenInfo::TK_Ident); 319259701Sdim const TokenInfo OpenToken = Tokenizer->consumeNextToken(); 320259701Sdim if (OpenToken.Kind != TokenInfo::TK_OpenParen) { 321259701Sdim Error->addError(OpenToken.Range, Error->ET_ParserNoOpenParen) 322259701Sdim << OpenToken.Text; 323259701Sdim return false; 324259701Sdim } 325259701Sdim 326276479Sdim llvm::Optional<MatcherCtor> Ctor = S->lookupMatcherCtor(NameToken.Text); 327276479Sdim 328276479Sdim if (!Ctor) { 329276479Sdim Error->addError(NameToken.Range, Error->ET_RegistryMatcherNotFound) 330276479Sdim << NameToken.Text; 331276479Sdim // Do not return here. We need to continue to give completion suggestions. 332276479Sdim } 333276479Sdim 334259701Sdim std::vector<ParserValue> Args; 335259701Sdim TokenInfo EndToken; 336276479Sdim 337276479Sdim { 338276479Sdim ScopedContextEntry SCE(this, Ctor ? *Ctor : nullptr); 339276479Sdim 340276479Sdim while (Tokenizer->nextTokenKind() != TokenInfo::TK_Eof) { 341276479Sdim if (Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen) { 342276479Sdim // End of args. 343276479Sdim EndToken = Tokenizer->consumeNextToken(); 344276479Sdim break; 345276479Sdim } 346276479Sdim if (Args.size() > 0) { 347276479Sdim // We must find a , token to continue. 348276479Sdim const TokenInfo CommaToken = Tokenizer->consumeNextToken(); 349276479Sdim if (CommaToken.Kind != TokenInfo::TK_Comma) { 350276479Sdim Error->addError(CommaToken.Range, Error->ET_ParserNoComma) 351276479Sdim << CommaToken.Text; 352276479Sdim return false; 353276479Sdim } 354276479Sdim } 355276479Sdim 356276479Sdim Diagnostics::Context Ctx(Diagnostics::Context::MatcherArg, Error, 357276479Sdim NameToken.Text, NameToken.Range, 358276479Sdim Args.size() + 1); 359276479Sdim ParserValue ArgValue; 360276479Sdim ArgValue.Text = Tokenizer->peekNextToken().Text; 361276479Sdim ArgValue.Range = Tokenizer->peekNextToken().Range; 362276479Sdim if (!parseExpressionImpl(&ArgValue.Value)) { 363259701Sdim return false; 364259701Sdim } 365276479Sdim 366276479Sdim Args.push_back(ArgValue); 367276479Sdim SCE.nextArg(); 368259701Sdim } 369259701Sdim } 370259701Sdim 371259701Sdim if (EndToken.Kind == TokenInfo::TK_Eof) { 372259701Sdim Error->addError(OpenToken.Range, Error->ET_ParserNoCloseParen); 373259701Sdim return false; 374259701Sdim } 375259701Sdim 376259701Sdim std::string BindID; 377259701Sdim if (Tokenizer->peekNextToken().Kind == TokenInfo::TK_Period) { 378259701Sdim // Parse .bind("foo") 379259701Sdim Tokenizer->consumeNextToken(); // consume the period. 380259701Sdim const TokenInfo BindToken = Tokenizer->consumeNextToken(); 381276479Sdim if (BindToken.Kind == TokenInfo::TK_CodeCompletion) { 382276479Sdim addCompletion(BindToken, "bind(\"", "bind"); 383276479Sdim return false; 384276479Sdim } 385276479Sdim 386259701Sdim const TokenInfo OpenToken = Tokenizer->consumeNextToken(); 387259701Sdim const TokenInfo IDToken = Tokenizer->consumeNextToken(); 388259701Sdim const TokenInfo CloseToken = Tokenizer->consumeNextToken(); 389259701Sdim 390259701Sdim // TODO: We could use different error codes for each/some to be more 391259701Sdim // explicit about the syntax error. 392259701Sdim if (BindToken.Kind != TokenInfo::TK_Ident || 393259701Sdim BindToken.Text != TokenInfo::ID_Bind) { 394259701Sdim Error->addError(BindToken.Range, Error->ET_ParserMalformedBindExpr); 395259701Sdim return false; 396259701Sdim } 397259701Sdim if (OpenToken.Kind != TokenInfo::TK_OpenParen) { 398259701Sdim Error->addError(OpenToken.Range, Error->ET_ParserMalformedBindExpr); 399259701Sdim return false; 400259701Sdim } 401259701Sdim if (IDToken.Kind != TokenInfo::TK_Literal || !IDToken.Value.isString()) { 402259701Sdim Error->addError(IDToken.Range, Error->ET_ParserMalformedBindExpr); 403259701Sdim return false; 404259701Sdim } 405259701Sdim if (CloseToken.Kind != TokenInfo::TK_CloseParen) { 406259701Sdim Error->addError(CloseToken.Range, Error->ET_ParserMalformedBindExpr); 407259701Sdim return false; 408259701Sdim } 409259701Sdim BindID = IDToken.Value.getString(); 410259701Sdim } 411259701Sdim 412276479Sdim if (!Ctor) 413276479Sdim return false; 414276479Sdim 415259701Sdim // Merge the start and end infos. 416259701Sdim Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error, 417259701Sdim NameToken.Text, NameToken.Range); 418259701Sdim SourceRange MatcherRange = NameToken.Range; 419259701Sdim MatcherRange.End = EndToken.Range.End; 420259701Sdim VariantMatcher Result = S->actOnMatcherExpression( 421276479Sdim *Ctor, MatcherRange, BindID, Args, Error); 422259701Sdim if (Result.isNull()) return false; 423259701Sdim 424259701Sdim *Value = Result; 425259701Sdim return true; 426259701Sdim} 427259701Sdim 428276479Sdim// If the prefix of this completion matches the completion token, add it to 429276479Sdim// Completions minus the prefix. 430276479Sdimvoid Parser::addCompletion(const TokenInfo &CompToken, StringRef TypedText, 431276479Sdim StringRef Decl) { 432276479Sdim if (TypedText.size() >= CompToken.Text.size() && 433276479Sdim TypedText.substr(0, CompToken.Text.size()) == CompToken.Text) { 434276479Sdim Completions.push_back( 435276479Sdim MatcherCompletion(TypedText.substr(CompToken.Text.size()), Decl)); 436276479Sdim } 437276479Sdim} 438276479Sdim 439276479Sdimvoid Parser::addExpressionCompletions() { 440276479Sdim const TokenInfo CompToken = Tokenizer->consumeNextToken(); 441276479Sdim assert(CompToken.Kind == TokenInfo::TK_CodeCompletion); 442276479Sdim 443276479Sdim // We cannot complete code if there is an invalid element on the context 444276479Sdim // stack. 445276479Sdim for (ContextStackTy::iterator I = ContextStack.begin(), 446276479Sdim E = ContextStack.end(); 447276479Sdim I != E; ++I) { 448276479Sdim if (!I->first) 449276479Sdim return; 450276479Sdim } 451276479Sdim 452276479Sdim std::vector<MatcherCompletion> RegCompletions = 453276479Sdim Registry::getCompletions(ContextStack); 454276479Sdim for (std::vector<MatcherCompletion>::iterator I = RegCompletions.begin(), 455276479Sdim E = RegCompletions.end(); 456276479Sdim I != E; ++I) { 457276479Sdim addCompletion(CompToken, I->TypedText, I->MatcherDecl); 458276479Sdim } 459276479Sdim} 460276479Sdim 461259701Sdim/// \brief Parse an <Expresssion> 462259701Sdimbool Parser::parseExpressionImpl(VariantValue *Value) { 463259701Sdim switch (Tokenizer->nextTokenKind()) { 464259701Sdim case TokenInfo::TK_Literal: 465259701Sdim *Value = Tokenizer->consumeNextToken().Value; 466259701Sdim return true; 467259701Sdim 468259701Sdim case TokenInfo::TK_Ident: 469276479Sdim return parseIdentifierPrefixImpl(Value); 470259701Sdim 471276479Sdim case TokenInfo::TK_CodeCompletion: 472276479Sdim addExpressionCompletions(); 473276479Sdim return false; 474276479Sdim 475259701Sdim case TokenInfo::TK_Eof: 476259701Sdim Error->addError(Tokenizer->consumeNextToken().Range, 477259701Sdim Error->ET_ParserNoCode); 478259701Sdim return false; 479259701Sdim 480259701Sdim case TokenInfo::TK_Error: 481259701Sdim // This error was already reported by the tokenizer. 482259701Sdim return false; 483259701Sdim 484259701Sdim case TokenInfo::TK_OpenParen: 485259701Sdim case TokenInfo::TK_CloseParen: 486259701Sdim case TokenInfo::TK_Comma: 487259701Sdim case TokenInfo::TK_Period: 488259701Sdim case TokenInfo::TK_InvalidChar: 489259701Sdim const TokenInfo Token = Tokenizer->consumeNextToken(); 490259701Sdim Error->addError(Token.Range, Error->ET_ParserInvalidToken) << Token.Text; 491259701Sdim return false; 492259701Sdim } 493259701Sdim 494259701Sdim llvm_unreachable("Unknown token kind."); 495259701Sdim} 496259701Sdim 497259701SdimParser::Parser(CodeTokenizer *Tokenizer, Sema *S, 498259701Sdim Diagnostics *Error) 499259701Sdim : Tokenizer(Tokenizer), S(S), Error(Error) {} 500259701Sdim 501276479SdimParser::RegistrySema::~RegistrySema() {} 502276479Sdim 503276479Sdimllvm::Optional<MatcherCtor> 504276479SdimParser::RegistrySema::lookupMatcherCtor(StringRef MatcherName) { 505276479Sdim return Registry::lookupMatcherCtor(MatcherName); 506276479Sdim} 507276479Sdim 508276479SdimVariantMatcher Parser::RegistrySema::actOnMatcherExpression( 509276479Sdim MatcherCtor Ctor, const SourceRange &NameRange, StringRef BindID, 510276479Sdim ArrayRef<ParserValue> Args, Diagnostics *Error) { 511276479Sdim if (BindID.empty()) { 512276479Sdim return Registry::constructMatcher(Ctor, NameRange, Args, Error); 513276479Sdim } else { 514276479Sdim return Registry::constructBoundMatcher(Ctor, NameRange, BindID, Args, 515276479Sdim Error); 516259701Sdim } 517276479Sdim} 518259701Sdim 519259701Sdimbool Parser::parseExpression(StringRef Code, VariantValue *Value, 520259701Sdim Diagnostics *Error) { 521259701Sdim RegistrySema S; 522259701Sdim return parseExpression(Code, &S, Value, Error); 523259701Sdim} 524259701Sdim 525259701Sdimbool Parser::parseExpression(StringRef Code, Sema *S, 526259701Sdim VariantValue *Value, Diagnostics *Error) { 527259701Sdim CodeTokenizer Tokenizer(Code, Error); 528259701Sdim if (!Parser(&Tokenizer, S, Error).parseExpressionImpl(Value)) return false; 529259701Sdim if (Tokenizer.peekNextToken().Kind != TokenInfo::TK_Eof) { 530259701Sdim Error->addError(Tokenizer.peekNextToken().Range, 531259701Sdim Error->ET_ParserTrailingCode); 532259701Sdim return false; 533259701Sdim } 534259701Sdim return true; 535259701Sdim} 536259701Sdim 537276479Sdimstd::vector<MatcherCompletion> 538276479SdimParser::completeExpression(StringRef Code, unsigned CompletionOffset) { 539276479Sdim Diagnostics Error; 540276479Sdim CodeTokenizer Tokenizer(Code, &Error, CompletionOffset); 541276479Sdim RegistrySema S; 542276479Sdim Parser P(&Tokenizer, &S, &Error); 543276479Sdim VariantValue Dummy; 544276479Sdim P.parseExpressionImpl(&Dummy); 545276479Sdim 546276479Sdim return P.Completions; 547276479Sdim} 548276479Sdim 549259701Sdimllvm::Optional<DynTypedMatcher> 550259701SdimParser::parseMatcherExpression(StringRef Code, Diagnostics *Error) { 551259701Sdim RegistrySema S; 552259701Sdim return parseMatcherExpression(Code, &S, Error); 553259701Sdim} 554259701Sdim 555259701Sdimllvm::Optional<DynTypedMatcher> 556259701SdimParser::parseMatcherExpression(StringRef Code, Parser::Sema *S, 557259701Sdim Diagnostics *Error) { 558259701Sdim VariantValue Value; 559259701Sdim if (!parseExpression(Code, S, &Value, Error)) 560259701Sdim return llvm::Optional<DynTypedMatcher>(); 561259701Sdim if (!Value.isMatcher()) { 562259701Sdim Error->addError(SourceRange(), Error->ET_ParserNotAMatcher); 563259701Sdim return llvm::Optional<DynTypedMatcher>(); 564259701Sdim } 565259701Sdim llvm::Optional<DynTypedMatcher> Result = 566259701Sdim Value.getMatcher().getSingleMatcher(); 567259701Sdim if (!Result.hasValue()) { 568259701Sdim Error->addError(SourceRange(), Error->ET_ParserOverloadedType) 569259701Sdim << Value.getTypeAsString(); 570259701Sdim } 571259701Sdim return Result; 572259701Sdim} 573259701Sdim 574259701Sdim} // namespace dynamic 575259701Sdim} // namespace ast_matchers 576259701Sdim} // namespace clang 577