19 #include "llvm/ADT/Optional.h"
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/Support/ErrorHandling.h"
22 #include "llvm/Support/ManagedStatic.h"
33 namespace ast_matchers {
72 : Code(MatcherCode), StartOfLine(MatcherCode),
Error(
Error) {
73 NextToken = getNextToken();
77 unsigned CodeCompletionOffset)
78 : Code(MatcherCode), StartOfLine(MatcherCode),
Error(
Error),
79 CodeCompletionLocation(MatcherCode.data() + CodeCompletionOffset) {
80 NextToken = getNextToken();
89 NextToken = getNextToken();
95 NextToken = getNextToken();
112 Result.Range.Start = currentLocation();
114 if (CodeCompletionLocation && CodeCompletionLocation <= Code.data()) {
116 Result.Text = StringRef(CodeCompletionLocation, 0);
117 CodeCompletionLocation =
nullptr;
129 Code = Code.drop_until([](
char c) {
return c ==
'\n'; });
130 return getNextToken();
133 Result.Text = Code.substr(0, 1);
134 Code = Code.drop_front();
138 Result.Text = Code.substr(0, 1);
139 Code = Code.drop_front();
143 StartOfLine = Code.drop_front();
145 Result.Text = Code.substr(0, 1);
146 Code = Code.drop_front();
150 Result.Text = Code.substr(0, 1);
151 Code = Code.drop_front();
155 Result.Text = Code.substr(0, 1);
156 Code = Code.drop_front();
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':
168 consumeNumberLiteral(&Result);
174 size_t TokenLength = 1;
179 if (CodeCompletionLocation == Code.data() + TokenLength) {
180 CodeCompletionLocation =
nullptr;
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")) {
193 }
else if (TokenLength == 5 && Code.startswith(
"false")) {
195 Result.Value =
false;
198 Result.Text = Code.substr(0, TokenLength);
200 Code = Code.drop_front(TokenLength);
203 Result.Text = Code.substr(0, 1);
204 Code = Code.drop_front(1);
209 Result.Range.End = currentLocation();
214 void consumeNumberLiteral(TokenInfo *Result) {
215 bool isFloatingLiteral =
false;
217 if (Code.size() > 1) {
220 case 'x':
case 'b': Length = 2;
223 while (Length < Code.size() &&
isHexDigit(Code[Length]))
227 while (Length < Code.size()) {
228 char c = Code[Length];
230 isFloatingLiteral =
true;
237 Result->Text = Code.substr(0, Length);
238 Code = Code.drop_front(Length);
240 if (isFloatingLiteral) {
244 double doubleValue = strtod(
Text.c_str(), &end);
245 if (*end == 0 && errno == 0) {
247 Result->Value = doubleValue;
252 if (!Result->Text.getAsInteger(0,
Value)) {
254 Result->Value =
Value;
260 Range.Start = Result->Range.Start;
261 Range.End = currentLocation();
262 Error->addError(Range,
Error->ET_ParserNumberError) << Result->Text;
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) {
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;
301 void consumeWhitespace() {
302 Code = Code.drop_while([](
char c) {
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;
330 std::vector<MatcherCompletion>
339 P->ContextStack.push_back(std::make_pair(C, 0u));
343 P->ContextStack.pop_back();
347 ++
P->ContextStack.back().second;
362 NamedValues ? NamedValues->lookup(NameToken.Text)
374 addCompletion(ChainCallToken, MatcherCompletion(
"bind(\"",
"bind", 1));
381 Error->
addError(ChainCallToken.Range,
388 NameToken.Text, NameToken.Range);
390 Error->addError(ChainCallToken.Range,
391 Error->ET_RegistryMatcherNoWithSupport);
394 if (!parseBindID(BindID))
397 assert(NamedValue.isMatcher());
399 NamedValue.getMatcher().getSingleMatcher();
412 Error->ET_ParserNoOpenParen)
424 Error->addError(NameToken.Range,
Error->ET_RegistryValueNotFound)
436 Error->addError(OpenToken.Range,
Error->ET_ParserNoOpenParen)
444 return parseMatcherExpressionImpl(NameToken, OpenToken, Ctor,
Value);
456 Error->addError(OpenToken.Range,
Error->ET_ParserMalformedBindExpr);
460 Error->addError(IDToken.Range,
Error->ET_ParserMalformedBindExpr);
464 Error->addError(CloseToken.Range,
Error->ET_ParserMalformedBindExpr);
471 bool Parser::parseMatcherBuilder(
MatcherCtor Ctor,
const TokenInfo &NameToken,
472 const TokenInfo &OpenToken,
473 VariantValue *
Value) {
474 std::vector<ParserValue> Args;
480 ScopedContextEntry SCE(
this, Ctor);
492 Error->addError(CommaToken.Range,
Error->ET_ParserNoComma)
499 NameToken.Text, NameToken.Range,
501 ParserValue ArgValue;
505 addExpressionCompletions();
512 Error->addError(NameToken.Range,
Error->ET_ParserFailedToBuildMatcher)
517 ArgValue.Text = NodeMatcherToken.Text;
518 ArgValue.Range = NodeMatcherToken.Range;
523 if (!MappedMatcher) {
524 Error->addError(NodeMatcherToken.Range,
525 Error->ET_RegistryMatcherNotFound)
526 << NodeMatcherToken.Text;
533 Error->addError(NodeMatcherToken.Range,
534 Error->ET_RegistryNonNodeMatcher)
535 << NodeMatcherToken.Text;
542 Args.push_back(ArgValue);
549 Error->addError(OpenToken.Range,
Error->ET_ParserNoCloseParen);
553 internal::MatcherDescriptorPtr BuiltCtor =
556 if (!BuiltCtor.get()) {
557 Error->addError(NameToken.Range,
Error->ET_ParserFailedToBuildMatcher)
567 addCompletion(ChainCallToken, MatcherCompletion(
"bind(\"",
"bind", 1));
568 addCompletion(ChainCallToken, MatcherCompletion(
"with(",
"with", 1));
574 Error->addError(ChainCallToken.Range,
575 Error->ET_ParserMalformedChainedExpr);
579 if (!parseBindID(BindID))
582 NameToken.Text, NameToken.Range);
583 SourceRange MatcherRange = NameToken.Range;
584 MatcherRange.End = ChainCallToken.Range.End;
586 BuiltCtor.get(), MatcherRange, BindID, {},
Error);
598 : Tokenizer->peekNextToken().
Text;
600 Error->ET_ParserNoOpenParen)
607 return parseMatcherExpressionImpl(NameToken, WithOpenToken,
608 BuiltCtor.get(),
Value);
613 NameToken.Text, NameToken.Range);
614 SourceRange MatcherRange = NameToken.Range;
615 MatcherRange.End = EndToken.Range.End;
617 BuiltCtor.get(), MatcherRange, BindID, {},
Error);
629 bool Parser::parseMatcherExpressionImpl(
const TokenInfo &NameToken,
630 const TokenInfo &OpenToken,
632 VariantValue *
Value) {
634 Error->addError(NameToken.Range,
Error->ET_RegistryMatcherNotFound)
640 return parseMatcherBuilder(*Ctor, NameToken, OpenToken,
Value);
642 std::vector<ParserValue> Args;
648 ScopedContextEntry SCE(
this, Ctor.value_or(
nullptr));
660 Error->addError(CommaToken.Range,
Error->ET_ParserNoComma)
667 NameToken.Text, NameToken.Range,
669 ParserValue ArgValue;
673 if (!parseExpressionImpl(&ArgValue.Value)) {
678 Args.push_back(ArgValue);
684 Error->addError(OpenToken.Range,
Error->ET_ParserNoCloseParen);
693 addCompletion(ChainCallToken, MatcherCompletion(
"bind(\"",
"bind", 1));
698 Error->addError(ChainCallToken.Range,
699 Error->ET_ParserMalformedChainedExpr);
705 NameToken.Text, NameToken.Range);
707 Error->addError(ChainCallToken.Range,
708 Error->ET_RegistryMatcherNoWithSupport);
712 Error->addError(ChainCallToken.Range,
713 Error->ET_ParserMalformedChainedExpr);
716 if (!parseBindID(BindID))
725 NameToken.Text, NameToken.Range);
726 SourceRange MatcherRange = NameToken.Range;
727 MatcherRange.End = EndToken.Range.End;
729 *Ctor, MatcherRange, BindID, Args,
Error);
730 if (Result.isNull())
return false;
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() {
768 for (ContextStackTy::iterator I = ContextStack.begin(),
769 E = ContextStack.end();
777 addCompletion(CompToken, Completion);
780 for (
const auto &Completion : getNamedValueCompletions(AcceptedTypes)) {
781 addCompletion(CompToken, Completion);
786 bool Parser::parseExpressionImpl(VariantValue *
Value) {
793 return parseIdentifierPrefixImpl(
Value);
796 addExpressionCompletions();
801 Error->ET_ParserNoCode);
814 Error->addError(Token.Range,
Error->ET_ParserInvalidToken)
819 llvm_unreachable(
"Unknown token kind.");
824 Parser::Parser(CodeTokenizer *Tokenizer,
Sema *S,
829 Parser::RegistrySema::~RegistrySema() =
default;
832 Parser::RegistrySema::lookupMatcherCtor(StringRef MatcherName) {
833 return Registry::lookupMatcherCtor(MatcherName);
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(
854 return Registry::getMatcherCompletions(AcceptedTypes);
857 bool Parser::RegistrySema::isBuilderMatcher(
MatcherCtor Ctor)
const {
858 return Registry::isBuilderMatcher(Ctor);
862 return Registry::nodeMatcherType(Ctor);
869 return Registry::buildMatcherCtor(Ctor, NameRange, Args,
Error);
872 bool Parser::parseExpression(StringRef &Code,
Sema *S,
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,
894 P.parseExpressionImpl(&Dummy);
897 llvm::sort(
P.Completions,
899 if (A.Specificity != B.Specificity)
900 return A.Specificity > B.Specificity;
901 return A.TypedText < B.TypedText;
904 return P.Completions;
908 Parser::parseMatcherExpression(StringRef &Code,
Sema *S,
912 if (!parseExpression(Code, S, NamedValues, &
Value,
Error))
914 if (!
Value.isMatcher()) {
919 Value.getMatcher().getSingleMatcher();
922 <<
Value.getTypeAsString();