clang  6.0.0svn
Parser.cpp
Go to the documentation of this file.
1 //===--- Parser.cpp - Matcher expression parser -----*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief Recursive parser implementation for the matcher expression grammar.
12 ///
13 //===----------------------------------------------------------------------===//
14 
17 #include "clang/Basic/CharInfo.h"
18 #include "llvm/ADT/Optional.h"
19 #include "llvm/Support/ManagedStatic.h"
20 #include <string>
21 #include <vector>
22 
23 namespace clang {
24 namespace ast_matchers {
25 namespace dynamic {
26 
27 /// \brief Simple structure to hold information for one token from the parser.
29  /// \brief Different possible tokens.
30  enum TokenKind {
41  };
42 
43  /// \brief Some known identifiers.
44  static const char* const ID_Bind;
45 
46  TokenInfo() : Text(), Kind(TK_Eof), Range(), Value() {}
47 
48  StringRef Text;
52 };
53 
54 const char* const Parser::TokenInfo::ID_Bind = "bind";
55 
56 /// \brief Simple tokenizer for the parser.
58 public:
59  explicit CodeTokenizer(StringRef MatcherCode, Diagnostics *Error)
60  : Code(MatcherCode), StartOfLine(MatcherCode), Line(1), Error(Error),
61  CodeCompletionLocation(nullptr) {
62  NextToken = getNextToken();
63  }
64 
65  CodeTokenizer(StringRef MatcherCode, Diagnostics *Error,
66  unsigned CodeCompletionOffset)
67  : Code(MatcherCode), StartOfLine(MatcherCode), Line(1), Error(Error),
68  CodeCompletionLocation(MatcherCode.data() + CodeCompletionOffset) {
69  NextToken = getNextToken();
70  }
71 
72  /// \brief Returns but doesn't consume the next token.
73  const TokenInfo &peekNextToken() const { return NextToken; }
74 
75  /// \brief Consumes and returns the next token.
77  TokenInfo ThisToken = NextToken;
78  NextToken = getNextToken();
79  return ThisToken;
80  }
81 
82  TokenInfo::TokenKind nextTokenKind() const { return NextToken.Kind; }
83 
84 private:
85  TokenInfo getNextToken() {
86  consumeWhitespace();
87  TokenInfo Result;
88  Result.Range.Start = currentLocation();
89 
90  if (CodeCompletionLocation && CodeCompletionLocation <= Code.data()) {
92  Result.Text = StringRef(CodeCompletionLocation, 0);
93  CodeCompletionLocation = nullptr;
94  return Result;
95  }
96 
97  if (Code.empty()) {
98  Result.Kind = TokenInfo::TK_Eof;
99  Result.Text = "";
100  return Result;
101  }
102 
103  switch (Code[0]) {
104  case ',':
105  Result.Kind = TokenInfo::TK_Comma;
106  Result.Text = Code.substr(0, 1);
107  Code = Code.drop_front();
108  break;
109  case '.':
110  Result.Kind = TokenInfo::TK_Period;
111  Result.Text = Code.substr(0, 1);
112  Code = Code.drop_front();
113  break;
114  case '(':
115  Result.Kind = TokenInfo::TK_OpenParen;
116  Result.Text = Code.substr(0, 1);
117  Code = Code.drop_front();
118  break;
119  case ')':
121  Result.Text = Code.substr(0, 1);
122  Code = Code.drop_front();
123  break;
124 
125  case '"':
126  case '\'':
127  // Parse a string literal.
128  consumeStringLiteral(&Result);
129  break;
130 
131  case '0': case '1': case '2': case '3': case '4':
132  case '5': case '6': case '7': case '8': case '9':
133  // Parse an unsigned and float literal.
134  consumeNumberLiteral(&Result);
135  break;
136 
137  default:
138  if (isAlphanumeric(Code[0])) {
139  // Parse an identifier
140  size_t TokenLength = 1;
141  while (1) {
142  // A code completion location in/immediately after an identifier will
143  // cause the portion of the identifier before the code completion
144  // location to become a code completion token.
145  if (CodeCompletionLocation == Code.data() + TokenLength) {
146  CodeCompletionLocation = nullptr;
148  Result.Text = Code.substr(0, TokenLength);
149  Code = Code.drop_front(TokenLength);
150  return Result;
151  }
152  if (TokenLength == Code.size() || !isAlphanumeric(Code[TokenLength]))
153  break;
154  ++TokenLength;
155  }
156  if (TokenLength == 4 && Code.startswith("true")) {
157  Result.Kind = TokenInfo::TK_Literal;
158  Result.Value = true;
159  } else if (TokenLength == 5 && Code.startswith("false")) {
160  Result.Kind = TokenInfo::TK_Literal;
161  Result.Value = false;
162  } else {
163  Result.Kind = TokenInfo::TK_Ident;
164  Result.Text = Code.substr(0, TokenLength);
165  }
166  Code = Code.drop_front(TokenLength);
167  } else {
169  Result.Text = Code.substr(0, 1);
170  Code = Code.drop_front(1);
171  }
172  break;
173  }
174 
175  Result.Range.End = currentLocation();
176  return Result;
177  }
178 
179  /// \brief Consume an unsigned and float literal.
180  void consumeNumberLiteral(TokenInfo *Result) {
181  bool isFloatingLiteral = false;
182  unsigned Length = 1;
183  if (Code.size() > 1) {
184  // Consume the 'x' or 'b' radix modifier, if present.
185  switch (toLowercase(Code[1])) {
186  case 'x': case 'b': Length = 2;
187  }
188  }
189  while (Length < Code.size() && isHexDigit(Code[Length]))
190  ++Length;
191 
192  // Try to recognize a floating point literal.
193  while (Length < Code.size()) {
194  char c = Code[Length];
195  if (c == '-' || c == '+' || c == '.' || isHexDigit(c)) {
196  isFloatingLiteral = true;
197  Length++;
198  } else {
199  break;
200  }
201  }
202 
203  Result->Text = Code.substr(0, Length);
204  Code = Code.drop_front(Length);
205 
206  if (isFloatingLiteral) {
207  char *end;
208  errno = 0;
209  std::string Text = Result->Text.str();
210  double doubleValue = strtod(Text.c_str(), &end);
211  if (*end == 0 && errno == 0) {
212  Result->Kind = TokenInfo::TK_Literal;
213  Result->Value = doubleValue;
214  return;
215  }
216  } else {
217  unsigned Value;
218  if (!Result->Text.getAsInteger(0, Value)) {
219  Result->Kind = TokenInfo::TK_Literal;
220  Result->Value = Value;
221  return;
222  }
223  }
224 
226  Range.Start = Result->Range.Start;
227  Range.End = currentLocation();
228  Error->addError(Range, Error->ET_ParserNumberError) << Result->Text;
229  Result->Kind = TokenInfo::TK_Error;
230  }
231 
232  /// \brief Consume a string literal.
233  ///
234  /// \c Code must be positioned at the start of the literal (the opening
235  /// quote). Consumed until it finds the same closing quote character.
236  void consumeStringLiteral(TokenInfo *Result) {
237  bool InEscape = false;
238  const char Marker = Code[0];
239  for (size_t Length = 1, Size = Code.size(); Length != Size; ++Length) {
240  if (InEscape) {
241  InEscape = false;
242  continue;
243  }
244  if (Code[Length] == '\\') {
245  InEscape = true;
246  continue;
247  }
248  if (Code[Length] == Marker) {
249  Result->Kind = TokenInfo::TK_Literal;
250  Result->Text = Code.substr(0, Length + 1);
251  Result->Value = Code.substr(1, Length - 1);
252  Code = Code.drop_front(Length + 1);
253  return;
254  }
255  }
256 
257  StringRef ErrorText = Code;
258  Code = Code.drop_front(Code.size());
260  Range.Start = Result->Range.Start;
261  Range.End = currentLocation();
262  Error->addError(Range, Error->ET_ParserStringError) << ErrorText;
263  Result->Kind = TokenInfo::TK_Error;
264  }
265 
266  /// \brief Consume all leading whitespace from \c Code.
267  void consumeWhitespace() {
268  while (!Code.empty() && isWhitespace(Code[0])) {
269  if (Code[0] == '\n') {
270  ++Line;
271  StartOfLine = Code.drop_front();
272  }
273  Code = Code.drop_front();
274  }
275  }
276 
277  SourceLocation currentLocation() {
278  SourceLocation Location;
279  Location.Line = Line;
280  Location.Column = Code.data() - StartOfLine.data() + 1;
281  return Location;
282  }
283 
284  StringRef Code;
285  StringRef StartOfLine;
286  unsigned Line;
287  Diagnostics *Error;
288  TokenInfo NextToken;
289  const char *CodeCompletionLocation;
290 };
291 
293 
295  llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context) {
296  return std::vector<ArgKind>();
297 }
298 
299 std::vector<MatcherCompletion>
301  return std::vector<MatcherCompletion>();
302 }
303 
306 
308  P->ContextStack.push_back(std::make_pair(C, 0u));
309  }
310 
312  P->ContextStack.pop_back();
313  }
314 
315  void nextArg() {
316  ++P->ContextStack.back().second;
317  }
318 };
319 
320 /// \brief Parse expressions that start with an identifier.
321 ///
322 /// This function can parse named values and matchers.
323 /// In case of failure it will try to determine the user's intent to give
324 /// an appropriate error message.
325 bool Parser::parseIdentifierPrefixImpl(VariantValue *Value) {
326  const TokenInfo NameToken = Tokenizer->consumeNextToken();
327 
328  if (Tokenizer->nextTokenKind() != TokenInfo::TK_OpenParen) {
329  // Parse as a named value.
330  if (const VariantValue NamedValue =
331  NamedValues ? NamedValues->lookup(NameToken.Text)
332  : VariantValue()) {
333  *Value = NamedValue;
334  return true;
335  }
336  // If the syntax is correct and the name is not a matcher either, report
337  // unknown named value.
338  if ((Tokenizer->nextTokenKind() == TokenInfo::TK_Comma ||
339  Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen ||
340  Tokenizer->nextTokenKind() == TokenInfo::TK_Eof) &&
341  !S->lookupMatcherCtor(NameToken.Text)) {
342  Error->addError(NameToken.Range, Error->ET_RegistryValueNotFound)
343  << NameToken.Text;
344  return false;
345  }
346  // Otherwise, fallback to the matcher parser.
347  }
348 
349  // Parse as a matcher expression.
350  return parseMatcherExpressionImpl(NameToken, Value);
351 }
352 
353 /// \brief Parse and validate a matcher expression.
354 /// \return \c true on success, in which case \c Value has the matcher parsed.
355 /// If the input is malformed, or some argument has an error, it
356 /// returns \c false.
357 bool Parser::parseMatcherExpressionImpl(const TokenInfo &NameToken,
358  VariantValue *Value) {
359  assert(NameToken.Kind == TokenInfo::TK_Ident);
360  const TokenInfo OpenToken = Tokenizer->consumeNextToken();
361  if (OpenToken.Kind != TokenInfo::TK_OpenParen) {
362  Error->addError(OpenToken.Range, Error->ET_ParserNoOpenParen)
363  << OpenToken.Text;
364  return false;
365  }
366 
367  llvm::Optional<MatcherCtor> Ctor = S->lookupMatcherCtor(NameToken.Text);
368 
369  if (!Ctor) {
370  Error->addError(NameToken.Range, Error->ET_RegistryMatcherNotFound)
371  << NameToken.Text;
372  // Do not return here. We need to continue to give completion suggestions.
373  }
374 
375  std::vector<ParserValue> Args;
376  TokenInfo EndToken;
377 
378  {
379  ScopedContextEntry SCE(this, Ctor ? *Ctor : nullptr);
380 
381  while (Tokenizer->nextTokenKind() != TokenInfo::TK_Eof) {
382  if (Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen) {
383  // End of args.
384  EndToken = Tokenizer->consumeNextToken();
385  break;
386  }
387  if (Args.size() > 0) {
388  // We must find a , token to continue.
389  const TokenInfo CommaToken = Tokenizer->consumeNextToken();
390  if (CommaToken.Kind != TokenInfo::TK_Comma) {
391  Error->addError(CommaToken.Range, Error->ET_ParserNoComma)
392  << CommaToken.Text;
393  return false;
394  }
395  }
396 
398  NameToken.Text, NameToken.Range,
399  Args.size() + 1);
400  ParserValue ArgValue;
401  ArgValue.Text = Tokenizer->peekNextToken().Text;
402  ArgValue.Range = Tokenizer->peekNextToken().Range;
403  if (!parseExpressionImpl(&ArgValue.Value)) {
404  return false;
405  }
406 
407  Args.push_back(ArgValue);
408  SCE.nextArg();
409  }
410  }
411 
412  if (EndToken.Kind == TokenInfo::TK_Eof) {
413  Error->addError(OpenToken.Range, Error->ET_ParserNoCloseParen);
414  return false;
415  }
416 
417  std::string BindID;
418  if (Tokenizer->peekNextToken().Kind == TokenInfo::TK_Period) {
419  // Parse .bind("foo")
420  Tokenizer->consumeNextToken(); // consume the period.
421  const TokenInfo BindToken = Tokenizer->consumeNextToken();
422  if (BindToken.Kind == TokenInfo::TK_CodeCompletion) {
423  addCompletion(BindToken, MatcherCompletion("bind(\"", "bind", 1));
424  return false;
425  }
426 
427  const TokenInfo OpenToken = Tokenizer->consumeNextToken();
428  const TokenInfo IDToken = Tokenizer->consumeNextToken();
429  const TokenInfo CloseToken = Tokenizer->consumeNextToken();
430 
431  // TODO: We could use different error codes for each/some to be more
432  // explicit about the syntax error.
433  if (BindToken.Kind != TokenInfo::TK_Ident ||
434  BindToken.Text != TokenInfo::ID_Bind) {
435  Error->addError(BindToken.Range, Error->ET_ParserMalformedBindExpr);
436  return false;
437  }
438  if (OpenToken.Kind != TokenInfo::TK_OpenParen) {
439  Error->addError(OpenToken.Range, Error->ET_ParserMalformedBindExpr);
440  return false;
441  }
442  if (IDToken.Kind != TokenInfo::TK_Literal || !IDToken.Value.isString()) {
443  Error->addError(IDToken.Range, Error->ET_ParserMalformedBindExpr);
444  return false;
445  }
446  if (CloseToken.Kind != TokenInfo::TK_CloseParen) {
447  Error->addError(CloseToken.Range, Error->ET_ParserMalformedBindExpr);
448  return false;
449  }
450  BindID = IDToken.Value.getString();
451  }
452 
453  if (!Ctor)
454  return false;
455 
456  // Merge the start and end infos.
458  NameToken.Text, NameToken.Range);
459  SourceRange MatcherRange = NameToken.Range;
460  MatcherRange.End = EndToken.Range.End;
461  VariantMatcher Result = S->actOnMatcherExpression(
462  *Ctor, MatcherRange, BindID, Args, Error);
463  if (Result.isNull()) return false;
464 
465  *Value = Result;
466  return true;
467 }
468 
469 // If the prefix of this completion matches the completion token, add it to
470 // Completions minus the prefix.
471 void Parser::addCompletion(const TokenInfo &CompToken,
472  const MatcherCompletion& Completion) {
473  if (StringRef(Completion.TypedText).startswith(CompToken.Text) &&
474  Completion.Specificity > 0) {
475  Completions.emplace_back(Completion.TypedText.substr(CompToken.Text.size()),
476  Completion.MatcherDecl, Completion.Specificity);
477  }
478 }
479 
480 std::vector<MatcherCompletion> Parser::getNamedValueCompletions(
481  ArrayRef<ArgKind> AcceptedTypes) {
482  if (!NamedValues) return std::vector<MatcherCompletion>();
483  std::vector<MatcherCompletion> Result;
484  for (const auto &Entry : *NamedValues) {
485  unsigned Specificity;
486  if (Entry.getValue().isConvertibleTo(AcceptedTypes, &Specificity)) {
487  std::string Decl =
488  (Entry.getValue().getTypeAsString() + " " + Entry.getKey()).str();
489  Result.emplace_back(Entry.getKey(), Decl, Specificity);
490  }
491  }
492  return Result;
493 }
494 
495 void Parser::addExpressionCompletions() {
496  const TokenInfo CompToken = Tokenizer->consumeNextToken();
497  assert(CompToken.Kind == TokenInfo::TK_CodeCompletion);
498 
499  // We cannot complete code if there is an invalid element on the context
500  // stack.
501  for (ContextStackTy::iterator I = ContextStack.begin(),
502  E = ContextStack.end();
503  I != E; ++I) {
504  if (!I->first)
505  return;
506  }
507 
508  auto AcceptedTypes = S->getAcceptedCompletionTypes(ContextStack);
509  for (const auto &Completion : S->getMatcherCompletions(AcceptedTypes)) {
510  addCompletion(CompToken, Completion);
511  }
512 
513  for (const auto &Completion : getNamedValueCompletions(AcceptedTypes)) {
514  addCompletion(CompToken, Completion);
515  }
516 }
517 
518 /// \brief Parse an <Expresssion>
519 bool Parser::parseExpressionImpl(VariantValue *Value) {
520  switch (Tokenizer->nextTokenKind()) {
522  *Value = Tokenizer->consumeNextToken().Value;
523  return true;
524 
525  case TokenInfo::TK_Ident:
526  return parseIdentifierPrefixImpl(Value);
527 
529  addExpressionCompletions();
530  return false;
531 
532  case TokenInfo::TK_Eof:
533  Error->addError(Tokenizer->consumeNextToken().Range,
534  Error->ET_ParserNoCode);
535  return false;
536 
537  case TokenInfo::TK_Error:
538  // This error was already reported by the tokenizer.
539  return false;
540 
543  case TokenInfo::TK_Comma:
546  const TokenInfo Token = Tokenizer->consumeNextToken();
547  Error->addError(Token.Range, Error->ET_ParserInvalidToken) << Token.Text;
548  return false;
549  }
550 
551  llvm_unreachable("Unknown token kind.");
552 }
553 
554 static llvm::ManagedStatic<Parser::RegistrySema> DefaultRegistrySema;
555 
556 Parser::Parser(CodeTokenizer *Tokenizer, Sema *S,
557  const NamedValueMap *NamedValues, Diagnostics *Error)
558  : Tokenizer(Tokenizer), S(S ? S : &*DefaultRegistrySema),
559  NamedValues(NamedValues), Error(Error) {}
560 
562 
565  return Registry::lookupMatcherCtor(MatcherName);
566 }
567 
569  MatcherCtor Ctor, SourceRange NameRange, StringRef BindID,
570  ArrayRef<ParserValue> Args, Diagnostics *Error) {
571  if (BindID.empty()) {
572  return Registry::constructMatcher(Ctor, NameRange, Args, Error);
573  } else {
574  return Registry::constructBoundMatcher(Ctor, NameRange, BindID, Args,
575  Error);
576  }
577 }
578 
580  ArrayRef<std::pair<MatcherCtor, unsigned>> Context) {
581  return Registry::getAcceptedCompletionTypes(Context);
582 }
583 
584 std::vector<MatcherCompletion> Parser::RegistrySema::getMatcherCompletions(
585  ArrayRef<ArgKind> AcceptedTypes) {
586  return Registry::getMatcherCompletions(AcceptedTypes);
587 }
588 
589 bool Parser::parseExpression(StringRef Code, Sema *S,
590  const NamedValueMap *NamedValues,
591  VariantValue *Value, Diagnostics *Error) {
592  CodeTokenizer Tokenizer(Code, Error);
593  if (!Parser(&Tokenizer, S, NamedValues, Error).parseExpressionImpl(Value))
594  return false;
595  if (Tokenizer.peekNextToken().Kind != TokenInfo::TK_Eof) {
596  Error->addError(Tokenizer.peekNextToken().Range,
597  Error->ET_ParserTrailingCode);
598  return false;
599  }
600  return true;
601 }
602 
603 std::vector<MatcherCompletion>
604 Parser::completeExpression(StringRef Code, unsigned CompletionOffset, Sema *S,
605  const NamedValueMap *NamedValues) {
606  Diagnostics Error;
607  CodeTokenizer Tokenizer(Code, &Error, CompletionOffset);
608  Parser P(&Tokenizer, S, NamedValues, &Error);
609  VariantValue Dummy;
610  P.parseExpressionImpl(&Dummy);
611 
612  // Sort by specificity, then by name.
613  std::sort(P.Completions.begin(), P.Completions.end(),
614  [](const MatcherCompletion &A, const MatcherCompletion &B) {
615  if (A.Specificity != B.Specificity)
616  return A.Specificity > B.Specificity;
617  return A.TypedText < B.TypedText;
618  });
619 
620  return P.Completions;
621 }
622 
625  const NamedValueMap *NamedValues,
626  Diagnostics *Error) {
628  if (!parseExpression(Code, S, NamedValues, &Value, Error))
630  if (!Value.isMatcher()) {
631  Error->addError(SourceRange(), Error->ET_ParserNotAMatcher);
633  }
635  Value.getMatcher().getSingleMatcher();
636  if (!Result.hasValue()) {
638  << Value.getTypeAsString();
639  }
640  return Result;
641 }
642 
643 } // namespace dynamic
644 } // namespace ast_matchers
645 } // namespace clang
static std::vector< MatcherCompletion > completeExpression(StringRef Code, unsigned CompletionOffset, Sema *S, const NamedValueMap *NamedValues)
Complete an expression at the given offset.
Definition: Parser.cpp:604
static VariantMatcher constructBoundMatcher(MatcherCtor Ctor, SourceRange NameRange, StringRef BindID, ArrayRef< ParserValue > Args, Diagnostics *Error)
Construct a matcher from the registry and bind it.
Definition: Registry.cpp:607
Simple matcher expression parser.
static std::vector< MatcherCompletion > getMatcherCompletions(ArrayRef< ArgKind > AcceptedTypes)
Compute the list of completions that match any of AcceptedTypes.
Definition: Registry.cpp:520
static LLVM_READONLY bool isWhitespace(unsigned char c)
Return true if this character is horizontal or vertical ASCII whitespace: &#39; &#39;, &#39;\t&#39;, &#39;\f&#39;, &#39;\v&#39;, &#39;\n&#39;, &#39;\r&#39;.
Definition: CharInfo.h:88
static bool parseExpression(StringRef Code, Sema *S, const NamedValueMap *NamedValues, VariantValue *Value, Diagnostics *Error)
Parse an expression.
Definition: Parser.cpp:589
Registry of all known matchers.
CodeTokenizer(StringRef MatcherCode, Diagnostics *Error)
Definition: Parser.cpp:59
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:81
CodeTokenizer(StringRef MatcherCode, Diagnostics *Error, unsigned CodeCompletionOffset)
Definition: Parser.cpp:65
StringRef P
llvm::Optional< DynTypedMatcher > getSingleMatcher() const
Return a single matcher, if there is no ambiguity.
Token - This structure provides full information about a lexed token.
Definition: Token.h:35
Simple tokenizer for the parser.
Definition: Parser.cpp:57
static std::vector< ArgKind > getAcceptedCompletionTypes(llvm::ArrayRef< std::pair< MatcherCtor, unsigned >> Context)
Compute the list of completion types for Context.
Definition: Registry.cpp:489
static const char *const ID_Bind
Some known identifiers.
Definition: Parser.cpp:44
Class defining a parser context.
Definition: Diagnostics.h:102
llvm::Optional< MatcherCtor > lookupMatcherCtor(StringRef MatcherName) override
Look up a matcher by name.
Definition: Parser.cpp:564
std::string MatcherDecl
The "declaration" of the matcher, with type information.
Definition: Registry.h:56
A VariantValue instance annotated with its parser context.
Definition: Diagnostics.h:43
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:274
static llvm::Optional< MatcherCtor > lookupMatcherCtor(StringRef MatcherName)
Look up a matcher in the registry by name,.
Definition: Registry.cpp:462
std::string getTypeAsString() const
String representation of the type of the value.
Matcher expression parser.
Definition: Parser.h:52
const AnnotatedLine * Line
TokenInfo::TokenKind nextTokenKind() const
Definition: Parser.cpp:82
VariantMatcher actOnMatcherExpression(MatcherCtor Ctor, SourceRange NameRange, StringRef BindID, ArrayRef< ParserValue > Args, Diagnostics *Error) override
Process a matcher expression.
Definition: Parser.cpp:568
Helper class to manage error messages.
Definition: Diagnostics.h:51
std::vector< ArgKind > getAcceptedCompletionTypes(llvm::ArrayRef< std::pair< MatcherCtor, unsigned >> Context) override
Compute the list of completion types for Context.
Definition: Parser.cpp:579
ArgStream addError(SourceRange Range, ErrorType Error)
Add an error to the diagnostics.
Definition: Diagnostics.cpp:66
static llvm::Optional< DynTypedMatcher > parseMatcherExpression(StringRef MatcherCode, Sema *S, const NamedValueMap *NamedValues, Diagnostics *Error)
Parse a matcher expression.
Definition: Parser.cpp:624
Kind
static LLVM_READONLY bool isAlphanumeric(unsigned char c)
Return true if this character is an ASCII letter or digit: [a-zA-Z0-9].
Definition: CharInfo.h:118
TokenKind
Different possible tokens.
Definition: Parser.cpp:30
const VariantMatcher & getMatcher() const
unsigned Specificity
Value corresponding to the "specificity" of the converted matcher.
Definition: Registry.h:63
const std::string & getString() const
std::string TypedText
The text to type to select this matcher.
Definition: Registry.h:53
static llvm::ManagedStatic< Parser::RegistrySema > DefaultRegistrySema
Definition: Parser.cpp:554
const TokenInfo & peekNextToken() const
Returns but doesn&#39;t consume the next token.
Definition: Parser.cpp:73
Dataflow Directional Tag Classes.
bool isMatcher() const
Matcher value functions.
Interface to connect the parser with the registry and more.
Definition: Parser.h:64
Simple structure to hold information for one token from the parser.
Definition: Parser.cpp:28
bool isNull() const
Whether the matcher is null.
Definition: VariantValue.h:159
virtual std::vector< ArgKind > getAcceptedCompletionTypes(llvm::ArrayRef< std::pair< MatcherCtor, unsigned >> Context)
Compute the list of completion types for Context.
Definition: Parser.cpp:294
std::vector< MatcherCompletion > getMatcherCompletions(llvm::ArrayRef< ArgKind > AcceptedTypes) override
Compute the list of completions that match any of AcceptedTypes.
Definition: Parser.cpp:584
static LLVM_READONLY char toLowercase(char c)
Converts the given ASCII character to its lowercase equivalent.
Definition: CharInfo.h:165
virtual std::vector< MatcherCompletion > getMatcherCompletions(llvm::ArrayRef< ArgKind > AcceptedTypes)
Compute the list of completions that match any of AcceptedTypes.
Definition: Parser.cpp:300
TokenInfo consumeNextToken()
Consumes and returns the next token.
Definition: Parser.cpp:76
llvm::StringMap< VariantValue > NamedValueMap
Definition: Parser.h:146
bool isString() const
String value functions.
static VariantMatcher constructMatcher(MatcherCtor Ctor, SourceRange NameRange, ArrayRef< ParserValue > Args, Diagnostics *Error)
Construct a matcher from the registry.
Definition: Registry.cpp:599
static LLVM_READONLY bool isHexDigit(unsigned char c)
Return true if this character is an ASCII hex digit: [0-9a-fA-F].
Definition: CharInfo.h:124