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_Comma;
115  Result.Text = Code.substr(0, 1);
116  Code = Code.drop_front();
117  break;
118  case '.':
119  Result.Kind = TokenInfo::TK_Period;
120  Result.Text = Code.substr(0, 1);
121  Code = Code.drop_front();
122  break;
123  case '(':
124  Result.Kind = TokenInfo::TK_OpenParen;
125  Result.Text = Code.substr(0, 1);
126  Code = Code.drop_front();
127  break;
128  case ')':
130  Result.Text = Code.substr(0, 1);
131  Code = Code.drop_front();
132  break;
133 
134  case '"':
135  case '\'':
136  // Parse a string literal.
137  consumeStringLiteral(&Result);
138  break;
139 
140  case '0': case '1': case '2': case '3': case '4':
141  case '5': case '6': case '7': case '8': case '9':
142  // Parse an unsigned and float literal.
143  consumeNumberLiteral(&Result);
144  break;
145 
146  default:
147  if (isAlphanumeric(Code[0])) {
148  // Parse an identifier
149  size_t TokenLength = 1;
150  while (true) {
151  // A code completion location in/immediately after an identifier will
152  // cause the portion of the identifier before the code completion
153  // location to become a code completion token.
154  if (CodeCompletionLocation == Code.data() + TokenLength) {
155  CodeCompletionLocation = nullptr;
157  Result.Text = Code.substr(0, TokenLength);
158  Code = Code.drop_front(TokenLength);
159  return Result;
160  }
161  if (TokenLength == Code.size() || !isAlphanumeric(Code[TokenLength]))
162  break;
163  ++TokenLength;
164  }
165  if (TokenLength == 4 && Code.startswith("true")) {
166  Result.Kind = TokenInfo::TK_Literal;
167  Result.Value = true;
168  } else if (TokenLength == 5 && Code.startswith("false")) {
169  Result.Kind = TokenInfo::TK_Literal;
170  Result.Value = false;
171  } else {
172  Result.Kind = TokenInfo::TK_Ident;
173  Result.Text = Code.substr(0, TokenLength);
174  }
175  Code = Code.drop_front(TokenLength);
176  } else {
178  Result.Text = Code.substr(0, 1);
179  Code = Code.drop_front(1);
180  }
181  break;
182  }
183 
184  Result.Range.End = currentLocation();
185  return Result;
186  }
187 
188  /// Consume an unsigned and float literal.
189  void consumeNumberLiteral(TokenInfo *Result) {
190  bool isFloatingLiteral = false;
191  unsigned Length = 1;
192  if (Code.size() > 1) {
193  // Consume the 'x' or 'b' radix modifier, if present.
194  switch (toLowercase(Code[1])) {
195  case 'x': case 'b': Length = 2;
196  }
197  }
198  while (Length < Code.size() && isHexDigit(Code[Length]))
199  ++Length;
200 
201  // Try to recognize a floating point literal.
202  while (Length < Code.size()) {
203  char c = Code[Length];
204  if (c == '-' || c == '+' || c == '.' || isHexDigit(c)) {
205  isFloatingLiteral = true;
206  Length++;
207  } else {
208  break;
209  }
210  }
211 
212  Result->Text = Code.substr(0, Length);
213  Code = Code.drop_front(Length);
214 
215  if (isFloatingLiteral) {
216  char *end;
217  errno = 0;
218  std::string Text = Result->Text.str();
219  double doubleValue = strtod(Text.c_str(), &end);
220  if (*end == 0 && errno == 0) {
221  Result->Kind = TokenInfo::TK_Literal;
222  Result->Value = doubleValue;
223  return;
224  }
225  } else {
226  unsigned Value;
227  if (!Result->Text.getAsInteger(0, Value)) {
228  Result->Kind = TokenInfo::TK_Literal;
229  Result->Value = Value;
230  return;
231  }
232  }
233 
235  Range.Start = Result->Range.Start;
236  Range.End = currentLocation();
237  Error->addError(Range, Error->ET_ParserNumberError) << Result->Text;
238  Result->Kind = TokenInfo::TK_Error;
239  }
240 
241  /// Consume a string literal.
242  ///
243  /// \c Code must be positioned at the start of the literal (the opening
244  /// quote). Consumed until it finds the same closing quote character.
245  void consumeStringLiteral(TokenInfo *Result) {
246  bool InEscape = false;
247  const char Marker = Code[0];
248  for (size_t Length = 1, Size = Code.size(); Length != Size; ++Length) {
249  if (InEscape) {
250  InEscape = false;
251  continue;
252  }
253  if (Code[Length] == '\\') {
254  InEscape = true;
255  continue;
256  }
257  if (Code[Length] == Marker) {
258  Result->Kind = TokenInfo::TK_Literal;
259  Result->Text = Code.substr(0, Length + 1);
260  Result->Value = Code.substr(1, Length - 1);
261  Code = Code.drop_front(Length + 1);
262  return;
263  }
264  }
265 
266  StringRef ErrorText = Code;
267  Code = Code.drop_front(Code.size());
269  Range.Start = Result->Range.Start;
270  Range.End = currentLocation();
271  Error->addError(Range, Error->ET_ParserStringError) << ErrorText;
272  Result->Kind = TokenInfo::TK_Error;
273  }
274 
275  /// Consume all leading whitespace from \c Code.
276  void consumeWhitespace() {
277  while (!Code.empty() && isWhitespace(Code[0])) {
278  if (Code[0] == '\n') {
279  ++Line;
280  StartOfLine = Code.drop_front();
281  }
282  Code = Code.drop_front();
283  }
284  }
285 
286  SourceLocation currentLocation() {
287  SourceLocation Location;
288  Location.Line = Line;
289  Location.Column = Code.data() - StartOfLine.data() + 1;
290  return Location;
291  }
292 
293  StringRef Code;
294  StringRef StartOfLine;
295  unsigned Line = 1;
296  Diagnostics *Error;
297  TokenInfo NextToken;
298  const char *CodeCompletionLocation = nullptr;
299 };
300 
301 Parser::Sema::~Sema() = default;
302 
304  llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context) {
305  return {};
306 }
307 
308 std::vector<MatcherCompletion>
310  return {};
311 }
312 
315 
317  P->ContextStack.push_back(std::make_pair(C, 0u));
318  }
319 
321  P->ContextStack.pop_back();
322  }
323 
324  void nextArg() {
325  ++P->ContextStack.back().second;
326  }
327 };
328 
329 /// Parse expressions that start with an identifier.
330 ///
331 /// This function can parse named values and matchers.
332 /// In case of failure it will try to determine the user's intent to give
333 /// an appropriate error message.
334 bool Parser::parseIdentifierPrefixImpl(VariantValue *Value) {
335  const TokenInfo NameToken = Tokenizer->consumeNextToken();
336 
337  if (Tokenizer->nextTokenKind() != TokenInfo::TK_OpenParen) {
338  // Parse as a named value.
339  if (const VariantValue NamedValue =
340  NamedValues ? NamedValues->lookup(NameToken.Text)
341  : VariantValue()) {
342 
343  if (Tokenizer->nextTokenKind() != TokenInfo::TK_Period) {
344  *Value = NamedValue;
345  return true;
346  }
347 
348  std::string BindID;
349  if (!parseBindID(BindID))
350  return false;
351 
352  assert(NamedValue.isMatcher());
354  NamedValue.getMatcher().getSingleMatcher();
355  if (Result.hasValue()) {
356  llvm::Optional<DynTypedMatcher> Bound = Result->tryBind(BindID);
357  if (Bound.hasValue()) {
358  *Value = VariantMatcher::SingleMatcher(*Bound);
359  return true;
360  }
361  }
362  return false;
363  }
364  // If the syntax is correct and the name is not a matcher either, report
365  // unknown named value.
366  if ((Tokenizer->nextTokenKind() == TokenInfo::TK_Comma ||
367  Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen ||
368  Tokenizer->nextTokenKind() == TokenInfo::TK_Eof) &&
369  !S->lookupMatcherCtor(NameToken.Text)) {
370  Error->addError(NameToken.Range, Error->ET_RegistryValueNotFound)
371  << NameToken.Text;
372  return false;
373  }
374  // Otherwise, fallback to the matcher parser.
375  }
376 
377  // Parse as a matcher expression.
378  return parseMatcherExpressionImpl(NameToken, Value);
379 }
380 
381 bool Parser::parseBindID(std::string &BindID) {
382  // Parse .bind("foo")
383  assert(Tokenizer->peekNextToken().Kind == TokenInfo::TK_Period);
384  Tokenizer->consumeNextToken(); // consume the period.
385  const TokenInfo BindToken = Tokenizer->consumeNextToken();
386  if (BindToken.Kind == TokenInfo::TK_CodeCompletion) {
387  addCompletion(BindToken, MatcherCompletion("bind(\"", "bind", 1));
388  return false;
389  }
390 
391  const TokenInfo OpenToken = Tokenizer->consumeNextToken();
392  const TokenInfo IDToken = Tokenizer->consumeNextToken();
393  const TokenInfo CloseToken = Tokenizer->consumeNextToken();
394 
395  // TODO: We could use different error codes for each/some to be more
396  // explicit about the syntax error.
397  if (BindToken.Kind != TokenInfo::TK_Ident ||
398  BindToken.Text != TokenInfo::ID_Bind) {
399  Error->addError(BindToken.Range, Error->ET_ParserMalformedBindExpr);
400  return false;
401  }
402  if (OpenToken.Kind != TokenInfo::TK_OpenParen) {
403  Error->addError(OpenToken.Range, Error->ET_ParserMalformedBindExpr);
404  return false;
405  }
406  if (IDToken.Kind != TokenInfo::TK_Literal || !IDToken.Value.isString()) {
407  Error->addError(IDToken.Range, Error->ET_ParserMalformedBindExpr);
408  return false;
409  }
410  if (CloseToken.Kind != TokenInfo::TK_CloseParen) {
411  Error->addError(CloseToken.Range, Error->ET_ParserMalformedBindExpr);
412  return false;
413  }
414  BindID = IDToken.Value.getString();
415  return true;
416 }
417 
418 /// Parse and validate a matcher expression.
419 /// \return \c true on success, in which case \c Value has the matcher parsed.
420 /// If the input is malformed, or some argument has an error, it
421 /// returns \c false.
422 bool Parser::parseMatcherExpressionImpl(const TokenInfo &NameToken,
423  VariantValue *Value) {
424  assert(NameToken.Kind == TokenInfo::TK_Ident);
425  const TokenInfo OpenToken = Tokenizer->consumeNextToken();
426  if (OpenToken.Kind != TokenInfo::TK_OpenParen) {
427  Error->addError(OpenToken.Range, Error->ET_ParserNoOpenParen)
428  << OpenToken.Text;
429  return false;
430  }
431 
432  llvm::Optional<MatcherCtor> Ctor = S->lookupMatcherCtor(NameToken.Text);
433 
434  if (!Ctor) {
435  Error->addError(NameToken.Range, Error->ET_RegistryMatcherNotFound)
436  << NameToken.Text;
437  // Do not return here. We need to continue to give completion suggestions.
438  }
439 
440  std::vector<ParserValue> Args;
441  TokenInfo EndToken;
442 
443  {
444  ScopedContextEntry SCE(this, Ctor ? *Ctor : nullptr);
445 
446  while (Tokenizer->nextTokenKind() != TokenInfo::TK_Eof) {
447  if (Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen) {
448  // End of args.
449  EndToken = Tokenizer->consumeNextToken();
450  break;
451  }
452  if (!Args.empty()) {
453  // We must find a , token to continue.
454  const TokenInfo CommaToken = Tokenizer->consumeNextToken();
455  if (CommaToken.Kind != TokenInfo::TK_Comma) {
456  Error->addError(CommaToken.Range, Error->ET_ParserNoComma)
457  << CommaToken.Text;
458  return false;
459  }
460  }
461 
463  NameToken.Text, NameToken.Range,
464  Args.size() + 1);
465  ParserValue ArgValue;
466  ArgValue.Text = Tokenizer->peekNextToken().Text;
467  ArgValue.Range = Tokenizer->peekNextToken().Range;
468  if (!parseExpressionImpl(&ArgValue.Value)) {
469  return false;
470  }
471 
472  Args.push_back(ArgValue);
473  SCE.nextArg();
474  }
475  }
476 
477  if (EndToken.Kind == TokenInfo::TK_Eof) {
478  Error->addError(OpenToken.Range, Error->ET_ParserNoCloseParen);
479  return false;
480  }
481 
482  std::string BindID;
483  if (Tokenizer->peekNextToken().Kind == TokenInfo::TK_Period) {
484  if (!parseBindID(BindID))
485  return false;
486  }
487 
488  if (!Ctor)
489  return false;
490 
491  // Merge the start and end infos.
493  NameToken.Text, NameToken.Range);
494  SourceRange MatcherRange = NameToken.Range;
495  MatcherRange.End = EndToken.Range.End;
496  VariantMatcher Result = S->actOnMatcherExpression(
497  *Ctor, MatcherRange, BindID, Args, Error);
498  if (Result.isNull()) return false;
499 
500  *Value = Result;
501  return true;
502 }
503 
504 // If the prefix of this completion matches the completion token, add it to
505 // Completions minus the prefix.
506 void Parser::addCompletion(const TokenInfo &CompToken,
507  const MatcherCompletion& Completion) {
508  if (StringRef(Completion.TypedText).startswith(CompToken.Text) &&
509  Completion.Specificity > 0) {
510  Completions.emplace_back(Completion.TypedText.substr(CompToken.Text.size()),
511  Completion.MatcherDecl, Completion.Specificity);
512  }
513 }
514 
515 std::vector<MatcherCompletion> Parser::getNamedValueCompletions(
516  ArrayRef<ArgKind> AcceptedTypes) {
517  if (!NamedValues) return std::vector<MatcherCompletion>();
518  std::vector<MatcherCompletion> Result;
519  for (const auto &Entry : *NamedValues) {
520  unsigned Specificity;
521  if (Entry.getValue().isConvertibleTo(AcceptedTypes, &Specificity)) {
522  std::string Decl =
523  (Entry.getValue().getTypeAsString() + " " + Entry.getKey()).str();
524  Result.emplace_back(Entry.getKey(), Decl, Specificity);
525  }
526  }
527  return Result;
528 }
529 
530 void Parser::addExpressionCompletions() {
531  const TokenInfo CompToken = Tokenizer->consumeNextToken();
532  assert(CompToken.Kind == TokenInfo::TK_CodeCompletion);
533 
534  // We cannot complete code if there is an invalid element on the context
535  // stack.
536  for (ContextStackTy::iterator I = ContextStack.begin(),
537  E = ContextStack.end();
538  I != E; ++I) {
539  if (!I->first)
540  return;
541  }
542 
543  auto AcceptedTypes = S->getAcceptedCompletionTypes(ContextStack);
544  for (const auto &Completion : S->getMatcherCompletions(AcceptedTypes)) {
545  addCompletion(CompToken, Completion);
546  }
547 
548  for (const auto &Completion : getNamedValueCompletions(AcceptedTypes)) {
549  addCompletion(CompToken, Completion);
550  }
551 }
552 
553 /// Parse an <Expression>
554 bool Parser::parseExpressionImpl(VariantValue *Value) {
555  switch (Tokenizer->nextTokenKind()) {
557  *Value = Tokenizer->consumeNextToken().Value;
558  return true;
559 
560  case TokenInfo::TK_Ident:
561  return parseIdentifierPrefixImpl(Value);
562 
564  addExpressionCompletions();
565  return false;
566 
567  case TokenInfo::TK_Eof:
568  Error->addError(Tokenizer->consumeNextToken().Range,
569  Error->ET_ParserNoCode);
570  return false;
571 
572  case TokenInfo::TK_Error:
573  // This error was already reported by the tokenizer.
574  return false;
575 
578  case TokenInfo::TK_Comma:
581  const TokenInfo Token = Tokenizer->consumeNextToken();
582  Error->addError(Token.Range, Error->ET_ParserInvalidToken) << Token.Text;
583  return false;
584  }
585 
586  llvm_unreachable("Unknown token kind.");
587 }
588 
589 static llvm::ManagedStatic<Parser::RegistrySema> DefaultRegistrySema;
590 
591 Parser::Parser(CodeTokenizer *Tokenizer, Sema *S,
592  const NamedValueMap *NamedValues, Diagnostics *Error)
593  : Tokenizer(Tokenizer), S(S ? S : &*DefaultRegistrySema),
594  NamedValues(NamedValues), Error(Error) {}
595 
597 
600  return Registry::lookupMatcherCtor(MatcherName);
601 }
602 
604  MatcherCtor Ctor, SourceRange NameRange, StringRef BindID,
605  ArrayRef<ParserValue> Args, Diagnostics *Error) {
606  if (BindID.empty()) {
607  return Registry::constructMatcher(Ctor, NameRange, Args, Error);
608  } else {
609  return Registry::constructBoundMatcher(Ctor, NameRange, BindID, Args,
610  Error);
611  }
612 }
613 
615  ArrayRef<std::pair<MatcherCtor, unsigned>> Context) {
616  return Registry::getAcceptedCompletionTypes(Context);
617 }
618 
619 std::vector<MatcherCompletion> Parser::RegistrySema::getMatcherCompletions(
620  ArrayRef<ArgKind> AcceptedTypes) {
621  return Registry::getMatcherCompletions(AcceptedTypes);
622 }
623 
624 bool Parser::parseExpression(StringRef Code, Sema *S,
625  const NamedValueMap *NamedValues,
626  VariantValue *Value, Diagnostics *Error) {
627  CodeTokenizer Tokenizer(Code, Error);
628  if (!Parser(&Tokenizer, S, NamedValues, Error).parseExpressionImpl(Value))
629  return false;
630  if (Tokenizer.peekNextToken().Kind != TokenInfo::TK_Eof) {
631  Error->addError(Tokenizer.peekNextToken().Range,
632  Error->ET_ParserTrailingCode);
633  return false;
634  }
635  return true;
636 }
637 
638 std::vector<MatcherCompletion>
639 Parser::completeExpression(StringRef Code, unsigned CompletionOffset, Sema *S,
640  const NamedValueMap *NamedValues) {
641  Diagnostics Error;
642  CodeTokenizer Tokenizer(Code, &Error, CompletionOffset);
643  Parser P(&Tokenizer, S, NamedValues, &Error);
644  VariantValue Dummy;
645  P.parseExpressionImpl(&Dummy);
646 
647  // Sort by specificity, then by name.
648  llvm::sort(P.Completions.begin(), P.Completions.end(),
649  [](const MatcherCompletion &A, const MatcherCompletion &B) {
650  if (A.Specificity != B.Specificity)
651  return A.Specificity > B.Specificity;
652  return A.TypedText < B.TypedText;
653  });
654 
655  return P.Completions;
656 }
657 
660  const NamedValueMap *NamedValues,
661  Diagnostics *Error) {
663  if (!parseExpression(Code, S, NamedValues, &Value, Error))
665  if (!Value.isMatcher()) {
666  Error->addError(SourceRange(), Error->ET_ParserNotAMatcher);
668  }
670  Value.getMatcher().getSingleMatcher();
671  if (!Result.hasValue()) {
673  << Value.getTypeAsString();
674  }
675  return Result;
676 }
677 
678 } // namespace dynamic
679 } // namespace ast_matchers
680 } // 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:639
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:640
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:555
static bool parseExpression(StringRef Code, Sema *S, const NamedValueMap *NamedValues, VariantValue *Value, Diagnostics *Error)
Parse an expression.
Definition: Parser.cpp:624
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:524
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:599
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:277
static llvm::Optional< MatcherCtor > lookupMatcherCtor(StringRef MatcherName)
Look up a matcher in the registry by name,.
Definition: Registry.cpp:501
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:603
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:614
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:659
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:589
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:303
std::vector< MatcherCompletion > getMatcherCompletions(llvm::ArrayRef< ArgKind > AcceptedTypes) override
Compute the list of completions that match any of AcceptedTypes.
Definition: Parser.cpp:619
virtual std::vector< MatcherCompletion > getMatcherCompletions(llvm::ArrayRef< ArgKind > AcceptedTypes)
Compute the list of completions that match any of AcceptedTypes.
Definition: Parser.cpp:309
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:633