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