20 #include "llvm/ADT/Optional.h" 21 #include "llvm/ADT/StringRef.h" 22 #include "llvm/Support/ErrorHandling.h" 23 #include "llvm/Support/ManagedStatic.h" 70 : Code(MatcherCode), StartOfLine(MatcherCode), Error(Error) {
71 NextToken = getNextToken();
75 unsigned CodeCompletionOffset)
76 : Code(MatcherCode), StartOfLine(MatcherCode), Error(Error),
77 CodeCompletionLocation(MatcherCode.data() + CodeCompletionOffset) {
78 NextToken = getNextToken();
87 NextToken = getNextToken();
99 if (CodeCompletionLocation && CodeCompletionLocation <= Code.data()) {
101 Result.
Text = StringRef(CodeCompletionLocation, 0);
102 CodeCompletionLocation =
nullptr;
115 Result.
Text = Code.substr(0, 1);
116 Code = Code.drop_front();
120 Result.
Text = Code.substr(0, 1);
121 Code = Code.drop_front();
125 Result.
Text = Code.substr(0, 1);
126 Code = Code.drop_front();
130 Result.
Text = Code.substr(0, 1);
131 Code = Code.drop_front();
137 consumeStringLiteral(&Result);
140 case '0':
case '1':
case '2':
case '3':
case '4':
141 case '5':
case '6':
case '7':
case '8':
case '9':
143 consumeNumberLiteral(&Result);
149 size_t TokenLength = 1;
154 if (CodeCompletionLocation == Code.data() + TokenLength) {
155 CodeCompletionLocation =
nullptr;
157 Result.
Text = Code.substr(0, TokenLength);
158 Code = Code.drop_front(TokenLength);
161 if (TokenLength == Code.size() || !
isAlphanumeric(Code[TokenLength]))
165 if (TokenLength == 4 && Code.startswith(
"true")) {
168 }
else if (TokenLength == 5 && Code.startswith(
"false")) {
170 Result.
Value =
false;
173 Result.
Text = Code.substr(0, TokenLength);
175 Code = Code.drop_front(TokenLength);
178 Result.
Text = Code.substr(0, 1);
179 Code = Code.drop_front(1);
184 Result.
Range.
End = currentLocation();
189 void consumeNumberLiteral(
TokenInfo *Result) {
190 bool isFloatingLiteral =
false;
192 if (Code.size() > 1) {
195 case 'x':
case 'b': Length = 2;
198 while (Length < Code.size() &&
isHexDigit(Code[Length]))
202 while (Length < Code.size()) {
203 char c = Code[Length];
204 if (c ==
'-' || c ==
'+' || c ==
'.' ||
isHexDigit(c)) {
205 isFloatingLiteral =
true;
212 Result->
Text = Code.substr(0, Length);
213 Code = Code.drop_front(Length);
215 if (isFloatingLiteral) {
218 std::string
Text = Result->
Text.str();
219 double doubleValue = strtod(Text.c_str(), &end);
220 if (*end == 0 && errno == 0) {
222 Result->
Value = doubleValue;
227 if (!Result->
Text.getAsInteger(0, Value)) {
236 Range.
End = currentLocation();
237 Error->addError(Range, Error->ET_ParserNumberError) << Result->
Text;
245 void consumeStringLiteral(
TokenInfo *Result) {
246 bool InEscape =
false;
247 const char Marker = Code[0];
248 for (
size_t Length = 1, Size = Code.size(); Length != Size; ++Length) {
253 if (Code[Length] ==
'\\') {
257 if (Code[Length] == Marker) {
259 Result->
Text = Code.substr(0, Length + 1);
260 Result->
Value = Code.substr(1, Length - 1);
261 Code = Code.drop_front(Length + 1);
266 StringRef ErrorText = Code;
267 Code = Code.drop_front(Code.size());
270 Range.
End = currentLocation();
271 Error->addError(Range, Error->ET_ParserStringError) << ErrorText;
276 void consumeWhitespace() {
278 if (Code[0] ==
'\n') {
280 StartOfLine = Code.drop_front();
282 Code = Code.drop_front();
289 Location.
Column = Code.data() - StartOfLine.data() + 1;
294 StringRef StartOfLine;
298 const char *CodeCompletionLocation =
nullptr;
308 std::vector<MatcherCompletion>
317 P->ContextStack.push_back(std::make_pair(C, 0u));
321 P->ContextStack.pop_back();
325 ++P->ContextStack.back().second;
335 const TokenInfo NameToken = Tokenizer->consumeNextToken();
340 NamedValues ? NamedValues->lookup(NameToken.
Text)
350 !S->lookupMatcherCtor(NameToken.
Text)) {
351 Error->addError(NameToken.
Range, Error->ET_RegistryValueNotFound)
359 return parseMatcherExpressionImpl(NameToken, Value);
366 bool Parser::parseMatcherExpressionImpl(
const TokenInfo &NameToken,
369 const TokenInfo OpenToken = Tokenizer->consumeNextToken();
371 Error->addError(OpenToken.
Range, Error->ET_ParserNoOpenParen)
379 Error->addError(NameToken.
Range, Error->ET_RegistryMatcherNotFound)
384 std::vector<ParserValue> Args;
393 EndToken = Tokenizer->consumeNextToken();
398 const TokenInfo CommaToken = Tokenizer->consumeNextToken();
400 Error->addError(CommaToken.
Range, Error->ET_ParserNoComma)
410 ArgValue.
Text = Tokenizer->peekNextToken().Text;
411 ArgValue.Range = Tokenizer->peekNextToken().Range;
412 if (!parseExpressionImpl(&ArgValue.Value)) {
416 Args.push_back(ArgValue);
422 Error->addError(OpenToken.
Range, Error->ET_ParserNoCloseParen);
429 Tokenizer->consumeNextToken();
430 const TokenInfo BindToken = Tokenizer->consumeNextToken();
436 const TokenInfo OpenToken = Tokenizer->consumeNextToken();
437 const TokenInfo IDToken = Tokenizer->consumeNextToken();
438 const TokenInfo CloseToken = Tokenizer->consumeNextToken();
444 Error->addError(BindToken.
Range, Error->ET_ParserMalformedBindExpr);
448 Error->addError(OpenToken.
Range, Error->ET_ParserMalformedBindExpr);
452 Error->addError(IDToken.
Range, Error->ET_ParserMalformedBindExpr);
456 Error->addError(CloseToken.
Range, Error->ET_ParserMalformedBindExpr);
471 *Ctor, MatcherRange, BindID, Args, Error);
472 if (Result.
isNull())
return false;
480 void Parser::addCompletion(
const TokenInfo &CompToken,
482 if (StringRef(Completion.
TypedText).startswith(CompToken.
Text) &&
484 Completions.emplace_back(Completion.
TypedText.substr(CompToken.
Text.size()),
489 std::vector<MatcherCompletion> Parser::getNamedValueCompletions(
491 if (!NamedValues)
return std::vector<MatcherCompletion>();
492 std::vector<MatcherCompletion> Result;
493 for (
const auto &Entry : *NamedValues) {
494 unsigned Specificity;
495 if (Entry.getValue().isConvertibleTo(AcceptedTypes, &Specificity)) {
497 (Entry.getValue().getTypeAsString() +
" " + Entry.getKey()).str();
498 Result.emplace_back(Entry.getKey(), Decl, Specificity);
504 void Parser::addExpressionCompletions() {
505 const TokenInfo CompToken = Tokenizer->consumeNextToken();
510 for (ContextStackTy::iterator I = ContextStack.begin(),
511 E = ContextStack.end();
517 auto AcceptedTypes = S->getAcceptedCompletionTypes(ContextStack);
518 for (
const auto &Completion : S->getMatcherCompletions(AcceptedTypes)) {
519 addCompletion(CompToken, Completion);
522 for (
const auto &Completion : getNamedValueCompletions(AcceptedTypes)) {
523 addCompletion(CompToken, Completion);
529 switch (Tokenizer->nextTokenKind()) {
531 *Value = Tokenizer->consumeNextToken().Value;
535 return parseIdentifierPrefixImpl(Value);
538 addExpressionCompletions();
542 Error->addError(Tokenizer->consumeNextToken().Range,
543 Error->ET_ParserNoCode);
556 Error->addError(Token.
Range, Error->ET_ParserInvalidToken) << Token.
Text;
560 llvm_unreachable(
"Unknown token kind.");
565 Parser::Parser(CodeTokenizer *Tokenizer,
Sema *S,
567 : Tokenizer(Tokenizer), S(S ? S : &*DefaultRegistrySema),
568 NamedValues(NamedValues), Error(Error) {}
580 if (BindID.empty()) {
589 ArrayRef<std::pair<MatcherCtor, unsigned>> Context) {
602 if (!
Parser(&Tokenizer, S, NamedValues, Error).parseExpressionImpl(Value))
612 std::vector<MatcherCompletion>
617 Parser P(&Tokenizer, S, NamedValues, &Error);
619 P.parseExpressionImpl(&Dummy);
622 llvm::sort(P.Completions.begin(), P.Completions.end(),
629 return P.Completions;
645 if (!Result.hasValue()) {
static std::vector< MatcherCompletion > completeExpression(StringRef Code, unsigned CompletionOffset, Sema *S, const NamedValueMap *NamedValues)
Complete an expression at the given offset.
static VariantMatcher constructBoundMatcher(MatcherCtor Ctor, SourceRange NameRange, StringRef BindID, ArrayRef< ParserValue > Args, Diagnostics *Error)
Construct a matcher from the registry and bind it.
Simple matcher expression parser.
static std::vector< MatcherCompletion > getMatcherCompletions(ArrayRef< ArgKind > AcceptedTypes)
Compute the list of completions that match any of AcceptedTypes.
static bool parseExpression(StringRef Code, Sema *S, const NamedValueMap *NamedValues, VariantValue *Value, Diagnostics *Error)
Parse an expression.
Registry of all known matchers.
CodeTokenizer(StringRef MatcherCode, Diagnostics *Error)
Decl - This represents one declaration (or definition), e.g.
CodeTokenizer(StringRef MatcherCode, Diagnostics *Error, unsigned CodeCompletionOffset)
llvm::StringMap< VariantValue > NamedValueMap
llvm::Optional< DynTypedMatcher > getSingleMatcher() const
Return a single matcher, if there is no ambiguity.
Token - This structure provides full information about a lexed token.
Matcher descriptor interface.
Simple tokenizer for the parser.
static std::vector< ArgKind > getAcceptedCompletionTypes(llvm::ArrayRef< std::pair< MatcherCtor, unsigned >> Context)
Compute the list of completion types for Context.
LLVM_READONLY bool isWhitespace(unsigned char c)
Return true if this character is horizontal or vertical ASCII whitespace: ' ', '\t', '\f', '\v', '\n', '\r'.
static const char *const ID_Bind
Some known identifiers.
Class defining a parser context.
llvm::Optional< MatcherCtor > lookupMatcherCtor(StringRef MatcherName) override
Look up a matcher by name.
std::string MatcherDecl
The "declaration" of the matcher, with type information.
A VariantValue instance annotated with its parser context.
Sema - This implements semantic analysis and AST building for C.
static llvm::Optional< MatcherCtor > lookupMatcherCtor(StringRef MatcherName)
Look up a matcher in the registry by name,.
std::string getTypeAsString() const
String representation of the type of the value.
Matcher expression parser.
const AnnotatedLine * Line
LLVM_READONLY bool isAlphanumeric(unsigned char c)
Return true if this character is an ASCII letter or digit: [a-zA-Z0-9].
Diagnostics class to manage error messages.
TokenInfo::TokenKind nextTokenKind() const
VariantMatcher actOnMatcherExpression(MatcherCtor Ctor, SourceRange NameRange, StringRef BindID, ArrayRef< ParserValue > Args, Diagnostics *Error) override
Process a matcher expression.
Helper class to manage error messages.
std::vector< ArgKind > getAcceptedCompletionTypes(llvm::ArrayRef< std::pair< MatcherCtor, unsigned >> Context) override
Compute the list of completion types for Context.
ArgStream addError(SourceRange Range, ErrorType Error)
Add an error to the diagnostics.
static llvm::Optional< DynTypedMatcher > parseMatcherExpression(StringRef MatcherCode, Sema *S, const NamedValueMap *NamedValues, Diagnostics *Error)
Parse a matcher expression.
LLVM_READONLY char toLowercase(char c)
Converts the given ASCII character to its lowercase equivalent.
TokenKind
Different possible tokens.
const VariantMatcher & getMatcher() const
unsigned Specificity
Value corresponding to the "specificity" of the converted matcher.
const std::string & getString() const
std::string TypedText
The text to type to select this matcher.
static llvm::ManagedStatic< Parser::RegistrySema > DefaultRegistrySema
const TokenInfo & peekNextToken() const
Returns but doesn't consume the next token.
Dataflow Directional Tag Classes.
bool isMatcher() const
Matcher value functions.
Interface to connect the parser with the registry and more.
Simple structure to hold information for one token from the parser.
bool isNull() const
Whether the matcher is null.
LLVM_READONLY bool isHexDigit(unsigned char c)
Return true if this character is an ASCII hex digit: [0-9a-fA-F].
virtual std::vector< ArgKind > getAcceptedCompletionTypes(llvm::ArrayRef< std::pair< MatcherCtor, unsigned >> Context)
Compute the list of completion types for Context.
A variant matcher object.
std::vector< MatcherCompletion > getMatcherCompletions(llvm::ArrayRef< ArgKind > AcceptedTypes) override
Compute the list of completions that match any of AcceptedTypes.
virtual std::vector< MatcherCompletion > getMatcherCompletions(llvm::ArrayRef< ArgKind > AcceptedTypes)
Compute the list of completions that match any of AcceptedTypes.
TokenInfo consumeNextToken()
Consumes and returns the next token.
bool isString() const
String value functions.
static VariantMatcher constructMatcher(MatcherCtor Ctor, SourceRange NameRange, ArrayRef< ParserValue > Args, Diagnostics *Error)
Construct a matcher from the registry.
ScopedContextEntry(Parser *P, MatcherCtor C)