xref: /minix3/external/bsd/llvm/dist/clang/lib/ASTMatchers/Dynamic/Parser.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===--- Parser.cpp - Matcher expression parser -----*- C++ -*-===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc ///
10f4a2713aSLionel Sambuc /// \file
11f4a2713aSLionel Sambuc /// \brief Recursive parser implementation for the matcher expression grammar.
12f4a2713aSLionel Sambuc ///
13f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
14f4a2713aSLionel Sambuc 
15f4a2713aSLionel Sambuc #include "clang/ASTMatchers/Dynamic/Parser.h"
16f4a2713aSLionel Sambuc #include "clang/ASTMatchers/Dynamic/Registry.h"
17f4a2713aSLionel Sambuc #include "clang/Basic/CharInfo.h"
18*0a6a1f1dSLionel Sambuc #include "llvm/ADT/Optional.h"
19f4a2713aSLionel Sambuc #include "llvm/ADT/Twine.h"
20*0a6a1f1dSLionel Sambuc #include "llvm/Support/ManagedStatic.h"
21*0a6a1f1dSLionel Sambuc #include <string>
22*0a6a1f1dSLionel Sambuc #include <vector>
23f4a2713aSLionel Sambuc 
24f4a2713aSLionel Sambuc namespace clang {
25f4a2713aSLionel Sambuc namespace ast_matchers {
26f4a2713aSLionel Sambuc namespace dynamic {
27f4a2713aSLionel Sambuc 
28f4a2713aSLionel Sambuc /// \brief Simple structure to hold information for one token from the parser.
29f4a2713aSLionel Sambuc struct Parser::TokenInfo {
30f4a2713aSLionel Sambuc   /// \brief Different possible tokens.
31f4a2713aSLionel Sambuc   enum TokenKind {
32*0a6a1f1dSLionel Sambuc     TK_Eof,
33*0a6a1f1dSLionel Sambuc     TK_OpenParen,
34*0a6a1f1dSLionel Sambuc     TK_CloseParen,
35*0a6a1f1dSLionel Sambuc     TK_Comma,
36*0a6a1f1dSLionel Sambuc     TK_Period,
37*0a6a1f1dSLionel Sambuc     TK_Literal,
38*0a6a1f1dSLionel Sambuc     TK_Ident,
39*0a6a1f1dSLionel Sambuc     TK_InvalidChar,
40*0a6a1f1dSLionel Sambuc     TK_Error,
41*0a6a1f1dSLionel Sambuc     TK_CodeCompletion
42f4a2713aSLionel Sambuc   };
43f4a2713aSLionel Sambuc 
44f4a2713aSLionel Sambuc   /// \brief Some known identifiers.
45f4a2713aSLionel Sambuc   static const char* const ID_Bind;
46f4a2713aSLionel Sambuc 
TokenInfoclang::ast_matchers::dynamic::Parser::TokenInfo47f4a2713aSLionel Sambuc   TokenInfo() : Text(), Kind(TK_Eof), Range(), Value() {}
48f4a2713aSLionel Sambuc 
49f4a2713aSLionel Sambuc   StringRef Text;
50f4a2713aSLionel Sambuc   TokenKind Kind;
51f4a2713aSLionel Sambuc   SourceRange Range;
52f4a2713aSLionel Sambuc   VariantValue Value;
53f4a2713aSLionel Sambuc };
54f4a2713aSLionel Sambuc 
55f4a2713aSLionel Sambuc const char* const Parser::TokenInfo::ID_Bind = "bind";
56f4a2713aSLionel Sambuc 
57f4a2713aSLionel Sambuc /// \brief Simple tokenizer for the parser.
58f4a2713aSLionel Sambuc class Parser::CodeTokenizer {
59f4a2713aSLionel Sambuc public:
CodeTokenizer(StringRef MatcherCode,Diagnostics * Error)60f4a2713aSLionel Sambuc   explicit CodeTokenizer(StringRef MatcherCode, Diagnostics *Error)
61*0a6a1f1dSLionel Sambuc       : Code(MatcherCode), StartOfLine(MatcherCode), Line(1), Error(Error),
62*0a6a1f1dSLionel Sambuc         CodeCompletionLocation(nullptr) {
63*0a6a1f1dSLionel Sambuc     NextToken = getNextToken();
64*0a6a1f1dSLionel Sambuc   }
65*0a6a1f1dSLionel Sambuc 
CodeTokenizer(StringRef MatcherCode,Diagnostics * Error,unsigned CodeCompletionOffset)66*0a6a1f1dSLionel Sambuc   CodeTokenizer(StringRef MatcherCode, Diagnostics *Error,
67*0a6a1f1dSLionel Sambuc                 unsigned CodeCompletionOffset)
68*0a6a1f1dSLionel Sambuc       : Code(MatcherCode), StartOfLine(MatcherCode), Line(1), Error(Error),
69*0a6a1f1dSLionel Sambuc         CodeCompletionLocation(MatcherCode.data() + CodeCompletionOffset) {
70f4a2713aSLionel Sambuc     NextToken = getNextToken();
71f4a2713aSLionel Sambuc   }
72f4a2713aSLionel Sambuc 
73f4a2713aSLionel Sambuc   /// \brief Returns but doesn't consume the next token.
peekNextToken() const74f4a2713aSLionel Sambuc   const TokenInfo &peekNextToken() const { return NextToken; }
75f4a2713aSLionel Sambuc 
76f4a2713aSLionel Sambuc   /// \brief Consumes and returns the next token.
consumeNextToken()77f4a2713aSLionel Sambuc   TokenInfo consumeNextToken() {
78f4a2713aSLionel Sambuc     TokenInfo ThisToken = NextToken;
79f4a2713aSLionel Sambuc     NextToken = getNextToken();
80f4a2713aSLionel Sambuc     return ThisToken;
81f4a2713aSLionel Sambuc   }
82f4a2713aSLionel Sambuc 
nextTokenKind() const83f4a2713aSLionel Sambuc   TokenInfo::TokenKind nextTokenKind() const { return NextToken.Kind; }
84f4a2713aSLionel Sambuc 
85f4a2713aSLionel Sambuc private:
getNextToken()86f4a2713aSLionel Sambuc   TokenInfo getNextToken() {
87f4a2713aSLionel Sambuc     consumeWhitespace();
88f4a2713aSLionel Sambuc     TokenInfo Result;
89f4a2713aSLionel Sambuc     Result.Range.Start = currentLocation();
90f4a2713aSLionel Sambuc 
91*0a6a1f1dSLionel Sambuc     if (CodeCompletionLocation && CodeCompletionLocation <= Code.data()) {
92*0a6a1f1dSLionel Sambuc       Result.Kind = TokenInfo::TK_CodeCompletion;
93*0a6a1f1dSLionel Sambuc       Result.Text = StringRef(CodeCompletionLocation, 0);
94*0a6a1f1dSLionel Sambuc       CodeCompletionLocation = nullptr;
95*0a6a1f1dSLionel Sambuc       return Result;
96*0a6a1f1dSLionel Sambuc     }
97*0a6a1f1dSLionel Sambuc 
98f4a2713aSLionel Sambuc     if (Code.empty()) {
99f4a2713aSLionel Sambuc       Result.Kind = TokenInfo::TK_Eof;
100f4a2713aSLionel Sambuc       Result.Text = "";
101f4a2713aSLionel Sambuc       return Result;
102f4a2713aSLionel Sambuc     }
103f4a2713aSLionel Sambuc 
104f4a2713aSLionel Sambuc     switch (Code[0]) {
105f4a2713aSLionel Sambuc     case ',':
106f4a2713aSLionel Sambuc       Result.Kind = TokenInfo::TK_Comma;
107f4a2713aSLionel Sambuc       Result.Text = Code.substr(0, 1);
108f4a2713aSLionel Sambuc       Code = Code.drop_front();
109f4a2713aSLionel Sambuc       break;
110f4a2713aSLionel Sambuc     case '.':
111f4a2713aSLionel Sambuc       Result.Kind = TokenInfo::TK_Period;
112f4a2713aSLionel Sambuc       Result.Text = Code.substr(0, 1);
113f4a2713aSLionel Sambuc       Code = Code.drop_front();
114f4a2713aSLionel Sambuc       break;
115f4a2713aSLionel Sambuc     case '(':
116f4a2713aSLionel Sambuc       Result.Kind = TokenInfo::TK_OpenParen;
117f4a2713aSLionel Sambuc       Result.Text = Code.substr(0, 1);
118f4a2713aSLionel Sambuc       Code = Code.drop_front();
119f4a2713aSLionel Sambuc       break;
120f4a2713aSLionel Sambuc     case ')':
121f4a2713aSLionel Sambuc       Result.Kind = TokenInfo::TK_CloseParen;
122f4a2713aSLionel Sambuc       Result.Text = Code.substr(0, 1);
123f4a2713aSLionel Sambuc       Code = Code.drop_front();
124f4a2713aSLionel Sambuc       break;
125f4a2713aSLionel Sambuc 
126f4a2713aSLionel Sambuc     case '"':
127f4a2713aSLionel Sambuc     case '\'':
128f4a2713aSLionel Sambuc       // Parse a string literal.
129f4a2713aSLionel Sambuc       consumeStringLiteral(&Result);
130f4a2713aSLionel Sambuc       break;
131f4a2713aSLionel Sambuc 
132f4a2713aSLionel Sambuc     case '0': case '1': case '2': case '3': case '4':
133f4a2713aSLionel Sambuc     case '5': case '6': case '7': case '8': case '9':
134f4a2713aSLionel Sambuc       // Parse an unsigned literal.
135f4a2713aSLionel Sambuc       consumeUnsignedLiteral(&Result);
136f4a2713aSLionel Sambuc       break;
137f4a2713aSLionel Sambuc 
138f4a2713aSLionel Sambuc     default:
139f4a2713aSLionel Sambuc       if (isAlphanumeric(Code[0])) {
140f4a2713aSLionel Sambuc         // Parse an identifier
141f4a2713aSLionel Sambuc         size_t TokenLength = 1;
142*0a6a1f1dSLionel Sambuc         while (1) {
143*0a6a1f1dSLionel Sambuc           // A code completion location in/immediately after an identifier will
144*0a6a1f1dSLionel Sambuc           // cause the portion of the identifier before the code completion
145*0a6a1f1dSLionel Sambuc           // location to become a code completion token.
146*0a6a1f1dSLionel Sambuc           if (CodeCompletionLocation == Code.data() + TokenLength) {
147*0a6a1f1dSLionel Sambuc             CodeCompletionLocation = nullptr;
148*0a6a1f1dSLionel Sambuc             Result.Kind = TokenInfo::TK_CodeCompletion;
149*0a6a1f1dSLionel Sambuc             Result.Text = Code.substr(0, TokenLength);
150*0a6a1f1dSLionel Sambuc             Code = Code.drop_front(TokenLength);
151*0a6a1f1dSLionel Sambuc             return Result;
152*0a6a1f1dSLionel Sambuc           }
153*0a6a1f1dSLionel Sambuc           if (TokenLength == Code.size() || !isAlphanumeric(Code[TokenLength]))
154*0a6a1f1dSLionel Sambuc             break;
155f4a2713aSLionel Sambuc           ++TokenLength;
156*0a6a1f1dSLionel Sambuc         }
157f4a2713aSLionel Sambuc         Result.Kind = TokenInfo::TK_Ident;
158f4a2713aSLionel Sambuc         Result.Text = Code.substr(0, TokenLength);
159f4a2713aSLionel Sambuc         Code = Code.drop_front(TokenLength);
160f4a2713aSLionel Sambuc       } else {
161f4a2713aSLionel Sambuc         Result.Kind = TokenInfo::TK_InvalidChar;
162f4a2713aSLionel Sambuc         Result.Text = Code.substr(0, 1);
163f4a2713aSLionel Sambuc         Code = Code.drop_front(1);
164f4a2713aSLionel Sambuc       }
165f4a2713aSLionel Sambuc       break;
166f4a2713aSLionel Sambuc     }
167f4a2713aSLionel Sambuc 
168f4a2713aSLionel Sambuc     Result.Range.End = currentLocation();
169f4a2713aSLionel Sambuc     return Result;
170f4a2713aSLionel Sambuc   }
171f4a2713aSLionel Sambuc 
172f4a2713aSLionel Sambuc   /// \brief Consume an unsigned literal.
consumeUnsignedLiteral(TokenInfo * Result)173f4a2713aSLionel Sambuc   void consumeUnsignedLiteral(TokenInfo *Result) {
174f4a2713aSLionel Sambuc     unsigned Length = 1;
175f4a2713aSLionel Sambuc     if (Code.size() > 1) {
176f4a2713aSLionel Sambuc       // Consume the 'x' or 'b' radix modifier, if present.
177f4a2713aSLionel Sambuc       switch (toLowercase(Code[1])) {
178f4a2713aSLionel Sambuc       case 'x': case 'b': Length = 2;
179f4a2713aSLionel Sambuc       }
180f4a2713aSLionel Sambuc     }
181f4a2713aSLionel Sambuc     while (Length < Code.size() && isHexDigit(Code[Length]))
182f4a2713aSLionel Sambuc       ++Length;
183f4a2713aSLionel Sambuc 
184f4a2713aSLionel Sambuc     Result->Text = Code.substr(0, Length);
185f4a2713aSLionel Sambuc     Code = Code.drop_front(Length);
186f4a2713aSLionel Sambuc 
187f4a2713aSLionel Sambuc     unsigned Value;
188f4a2713aSLionel Sambuc     if (!Result->Text.getAsInteger(0, Value)) {
189f4a2713aSLionel Sambuc       Result->Kind = TokenInfo::TK_Literal;
190f4a2713aSLionel Sambuc       Result->Value = Value;
191f4a2713aSLionel Sambuc     } else {
192f4a2713aSLionel Sambuc       SourceRange Range;
193f4a2713aSLionel Sambuc       Range.Start = Result->Range.Start;
194f4a2713aSLionel Sambuc       Range.End = currentLocation();
195f4a2713aSLionel Sambuc       Error->addError(Range, Error->ET_ParserUnsignedError) << Result->Text;
196f4a2713aSLionel Sambuc       Result->Kind = TokenInfo::TK_Error;
197f4a2713aSLionel Sambuc     }
198f4a2713aSLionel Sambuc   }
199f4a2713aSLionel Sambuc 
200f4a2713aSLionel Sambuc   /// \brief Consume a string literal.
201f4a2713aSLionel Sambuc   ///
202f4a2713aSLionel Sambuc   /// \c Code must be positioned at the start of the literal (the opening
203f4a2713aSLionel Sambuc   /// quote). Consumed until it finds the same closing quote character.
consumeStringLiteral(TokenInfo * Result)204f4a2713aSLionel Sambuc   void consumeStringLiteral(TokenInfo *Result) {
205f4a2713aSLionel Sambuc     bool InEscape = false;
206f4a2713aSLionel Sambuc     const char Marker = Code[0];
207f4a2713aSLionel Sambuc     for (size_t Length = 1, Size = Code.size(); Length != Size; ++Length) {
208f4a2713aSLionel Sambuc       if (InEscape) {
209f4a2713aSLionel Sambuc         InEscape = false;
210f4a2713aSLionel Sambuc         continue;
211f4a2713aSLionel Sambuc       }
212f4a2713aSLionel Sambuc       if (Code[Length] == '\\') {
213f4a2713aSLionel Sambuc         InEscape = true;
214f4a2713aSLionel Sambuc         continue;
215f4a2713aSLionel Sambuc       }
216f4a2713aSLionel Sambuc       if (Code[Length] == Marker) {
217f4a2713aSLionel Sambuc         Result->Kind = TokenInfo::TK_Literal;
218f4a2713aSLionel Sambuc         Result->Text = Code.substr(0, Length + 1);
219f4a2713aSLionel Sambuc         Result->Value = Code.substr(1, Length - 1).str();
220f4a2713aSLionel Sambuc         Code = Code.drop_front(Length + 1);
221f4a2713aSLionel Sambuc         return;
222f4a2713aSLionel Sambuc       }
223f4a2713aSLionel Sambuc     }
224f4a2713aSLionel Sambuc 
225f4a2713aSLionel Sambuc     StringRef ErrorText = Code;
226f4a2713aSLionel Sambuc     Code = Code.drop_front(Code.size());
227f4a2713aSLionel Sambuc     SourceRange Range;
228f4a2713aSLionel Sambuc     Range.Start = Result->Range.Start;
229f4a2713aSLionel Sambuc     Range.End = currentLocation();
230f4a2713aSLionel Sambuc     Error->addError(Range, Error->ET_ParserStringError) << ErrorText;
231f4a2713aSLionel Sambuc     Result->Kind = TokenInfo::TK_Error;
232f4a2713aSLionel Sambuc   }
233f4a2713aSLionel Sambuc 
234f4a2713aSLionel Sambuc   /// \brief Consume all leading whitespace from \c Code.
consumeWhitespace()235f4a2713aSLionel Sambuc   void consumeWhitespace() {
236f4a2713aSLionel Sambuc     while (!Code.empty() && isWhitespace(Code[0])) {
237f4a2713aSLionel Sambuc       if (Code[0] == '\n') {
238f4a2713aSLionel Sambuc         ++Line;
239f4a2713aSLionel Sambuc         StartOfLine = Code.drop_front();
240f4a2713aSLionel Sambuc       }
241f4a2713aSLionel Sambuc       Code = Code.drop_front();
242f4a2713aSLionel Sambuc     }
243f4a2713aSLionel Sambuc   }
244f4a2713aSLionel Sambuc 
currentLocation()245f4a2713aSLionel Sambuc   SourceLocation currentLocation() {
246f4a2713aSLionel Sambuc     SourceLocation Location;
247f4a2713aSLionel Sambuc     Location.Line = Line;
248f4a2713aSLionel Sambuc     Location.Column = Code.data() - StartOfLine.data() + 1;
249f4a2713aSLionel Sambuc     return Location;
250f4a2713aSLionel Sambuc   }
251f4a2713aSLionel Sambuc 
252f4a2713aSLionel Sambuc   StringRef Code;
253f4a2713aSLionel Sambuc   StringRef StartOfLine;
254f4a2713aSLionel Sambuc   unsigned Line;
255f4a2713aSLionel Sambuc   Diagnostics *Error;
256f4a2713aSLionel Sambuc   TokenInfo NextToken;
257*0a6a1f1dSLionel Sambuc   const char *CodeCompletionLocation;
258f4a2713aSLionel Sambuc };
259f4a2713aSLionel Sambuc 
~Sema()260f4a2713aSLionel Sambuc Parser::Sema::~Sema() {}
261f4a2713aSLionel Sambuc 
getAcceptedCompletionTypes(llvm::ArrayRef<std::pair<MatcherCtor,unsigned>> Context)262*0a6a1f1dSLionel Sambuc std::vector<ArgKind> Parser::Sema::getAcceptedCompletionTypes(
263*0a6a1f1dSLionel Sambuc     llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context) {
264*0a6a1f1dSLionel Sambuc   return std::vector<ArgKind>();
265*0a6a1f1dSLionel Sambuc }
266*0a6a1f1dSLionel Sambuc 
267*0a6a1f1dSLionel Sambuc std::vector<MatcherCompletion>
getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes)268*0a6a1f1dSLionel Sambuc Parser::Sema::getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes) {
269*0a6a1f1dSLionel Sambuc   return std::vector<MatcherCompletion>();
270*0a6a1f1dSLionel Sambuc }
271*0a6a1f1dSLionel Sambuc 
272*0a6a1f1dSLionel Sambuc struct Parser::ScopedContextEntry {
273*0a6a1f1dSLionel Sambuc   Parser *P;
274*0a6a1f1dSLionel Sambuc 
ScopedContextEntryclang::ast_matchers::dynamic::Parser::ScopedContextEntry275*0a6a1f1dSLionel Sambuc   ScopedContextEntry(Parser *P, MatcherCtor C) : P(P) {
276*0a6a1f1dSLionel Sambuc     P->ContextStack.push_back(std::make_pair(C, 0u));
277*0a6a1f1dSLionel Sambuc   }
278*0a6a1f1dSLionel Sambuc 
~ScopedContextEntryclang::ast_matchers::dynamic::Parser::ScopedContextEntry279*0a6a1f1dSLionel Sambuc   ~ScopedContextEntry() {
280*0a6a1f1dSLionel Sambuc     P->ContextStack.pop_back();
281*0a6a1f1dSLionel Sambuc   }
282*0a6a1f1dSLionel Sambuc 
nextArgclang::ast_matchers::dynamic::Parser::ScopedContextEntry283*0a6a1f1dSLionel Sambuc   void nextArg() {
284*0a6a1f1dSLionel Sambuc     ++P->ContextStack.back().second;
285*0a6a1f1dSLionel Sambuc   }
286*0a6a1f1dSLionel Sambuc };
287*0a6a1f1dSLionel Sambuc 
288*0a6a1f1dSLionel Sambuc /// \brief Parse expressions that start with an identifier.
289*0a6a1f1dSLionel Sambuc ///
290*0a6a1f1dSLionel Sambuc /// This function can parse named values and matchers.
291*0a6a1f1dSLionel Sambuc /// In case of failure it will try to determine the user's intent to give
292*0a6a1f1dSLionel Sambuc /// an appropriate error message.
parseIdentifierPrefixImpl(VariantValue * Value)293*0a6a1f1dSLionel Sambuc bool Parser::parseIdentifierPrefixImpl(VariantValue *Value) {
294*0a6a1f1dSLionel Sambuc   const TokenInfo NameToken = Tokenizer->consumeNextToken();
295*0a6a1f1dSLionel Sambuc 
296*0a6a1f1dSLionel Sambuc   if (Tokenizer->nextTokenKind() != TokenInfo::TK_OpenParen) {
297*0a6a1f1dSLionel Sambuc     // Parse as a named value.
298*0a6a1f1dSLionel Sambuc     if (const VariantValue NamedValue =
299*0a6a1f1dSLionel Sambuc             NamedValues ? NamedValues->lookup(NameToken.Text)
300*0a6a1f1dSLionel Sambuc                         : VariantValue()) {
301*0a6a1f1dSLionel Sambuc       *Value = NamedValue;
302*0a6a1f1dSLionel Sambuc       return true;
303*0a6a1f1dSLionel Sambuc     }
304*0a6a1f1dSLionel Sambuc     // If the syntax is correct and the name is not a matcher either, report
305*0a6a1f1dSLionel Sambuc     // unknown named value.
306*0a6a1f1dSLionel Sambuc     if ((Tokenizer->nextTokenKind() == TokenInfo::TK_Comma ||
307*0a6a1f1dSLionel Sambuc          Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen ||
308*0a6a1f1dSLionel Sambuc          Tokenizer->nextTokenKind() == TokenInfo::TK_Eof) &&
309*0a6a1f1dSLionel Sambuc         !S->lookupMatcherCtor(NameToken.Text)) {
310*0a6a1f1dSLionel Sambuc       Error->addError(NameToken.Range, Error->ET_RegistryValueNotFound)
311*0a6a1f1dSLionel Sambuc           << NameToken.Text;
312*0a6a1f1dSLionel Sambuc       return false;
313*0a6a1f1dSLionel Sambuc     }
314*0a6a1f1dSLionel Sambuc     // Otherwise, fallback to the matcher parser.
315*0a6a1f1dSLionel Sambuc   }
316*0a6a1f1dSLionel Sambuc 
317*0a6a1f1dSLionel Sambuc   // Parse as a matcher expression.
318*0a6a1f1dSLionel Sambuc   return parseMatcherExpressionImpl(NameToken, Value);
319*0a6a1f1dSLionel Sambuc }
320*0a6a1f1dSLionel Sambuc 
321f4a2713aSLionel Sambuc /// \brief Parse and validate a matcher expression.
322f4a2713aSLionel Sambuc /// \return \c true on success, in which case \c Value has the matcher parsed.
323f4a2713aSLionel Sambuc ///   If the input is malformed, or some argument has an error, it
324f4a2713aSLionel Sambuc ///   returns \c false.
parseMatcherExpressionImpl(const TokenInfo & NameToken,VariantValue * Value)325*0a6a1f1dSLionel Sambuc bool Parser::parseMatcherExpressionImpl(const TokenInfo &NameToken,
326*0a6a1f1dSLionel Sambuc                                         VariantValue *Value) {
327f4a2713aSLionel Sambuc   assert(NameToken.Kind == TokenInfo::TK_Ident);
328f4a2713aSLionel Sambuc   const TokenInfo OpenToken = Tokenizer->consumeNextToken();
329f4a2713aSLionel Sambuc   if (OpenToken.Kind != TokenInfo::TK_OpenParen) {
330f4a2713aSLionel Sambuc     Error->addError(OpenToken.Range, Error->ET_ParserNoOpenParen)
331f4a2713aSLionel Sambuc         << OpenToken.Text;
332f4a2713aSLionel Sambuc     return false;
333f4a2713aSLionel Sambuc   }
334f4a2713aSLionel Sambuc 
335*0a6a1f1dSLionel Sambuc   llvm::Optional<MatcherCtor> Ctor = S->lookupMatcherCtor(NameToken.Text);
336*0a6a1f1dSLionel Sambuc 
337*0a6a1f1dSLionel Sambuc   if (!Ctor) {
338*0a6a1f1dSLionel Sambuc     Error->addError(NameToken.Range, Error->ET_RegistryMatcherNotFound)
339*0a6a1f1dSLionel Sambuc         << NameToken.Text;
340*0a6a1f1dSLionel Sambuc     // Do not return here. We need to continue to give completion suggestions.
341*0a6a1f1dSLionel Sambuc   }
342*0a6a1f1dSLionel Sambuc 
343f4a2713aSLionel Sambuc   std::vector<ParserValue> Args;
344f4a2713aSLionel Sambuc   TokenInfo EndToken;
345*0a6a1f1dSLionel Sambuc 
346*0a6a1f1dSLionel Sambuc   {
347*0a6a1f1dSLionel Sambuc     ScopedContextEntry SCE(this, Ctor ? *Ctor : nullptr);
348*0a6a1f1dSLionel Sambuc 
349f4a2713aSLionel Sambuc     while (Tokenizer->nextTokenKind() != TokenInfo::TK_Eof) {
350f4a2713aSLionel Sambuc       if (Tokenizer->nextTokenKind() == TokenInfo::TK_CloseParen) {
351f4a2713aSLionel Sambuc         // End of args.
352f4a2713aSLionel Sambuc         EndToken = Tokenizer->consumeNextToken();
353f4a2713aSLionel Sambuc         break;
354f4a2713aSLionel Sambuc       }
355f4a2713aSLionel Sambuc       if (Args.size() > 0) {
356f4a2713aSLionel Sambuc         // We must find a , token to continue.
357f4a2713aSLionel Sambuc         const TokenInfo CommaToken = Tokenizer->consumeNextToken();
358f4a2713aSLionel Sambuc         if (CommaToken.Kind != TokenInfo::TK_Comma) {
359f4a2713aSLionel Sambuc           Error->addError(CommaToken.Range, Error->ET_ParserNoComma)
360f4a2713aSLionel Sambuc               << CommaToken.Text;
361f4a2713aSLionel Sambuc           return false;
362f4a2713aSLionel Sambuc         }
363f4a2713aSLionel Sambuc       }
364f4a2713aSLionel Sambuc 
365f4a2713aSLionel Sambuc       Diagnostics::Context Ctx(Diagnostics::Context::MatcherArg, Error,
366*0a6a1f1dSLionel Sambuc                                NameToken.Text, NameToken.Range,
367*0a6a1f1dSLionel Sambuc                                Args.size() + 1);
368f4a2713aSLionel Sambuc       ParserValue ArgValue;
369f4a2713aSLionel Sambuc       ArgValue.Text = Tokenizer->peekNextToken().Text;
370f4a2713aSLionel Sambuc       ArgValue.Range = Tokenizer->peekNextToken().Range;
371*0a6a1f1dSLionel Sambuc       if (!parseExpressionImpl(&ArgValue.Value)) {
372*0a6a1f1dSLionel Sambuc         return false;
373*0a6a1f1dSLionel Sambuc       }
374f4a2713aSLionel Sambuc 
375f4a2713aSLionel Sambuc       Args.push_back(ArgValue);
376*0a6a1f1dSLionel Sambuc       SCE.nextArg();
377*0a6a1f1dSLionel Sambuc     }
378f4a2713aSLionel Sambuc   }
379f4a2713aSLionel Sambuc 
380f4a2713aSLionel Sambuc   if (EndToken.Kind == TokenInfo::TK_Eof) {
381f4a2713aSLionel Sambuc     Error->addError(OpenToken.Range, Error->ET_ParserNoCloseParen);
382f4a2713aSLionel Sambuc     return false;
383f4a2713aSLionel Sambuc   }
384f4a2713aSLionel Sambuc 
385f4a2713aSLionel Sambuc   std::string BindID;
386f4a2713aSLionel Sambuc   if (Tokenizer->peekNextToken().Kind == TokenInfo::TK_Period) {
387f4a2713aSLionel Sambuc     // Parse .bind("foo")
388f4a2713aSLionel Sambuc     Tokenizer->consumeNextToken();  // consume the period.
389f4a2713aSLionel Sambuc     const TokenInfo BindToken = Tokenizer->consumeNextToken();
390*0a6a1f1dSLionel Sambuc     if (BindToken.Kind == TokenInfo::TK_CodeCompletion) {
391*0a6a1f1dSLionel Sambuc       addCompletion(BindToken, MatcherCompletion("bind(\"", "bind", 1));
392*0a6a1f1dSLionel Sambuc       return false;
393*0a6a1f1dSLionel Sambuc     }
394*0a6a1f1dSLionel Sambuc 
395f4a2713aSLionel Sambuc     const TokenInfo OpenToken = Tokenizer->consumeNextToken();
396f4a2713aSLionel Sambuc     const TokenInfo IDToken = Tokenizer->consumeNextToken();
397f4a2713aSLionel Sambuc     const TokenInfo CloseToken = Tokenizer->consumeNextToken();
398f4a2713aSLionel Sambuc 
399f4a2713aSLionel Sambuc     // TODO: We could use different error codes for each/some to be more
400f4a2713aSLionel Sambuc     //       explicit about the syntax error.
401f4a2713aSLionel Sambuc     if (BindToken.Kind != TokenInfo::TK_Ident ||
402f4a2713aSLionel Sambuc         BindToken.Text != TokenInfo::ID_Bind) {
403f4a2713aSLionel Sambuc       Error->addError(BindToken.Range, Error->ET_ParserMalformedBindExpr);
404f4a2713aSLionel Sambuc       return false;
405f4a2713aSLionel Sambuc     }
406f4a2713aSLionel Sambuc     if (OpenToken.Kind != TokenInfo::TK_OpenParen) {
407f4a2713aSLionel Sambuc       Error->addError(OpenToken.Range, Error->ET_ParserMalformedBindExpr);
408f4a2713aSLionel Sambuc       return false;
409f4a2713aSLionel Sambuc     }
410f4a2713aSLionel Sambuc     if (IDToken.Kind != TokenInfo::TK_Literal || !IDToken.Value.isString()) {
411f4a2713aSLionel Sambuc       Error->addError(IDToken.Range, Error->ET_ParserMalformedBindExpr);
412f4a2713aSLionel Sambuc       return false;
413f4a2713aSLionel Sambuc     }
414f4a2713aSLionel Sambuc     if (CloseToken.Kind != TokenInfo::TK_CloseParen) {
415f4a2713aSLionel Sambuc       Error->addError(CloseToken.Range, Error->ET_ParserMalformedBindExpr);
416f4a2713aSLionel Sambuc       return false;
417f4a2713aSLionel Sambuc     }
418f4a2713aSLionel Sambuc     BindID = IDToken.Value.getString();
419f4a2713aSLionel Sambuc   }
420f4a2713aSLionel Sambuc 
421*0a6a1f1dSLionel Sambuc   if (!Ctor)
422*0a6a1f1dSLionel Sambuc     return false;
423*0a6a1f1dSLionel Sambuc 
424f4a2713aSLionel Sambuc   // Merge the start and end infos.
425f4a2713aSLionel Sambuc   Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error,
426f4a2713aSLionel Sambuc                            NameToken.Text, NameToken.Range);
427f4a2713aSLionel Sambuc   SourceRange MatcherRange = NameToken.Range;
428f4a2713aSLionel Sambuc   MatcherRange.End = EndToken.Range.End;
429f4a2713aSLionel Sambuc   VariantMatcher Result = S->actOnMatcherExpression(
430*0a6a1f1dSLionel Sambuc       *Ctor, MatcherRange, BindID, Args, Error);
431f4a2713aSLionel Sambuc   if (Result.isNull()) return false;
432f4a2713aSLionel Sambuc 
433f4a2713aSLionel Sambuc   *Value = Result;
434f4a2713aSLionel Sambuc   return true;
435f4a2713aSLionel Sambuc }
436f4a2713aSLionel Sambuc 
437*0a6a1f1dSLionel Sambuc // If the prefix of this completion matches the completion token, add it to
438*0a6a1f1dSLionel Sambuc // Completions minus the prefix.
addCompletion(const TokenInfo & CompToken,const MatcherCompletion & Completion)439*0a6a1f1dSLionel Sambuc void Parser::addCompletion(const TokenInfo &CompToken,
440*0a6a1f1dSLionel Sambuc                            const MatcherCompletion& Completion) {
441*0a6a1f1dSLionel Sambuc   if (StringRef(Completion.TypedText).startswith(CompToken.Text) &&
442*0a6a1f1dSLionel Sambuc       Completion.Specificity > 0) {
443*0a6a1f1dSLionel Sambuc     Completions.emplace_back(Completion.TypedText.substr(CompToken.Text.size()),
444*0a6a1f1dSLionel Sambuc                              Completion.MatcherDecl, Completion.Specificity);
445*0a6a1f1dSLionel Sambuc   }
446*0a6a1f1dSLionel Sambuc }
447*0a6a1f1dSLionel Sambuc 
getNamedValueCompletions(ArrayRef<ArgKind> AcceptedTypes)448*0a6a1f1dSLionel Sambuc std::vector<MatcherCompletion> Parser::getNamedValueCompletions(
449*0a6a1f1dSLionel Sambuc     ArrayRef<ArgKind> AcceptedTypes) {
450*0a6a1f1dSLionel Sambuc   if (!NamedValues) return std::vector<MatcherCompletion>();
451*0a6a1f1dSLionel Sambuc   std::vector<MatcherCompletion> Result;
452*0a6a1f1dSLionel Sambuc   for (const auto &Entry : *NamedValues) {
453*0a6a1f1dSLionel Sambuc     unsigned Specificity;
454*0a6a1f1dSLionel Sambuc     if (Entry.getValue().isConvertibleTo(AcceptedTypes, &Specificity)) {
455*0a6a1f1dSLionel Sambuc       std::string Decl =
456*0a6a1f1dSLionel Sambuc           (Entry.getValue().getTypeAsString() + " " + Entry.getKey()).str();
457*0a6a1f1dSLionel Sambuc       Result.emplace_back(Entry.getKey(), Decl, Specificity);
458*0a6a1f1dSLionel Sambuc     }
459*0a6a1f1dSLionel Sambuc   }
460*0a6a1f1dSLionel Sambuc   return Result;
461*0a6a1f1dSLionel Sambuc }
462*0a6a1f1dSLionel Sambuc 
addExpressionCompletions()463*0a6a1f1dSLionel Sambuc void Parser::addExpressionCompletions() {
464*0a6a1f1dSLionel Sambuc   const TokenInfo CompToken = Tokenizer->consumeNextToken();
465*0a6a1f1dSLionel Sambuc   assert(CompToken.Kind == TokenInfo::TK_CodeCompletion);
466*0a6a1f1dSLionel Sambuc 
467*0a6a1f1dSLionel Sambuc   // We cannot complete code if there is an invalid element on the context
468*0a6a1f1dSLionel Sambuc   // stack.
469*0a6a1f1dSLionel Sambuc   for (ContextStackTy::iterator I = ContextStack.begin(),
470*0a6a1f1dSLionel Sambuc                                 E = ContextStack.end();
471*0a6a1f1dSLionel Sambuc        I != E; ++I) {
472*0a6a1f1dSLionel Sambuc     if (!I->first)
473*0a6a1f1dSLionel Sambuc       return;
474*0a6a1f1dSLionel Sambuc   }
475*0a6a1f1dSLionel Sambuc 
476*0a6a1f1dSLionel Sambuc   auto AcceptedTypes = S->getAcceptedCompletionTypes(ContextStack);
477*0a6a1f1dSLionel Sambuc   for (const auto &Completion : S->getMatcherCompletions(AcceptedTypes)) {
478*0a6a1f1dSLionel Sambuc     addCompletion(CompToken, Completion);
479*0a6a1f1dSLionel Sambuc   }
480*0a6a1f1dSLionel Sambuc 
481*0a6a1f1dSLionel Sambuc   for (const auto &Completion : getNamedValueCompletions(AcceptedTypes)) {
482*0a6a1f1dSLionel Sambuc     addCompletion(CompToken, Completion);
483*0a6a1f1dSLionel Sambuc   }
484*0a6a1f1dSLionel Sambuc }
485*0a6a1f1dSLionel Sambuc 
486f4a2713aSLionel Sambuc /// \brief Parse an <Expresssion>
parseExpressionImpl(VariantValue * Value)487f4a2713aSLionel Sambuc bool Parser::parseExpressionImpl(VariantValue *Value) {
488f4a2713aSLionel Sambuc   switch (Tokenizer->nextTokenKind()) {
489f4a2713aSLionel Sambuc   case TokenInfo::TK_Literal:
490f4a2713aSLionel Sambuc     *Value = Tokenizer->consumeNextToken().Value;
491f4a2713aSLionel Sambuc     return true;
492f4a2713aSLionel Sambuc 
493f4a2713aSLionel Sambuc   case TokenInfo::TK_Ident:
494*0a6a1f1dSLionel Sambuc     return parseIdentifierPrefixImpl(Value);
495*0a6a1f1dSLionel Sambuc 
496*0a6a1f1dSLionel Sambuc   case TokenInfo::TK_CodeCompletion:
497*0a6a1f1dSLionel Sambuc     addExpressionCompletions();
498*0a6a1f1dSLionel Sambuc     return false;
499f4a2713aSLionel Sambuc 
500f4a2713aSLionel Sambuc   case TokenInfo::TK_Eof:
501f4a2713aSLionel Sambuc     Error->addError(Tokenizer->consumeNextToken().Range,
502f4a2713aSLionel Sambuc                     Error->ET_ParserNoCode);
503f4a2713aSLionel Sambuc     return false;
504f4a2713aSLionel Sambuc 
505f4a2713aSLionel Sambuc   case TokenInfo::TK_Error:
506f4a2713aSLionel Sambuc     // This error was already reported by the tokenizer.
507f4a2713aSLionel Sambuc     return false;
508f4a2713aSLionel Sambuc 
509f4a2713aSLionel Sambuc   case TokenInfo::TK_OpenParen:
510f4a2713aSLionel Sambuc   case TokenInfo::TK_CloseParen:
511f4a2713aSLionel Sambuc   case TokenInfo::TK_Comma:
512f4a2713aSLionel Sambuc   case TokenInfo::TK_Period:
513f4a2713aSLionel Sambuc   case TokenInfo::TK_InvalidChar:
514f4a2713aSLionel Sambuc     const TokenInfo Token = Tokenizer->consumeNextToken();
515f4a2713aSLionel Sambuc     Error->addError(Token.Range, Error->ET_ParserInvalidToken) << Token.Text;
516f4a2713aSLionel Sambuc     return false;
517f4a2713aSLionel Sambuc   }
518f4a2713aSLionel Sambuc 
519f4a2713aSLionel Sambuc   llvm_unreachable("Unknown token kind.");
520f4a2713aSLionel Sambuc }
521f4a2713aSLionel Sambuc 
522*0a6a1f1dSLionel Sambuc static llvm::ManagedStatic<Parser::RegistrySema> DefaultRegistrySema;
523*0a6a1f1dSLionel Sambuc 
Parser(CodeTokenizer * Tokenizer,Sema * S,const NamedValueMap * NamedValues,Diagnostics * Error)524f4a2713aSLionel Sambuc Parser::Parser(CodeTokenizer *Tokenizer, Sema *S,
525*0a6a1f1dSLionel Sambuc                const NamedValueMap *NamedValues, Diagnostics *Error)
526*0a6a1f1dSLionel Sambuc     : Tokenizer(Tokenizer), S(S ? S : &*DefaultRegistrySema),
527*0a6a1f1dSLionel Sambuc       NamedValues(NamedValues), Error(Error) {}
528f4a2713aSLionel Sambuc 
~RegistrySema()529*0a6a1f1dSLionel Sambuc Parser::RegistrySema::~RegistrySema() {}
530*0a6a1f1dSLionel Sambuc 
531*0a6a1f1dSLionel Sambuc llvm::Optional<MatcherCtor>
lookupMatcherCtor(StringRef MatcherName)532*0a6a1f1dSLionel Sambuc Parser::RegistrySema::lookupMatcherCtor(StringRef MatcherName) {
533*0a6a1f1dSLionel Sambuc   return Registry::lookupMatcherCtor(MatcherName);
534*0a6a1f1dSLionel Sambuc }
535*0a6a1f1dSLionel Sambuc 
actOnMatcherExpression(MatcherCtor Ctor,const SourceRange & NameRange,StringRef BindID,ArrayRef<ParserValue> Args,Diagnostics * Error)536*0a6a1f1dSLionel Sambuc VariantMatcher Parser::RegistrySema::actOnMatcherExpression(
537*0a6a1f1dSLionel Sambuc     MatcherCtor Ctor, const SourceRange &NameRange, StringRef BindID,
538*0a6a1f1dSLionel Sambuc     ArrayRef<ParserValue> Args, Diagnostics *Error) {
539f4a2713aSLionel Sambuc   if (BindID.empty()) {
540*0a6a1f1dSLionel Sambuc     return Registry::constructMatcher(Ctor, NameRange, Args, Error);
541f4a2713aSLionel Sambuc   } else {
542*0a6a1f1dSLionel Sambuc     return Registry::constructBoundMatcher(Ctor, NameRange, BindID, Args,
543*0a6a1f1dSLionel Sambuc                                            Error);
544f4a2713aSLionel Sambuc   }
545f4a2713aSLionel Sambuc }
546f4a2713aSLionel Sambuc 
getAcceptedCompletionTypes(ArrayRef<std::pair<MatcherCtor,unsigned>> Context)547*0a6a1f1dSLionel Sambuc std::vector<ArgKind> Parser::RegistrySema::getAcceptedCompletionTypes(
548*0a6a1f1dSLionel Sambuc     ArrayRef<std::pair<MatcherCtor, unsigned>> Context) {
549*0a6a1f1dSLionel Sambuc   return Registry::getAcceptedCompletionTypes(Context);
550*0a6a1f1dSLionel Sambuc }
551*0a6a1f1dSLionel Sambuc 
getMatcherCompletions(ArrayRef<ArgKind> AcceptedTypes)552*0a6a1f1dSLionel Sambuc std::vector<MatcherCompletion> Parser::RegistrySema::getMatcherCompletions(
553*0a6a1f1dSLionel Sambuc     ArrayRef<ArgKind> AcceptedTypes) {
554*0a6a1f1dSLionel Sambuc   return Registry::getMatcherCompletions(AcceptedTypes);
555f4a2713aSLionel Sambuc }
556f4a2713aSLionel Sambuc 
parseExpression(StringRef Code,Sema * S,const NamedValueMap * NamedValues,VariantValue * Value,Diagnostics * Error)557f4a2713aSLionel Sambuc bool Parser::parseExpression(StringRef Code, Sema *S,
558*0a6a1f1dSLionel Sambuc                              const NamedValueMap *NamedValues,
559f4a2713aSLionel Sambuc                              VariantValue *Value, Diagnostics *Error) {
560f4a2713aSLionel Sambuc   CodeTokenizer Tokenizer(Code, Error);
561*0a6a1f1dSLionel Sambuc   if (!Parser(&Tokenizer, S, NamedValues, Error).parseExpressionImpl(Value))
562*0a6a1f1dSLionel Sambuc     return false;
563f4a2713aSLionel Sambuc   if (Tokenizer.peekNextToken().Kind != TokenInfo::TK_Eof) {
564f4a2713aSLionel Sambuc     Error->addError(Tokenizer.peekNextToken().Range,
565f4a2713aSLionel Sambuc                     Error->ET_ParserTrailingCode);
566f4a2713aSLionel Sambuc     return false;
567f4a2713aSLionel Sambuc   }
568f4a2713aSLionel Sambuc   return true;
569f4a2713aSLionel Sambuc }
570f4a2713aSLionel Sambuc 
571*0a6a1f1dSLionel Sambuc std::vector<MatcherCompletion>
completeExpression(StringRef Code,unsigned CompletionOffset,Sema * S,const NamedValueMap * NamedValues)572*0a6a1f1dSLionel Sambuc Parser::completeExpression(StringRef Code, unsigned CompletionOffset, Sema *S,
573*0a6a1f1dSLionel Sambuc                            const NamedValueMap *NamedValues) {
574*0a6a1f1dSLionel Sambuc   Diagnostics Error;
575*0a6a1f1dSLionel Sambuc   CodeTokenizer Tokenizer(Code, &Error, CompletionOffset);
576*0a6a1f1dSLionel Sambuc   Parser P(&Tokenizer, S, NamedValues, &Error);
577*0a6a1f1dSLionel Sambuc   VariantValue Dummy;
578*0a6a1f1dSLionel Sambuc   P.parseExpressionImpl(&Dummy);
579*0a6a1f1dSLionel Sambuc 
580*0a6a1f1dSLionel Sambuc   // Sort by specificity, then by name.
581*0a6a1f1dSLionel Sambuc   std::sort(P.Completions.begin(), P.Completions.end(),
582*0a6a1f1dSLionel Sambuc             [](const MatcherCompletion &A, const MatcherCompletion &B) {
583*0a6a1f1dSLionel Sambuc     if (A.Specificity != B.Specificity)
584*0a6a1f1dSLionel Sambuc       return A.Specificity > B.Specificity;
585*0a6a1f1dSLionel Sambuc     return A.TypedText < B.TypedText;
586*0a6a1f1dSLionel Sambuc   });
587*0a6a1f1dSLionel Sambuc 
588*0a6a1f1dSLionel Sambuc   return P.Completions;
589f4a2713aSLionel Sambuc }
590f4a2713aSLionel Sambuc 
591f4a2713aSLionel Sambuc llvm::Optional<DynTypedMatcher>
parseMatcherExpression(StringRef Code,Sema * S,const NamedValueMap * NamedValues,Diagnostics * Error)592*0a6a1f1dSLionel Sambuc Parser::parseMatcherExpression(StringRef Code, Sema *S,
593*0a6a1f1dSLionel Sambuc                                const NamedValueMap *NamedValues,
594f4a2713aSLionel Sambuc                                Diagnostics *Error) {
595f4a2713aSLionel Sambuc   VariantValue Value;
596*0a6a1f1dSLionel Sambuc   if (!parseExpression(Code, S, NamedValues, &Value, Error))
597f4a2713aSLionel Sambuc     return llvm::Optional<DynTypedMatcher>();
598f4a2713aSLionel Sambuc   if (!Value.isMatcher()) {
599f4a2713aSLionel Sambuc     Error->addError(SourceRange(), Error->ET_ParserNotAMatcher);
600f4a2713aSLionel Sambuc     return llvm::Optional<DynTypedMatcher>();
601f4a2713aSLionel Sambuc   }
602f4a2713aSLionel Sambuc   llvm::Optional<DynTypedMatcher> Result =
603f4a2713aSLionel Sambuc       Value.getMatcher().getSingleMatcher();
604f4a2713aSLionel Sambuc   if (!Result.hasValue()) {
605f4a2713aSLionel Sambuc     Error->addError(SourceRange(), Error->ET_ParserOverloadedType)
606f4a2713aSLionel Sambuc         << Value.getTypeAsString();
607f4a2713aSLionel Sambuc   }
608f4a2713aSLionel Sambuc   return Result;
609f4a2713aSLionel Sambuc }
610f4a2713aSLionel Sambuc 
611f4a2713aSLionel Sambuc }  // namespace dynamic
612f4a2713aSLionel Sambuc }  // namespace ast_matchers
613f4a2713aSLionel Sambuc }  // namespace clang
614