Coverage Report

Created: 2023-11-11 10:31

/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/StringRef.h"
20
#include "llvm/Support/ErrorHandling.h"
21
#include "llvm/Support/ManagedStatic.h"
22
#include <algorithm>
23
#include <cassert>
24
#include <cerrno>
25
#include <cstddef>
26
#include <cstdlib>
27
#include <optional>
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
  static const char *const ID_With;
56
57
620
  TokenInfo() = default;
58
59
  StringRef Text;
60
  TokenKind Kind = TK_Eof;
61
  SourceRange Range;
62
  VariantValue Value;
63
};
64
65
const char* const Parser::TokenInfo::ID_Bind = "bind";
66
const char *const Parser::TokenInfo::ID_With = "with";
67
68
/// Simple tokenizer for the parser.
69
class Parser::CodeTokenizer {
70
public:
71
  explicit CodeTokenizer(StringRef &MatcherCode, Diagnostics *Error)
72
65
      : Code(MatcherCode), StartOfLine(MatcherCode), Error(Error) {
73
65
    NextToken = getNextToken();
74
65
  }
75
76
  CodeTokenizer(StringRef &MatcherCode, Diagnostics *Error,
77
                unsigned CodeCompletionOffset)
78
8
      : Code(MatcherCode), StartOfLine(MatcherCode), Error(Error),
79
8
        CodeCompletionLocation(MatcherCode.data() + CodeCompletionOffset) {
80
8
    NextToken = getNextToken();
81
8
  }
82
83
  /// Returns but doesn't consume the next token.
84
245
  const TokenInfo &peekNextToken() const { return NextToken; }
85
86
  /// Consumes and returns the next token.
87
369
  TokenInfo consumeNextToken() {
88
369
    TokenInfo ThisToken = NextToken;
89
369
    NextToken = getNextToken();
90
369
    return ThisToken;
91
369
  }
92
93
333
  TokenInfo SkipNewlines() {
94
348
    while (NextToken.Kind == TokenInfo::TK_NewLine)
95
15
      NextToken = getNextToken();
96
333
    return NextToken;
97
333
  }
98
99
26
  TokenInfo consumeNextTokenIgnoreNewlines() {
100
26
    SkipNewlines();
101
26
    if (NextToken.Kind == TokenInfo::TK_Eof)
102
4
      return NextToken;
103
22
    return consumeNextToken();
104
26
  }
105
106
542
  TokenInfo::TokenKind nextTokenKind() const { return NextToken.Kind; }
107
108
private:
109
462
  TokenInfo getNextToken() {
110
462
    consumeWhitespace();
111
462
    TokenInfo Result;
112
462
    Result.Range.Start = currentLocation();
113
114
462
    if (CodeCompletionLocation && 
CodeCompletionLocation <= Code.data()32
) {
115
4
      Result.Kind = TokenInfo::TK_CodeCompletion;
116
4
      Result.Text = StringRef(CodeCompletionLocation, 0);
117
4
      CodeCompletionLocation = nullptr;
118
4
      return Result;
119
4
    }
120
121
458
    if (Code.empty()) {
122
52
      Result.Kind = TokenInfo::TK_Eof;
123
52
      Result.Text = "";
124
52
      return Result;
125
52
    }
126
127
406
    switch (Code[0]) {
128
5
    case '#':
129
68
      Code = Code.drop_until([](char c) { return c == '\n'; });
130
5
      return getNextToken();
131
13
    case ',':
132
13
      Result.Kind = TokenInfo::TK_Comma;
133
13
      Result.Text = Code.substr(0, 1);
134
13
      Code = Code.drop_front();
135
13
      break;
136
17
    case '.':
137
17
      Result.Kind = TokenInfo::TK_Period;
138
17
      Result.Text = Code.substr(0, 1);
139
17
      Code = Code.drop_front();
140
17
      break;
141
23
    case '\n':
142
23
      ++Line;
143
23
      StartOfLine = Code.drop_front();
144
23
      Result.Kind = TokenInfo::TK_NewLine;
145
23
      Result.Text = Code.substr(0, 1);
146
23
      Code = Code.drop_front();
147
23
      break;
148
95
    case '(':
149
95
      Result.Kind = TokenInfo::TK_OpenParen;
150
95
      Result.Text = Code.substr(0, 1);
151
95
      Code = Code.drop_front();
152
95
      break;
153
81
    case ')':
154
81
      Result.Kind = TokenInfo::TK_CloseParen;
155
81
      Result.Text = Code.substr(0, 1);
156
81
      Code = Code.drop_front();
157
81
      break;
158
159
37
    case '"':
160
37
    case '\'':
161
      // Parse a string literal.
162
37
      consumeStringLiteral(&Result);
163
37
      break;
164
165
15
    
case '0': 2
case '1': 12
case '2': 13
case '3': 14
case '4':
166
15
    case '5': case '6': case '7': case '8': case '9':
167
      // Parse an unsigned and float literal.
168
15
      consumeNumberLiteral(&Result);
169
15
      break;
170
171
120
    default:
172
120
      if (isAlphanumeric(Code[0])) {
173
        // Parse an identifier
174
120
        size_t TokenLength = 1;
175
859
        while (true) {
176
          // A code completion location in/immediately after an identifier will
177
          // cause the portion of the identifier before the code completion
178
          // location to become a code completion token.
179
859
          if (CodeCompletionLocation == Code.data() + TokenLength) {
180
4
            CodeCompletionLocation = nullptr;
181
4
            Result.Kind = TokenInfo::TK_CodeCompletion;
182
4
            Result.Text = Code.substr(0, TokenLength);
183
4
            Code = Code.drop_front(TokenLength);
184
4
            return Result;
185
4
          }
186
855
          if (TokenLength == Code.size() || 
!isAlphanumeric(Code[TokenLength])847
)
187
116
            break;
188
739
          ++TokenLength;
189
739
        }
190
116
        if (TokenLength == 4 && 
Code.startswith("true")30
) {
191
1
          Result.Kind = TokenInfo::TK_Literal;
192
1
          Result.Value = true;
193
115
        } else if (TokenLength == 5 && 
Code.startswith("false")4
) {
194
1
          Result.Kind = TokenInfo::TK_Literal;
195
1
          Result.Value = false;
196
114
        } else {
197
114
          Result.Kind = TokenInfo::TK_Ident;
198
114
          Result.Text = Code.substr(0, TokenLength);
199
114
        }
200
116
        Code = Code.drop_front(TokenLength);
201
116
      } else {
202
0
        Result.Kind = TokenInfo::TK_InvalidChar;
203
0
        Result.Text = Code.substr(0, 1);
204
0
        Code = Code.drop_front(1);
205
0
      }
206
116
      break;
207
406
    }
208
209
397
    Result.Range.End = currentLocation();
210
397
    return Result;
211
406
  }
212
213
  /// Consume an unsigned and float literal.
214
15
  void consumeNumberLiteral(TokenInfo *Result) {
215
15
    bool isFloatingLiteral = false;
216
15
    unsigned Length = 1;
217
15
    if (Code.size() > 1) {
218
      // Consume the 'x' or 'b' radix modifier, if present.
219
13
      switch (toLowercase(Code[1])) {
220
1
      case 'x': case 'b': Length = 2;
221
13
      }
222
13
    }
223
37
    
while (15
Length < Code.size() &&
isHexDigit(Code[Length])30
)
224
22
      ++Length;
225
226
    // Try to recognize a floating point literal.
227
31
    while (Length < Code.size()) {
228
20
      char c = Code[Length];
229
20
      if (c == '-' || 
c == '+'19
||
c == '.'18
||
isHexDigit(c)14
) {
230
16
        isFloatingLiteral = true;
231
16
        Length++;
232
16
      } else {
233
4
        break;
234
4
      }
235
20
    }
236
237
15
    Result->Text = Code.substr(0, Length);
238
15
    Code = Code.drop_front(Length);
239
240
15
    if (isFloatingLiteral) {
241
4
      char *end;
242
4
      errno = 0;
243
4
      std::string Text = Result->Text.str();
244
4
      double doubleValue = strtod(Text.c_str(), &end);
245
4
      if (*end == 0 && errno
== 03
) {
246
3
        Result->Kind = TokenInfo::TK_Literal;
247
3
        Result->Value = doubleValue;
248
3
        return;
249
3
      }
250
11
    } else {
251
11
      unsigned Value;
252
11
      if (!Result->Text.getAsInteger(0, Value)) {
253
9
        Result->Kind = TokenInfo::TK_Literal;
254
9
        Result->Value = Value;
255
9
        return;
256
9
      }
257
11
    }
258
259
3
    SourceRange Range;
260
3
    Range.Start = Result->Range.Start;
261
3
    Range.End = currentLocation();
262
3
    Error->addError(Range, Error->ET_ParserNumberError) << Result->Text;
263
3
    Result->Kind = TokenInfo::TK_Error;
264
3
  }
265
266
  /// Consume a string literal.
267
  ///
268
  /// \c Code must be positioned at the start of the literal (the opening
269
  /// quote). Consumed until it finds the same closing quote character.
270
37
  void consumeStringLiteral(TokenInfo *Result) {
271
37
    bool InEscape = false;
272
37
    const char Marker = Code[0];
273
301
    for (size_t Length = 1, Size = Code.size(); Length != Size; 
++Length264
) {
274
300
      if (InEscape) {
275
0
        InEscape = false;
276
0
        continue;
277
0
      }
278
300
      if (Code[Length] == '\\') {
279
0
        InEscape = true;
280
0
        continue;
281
0
      }
282
300
      if (Code[Length] == Marker) {
283
36
        Result->Kind = TokenInfo::TK_Literal;
284
36
        Result->Text = Code.substr(0, Length + 1);
285
36
        Result->Value = Code.substr(1, Length - 1);
286
36
        Code = Code.drop_front(Length + 1);
287
36
        return;
288
36
      }
289
300
    }
290
291
1
    StringRef ErrorText = Code;
292
1
    Code = Code.drop_front(Code.size());
293
1
    SourceRange Range;
294
1
    Range.Start = Result->Range.Start;
295
1
    Range.End = currentLocation();
296
1
    Error->addError(Range, Error->ET_ParserStringError) << ErrorText;
297
1
    Result->Kind = TokenInfo::TK_Error;
298
1
  }
299
300
  /// Consume all leading whitespace from \c Code.
301
462
  void consumeWhitespace() {
302
497
    Code = Code.drop_while([](char c) {
303
      // Don't trim newlines.
304
497
      return StringRef(" \t\v\f\r").contains(c);
305
497
    });
306
462
  }
307
308
863
  SourceLocation currentLocation() {
309
863
    SourceLocation Location;
310
863
    Location.Line = Line;
311
863
    Location.Column = Code.data() - StartOfLine.data() + 1;
312
863
    return Location;
313
863
  }
314
315
  StringRef &Code;
316
  StringRef StartOfLine;
317
  unsigned Line = 1;
318
  Diagnostics *Error;
319
  TokenInfo NextToken;
320
  const char *CodeCompletionLocation = nullptr;
321
};
322
323
6
Parser::Sema::~Sema() = default;
324
325
std::vector<ArgKind> Parser::Sema::getAcceptedCompletionTypes(
326
0
    llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context) {
327
0
  return {};
328
0
}
329
330
std::vector<MatcherCompletion>
331
0
Parser::Sema::getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes) {
332
0
  return {};
333
0
}
334
335
struct Parser::ScopedContextEntry {
336
  Parser *P;
337
338
85
  ScopedContextEntry(Parser *P, MatcherCtor C) : P(P) {
339
85
    P->ContextStack.push_back(std::make_pair(C, 0u));
340
85
  }
341
342
85
  ~ScopedContextEntry() {
343
85
    P->ContextStack.pop_back();
344
85
  }
345
346
59
  void nextArg() {
347
59
    ++P->ContextStack.back().second;
348
59
  }
349
};
350
351
/// Parse expressions that start with an identifier.
352
///
353
/// This function can parse named values and matchers.
354
/// In case of failure it will try to determine the user's intent to give
355
/// an appropriate error message.
356
94
bool Parser::parseIdentifierPrefixImpl(VariantValue *Value) {
357
94
  const TokenInfo NameToken = Tokenizer->consumeNextToken();
358
359
94
  if (Tokenizer->nextTokenKind() != TokenInfo::TK_OpenParen) {
360
    // Parse as a named value.
361
10
    if (const VariantValue NamedValue =
362
10
            NamedValues ? NamedValues->lookup(NameToken.Text)
363
10
                        : VariantValue()) {
364
365
7
      if (Tokenizer->nextTokenKind() != TokenInfo::TK_Period) {
366
3
        *Value = NamedValue;
367
3
        return true;
368
3
      }
369
370
4
      std::string BindID;
371
4
      Tokenizer->consumeNextToken();
372
4
      TokenInfo ChainCallToken = Tokenizer->consumeNextToken();
373
4
      if (ChainCallToken.Kind == TokenInfo::TK_CodeCompletion) {
374
0
        addCompletion(ChainCallToken, MatcherCompletion("bind(\"", "bind", 1));
375
0
        return false;
376
0
      }
377
378
4
      if (ChainCallToken.Kind != TokenInfo::TK_Ident ||
379
4
          
(3
ChainCallToken.Text != TokenInfo::ID_Bind3
&&
380
3
           
ChainCallToken.Text != TokenInfo::ID_With0
)) {
381
1
        Error->addError(ChainCallToken.Range,
382
1
                        Error->ET_ParserMalformedChainedExpr);
383
1
        return false;
384
1
      }
385
3
      if (ChainCallToken.Text == TokenInfo::ID_With) {
386
387
0
        Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error,
388
0
                                 NameToken.Text, NameToken.Range);
389
390
0
        Error->addError(ChainCallToken.Range,
391
0
                        Error->ET_RegistryMatcherNoWithSupport);
392
0
        return false;
393
0
      }
394
3
      if (!parseBindID(BindID))
395
1
        return false;
396
397
2
      assert(NamedValue.isMatcher());
398
2
      std::optional<DynTypedMatcher> Result =
399
2
          NamedValue.getMatcher().getSingleMatcher();
400
2
      if (Result) {
401
2
        std::optional<DynTypedMatcher> Bound = Result->tryBind(BindID);
402
2
        if (Bound) {
403
2
          *Value = VariantMatcher::SingleMatcher(*Bound);
404
2
          return true;
405
2
        }
406
2
      }
407
0
      return false;
408
2
    }
409
410
3
    if (Tokenizer->nextTokenKind() == TokenInfo::TK_NewLine) {
411
1
      Error->addError(Tokenizer->peekNextToken().Range,
412
1
                      Error->ET_ParserNoOpenParen)
413
1
          << "NewLine";
414
1
      return false;
415
1
    }
416
417
    // If the syntax is correct and the name is not a matcher either, report
418
    // unknown named value.
419
2
    if ((Tokenizer->nextTokenKind() == TokenInfo::TK_Comma ||
420
2
         Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen ||
421
2
         
Tokenizer->nextTokenKind() == TokenInfo::TK_NewLine1
||
422
2
         
Tokenizer->nextTokenKind() == TokenInfo::TK_Eof1
) &&
423
2
        
!S->lookupMatcherCtor(NameToken.Text)1
) {
424
1
      Error->addError(NameToken.Range, Error->ET_RegistryValueNotFound)
425
1
          << NameToken.Text;
426
1
      return false;
427
1
    }
428
    // Otherwise, fallback to the matcher parser.
429
2
  }
430
431
85
  Tokenizer->SkipNewlines();
432
433
85
  assert(NameToken.Kind == TokenInfo::TK_Ident);
434
85
  TokenInfo OpenToken = Tokenizer->consumeNextToken();
435
85
  if (OpenToken.Kind != TokenInfo::TK_OpenParen) {
436
1
    Error->addError(OpenToken.Range, Error->ET_ParserNoOpenParen)
437
1
        << OpenToken.Text;
438
1
    return false;
439
1
  }
440
441
84
  std::optional<MatcherCtor> Ctor = S->lookupMatcherCtor(NameToken.Text);
442
443
  // Parse as a matcher expression.
444
84
  return parseMatcherExpressionImpl(NameToken, OpenToken, Ctor, Value);
445
85
}
446
447
10
bool Parser::parseBindID(std::string &BindID) {
448
  // Parse the parenthesized argument to .bind("foo")
449
10
  const TokenInfo OpenToken = Tokenizer->consumeNextToken();
450
10
  const TokenInfo IDToken = Tokenizer->consumeNextTokenIgnoreNewlines();
451
10
  const TokenInfo CloseToken = Tokenizer->consumeNextTokenIgnoreNewlines();
452
453
  // TODO: We could use different error codes for each/some to be more
454
  //       explicit about the syntax error.
455
10
  if (OpenToken.Kind != TokenInfo::TK_OpenParen) {
456
2
    Error->addError(OpenToken.Range, Error->ET_ParserMalformedBindExpr);
457
2
    return false;
458
2
  }
459
8
  if (IDToken.Kind != TokenInfo::TK_Literal || 
!IDToken.Value.isString()7
) {
460
1
    Error->addError(IDToken.Range, Error->ET_ParserMalformedBindExpr);
461
1
    return false;
462
1
  }
463
7
  if (CloseToken.Kind != TokenInfo::TK_CloseParen) {
464
1
    Error->addError(CloseToken.Range, Error->ET_ParserMalformedBindExpr);
465
1
    return false;
466
1
  }
467
6
  BindID = IDToken.Value.getString();
468
6
  return true;
469
7
}
470
471
bool Parser::parseMatcherBuilder(MatcherCtor Ctor, const TokenInfo &NameToken,
472
                                 const TokenInfo &OpenToken,
473
6
                                 VariantValue *Value) {
474
6
  std::vector<ParserValue> Args;
475
6
  TokenInfo EndToken;
476
477
6
  Tokenizer->SkipNewlines();
478
479
6
  {
480
6
    ScopedContextEntry SCE(this, Ctor);
481
482
9
    while (Tokenizer->nextTokenKind() != TokenInfo::TK_Eof) {
483
9
      if (Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen) {
484
        // End of args.
485
4
        EndToken = Tokenizer->consumeNextToken();
486
4
        break;
487
4
      }
488
5
      if (!Args.empty()) {
489
        // We must find a , token to continue.
490
0
        TokenInfo CommaToken = Tokenizer->consumeNextToken();
491
0
        if (CommaToken.Kind != TokenInfo::TK_Comma) {
492
0
          Error->addError(CommaToken.Range, Error->ET_ParserNoComma)
493
0
              << CommaToken.Text;
494
0
          return false;
495
0
        }
496
0
      }
497
498
5
      Diagnostics::Context Ctx(Diagnostics::Context::MatcherArg, Error,
499
5
                               NameToken.Text, NameToken.Range,
500
5
                               Args.size() + 1);
501
5
      ParserValue ArgValue;
502
5
      Tokenizer->SkipNewlines();
503
504
5
      if (Tokenizer->peekNextToken().Kind == TokenInfo::TK_CodeCompletion) {
505
1
        addExpressionCompletions();
506
1
        return false;
507
1
      }
508
509
4
      TokenInfo NodeMatcherToken = Tokenizer->consumeNextToken();
510
511
4
      if (NodeMatcherToken.Kind != TokenInfo::TK_Ident) {
512
1
        Error->addError(NameToken.Range, Error->ET_ParserFailedToBuildMatcher)
513
1
            << NameToken.Text;
514
1
        return false;
515
1
      }
516
517
3
      ArgValue.Text = NodeMatcherToken.Text;
518
3
      ArgValue.Range = NodeMatcherToken.Range;
519
520
3
      std::optional<MatcherCtor> MappedMatcher =
521
3
          S->lookupMatcherCtor(ArgValue.Text);
522
523
3
      if (!MappedMatcher) {
524
0
        Error->addError(NodeMatcherToken.Range,
525
0
                        Error->ET_RegistryMatcherNotFound)
526
0
            << NodeMatcherToken.Text;
527
0
        return false;
528
0
      }
529
530
3
      ASTNodeKind NK = S->nodeMatcherType(*MappedMatcher);
531
532
3
      if (NK.isNone()) {
533
0
        Error->addError(NodeMatcherToken.Range,
534
0
                        Error->ET_RegistryNonNodeMatcher)
535
0
            << NodeMatcherToken.Text;
536
0
        return false;
537
0
      }
538
539
3
      ArgValue.Value = NK;
540
541
3
      Tokenizer->SkipNewlines();
542
3
      Args.push_back(ArgValue);
543
544
3
      SCE.nextArg();
545
3
    }
546
6
  }
547
548
4
  if (EndToken.Kind == TokenInfo::TK_Eof) {
549
0
    Error->addError(OpenToken.Range, Error->ET_ParserNoCloseParen);
550
0
    return false;
551
0
  }
552
553
4
  internal::MatcherDescriptorPtr BuiltCtor =
554
4
      S->buildMatcherCtor(Ctor, NameToken.Range, Args, Error);
555
556
4
  if (!BuiltCtor.get()) {
557
1
    Error->addError(NameToken.Range, Error->ET_ParserFailedToBuildMatcher)
558
1
        << NameToken.Text;
559
1
    return false;
560
1
  }
561
562
3
  std::string BindID;
563
3
  if (Tokenizer->peekNextToken().Kind == TokenInfo::TK_Period) {
564
3
    Tokenizer->consumeNextToken();
565
3
    TokenInfo ChainCallToken = Tokenizer->consumeNextToken();
566
3
    if (ChainCallToken.Kind == TokenInfo::TK_CodeCompletion) {
567
1
      addCompletion(ChainCallToken, MatcherCompletion("bind(\"", "bind", 1));
568
1
      addCompletion(ChainCallToken, MatcherCompletion("with(", "with", 1));
569
1
      return false;
570
1
    }
571
2
    if (ChainCallToken.Kind != TokenInfo::TK_Ident ||
572
2
        (ChainCallToken.Text != TokenInfo::ID_Bind &&
573
2
         ChainCallToken.Text != TokenInfo::ID_With)) {
574
0
      Error->addError(ChainCallToken.Range,
575
0
                      Error->ET_ParserMalformedChainedExpr);
576
0
      return false;
577
0
    }
578
2
    if (ChainCallToken.Text == TokenInfo::ID_Bind) {
579
0
      if (!parseBindID(BindID))
580
0
        return false;
581
0
      Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error,
582
0
                               NameToken.Text, NameToken.Range);
583
0
      SourceRange MatcherRange = NameToken.Range;
584
0
      MatcherRange.End = ChainCallToken.Range.End;
585
0
      VariantMatcher Result = S->actOnMatcherExpression(
586
0
          BuiltCtor.get(), MatcherRange, BindID, {}, Error);
587
0
      if (Result.isNull())
588
0
        return false;
589
590
0
      *Value = Result;
591
0
      return true;
592
2
    } else if (ChainCallToken.Text == TokenInfo::ID_With) {
593
2
      Tokenizer->SkipNewlines();
594
595
2
      if (Tokenizer->nextTokenKind() != TokenInfo::TK_OpenParen) {
596
1
        StringRef ErrTxt = Tokenizer->nextTokenKind() == TokenInfo::TK_Eof
597
1
                               ? StringRef("EOF")
598
1
                               : 
Tokenizer->peekNextToken().Text0
;
599
1
        Error->addError(Tokenizer->peekNextToken().Range,
600
1
                        Error->ET_ParserNoOpenParen)
601
1
            << ErrTxt;
602
1
        return false;
603
1
      }
604
605
1
      TokenInfo WithOpenToken = Tokenizer->consumeNextToken();
606
607
1
      return parseMatcherExpressionImpl(NameToken, WithOpenToken,
608
1
                                        BuiltCtor.get(), Value);
609
2
    }
610
2
  }
611
612
0
  Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error,
613
0
                           NameToken.Text, NameToken.Range);
614
0
  SourceRange MatcherRange = NameToken.Range;
615
0
  MatcherRange.End = EndToken.Range.End;
616
0
  VariantMatcher Result = S->actOnMatcherExpression(
617
0
      BuiltCtor.get(), MatcherRange, BindID, {}, Error);
618
0
  if (Result.isNull())
619
0
    return false;
620
621
0
  *Value = Result;
622
0
  return true;
623
0
}
624
625
/// Parse and validate a matcher expression.
626
/// \return \c true on success, in which case \c Value has the matcher parsed.
627
///   If the input is malformed, or some argument has an error, it
628
///   returns \c false.
629
bool Parser::parseMatcherExpressionImpl(const TokenInfo &NameToken,
630
                                        const TokenInfo &OpenToken,
631
                                        std::optional<MatcherCtor> Ctor,
632
85
                                        VariantValue *Value) {
633
85
  if (!Ctor) {
634
4
    Error->addError(NameToken.Range, Error->ET_RegistryMatcherNotFound)
635
4
        << NameToken.Text;
636
    // Do not return here. We need to continue to give completion suggestions.
637
4
  }
638
639
85
  if (Ctor && 
*Ctor81
&&
S->isBuilderMatcher(*Ctor)81
)
640
6
    return parseMatcherBuilder(*Ctor, NameToken, OpenToken, Value);
641
642
79
  std::vector<ParserValue> Args;
643
79
  TokenInfo EndToken;
644
645
79
  Tokenizer->SkipNewlines();
646
647
79
  {
648
79
    ScopedContextEntry SCE(this, Ctor.value_or(nullptr));
649
650
135
    while (Tokenizer->nextTokenKind() != TokenInfo::TK_Eof) {
651
132
      if (Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen) {
652
        // End of args.
653
60
        EndToken = Tokenizer->consumeNextToken();
654
60
        break;
655
60
      }
656
72
      if (!Args.empty()) {
657
        // We must find a , token to continue.
658
14
        const TokenInfo CommaToken = Tokenizer->consumeNextToken();
659
14
        if (CommaToken.Kind != TokenInfo::TK_Comma) {
660
1
          Error->addError(CommaToken.Range, Error->ET_ParserNoComma)
661
1
              << CommaToken.Text;
662
1
          return false;
663
1
        }
664
14
      }
665
666
71
      Diagnostics::Context Ctx(Diagnostics::Context::MatcherArg, Error,
667
71
                               NameToken.Text, NameToken.Range,
668
71
                               Args.size() + 1);
669
71
      ParserValue ArgValue;
670
71
      Tokenizer->SkipNewlines();
671
71
      ArgValue.Text = Tokenizer->peekNextToken().Text;
672
71
      ArgValue.Range = Tokenizer->peekNextToken().Range;
673
71
      if (!parseExpressionImpl(&ArgValue.Value)) {
674
15
        return false;
675
15
      }
676
677
56
      Tokenizer->SkipNewlines();
678
56
      Args.push_back(ArgValue);
679
56
      SCE.nextArg();
680
56
    }
681
79
  }
682
683
63
  if (EndToken.Kind == TokenInfo::TK_Eof) {
684
3
    Error->addError(OpenToken.Range, Error->ET_ParserNoCloseParen);
685
3
    return false;
686
3
  }
687
688
60
  std::string BindID;
689
60
  if (Tokenizer->peekNextToken().Kind == TokenInfo::TK_Period) {
690
10
    Tokenizer->consumeNextToken();
691
10
    TokenInfo ChainCallToken = Tokenizer->consumeNextToken();
692
10
    if (ChainCallToken.Kind == TokenInfo::TK_CodeCompletion) {
693
1
      addCompletion(ChainCallToken, MatcherCompletion("bind(\"", "bind", 1));
694
1
      return false;
695
1
    }
696
697
9
    if (ChainCallToken.Kind != TokenInfo::TK_Ident) {
698
0
      Error->addError(ChainCallToken.Range,
699
0
                      Error->ET_ParserMalformedChainedExpr);
700
0
      return false;
701
0
    }
702
9
    if (ChainCallToken.Text == TokenInfo::ID_With) {
703
704
1
      Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error,
705
1
                               NameToken.Text, NameToken.Range);
706
707
1
      Error->addError(ChainCallToken.Range,
708
1
                      Error->ET_RegistryMatcherNoWithSupport);
709
1
      return false;
710
1
    }
711
8
    if (ChainCallToken.Text != TokenInfo::ID_Bind) {
712
1
      Error->addError(ChainCallToken.Range,
713
1
                      Error->ET_ParserMalformedChainedExpr);
714
1
      return false;
715
1
    }
716
7
    if (!parseBindID(BindID))
717
3
      return false;
718
7
  }
719
720
54
  if (!Ctor)
721
1
    return false;
722
723
  // Merge the start and end infos.
724
53
  Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error,
725
53
                           NameToken.Text, NameToken.Range);
726
53
  SourceRange MatcherRange = NameToken.Range;
727
53
  MatcherRange.End = EndToken.Range.End;
728
53
  VariantMatcher Result = S->actOnMatcherExpression(
729
53
      *Ctor, MatcherRange, BindID, Args, Error);
730
53
  if (Result.isNull()) 
return false9
;
731
732
44
  *Value = Result;
733
44
  return true;
734
53
}
735
736
// If the prefix of this completion matches the completion token, add it to
737
// Completions minus the prefix.
738
void Parser::addCompletion(const TokenInfo &CompToken,
739
942
                           const MatcherCompletion& Completion) {
740
942
  if (StringRef(Completion.TypedText).startswith(CompToken.Text) &&
741
942
      
Completion.Specificity > 092
) {
742
92
    Completions.emplace_back(Completion.TypedText.substr(CompToken.Text.size()),
743
92
                             Completion.MatcherDecl, Completion.Specificity);
744
92
  }
745
942
}
746
747
std::vector<MatcherCompletion> Parser::getNamedValueCompletions(
748
6
    ArrayRef<ArgKind> AcceptedTypes) {
749
6
  if (!NamedValues) 
return std::vector<MatcherCompletion>()3
;
750
3
  std::vector<MatcherCompletion> Result;
751
6
  for (const auto &Entry : *NamedValues) {
752
6
    unsigned Specificity;
753
6
    if (Entry.getValue().isConvertibleTo(AcceptedTypes, &Specificity)) {
754
3
      std::string Decl =
755
3
          (Entry.getValue().getTypeAsString() + " " + Entry.getKey()).str();
756
3
      Result.emplace_back(Entry.getKey(), Decl, Specificity);
757
3
    }
758
6
  }
759
3
  return Result;
760
6
}
761
762
6
void Parser::addExpressionCompletions() {
763
6
  const TokenInfo CompToken = Tokenizer->consumeNextTokenIgnoreNewlines();
764
6
  assert(CompToken.Kind == TokenInfo::TK_CodeCompletion);
765
766
  // We cannot complete code if there is an invalid element on the context
767
  // stack.
768
6
  for (ContextStackTy::iterator I = ContextStack.begin(),
769
6
                                E = ContextStack.end();
770
11
       I != E; 
++I5
) {
771
5
    if (!I->first)
772
0
      return;
773
5
  }
774
775
6
  auto AcceptedTypes = S->getAcceptedCompletionTypes(ContextStack);
776
936
  for (const auto &Completion : S->getMatcherCompletions(AcceptedTypes)) {
777
936
    addCompletion(CompToken, Completion);
778
936
  }
779
780
6
  for (const auto &Completion : getNamedValueCompletions(AcceptedTypes)) {
781
3
    addCompletion(CompToken, Completion);
782
3
  }
783
6
}
784
785
/// Parse an <Expression>
786
144
bool Parser::parseExpressionImpl(VariantValue *Value) {
787
144
  switch (Tokenizer->nextTokenKind()) {
788
39
  case TokenInfo::TK_Literal:
789
39
    *Value = Tokenizer->consumeNextToken().Value;
790
39
    return true;
791
792
94
  case TokenInfo::TK_Ident:
793
94
    return parseIdentifierPrefixImpl(Value);
794
795
5
  case TokenInfo::TK_CodeCompletion:
796
5
    addExpressionCompletions();
797
5
    return false;
798
799
1
  case TokenInfo::TK_Eof:
800
1
    Error->addError(Tokenizer->consumeNextToken().Range,
801
1
                    Error->ET_ParserNoCode);
802
1
    return false;
803
804
4
  case TokenInfo::TK_Error:
805
    // This error was already reported by the tokenizer.
806
4
    return false;
807
0
  case TokenInfo::TK_NewLine:
808
1
  case TokenInfo::TK_OpenParen:
809
1
  case TokenInfo::TK_CloseParen:
810
1
  case TokenInfo::TK_Comma:
811
1
  case TokenInfo::TK_Period:
812
1
  case TokenInfo::TK_InvalidChar:
813
1
    const TokenInfo Token = Tokenizer->consumeNextToken();
814
1
    Error->addError(Token.Range, Error->ET_ParserInvalidToken)
815
1
        << (Token.Kind == TokenInfo::TK_NewLine ? 
"NewLine"0
: Token.Text);
816
1
    return false;
817
144
  }
818
819
0
  llvm_unreachable("Unknown token kind.");
820
0
}
821
822
static llvm::ManagedStatic<Parser::RegistrySema> DefaultRegistrySema;
823
824
Parser::Parser(CodeTokenizer *Tokenizer, Sema *S,
825
               const NamedValueMap *NamedValues, Diagnostics *Error)
826
73
    : Tokenizer(Tokenizer), S(S ? 
S18
:
&*DefaultRegistrySema55
),
827
73
      NamedValues(NamedValues), Error(Error) {}
828
829
0
Parser::RegistrySema::~RegistrySema() = default;
830
831
std::optional<MatcherCtor>
832
83
Parser::RegistrySema::lookupMatcherCtor(StringRef MatcherName) {
833
83
  return Registry::lookupMatcherCtor(MatcherName);
834
83
}
835
836
VariantMatcher Parser::RegistrySema::actOnMatcherExpression(
837
    MatcherCtor Ctor, SourceRange NameRange, StringRef BindID,
838
49
    ArrayRef<ParserValue> Args, Diagnostics *Error) {
839
49
  if (BindID.empty()) {
840
46
    return Registry::constructMatcher(Ctor, NameRange, Args, Error);
841
46
  } else {
842
3
    return Registry::constructBoundMatcher(Ctor, NameRange, BindID, Args,
843
3
                                           Error);
844
3
  }
845
49
}
846
847
std::vector<ArgKind> Parser::RegistrySema::getAcceptedCompletionTypes(
848
6
    ArrayRef<std::pair<MatcherCtor, unsigned>> Context) {
849
6
  return Registry::getAcceptedCompletionTypes(Context);
850
6
}
851
852
std::vector<MatcherCompletion> Parser::RegistrySema::getMatcherCompletions(
853
6
    ArrayRef<ArgKind> AcceptedTypes) {
854
6
  return Registry::getMatcherCompletions(AcceptedTypes);
855
6
}
856
857
76
bool Parser::RegistrySema::isBuilderMatcher(MatcherCtor Ctor) const {
858
76
  return Registry::isBuilderMatcher(Ctor);
859
76
}
860
861
3
ASTNodeKind Parser::RegistrySema::nodeMatcherType(MatcherCtor Ctor) const {
862
3
  return Registry::nodeMatcherType(Ctor);
863
3
}
864
865
internal::MatcherDescriptorPtr
866
Parser::RegistrySema::buildMatcherCtor(MatcherCtor Ctor, SourceRange NameRange,
867
                                       ArrayRef<ParserValue> Args,
868
4
                                       Diagnostics *Error) const {
869
4
  return Registry::buildMatcherCtor(Ctor, NameRange, Args, Error);
870
4
}
871
872
bool Parser::parseExpression(StringRef &Code, Sema *S,
873
                             const NamedValueMap *NamedValues,
874
65
                             VariantValue *Value, Diagnostics *Error) {
875
65
  CodeTokenizer Tokenizer(Code, Error);
876
65
  if (!Parser(&Tokenizer, S, NamedValues, Error).parseExpressionImpl(Value))
877
33
    return false;
878
32
  auto NT = Tokenizer.peekNextToken();
879
32
  if (NT.Kind != TokenInfo::TK_Eof && 
NT.Kind != TokenInfo::TK_NewLine5
) {
880
1
    Error->addError(Tokenizer.peekNextToken().Range,
881
1
                    Error->ET_ParserTrailingCode);
882
1
    return false;
883
1
  }
884
31
  return true;
885
32
}
886
887
std::vector<MatcherCompletion>
888
Parser::completeExpression(StringRef &Code, unsigned CompletionOffset, Sema *S,
889
8
                           const NamedValueMap *NamedValues) {
890
8
  Diagnostics Error;
891
8
  CodeTokenizer Tokenizer(Code, &Error, CompletionOffset);
892
8
  Parser P(&Tokenizer, S, NamedValues, &Error);
893
8
  VariantValue Dummy;
894
8
  P.parseExpressionImpl(&Dummy);
895
896
  // Sort by specificity, then by name.
897
8
  llvm::sort(P.Completions,
898
520
             [](const MatcherCompletion &A, const MatcherCompletion &B) {
899
520
               if (A.Specificity != B.Specificity)
900
174
                 return A.Specificity > B.Specificity;
901
346
               return A.TypedText < B.TypedText;
902
520
             });
903
904
8
  return P.Completions;
905
8
}
906
907
std::optional<DynTypedMatcher>
908
Parser::parseMatcherExpression(StringRef &Code, Sema *S,
909
                               const NamedValueMap *NamedValues,
910
29
                               Diagnostics *Error) {
911
29
  VariantValue Value;
912
29
  if (!parseExpression(Code, S, NamedValues, &Value, Error))
913
11
    return std::nullopt;
914
18
  if (!Value.isMatcher()) {
915
1
    Error->addError(SourceRange(), Error->ET_ParserNotAMatcher);
916
1
    return std::nullopt;
917
1
  }
918
17
  std::optional<DynTypedMatcher> Result = Value.getMatcher().getSingleMatcher();
919
17
  if (!Result) {
920
1
    Error->addError(SourceRange(), Error->ET_ParserOverloadedType)
921
1
        << Value.getTypeAsString();
922
1
  }
923
17
  return Result;
924
18
}
925
926
} // namespace dynamic
927
} // namespace ast_matchers
928
} // namespace clang