Coverage Report

Created: 2020-02-25 14:32

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/ASTMatchers/Dynamic/Parser.cpp
Line
Count
Source (jump to first uncovered line)
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
14
#include "clang/ASTMatchers/Dynamic/Parser.h"
15
#include "clang/ASTMatchers/ASTMatchersInternal.h"
16
#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
17
#include "clang/ASTMatchers/Dynamic/Registry.h"
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.
37
struct Parser::TokenInfo {
38
  /// Different possible tokens.
39
  enum TokenKind {
40
    TK_Eof,
41
    TK_NewLine,
42
    TK_OpenParen,
43
    TK_CloseParen,
44
    TK_Comma,
45
    TK_Period,
46
    TK_Literal,
47
    TK_Ident,
48
    TK_InvalidChar,
49
    TK_Error,
50
    TK_CodeCompletion
51
  };
52
53
  /// Some known identifiers.
54
  static const char* const ID_Bind;
55
56
465
  TokenInfo() = default;
57
58
  StringRef Text;
59
  TokenKind Kind = TK_Eof;
60
  SourceRange Range;
61
  VariantValue Value;
62
};
63
64
const char* const Parser::TokenInfo::ID_Bind = "bind";
65
66
/// Simple tokenizer for the parser.
67
class Parser::CodeTokenizer {
68
public:
69
  explicit CodeTokenizer(StringRef &MatcherCode, Diagnostics *Error)
70
51
      : Code(MatcherCode), StartOfLine(MatcherCode), Error(Error) {
71
51
    NextToken = getNextToken();
72
51
  }
73
74
  CodeTokenizer(StringRef &MatcherCode, Diagnostics *Error,
75
                unsigned CodeCompletionOffset)
76
      : Code(MatcherCode), StartOfLine(MatcherCode), Error(Error),
77
5
        CodeCompletionLocation(MatcherCode.data() + CodeCompletionOffset) {
78
5
    NextToken = getNextToken();
79
5
  }
80
81
  /// Returns but doesn't consume the next token.
82
189
  const TokenInfo &peekNextToken() const { return NextToken; }
83
84
  /// Consumes and returns the next token.
85
274
  TokenInfo consumeNextToken() {
86
274
    TokenInfo ThisToken = NextToken;
87
274
    NextToken = getNextToken();
88
274
    return ThisToken;
89
274
  }
90
91
236
  TokenInfo SkipNewlines() {
92
251
    while (NextToken.Kind == TokenInfo::TK_NewLine)
93
15
      NextToken = getNextToken();
94
236
    return NextToken;
95
236
  }
96
97
28
  TokenInfo consumeNextTokenIgnoreNewlines() {
98
28
    SkipNewlines();
99
28
    if (NextToken.Kind == TokenInfo::TK_Eof)
100
6
      return NextToken;
101
22
    return consumeNextToken();
102
22
  }
103
104
386
  TokenInfo::TokenKind nextTokenKind() const { return NextToken.Kind; }
105
106
private:
107
350
  TokenInfo getNextToken() {
108
350
    consumeWhitespace();
109
350
    TokenInfo Result;
110
350
    Result.Range.Start = currentLocation();
111
350
112
350
    if (CodeCompletionLocation && 
CodeCompletionLocation <= Code.data()22
) {
113
3
      Result.Kind = TokenInfo::TK_CodeCompletion;
114
3
      Result.Text = StringRef(CodeCompletionLocation, 0);
115
3
      CodeCompletionLocation = nullptr;
116
3
      return Result;
117
3
    }
118
347
119
347
    if (Code.empty()) {
120
43
      Result.Kind = TokenInfo::TK_Eof;
121
43
      Result.Text = "";
122
43
      return Result;
123
43
    }
124
304
125
304
    switch (Code[0]) {
126
5
    case '#':
127
68
      Code = Code.drop_until([](char c) { return c == '\n'; });
128
5
      return getNextToken();
129
9
    case ',':
130
9
      Result.Kind = TokenInfo::TK_Comma;
131
9
      Result.Text = Code.substr(0, 1);
132
9
      Code = Code.drop_front();
133
9
      break;
134
13
    case '.':
135
13
      Result.Kind = TokenInfo::TK_Period;
136
13
      Result.Text = Code.substr(0, 1);
137
13
      Code = Code.drop_front();
138
13
      break;
139
23
    case '\n':
140
23
      ++Line;
141
23
      StartOfLine = Code.drop_front();
142
23
      Result.Kind = TokenInfo::TK_NewLine;
143
23
      Result.Text = Code.substr(0, 1);
144
23
      Code = Code.drop_front();
145
23
      break;
146
70
    case '(':
147
70
      Result.Kind = TokenInfo::TK_OpenParen;
148
70
      Result.Text = Code.substr(0, 1);
149
70
      Code = Code.drop_front();
150
70
      break;
151
58
    case ')':
152
58
      Result.Kind = TokenInfo::TK_CloseParen;
153
58
      Result.Text = Code.substr(0, 1);
154
58
      Code = Code.drop_front();
155
58
      break;
156
0
157
24
    case '"':
158
24
    case '\'':
159
24
      // Parse a string literal.
160
24
      consumeStringLiteral(&Result);
161
24
      break;
162
24
163
24
    
case '0': 15
case '1': 15
case '2': 15
case '3': 15
case '4':
164
15
    case '5': case '6': case '7': case '8': case '9':
165
15
      // Parse an unsigned and float literal.
166
15
      consumeNumberLiteral(&Result);
167
15
      break;
168
15
169
87
    default:
170
87
      if (isAlphanumeric(Code[0])) {
171
87
        // Parse an identifier
172
87
        size_t TokenLength = 1;
173
595
        while (true) {
174
595
          // A code completion location in/immediately after an identifier will
175
595
          // cause the portion of the identifier before the code completion
176
595
          // location to become a code completion token.
177
595
          if (CodeCompletionLocation == Code.data() + TokenLength) {
178
2
            CodeCompletionLocation = nullptr;
179
2
            Result.Kind = TokenInfo::TK_CodeCompletion;
180
2
            Result.Text = Code.substr(0, TokenLength);
181
2
            Code = Code.drop_front(TokenLength);
182
2
            return Result;
183
2
          }
184
593
          if (TokenLength == Code.size() || 
!isAlphanumeric(Code[TokenLength])587
)
185
85
            break;
186
508
          ++TokenLength;
187
508
        }
188
87
        
if (85
TokenLength == 485
&&
Code.startswith("true")24
) {
189
1
          Result.Kind = TokenInfo::TK_Literal;
190
1
          Result.Value = true;
191
84
        } else if (TokenLength == 5 && 
Code.startswith("false")4
) {
192
1
          Result.Kind = TokenInfo::TK_Literal;
193
1
          Result.Value = false;
194
83
        } else {
195
83
          Result.Kind = TokenInfo::TK_Ident;
196
83
          Result.Text = Code.substr(0, TokenLength);
197
83
        }
198
85
        Code = Code.drop_front(TokenLength);
199
85
      } else {
200
0
        Result.Kind = TokenInfo::TK_InvalidChar;
201
0
        Result.Text = Code.substr(0, 1);
202
0
        Code = Code.drop_front(1);
203
0
      }
204
87
      
break85
;
205
297
    }
206
297
207
297
    Result.Range.End = currentLocation();
208
297
    return Result;
209
297
  }
210
211
  /// Consume an unsigned and float literal.
212
15
  void consumeNumberLiteral(TokenInfo *Result) {
213
15
    bool isFloatingLiteral = false;
214
15
    unsigned Length = 1;
215
15
    if (Code.size() > 1) {
216
13
      // Consume the 'x' or 'b' radix modifier, if present.
217
13
      switch (toLowercase(Code[1])) {
218
1
      case 'x': case 'b': Length = 2;
219
13
      }
220
13
    }
221
37
    
while (15
Length < Code.size() &&
isHexDigit(Code[Length])30
)
222
22
      ++Length;
223
15
224
15
    // Try to recognize a floating point literal.
225
31
    while (Length < Code.size()) {
226
20
      char c = Code[Length];
227
20
      if (c == '-' || 
c == '+'19
||
c == '.'18
||
isHexDigit(c)14
) {
228
16
        isFloatingLiteral = true;
229
16
        Length++;
230
16
      } else {
231
4
        break;
232
4
      }
233
20
    }
234
15
235
15
    Result->Text = Code.substr(0, Length);
236
15
    Code = Code.drop_front(Length);
237
15
238
15
    if (isFloatingLiteral) {
239
4
      char *end;
240
4
      errno = 0;
241
4
      std::string Text = Result->Text.str();
242
4
      double doubleValue = strtod(Text.c_str(), &end);
243
4
      if (*end == 0 && errno
== 03
) {
244
3
        Result->Kind = TokenInfo::TK_Literal;
245
3
        Result->Value = doubleValue;
246
3
        return;
247
3
      }
248
11
    } else {
249
11
      unsigned Value;
250
11
      if (!Result->Text.getAsInteger(0, Value)) {
251
9
        Result->Kind = TokenInfo::TK_Literal;
252
9
        Result->Value = Value;
253
9
        return;
254
9
      }
255
3
    }
256
3
257
3
    SourceRange Range;
258
3
    Range.Start = Result->Range.Start;
259
3
    Range.End = currentLocation();
260
3
    Error->addError(Range, Error->ET_ParserNumberError) << Result->Text;
261
3
    Result->Kind = TokenInfo::TK_Error;
262
3
  }
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
24
  void consumeStringLiteral(TokenInfo *Result) {
269
24
    bool InEscape = false;
270
24
    const char Marker = Code[0];
271
132
    for (size_t Length = 1, Size = Code.size(); Length != Size; 
++Length108
) {
272
131
      if (InEscape) {
273
0
        InEscape = false;
274
0
        continue;
275
0
      }
276
131
      if (Code[Length] == '\\') {
277
0
        InEscape = true;
278
0
        continue;
279
0
      }
280
131
      if (Code[Length] == Marker) {
281
23
        Result->Kind = TokenInfo::TK_Literal;
282
23
        Result->Text = Code.substr(0, Length + 1);
283
23
        Result->Value = Code.substr(1, Length - 1);
284
23
        Code = Code.drop_front(Length + 1);
285
23
        return;
286
23
      }
287
131
    }
288
24
289
24
    StringRef ErrorText = Code;
290
1
    Code = Code.drop_front(Code.size());
291
1
    SourceRange Range;
292
1
    Range.Start = Result->Range.Start;
293
1
    Range.End = currentLocation();
294
1
    Error->addError(Range, Error->ET_ParserStringError) << ErrorText;
295
1
    Result->Kind = TokenInfo::TK_Error;
296
1
  }
297
298
  /// Consume all leading whitespace from \c Code.
299
350
  void consumeWhitespace() {
300
391
    Code = Code.drop_while([](char c) {
301
391
      // Don't trim newlines.
302
391
      return StringRef(" \t\v\f\r").contains(c);
303
391
    });
304
350
  }
305
306
651
  SourceLocation currentLocation() {
307
651
    SourceLocation Location;
308
651
    Location.Line = Line;
309
651
    Location.Column = Code.data() - StartOfLine.data() + 1;
310
651
    return Location;
311
651
  }
312
313
  StringRef &Code;
314
  StringRef StartOfLine;
315
  unsigned Line = 1;
316
  Diagnostics *Error;
317
  TokenInfo NextToken;
318
  const char *CodeCompletionLocation = nullptr;
319
};
320
321
6
Parser::Sema::~Sema() = default;
322
323
std::vector<ArgKind> Parser::Sema::getAcceptedCompletionTypes(
324
0
    llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context) {
325
0
  return {};
326
0
}
327
328
std::vector<MatcherCompletion>
329
0
Parser::Sema::getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes) {
330
0
  return {};
331
0
}
332
333
struct Parser::ScopedContextEntry {
334
  Parser *P;
335
336
59
  ScopedContextEntry(Parser *P, MatcherCtor C) : P(P) {
337
59
    P->ContextStack.push_back(std::make_pair(C, 0u));
338
59
  }
339
340
59
  ~ScopedContextEntry() {
341
59
    P->ContextStack.pop_back();
342
59
  }
343
344
40
  void nextArg() {
345
40
    ++P->ContextStack.back().second;
346
40
  }
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
69
bool Parser::parseIdentifierPrefixImpl(VariantValue *Value) {
355
69
  const TokenInfo NameToken = Tokenizer->consumeNextToken();
356
69
357
69
  if (Tokenizer->nextTokenKind() != TokenInfo::TK_OpenParen) {
358
10
    // Parse as a named value.
359
10
    if (const VariantValue NamedValue =
360
7
            NamedValues ? NamedValues->lookup(NameToken.Text)
361
7
                        : VariantValue()) {
362
7
363
7
      if (Tokenizer->nextTokenKind() != TokenInfo::TK_Period) {
364
3
        *Value = NamedValue;
365
3
        return true;
366
3
      }
367
4
368
4
      std::string BindID;
369
4
      if (!parseBindID(BindID))
370
2
        return false;
371
2
372
2
      assert(NamedValue.isMatcher());
373
2
      llvm::Optional<DynTypedMatcher> Result =
374
2
          NamedValue.getMatcher().getSingleMatcher();
375
2
      if (Result.hasValue()) {
376
2
        llvm::Optional<DynTypedMatcher> Bound = Result->tryBind(BindID);
377
2
        if (Bound.hasValue()) {
378
2
          *Value = VariantMatcher::SingleMatcher(*Bound);
379
2
          return true;
380
2
        }
381
0
      }
382
0
      return false;
383
0
    }
384
3
385
3
    if (Tokenizer->nextTokenKind() == TokenInfo::TK_NewLine) {
386
1
      Error->addError(Tokenizer->peekNextToken().Range,
387
1
                      Error->ET_ParserNoOpenParen)
388
1
          << "NewLine";
389
1
      return false;
390
1
    }
391
2
392
2
    // If the syntax is correct and the name is not a matcher either, report
393
2
    // unknown named value.
394
2
    if ((Tokenizer->nextTokenKind() == TokenInfo::TK_Comma ||
395
2
         Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen ||
396
2
         
Tokenizer->nextTokenKind() == TokenInfo::TK_NewLine1
||
397
2
         
Tokenizer->nextTokenKind() == TokenInfo::TK_Eof1
) &&
398
2
        
!S->lookupMatcherCtor(NameToken.Text)1
) {
399
1
      Error->addError(NameToken.Range, Error->ET_RegistryValueNotFound)
400
1
          << NameToken.Text;
401
1
      return false;
402
1
    }
403
60
    // Otherwise, fallback to the matcher parser.
404
60
  }
405
60
406
60
  Tokenizer->SkipNewlines();
407
60
408
60
  // Parse as a matcher expression.
409
60
  return parseMatcherExpressionImpl(NameToken, Value);
410
60
}
411
412
13
bool Parser::parseBindID(std::string &BindID) {
413
13
  // Parse .bind("foo")
414
13
  assert(Tokenizer->peekNextToken().Kind == TokenInfo::TK_Period);
415
13
  Tokenizer->consumeNextToken(); // consume the period.
416
13
  const TokenInfo BindToken = Tokenizer->consumeNextToken();
417
13
  if (BindToken.Kind == TokenInfo::TK_CodeCompletion) {
418
1
    addCompletion(BindToken, MatcherCompletion("bind(\"", "bind", 1));
419
1
    return false;
420
1
  }
421
12
422
12
  const TokenInfo OpenToken = Tokenizer->consumeNextToken();
423
12
  const TokenInfo IDToken = Tokenizer->consumeNextTokenIgnoreNewlines();
424
12
  const TokenInfo CloseToken = Tokenizer->consumeNextTokenIgnoreNewlines();
425
12
426
12
  // TODO: We could use different error codes for each/some to be more
427
12
  //       explicit about the syntax error.
428
12
  if (BindToken.Kind != TokenInfo::TK_Ident ||
429
12
      
BindToken.Text != TokenInfo::ID_Bind11
) {
430
2
    Error->addError(BindToken.Range, Error->ET_ParserMalformedBindExpr);
431
2
    return false;
432
2
  }
433
10
  if (OpenToken.Kind != TokenInfo::TK_OpenParen) {
434
2
    Error->addError(OpenToken.Range, Error->ET_ParserMalformedBindExpr);
435
2
    return false;
436
2
  }
437
8
  if (IDToken.Kind != TokenInfo::TK_Literal || 
!IDToken.Value.isString()7
) {
438
1
    Error->addError(IDToken.Range, Error->ET_ParserMalformedBindExpr);
439
1
    return false;
440
1
  }
441
7
  if (CloseToken.Kind != TokenInfo::TK_CloseParen) {
442
1
    Error->addError(CloseToken.Range, Error->ET_ParserMalformedBindExpr);
443
1
    return false;
444
1
  }
445
6
  BindID = IDToken.Value.getString();
446
6
  return true;
447
6
}
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
60
                                        VariantValue *Value) {
455
60
  assert(NameToken.Kind == TokenInfo::TK_Ident);
456
60
  const TokenInfo OpenToken = Tokenizer->consumeNextToken();
457
60
  if (OpenToken.Kind != TokenInfo::TK_OpenParen) {
458
1
    Error->addError(OpenToken.Range, Error->ET_ParserNoOpenParen)
459
1
        << OpenToken.Text;
460
1
    return false;
461
1
  }
462
59
463
59
  llvm::Optional<MatcherCtor> Ctor = S->lookupMatcherCtor(NameToken.Text);
464
59
465
59
  if (!Ctor) {
466
4
    Error->addError(NameToken.Range, Error->ET_RegistryMatcherNotFound)
467
4
        << NameToken.Text;
468
4
    // Do not return here. We need to continue to give completion suggestions.
469
4
  }
470
59
471
59
  std::vector<ParserValue> Args;
472
59
  TokenInfo EndToken;
473
59
474
59
  Tokenizer->SkipNewlines();
475
59
476
59
  {
477
59
    ScopedContextEntry SCE(this, Ctor ? 
*Ctor55
:
nullptr4
);
478
59
479
99
    while (Tokenizer->nextTokenKind() != TokenInfo::TK_Eof) {
480
97
      if (Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen) {
481
47
        // End of args.
482
47
        EndToken = Tokenizer->consumeNextToken();
483
47
        break;
484
47
      }
485
50
      if (!Args.empty()) {
486
10
        // We must find a , token to continue.
487
10
        const TokenInfo CommaToken = Tokenizer->consumeNextToken();
488
10
        if (CommaToken.Kind != TokenInfo::TK_Comma) {
489
1
          Error->addError(CommaToken.Range, Error->ET_ParserNoComma)
490
1
              << CommaToken.Text;
491
1
          return false;
492
1
        }
493
49
      }
494
49
495
49
      Diagnostics::Context Ctx(Diagnostics::Context::MatcherArg, Error,
496
49
                               NameToken.Text, NameToken.Range,
497
49
                               Args.size() + 1);
498
49
      ParserValue ArgValue;
499
49
      Tokenizer->SkipNewlines();
500
49
      ArgValue.Text = Tokenizer->peekNextToken().Text;
501
49
      ArgValue.Range = Tokenizer->peekNextToken().Range;
502
49
      if (!parseExpressionImpl(&ArgValue.Value)) {
503
9
        return false;
504
9
      }
505
40
506
40
      Tokenizer->SkipNewlines();
507
40
      Args.push_back(ArgValue);
508
40
      SCE.nextArg();
509
40
    }
510
59
  }
511
59
512
59
  
if (49
EndToken.Kind == TokenInfo::TK_Eof49
) {
513
2
    Error->addError(OpenToken.Range, Error->ET_ParserNoCloseParen);
514
2
    return false;
515
2
  }
516
47
517
47
  std::string BindID;
518
47
  if (Tokenizer->peekNextToken().Kind == TokenInfo::TK_Period) {
519
9
    if (!parseBindID(BindID))
520
5
      return false;
521
42
  }
522
42
523
42
  if (!Ctor)
524
1
    return false;
525
41
526
41
  // Merge the start and end infos.
527
41
  Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error,
528
41
                           NameToken.Text, NameToken.Range);
529
41
  SourceRange MatcherRange = NameToken.Range;
530
41
  MatcherRange.End = EndToken.Range.End;
531
41
  VariantMatcher Result = S->actOnMatcherExpression(
532
41
      *Ctor, MatcherRange, BindID, Args, Error);
533
41
  if (Result.isNull()) 
return false3
;
534
38
535
38
  *Value = Result;
536
38
  return true;
537
38
}
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
365
                           const MatcherCompletion& Completion) {
543
365
  if (StringRef(Completion.TypedText).startswith(CompToken.Text) &&
544
365
      
Completion.Specificity > 077
) {
545
77
    Completions.emplace_back(Completion.TypedText.substr(CompToken.Text.size()),
546
77
                             Completion.MatcherDecl, Completion.Specificity);
547
77
  }
548
365
}
549
550
std::vector<MatcherCompletion> Parser::getNamedValueCompletions(
551
4
    ArrayRef<ArgKind> AcceptedTypes) {
552
4
  if (!NamedValues) 
return std::vector<MatcherCompletion>()1
;
553
3
  std::vector<MatcherCompletion> Result;
554
6
  for (const auto &Entry : *NamedValues) {
555
6
    unsigned Specificity;
556
6
    if (Entry.getValue().isConvertibleTo(AcceptedTypes, &Specificity)) {
557
3
      std::string Decl =
558
3
          (Entry.getValue().getTypeAsString() + " " + Entry.getKey()).str();
559
3
      Result.emplace_back(Entry.getKey(), Decl, Specificity);
560
3
    }
561
6
  }
562
3
  return Result;
563
3
}
564
565
4
void Parser::addExpressionCompletions() {
566
4
  const TokenInfo CompToken = Tokenizer->consumeNextTokenIgnoreNewlines();
567
4
  assert(CompToken.Kind == TokenInfo::TK_CodeCompletion);
568
4
569
4
  // We cannot complete code if there is an invalid element on the context
570
4
  // stack.
571
4
  for (ContextStackTy::iterator I = ContextStack.begin(),
572
4
                                E = ContextStack.end();
573
8
       I != E; 
++I4
) {
574
4
    if (!I->first)
575
0
      return;
576
4
  }
577
4
578
4
  auto AcceptedTypes = S->getAcceptedCompletionTypes(ContextStack);
579
361
  for (const auto &Completion : S->getMatcherCompletions(AcceptedTypes)) {
580
361
    addCompletion(CompToken, Completion);
581
361
  }
582
4
583
4
  for (const auto &Completion : getNamedValueCompletions(AcceptedTypes)) {
584
3
    addCompletion(CompToken, Completion);
585
3
  }
586
4
}
587
588
/// Parse an <Expression>
589
105
bool Parser::parseExpressionImpl(VariantValue *Value) {
590
105
  switch (Tokenizer->nextTokenKind()) {
591
26
  case TokenInfo::TK_Literal:
592
26
    *Value = Tokenizer->consumeNextToken().Value;
593
26
    return true;
594
0
595
69
  case TokenInfo::TK_Ident:
596
69
    return parseIdentifierPrefixImpl(Value);
597
0
598
4
  case TokenInfo::TK_CodeCompletion:
599
4
    addExpressionCompletions();
600
4
    return false;
601
0
602
1
  case TokenInfo::TK_Eof:
603
1
    Error->addError(Tokenizer->consumeNextToken().Range,
604
1
                    Error->ET_ParserNoCode);
605
1
    return false;
606
0
607
4
  case TokenInfo::TK_Error:
608
4
    // This error was already reported by the tokenizer.
609
4
    return false;
610
1
  case TokenInfo::TK_NewLine:
611
1
  case TokenInfo::TK_OpenParen:
612
1
  case TokenInfo::TK_CloseParen:
613
1
  case TokenInfo::TK_Comma:
614
1
  case TokenInfo::TK_Period:
615
1
  case TokenInfo::TK_InvalidChar:
616
1
    const TokenInfo Token = Tokenizer->consumeNextToken();
617
1
    Error->addError(Token.Range, Error->ET_ParserInvalidToken)
618
1
        << (Token.Kind == TokenInfo::TK_NewLine ? 
"NewLine"0
: Token.Text);
619
1
    return false;
620
0
  }
621
0
622
0
  llvm_unreachable("Unknown token kind.");
623
0
}
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
56
      NamedValues(NamedValues), Error(Error) {}
631
632
0
Parser::RegistrySema::~RegistrySema() = default;
633
634
llvm::Optional<MatcherCtor>
635
55
Parser::RegistrySema::lookupMatcherCtor(StringRef MatcherName) {
636
55
  return Registry::lookupMatcherCtor(MatcherName);
637
55
}
638
639
VariantMatcher Parser::RegistrySema::actOnMatcherExpression(
640
    MatcherCtor Ctor, SourceRange NameRange, StringRef BindID,
641
37
    ArrayRef<ParserValue> Args, Diagnostics *Error) {
642
37
  if (BindID.empty()) {
643
34
    return Registry::constructMatcher(Ctor, NameRange, Args, Error);
644
34
  } else {
645
3
    return Registry::constructBoundMatcher(Ctor, NameRange, BindID, Args,
646
3
                                           Error);
647
3
  }
648
37
}
649
650
std::vector<ArgKind> Parser::RegistrySema::getAcceptedCompletionTypes(
651
4
    ArrayRef<std::pair<MatcherCtor, unsigned>> Context) {
652
4
  return Registry::getAcceptedCompletionTypes(Context);
653
4
}
654
655
std::vector<MatcherCompletion> Parser::RegistrySema::getMatcherCompletions(
656
4
    ArrayRef<ArgKind> AcceptedTypes) {
657
4
  return Registry::getMatcherCompletions(AcceptedTypes);
658
4
}
659
660
bool Parser::parseExpression(StringRef &Code, Sema *S,
661
                             const NamedValueMap *NamedValues,
662
51
                             VariantValue *Value, Diagnostics *Error) {
663
51
  CodeTokenizer Tokenizer(Code, Error);
664
51
  if (!Parser(&Tokenizer, S, NamedValues, Error).parseExpressionImpl(Value))
665
22
    return false;
666
29
  auto NT = Tokenizer.peekNextToken();
667
29
  if (NT.Kind != TokenInfo::TK_Eof && 
NT.Kind != TokenInfo::TK_NewLine5
) {
668
1
    Error->addError(Tokenizer.peekNextToken().Range,
669
1
                    Error->ET_ParserTrailingCode);
670
1
    return false;
671
1
  }
672
28
  return true;
673
28
}
674
675
std::vector<MatcherCompletion>
676
Parser::completeExpression(StringRef &Code, unsigned CompletionOffset, Sema *S,
677
5
                           const NamedValueMap *NamedValues) {
678
5
  Diagnostics Error;
679
5
  CodeTokenizer Tokenizer(Code, &Error, CompletionOffset);
680
5
  Parser P(&Tokenizer, S, NamedValues, &Error);
681
5
  VariantValue Dummy;
682
5
  P.parseExpressionImpl(&Dummy);
683
5
684
5
  // Sort by specificity, then by name.
685
5
  llvm::sort(P.Completions,
686
446
             [](const MatcherCompletion &A, const MatcherCompletion &B) {
687
446
               if (A.Specificity != B.Specificity)
688
190
                 return A.Specificity > B.Specificity;
689
256
               return A.TypedText < B.TypedText;
690
256
             });
691
5
692
5
  return P.Completions;
693
5
}
694
695
llvm::Optional<DynTypedMatcher>
696
Parser::parseMatcherExpression(StringRef &Code, Sema *S,
697
                               const NamedValueMap *NamedValues,
698
20
                               Diagnostics *Error) {
699
20
  VariantValue Value;
700
20
  if (!parseExpression(Code, S, NamedValues, &Value, Error))
701
5
    return llvm::Optional<DynTypedMatcher>();
702
15
  if (!Value.isMatcher()) {
703
1
    Error->addError(SourceRange(), Error->ET_ParserNotAMatcher);
704
1
    return llvm::Optional<DynTypedMatcher>();
705
1
  }
706
14
  llvm::Optional<DynTypedMatcher> Result =
707
14
      Value.getMatcher().getSingleMatcher();
708
14
  if (!Result.hasValue()) {
709
1
    Error->addError(SourceRange(), Error->ET_ParserOverloadedType)
710
1
        << Value.getTypeAsString();
711
1
  }
712
14
  return Result;
713
14
}
714
715
} // namespace dynamic
716
} // namespace ast_matchers
717
} // namespace clang