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