1 //===- Parser.cpp - Matcher expression parser -----------------------------===//
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
7 //===----------------------------------------------------------------------===//
10 /// Recursive parser implementation for the matcher expression grammar.
12 //===----------------------------------------------------------------------===//
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"
33 namespace ast_matchers
{
36 /// Simple structure to hold information for one token from the parser.
37 struct Parser::TokenInfo
{
38 /// Different possible tokens.
53 /// Some known identifiers.
54 static const char* const ID_Bind
;
55 static const char *const ID_With
;
57 TokenInfo() = default;
60 TokenKind Kind
= TK_Eof
;
65 const char* const Parser::TokenInfo::ID_Bind
= "bind";
66 const char *const Parser::TokenInfo::ID_With
= "with";
68 /// Simple tokenizer for the parser.
69 class Parser::CodeTokenizer
{
71 explicit CodeTokenizer(StringRef
&MatcherCode
, Diagnostics
*Error
)
72 : Code(MatcherCode
), StartOfLine(MatcherCode
), Error(Error
) {
73 NextToken
= getNextToken();
76 CodeTokenizer(StringRef
&MatcherCode
, Diagnostics
*Error
,
77 unsigned CodeCompletionOffset
)
78 : Code(MatcherCode
), StartOfLine(MatcherCode
), Error(Error
),
79 CodeCompletionLocation(MatcherCode
.data() + CodeCompletionOffset
) {
80 NextToken
= getNextToken();
83 /// Returns but doesn't consume the next token.
84 const TokenInfo
&peekNextToken() const { return NextToken
; }
86 /// Consumes and returns the next token.
87 TokenInfo
consumeNextToken() {
88 TokenInfo ThisToken
= NextToken
;
89 NextToken
= getNextToken();
93 TokenInfo
SkipNewlines() {
94 while (NextToken
.Kind
== TokenInfo::TK_NewLine
)
95 NextToken
= getNextToken();
99 TokenInfo
consumeNextTokenIgnoreNewlines() {
101 if (NextToken
.Kind
== TokenInfo::TK_Eof
)
103 return consumeNextToken();
106 TokenInfo::TokenKind
nextTokenKind() const { return NextToken
.Kind
; }
109 TokenInfo
getNextToken() {
112 Result
.Range
.Start
= currentLocation();
114 if (CodeCompletionLocation
&& CodeCompletionLocation
<= Code
.data()) {
115 Result
.Kind
= TokenInfo::TK_CodeCompletion
;
116 Result
.Text
= StringRef(CodeCompletionLocation
, 0);
117 CodeCompletionLocation
= nullptr;
122 Result
.Kind
= TokenInfo::TK_Eof
;
129 Code
= Code
.drop_until([](char c
) { return c
== '\n'; });
130 return getNextToken();
132 Result
.Kind
= TokenInfo::TK_Comma
;
133 Result
.Text
= Code
.substr(0, 1);
134 Code
= Code
.drop_front();
137 Result
.Kind
= TokenInfo::TK_Period
;
138 Result
.Text
= Code
.substr(0, 1);
139 Code
= Code
.drop_front();
143 StartOfLine
= Code
.drop_front();
144 Result
.Kind
= TokenInfo::TK_NewLine
;
145 Result
.Text
= Code
.substr(0, 1);
146 Code
= Code
.drop_front();
149 Result
.Kind
= TokenInfo::TK_OpenParen
;
150 Result
.Text
= Code
.substr(0, 1);
151 Code
= Code
.drop_front();
154 Result
.Kind
= TokenInfo::TK_CloseParen
;
155 Result
.Text
= Code
.substr(0, 1);
156 Code
= Code
.drop_front();
161 // Parse a string literal.
162 consumeStringLiteral(&Result
);
165 case '0': case '1': case '2': case '3': case '4':
166 case '5': case '6': case '7': case '8': case '9':
167 // Parse an unsigned and float literal.
168 consumeNumberLiteral(&Result
);
172 if (isAlphanumeric(Code
[0])) {
173 // Parse an identifier
174 size_t TokenLength
= 1;
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 if (CodeCompletionLocation
== Code
.data() + TokenLength
) {
180 CodeCompletionLocation
= nullptr;
181 Result
.Kind
= TokenInfo::TK_CodeCompletion
;
182 Result
.Text
= Code
.substr(0, TokenLength
);
183 Code
= Code
.drop_front(TokenLength
);
186 if (TokenLength
== Code
.size() || !isAlphanumeric(Code
[TokenLength
]))
190 if (TokenLength
== 4 && Code
.startswith("true")) {
191 Result
.Kind
= TokenInfo::TK_Literal
;
193 } else if (TokenLength
== 5 && Code
.startswith("false")) {
194 Result
.Kind
= TokenInfo::TK_Literal
;
195 Result
.Value
= false;
197 Result
.Kind
= TokenInfo::TK_Ident
;
198 Result
.Text
= Code
.substr(0, TokenLength
);
200 Code
= Code
.drop_front(TokenLength
);
202 Result
.Kind
= TokenInfo::TK_InvalidChar
;
203 Result
.Text
= Code
.substr(0, 1);
204 Code
= Code
.drop_front(1);
209 Result
.Range
.End
= currentLocation();
213 /// Consume an unsigned and float literal.
214 void consumeNumberLiteral(TokenInfo
*Result
) {
215 bool isFloatingLiteral
= false;
217 if (Code
.size() > 1) {
218 // Consume the 'x' or 'b' radix modifier, if present.
219 switch (toLowercase(Code
[1])) {
220 case 'x': case 'b': Length
= 2;
223 while (Length
< Code
.size() && isHexDigit(Code
[Length
]))
226 // Try to recognize a floating point literal.
227 while (Length
< Code
.size()) {
228 char c
= Code
[Length
];
229 if (c
== '-' || c
== '+' || c
== '.' || isHexDigit(c
)) {
230 isFloatingLiteral
= true;
237 Result
->Text
= Code
.substr(0, Length
);
238 Code
= Code
.drop_front(Length
);
240 if (isFloatingLiteral
) {
243 std::string Text
= Result
->Text
.str();
244 double doubleValue
= strtod(Text
.c_str(), &end
);
245 if (*end
== 0 && errno
== 0) {
246 Result
->Kind
= TokenInfo::TK_Literal
;
247 Result
->Value
= doubleValue
;
252 if (!Result
->Text
.getAsInteger(0, Value
)) {
253 Result
->Kind
= TokenInfo::TK_Literal
;
254 Result
->Value
= Value
;
260 Range
.Start
= Result
->Range
.Start
;
261 Range
.End
= currentLocation();
262 Error
->addError(Range
, Error
->ET_ParserNumberError
) << Result
->Text
;
263 Result
->Kind
= TokenInfo::TK_Error
;
266 /// Consume a string literal.
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 void consumeStringLiteral(TokenInfo
*Result
) {
271 bool InEscape
= false;
272 const char Marker
= Code
[0];
273 for (size_t Length
= 1, Size
= Code
.size(); Length
!= Size
; ++Length
) {
278 if (Code
[Length
] == '\\') {
282 if (Code
[Length
] == Marker
) {
283 Result
->Kind
= TokenInfo::TK_Literal
;
284 Result
->Text
= Code
.substr(0, Length
+ 1);
285 Result
->Value
= Code
.substr(1, Length
- 1);
286 Code
= Code
.drop_front(Length
+ 1);
291 StringRef ErrorText
= Code
;
292 Code
= Code
.drop_front(Code
.size());
294 Range
.Start
= Result
->Range
.Start
;
295 Range
.End
= currentLocation();
296 Error
->addError(Range
, Error
->ET_ParserStringError
) << ErrorText
;
297 Result
->Kind
= TokenInfo::TK_Error
;
300 /// Consume all leading whitespace from \c Code.
301 void consumeWhitespace() {
302 Code
= Code
.drop_while([](char c
) {
303 // Don't trim newlines.
304 return StringRef(" \t\v\f\r").contains(c
);
308 SourceLocation
currentLocation() {
309 SourceLocation Location
;
310 Location
.Line
= Line
;
311 Location
.Column
= Code
.data() - StartOfLine
.data() + 1;
316 StringRef StartOfLine
;
320 const char *CodeCompletionLocation
= nullptr;
323 Parser::Sema::~Sema() = default;
325 std::vector
<ArgKind
> Parser::Sema::getAcceptedCompletionTypes(
326 llvm::ArrayRef
<std::pair
<MatcherCtor
, unsigned>> Context
) {
330 std::vector
<MatcherCompletion
>
331 Parser::Sema::getMatcherCompletions(llvm::ArrayRef
<ArgKind
> AcceptedTypes
) {
335 struct Parser::ScopedContextEntry
{
338 ScopedContextEntry(Parser
*P
, MatcherCtor C
) : P(P
) {
339 P
->ContextStack
.push_back(std::make_pair(C
, 0u));
342 ~ScopedContextEntry() {
343 P
->ContextStack
.pop_back();
347 ++P
->ContextStack
.back().second
;
351 /// Parse expressions that start with an identifier.
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 bool Parser::parseIdentifierPrefixImpl(VariantValue
*Value
) {
357 const TokenInfo NameToken
= Tokenizer
->consumeNextToken();
359 if (Tokenizer
->nextTokenKind() != TokenInfo::TK_OpenParen
) {
360 // Parse as a named value.
361 if (const VariantValue NamedValue
=
362 NamedValues
? NamedValues
->lookup(NameToken
.Text
)
365 if (Tokenizer
->nextTokenKind() != TokenInfo::TK_Period
) {
371 Tokenizer
->consumeNextToken();
372 TokenInfo ChainCallToken
= Tokenizer
->consumeNextToken();
373 if (ChainCallToken
.Kind
== TokenInfo::TK_CodeCompletion
) {
374 addCompletion(ChainCallToken
, MatcherCompletion("bind(\"", "bind", 1));
378 if (ChainCallToken
.Kind
!= TokenInfo::TK_Ident
||
379 (ChainCallToken
.Text
!= TokenInfo::ID_Bind
&&
380 ChainCallToken
.Text
!= TokenInfo::ID_With
)) {
381 Error
->addError(ChainCallToken
.Range
,
382 Error
->ET_ParserMalformedChainedExpr
);
385 if (ChainCallToken
.Text
== TokenInfo::ID_With
) {
387 Diagnostics::Context
Ctx(Diagnostics::Context::ConstructMatcher
, Error
,
388 NameToken
.Text
, NameToken
.Range
);
390 Error
->addError(ChainCallToken
.Range
,
391 Error
->ET_RegistryMatcherNoWithSupport
);
394 if (!parseBindID(BindID
))
397 assert(NamedValue
.isMatcher());
398 std::optional
<DynTypedMatcher
> Result
=
399 NamedValue
.getMatcher().getSingleMatcher();
401 std::optional
<DynTypedMatcher
> Bound
= Result
->tryBind(BindID
);
403 *Value
= VariantMatcher::SingleMatcher(*Bound
);
410 if (Tokenizer
->nextTokenKind() == TokenInfo::TK_NewLine
) {
411 Error
->addError(Tokenizer
->peekNextToken().Range
,
412 Error
->ET_ParserNoOpenParen
)
417 // If the syntax is correct and the name is not a matcher either, report
418 // unknown named value.
419 if ((Tokenizer
->nextTokenKind() == TokenInfo::TK_Comma
||
420 Tokenizer
->nextTokenKind() == TokenInfo::TK_CloseParen
||
421 Tokenizer
->nextTokenKind() == TokenInfo::TK_NewLine
||
422 Tokenizer
->nextTokenKind() == TokenInfo::TK_Eof
) &&
423 !S
->lookupMatcherCtor(NameToken
.Text
)) {
424 Error
->addError(NameToken
.Range
, Error
->ET_RegistryValueNotFound
)
428 // Otherwise, fallback to the matcher parser.
431 Tokenizer
->SkipNewlines();
433 assert(NameToken
.Kind
== TokenInfo::TK_Ident
);
434 TokenInfo OpenToken
= Tokenizer
->consumeNextToken();
435 if (OpenToken
.Kind
!= TokenInfo::TK_OpenParen
) {
436 Error
->addError(OpenToken
.Range
, Error
->ET_ParserNoOpenParen
)
441 std::optional
<MatcherCtor
> Ctor
= S
->lookupMatcherCtor(NameToken
.Text
);
443 // Parse as a matcher expression.
444 return parseMatcherExpressionImpl(NameToken
, OpenToken
, Ctor
, Value
);
447 bool Parser::parseBindID(std::string
&BindID
) {
448 // Parse the parenthesized argument to .bind("foo")
449 const TokenInfo OpenToken
= Tokenizer
->consumeNextToken();
450 const TokenInfo IDToken
= Tokenizer
->consumeNextTokenIgnoreNewlines();
451 const TokenInfo CloseToken
= Tokenizer
->consumeNextTokenIgnoreNewlines();
453 // TODO: We could use different error codes for each/some to be more
454 // explicit about the syntax error.
455 if (OpenToken
.Kind
!= TokenInfo::TK_OpenParen
) {
456 Error
->addError(OpenToken
.Range
, Error
->ET_ParserMalformedBindExpr
);
459 if (IDToken
.Kind
!= TokenInfo::TK_Literal
|| !IDToken
.Value
.isString()) {
460 Error
->addError(IDToken
.Range
, Error
->ET_ParserMalformedBindExpr
);
463 if (CloseToken
.Kind
!= TokenInfo::TK_CloseParen
) {
464 Error
->addError(CloseToken
.Range
, Error
->ET_ParserMalformedBindExpr
);
467 BindID
= IDToken
.Value
.getString();
471 bool Parser::parseMatcherBuilder(MatcherCtor Ctor
, const TokenInfo
&NameToken
,
472 const TokenInfo
&OpenToken
,
473 VariantValue
*Value
) {
474 std::vector
<ParserValue
> Args
;
477 Tokenizer
->SkipNewlines();
480 ScopedContextEntry
SCE(this, Ctor
);
482 while (Tokenizer
->nextTokenKind() != TokenInfo::TK_Eof
) {
483 if (Tokenizer
->nextTokenKind() == TokenInfo::TK_CloseParen
) {
485 EndToken
= Tokenizer
->consumeNextToken();
489 // We must find a , token to continue.
490 TokenInfo CommaToken
= Tokenizer
->consumeNextToken();
491 if (CommaToken
.Kind
!= TokenInfo::TK_Comma
) {
492 Error
->addError(CommaToken
.Range
, Error
->ET_ParserNoComma
)
498 Diagnostics::Context
Ctx(Diagnostics::Context::MatcherArg
, Error
,
499 NameToken
.Text
, NameToken
.Range
,
501 ParserValue ArgValue
;
502 Tokenizer
->SkipNewlines();
504 if (Tokenizer
->peekNextToken().Kind
== TokenInfo::TK_CodeCompletion
) {
505 addExpressionCompletions();
509 TokenInfo NodeMatcherToken
= Tokenizer
->consumeNextToken();
511 if (NodeMatcherToken
.Kind
!= TokenInfo::TK_Ident
) {
512 Error
->addError(NameToken
.Range
, Error
->ET_ParserFailedToBuildMatcher
)
517 ArgValue
.Text
= NodeMatcherToken
.Text
;
518 ArgValue
.Range
= NodeMatcherToken
.Range
;
520 std::optional
<MatcherCtor
> MappedMatcher
=
521 S
->lookupMatcherCtor(ArgValue
.Text
);
523 if (!MappedMatcher
) {
524 Error
->addError(NodeMatcherToken
.Range
,
525 Error
->ET_RegistryMatcherNotFound
)
526 << NodeMatcherToken
.Text
;
530 ASTNodeKind NK
= S
->nodeMatcherType(*MappedMatcher
);
533 Error
->addError(NodeMatcherToken
.Range
,
534 Error
->ET_RegistryNonNodeMatcher
)
535 << NodeMatcherToken
.Text
;
541 Tokenizer
->SkipNewlines();
542 Args
.push_back(ArgValue
);
548 if (EndToken
.Kind
== TokenInfo::TK_Eof
) {
549 Error
->addError(OpenToken
.Range
, Error
->ET_ParserNoCloseParen
);
553 internal::MatcherDescriptorPtr BuiltCtor
=
554 S
->buildMatcherCtor(Ctor
, NameToken
.Range
, Args
, Error
);
556 if (!BuiltCtor
.get()) {
557 Error
->addError(NameToken
.Range
, Error
->ET_ParserFailedToBuildMatcher
)
563 if (Tokenizer
->peekNextToken().Kind
== TokenInfo::TK_Period
) {
564 Tokenizer
->consumeNextToken();
565 TokenInfo ChainCallToken
= Tokenizer
->consumeNextToken();
566 if (ChainCallToken
.Kind
== TokenInfo::TK_CodeCompletion
) {
567 addCompletion(ChainCallToken
, MatcherCompletion("bind(\"", "bind", 1));
568 addCompletion(ChainCallToken
, MatcherCompletion("with(", "with", 1));
571 if (ChainCallToken
.Kind
!= TokenInfo::TK_Ident
||
572 (ChainCallToken
.Text
!= TokenInfo::ID_Bind
&&
573 ChainCallToken
.Text
!= TokenInfo::ID_With
)) {
574 Error
->addError(ChainCallToken
.Range
,
575 Error
->ET_ParserMalformedChainedExpr
);
578 if (ChainCallToken
.Text
== TokenInfo::ID_Bind
) {
579 if (!parseBindID(BindID
))
581 Diagnostics::Context
Ctx(Diagnostics::Context::ConstructMatcher
, Error
,
582 NameToken
.Text
, NameToken
.Range
);
583 SourceRange MatcherRange
= NameToken
.Range
;
584 MatcherRange
.End
= ChainCallToken
.Range
.End
;
585 VariantMatcher Result
= S
->actOnMatcherExpression(
586 BuiltCtor
.get(), MatcherRange
, BindID
, {}, Error
);
592 } else if (ChainCallToken
.Text
== TokenInfo::ID_With
) {
593 Tokenizer
->SkipNewlines();
595 if (Tokenizer
->nextTokenKind() != TokenInfo::TK_OpenParen
) {
596 StringRef ErrTxt
= Tokenizer
->nextTokenKind() == TokenInfo::TK_Eof
598 : Tokenizer
->peekNextToken().Text
;
599 Error
->addError(Tokenizer
->peekNextToken().Range
,
600 Error
->ET_ParserNoOpenParen
)
605 TokenInfo WithOpenToken
= Tokenizer
->consumeNextToken();
607 return parseMatcherExpressionImpl(NameToken
, WithOpenToken
,
608 BuiltCtor
.get(), Value
);
612 Diagnostics::Context
Ctx(Diagnostics::Context::ConstructMatcher
, Error
,
613 NameToken
.Text
, NameToken
.Range
);
614 SourceRange MatcherRange
= NameToken
.Range
;
615 MatcherRange
.End
= EndToken
.Range
.End
;
616 VariantMatcher Result
= S
->actOnMatcherExpression(
617 BuiltCtor
.get(), MatcherRange
, BindID
, {}, Error
);
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 VariantValue
*Value
) {
634 Error
->addError(NameToken
.Range
, Error
->ET_RegistryMatcherNotFound
)
636 // Do not return here. We need to continue to give completion suggestions.
639 if (Ctor
&& *Ctor
&& S
->isBuilderMatcher(*Ctor
))
640 return parseMatcherBuilder(*Ctor
, NameToken
, OpenToken
, Value
);
642 std::vector
<ParserValue
> Args
;
645 Tokenizer
->SkipNewlines();
648 ScopedContextEntry
SCE(this, Ctor
.value_or(nullptr));
650 while (Tokenizer
->nextTokenKind() != TokenInfo::TK_Eof
) {
651 if (Tokenizer
->nextTokenKind() == TokenInfo::TK_CloseParen
) {
653 EndToken
= Tokenizer
->consumeNextToken();
657 // We must find a , token to continue.
658 const TokenInfo CommaToken
= Tokenizer
->consumeNextToken();
659 if (CommaToken
.Kind
!= TokenInfo::TK_Comma
) {
660 Error
->addError(CommaToken
.Range
, Error
->ET_ParserNoComma
)
666 Diagnostics::Context
Ctx(Diagnostics::Context::MatcherArg
, Error
,
667 NameToken
.Text
, NameToken
.Range
,
669 ParserValue ArgValue
;
670 Tokenizer
->SkipNewlines();
671 ArgValue
.Text
= Tokenizer
->peekNextToken().Text
;
672 ArgValue
.Range
= Tokenizer
->peekNextToken().Range
;
673 if (!parseExpressionImpl(&ArgValue
.Value
)) {
677 Tokenizer
->SkipNewlines();
678 Args
.push_back(ArgValue
);
683 if (EndToken
.Kind
== TokenInfo::TK_Eof
) {
684 Error
->addError(OpenToken
.Range
, Error
->ET_ParserNoCloseParen
);
689 if (Tokenizer
->peekNextToken().Kind
== TokenInfo::TK_Period
) {
690 Tokenizer
->consumeNextToken();
691 TokenInfo ChainCallToken
= Tokenizer
->consumeNextToken();
692 if (ChainCallToken
.Kind
== TokenInfo::TK_CodeCompletion
) {
693 addCompletion(ChainCallToken
, MatcherCompletion("bind(\"", "bind", 1));
697 if (ChainCallToken
.Kind
!= TokenInfo::TK_Ident
) {
698 Error
->addError(ChainCallToken
.Range
,
699 Error
->ET_ParserMalformedChainedExpr
);
702 if (ChainCallToken
.Text
== TokenInfo::ID_With
) {
704 Diagnostics::Context
Ctx(Diagnostics::Context::ConstructMatcher
, Error
,
705 NameToken
.Text
, NameToken
.Range
);
707 Error
->addError(ChainCallToken
.Range
,
708 Error
->ET_RegistryMatcherNoWithSupport
);
711 if (ChainCallToken
.Text
!= TokenInfo::ID_Bind
) {
712 Error
->addError(ChainCallToken
.Range
,
713 Error
->ET_ParserMalformedChainedExpr
);
716 if (!parseBindID(BindID
))
723 // Merge the start and end infos.
724 Diagnostics::Context
Ctx(Diagnostics::Context::ConstructMatcher
, Error
,
725 NameToken
.Text
, NameToken
.Range
);
726 SourceRange MatcherRange
= NameToken
.Range
;
727 MatcherRange
.End
= EndToken
.Range
.End
;
728 VariantMatcher Result
= S
->actOnMatcherExpression(
729 *Ctor
, MatcherRange
, BindID
, Args
, Error
);
730 if (Result
.isNull()) return false;
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 const MatcherCompletion
& Completion
) {
740 if (StringRef(Completion
.TypedText
).startswith(CompToken
.Text
) &&
741 Completion
.Specificity
> 0) {
742 Completions
.emplace_back(Completion
.TypedText
.substr(CompToken
.Text
.size()),
743 Completion
.MatcherDecl
, Completion
.Specificity
);
747 std::vector
<MatcherCompletion
> Parser::getNamedValueCompletions(
748 ArrayRef
<ArgKind
> AcceptedTypes
) {
749 if (!NamedValues
) return std::vector
<MatcherCompletion
>();
750 std::vector
<MatcherCompletion
> Result
;
751 for (const auto &Entry
: *NamedValues
) {
752 unsigned Specificity
;
753 if (Entry
.getValue().isConvertibleTo(AcceptedTypes
, &Specificity
)) {
755 (Entry
.getValue().getTypeAsString() + " " + Entry
.getKey()).str();
756 Result
.emplace_back(Entry
.getKey(), Decl
, Specificity
);
762 void Parser::addExpressionCompletions() {
763 const TokenInfo CompToken
= Tokenizer
->consumeNextTokenIgnoreNewlines();
764 assert(CompToken
.Kind
== TokenInfo::TK_CodeCompletion
);
766 // We cannot complete code if there is an invalid element on the context
768 for (ContextStackTy::iterator I
= ContextStack
.begin(),
769 E
= ContextStack
.end();
775 auto AcceptedTypes
= S
->getAcceptedCompletionTypes(ContextStack
);
776 for (const auto &Completion
: S
->getMatcherCompletions(AcceptedTypes
)) {
777 addCompletion(CompToken
, Completion
);
780 for (const auto &Completion
: getNamedValueCompletions(AcceptedTypes
)) {
781 addCompletion(CompToken
, Completion
);
785 /// Parse an <Expression>
786 bool Parser::parseExpressionImpl(VariantValue
*Value
) {
787 switch (Tokenizer
->nextTokenKind()) {
788 case TokenInfo::TK_Literal
:
789 *Value
= Tokenizer
->consumeNextToken().Value
;
792 case TokenInfo::TK_Ident
:
793 return parseIdentifierPrefixImpl(Value
);
795 case TokenInfo::TK_CodeCompletion
:
796 addExpressionCompletions();
799 case TokenInfo::TK_Eof
:
800 Error
->addError(Tokenizer
->consumeNextToken().Range
,
801 Error
->ET_ParserNoCode
);
804 case TokenInfo::TK_Error
:
805 // This error was already reported by the tokenizer.
807 case TokenInfo::TK_NewLine
:
808 case TokenInfo::TK_OpenParen
:
809 case TokenInfo::TK_CloseParen
:
810 case TokenInfo::TK_Comma
:
811 case TokenInfo::TK_Period
:
812 case TokenInfo::TK_InvalidChar
:
813 const TokenInfo Token
= Tokenizer
->consumeNextToken();
814 Error
->addError(Token
.Range
, Error
->ET_ParserInvalidToken
)
815 << (Token
.Kind
== TokenInfo::TK_NewLine
? "NewLine" : Token
.Text
);
819 llvm_unreachable("Unknown token kind.");
822 static llvm::ManagedStatic
<Parser::RegistrySema
> DefaultRegistrySema
;
824 Parser::Parser(CodeTokenizer
*Tokenizer
, Sema
*S
,
825 const NamedValueMap
*NamedValues
, Diagnostics
*Error
)
826 : Tokenizer(Tokenizer
), S(S
? S
: &*DefaultRegistrySema
),
827 NamedValues(NamedValues
), Error(Error
) {}
829 Parser::RegistrySema::~RegistrySema() = default;
831 std::optional
<MatcherCtor
>
832 Parser::RegistrySema::lookupMatcherCtor(StringRef MatcherName
) {
833 return Registry::lookupMatcherCtor(MatcherName
);
836 VariantMatcher
Parser::RegistrySema::actOnMatcherExpression(
837 MatcherCtor Ctor
, SourceRange NameRange
, StringRef BindID
,
838 ArrayRef
<ParserValue
> Args
, Diagnostics
*Error
) {
839 if (BindID
.empty()) {
840 return Registry::constructMatcher(Ctor
, NameRange
, Args
, Error
);
842 return Registry::constructBoundMatcher(Ctor
, NameRange
, BindID
, Args
,
847 std::vector
<ArgKind
> Parser::RegistrySema::getAcceptedCompletionTypes(
848 ArrayRef
<std::pair
<MatcherCtor
, unsigned>> Context
) {
849 return Registry::getAcceptedCompletionTypes(Context
);
852 std::vector
<MatcherCompletion
> Parser::RegistrySema::getMatcherCompletions(
853 ArrayRef
<ArgKind
> AcceptedTypes
) {
854 return Registry::getMatcherCompletions(AcceptedTypes
);
857 bool Parser::RegistrySema::isBuilderMatcher(MatcherCtor Ctor
) const {
858 return Registry::isBuilderMatcher(Ctor
);
861 ASTNodeKind
Parser::RegistrySema::nodeMatcherType(MatcherCtor Ctor
) const {
862 return Registry::nodeMatcherType(Ctor
);
865 internal::MatcherDescriptorPtr
866 Parser::RegistrySema::buildMatcherCtor(MatcherCtor Ctor
, SourceRange NameRange
,
867 ArrayRef
<ParserValue
> Args
,
868 Diagnostics
*Error
) const {
869 return Registry::buildMatcherCtor(Ctor
, NameRange
, Args
, Error
);
872 bool Parser::parseExpression(StringRef
&Code
, Sema
*S
,
873 const NamedValueMap
*NamedValues
,
874 VariantValue
*Value
, Diagnostics
*Error
) {
875 CodeTokenizer
Tokenizer(Code
, Error
);
876 if (!Parser(&Tokenizer
, S
, NamedValues
, Error
).parseExpressionImpl(Value
))
878 auto NT
= Tokenizer
.peekNextToken();
879 if (NT
.Kind
!= TokenInfo::TK_Eof
&& NT
.Kind
!= TokenInfo::TK_NewLine
) {
880 Error
->addError(Tokenizer
.peekNextToken().Range
,
881 Error
->ET_ParserTrailingCode
);
887 std::vector
<MatcherCompletion
>
888 Parser::completeExpression(StringRef
&Code
, unsigned CompletionOffset
, Sema
*S
,
889 const NamedValueMap
*NamedValues
) {
891 CodeTokenizer
Tokenizer(Code
, &Error
, CompletionOffset
);
892 Parser
P(&Tokenizer
, S
, NamedValues
, &Error
);
894 P
.parseExpressionImpl(&Dummy
);
896 // Sort by specificity, then by name.
897 llvm::sort(P
.Completions
,
898 [](const MatcherCompletion
&A
, const MatcherCompletion
&B
) {
899 if (A
.Specificity
!= B
.Specificity
)
900 return A
.Specificity
> B
.Specificity
;
901 return A
.TypedText
< B
.TypedText
;
904 return P
.Completions
;
907 std::optional
<DynTypedMatcher
>
908 Parser::parseMatcherExpression(StringRef
&Code
, Sema
*S
,
909 const NamedValueMap
*NamedValues
,
910 Diagnostics
*Error
) {
912 if (!parseExpression(Code
, S
, NamedValues
, &Value
, Error
))
914 if (!Value
.isMatcher()) {
915 Error
->addError(SourceRange(), Error
->ET_ParserNotAMatcher
);
918 std::optional
<DynTypedMatcher
> Result
= Value
.getMatcher().getSingleMatcher();
920 Error
->addError(SourceRange(), Error
->ET_ParserOverloadedType
)
921 << Value
.getTypeAsString();
926 } // namespace dynamic
927 } // namespace ast_matchers