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