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