44 : code(matcherCode), startOfLine(matcherCode), error(error) {
45 nextToken = getNextToken();
50 unsigned codeCompletionOffset)
51 : code(matcherCode), startOfLine(matcherCode), error(error),
52 codeCompletionLocation(matcherCode.data() + codeCompletionOffset) {
53 nextToken = getNextToken();
62 nextToken = getNextToken();
69 nextToken = getNextToken();
85 llvm::StringRef firstCharacterAndDrop(llvm::StringRef &str) {
87 llvm::StringRef firstChar = str.substr(0, 1);
88 str = str.drop_front();
93 TokenInfo getNextToken() {
96 result.range.start = currentLocation();
99 if (codeCompletionLocation && codeCompletionLocation <= code.data()) {
101 llvm::StringRef(codeCompletionLocation, 0));
102 codeCompletionLocation =
nullptr;
115 code = code.drop_until([](
char c) {
return c ==
'\n'; });
116 return getNextToken();
125 startOfLine = code.drop_front();
136 consumeStringLiteral(&result);
148 consumeNumberLiteral(&result);
151 parseIdentifierOrInvalid(&result);
155 result.range.end = currentLocation();
159 void consumeNumberLiteral(TokenInfo *result) {
160 StringRef original = code;
162 if (!code.consumeInteger(0, value)) {
163 size_t numConsumed = original.size() - code.size();
164 result->text = original.take_front(numConsumed);
166 result->value =
static_cast<int64_t
>(value);
173 void consumeStringLiteral(TokenInfo *result) {
174 bool inEscape =
false;
175 const char marker = code[0];
176 for (
size_t length = 1; length < code.size(); ++length) {
181 if (code[length] ==
'\\') {
185 if (code[length] == marker) {
187 result->text = code.substr(0, length + 1);
188 result->value = code.substr(1, length - 1);
189 code = code.drop_front(length + 1);
193 llvm::StringRef errorText = code;
194 code = code.drop_front(code.size());
196 range.start = result->range.start;
197 range.end = currentLocation();
202 void parseIdentifierOrInvalid(TokenInfo *result) {
203 if (isalnum(code[0])) {
205 size_t tokenLength = 1;
211 if (codeCompletionLocation == code.data() + tokenLength) {
212 codeCompletionLocation =
nullptr;
214 result->text = code.substr(0, tokenLength);
215 code = code.drop_front(tokenLength);
218 if (tokenLength == code.size() || !(isalnum(code[tokenLength])))
222 llvm::StringRef token = code.substr(0, tokenLength);
223 code = code.drop_front(tokenLength);
225 if (token ==
"true") {
226 result->text =
"false";
228 result->value =
true;
229 }
else if (token ==
"false") {
230 result->text =
"false";
232 result->value =
false;
236 result->text = token;
240 result->text = code.substr(0, 1);
241 code = code.drop_front(1);
246 void consumeWhitespace() { code = code.ltrim(
" \t\v\f\r"); }
249 SourceLocation currentLocation() {
250 SourceLocation location;
251 location.line = line;
252 location.column = code.data() - startOfLine.data() + 1;
256 llvm::StringRef code;
257 llvm::StringRef startOfLine;
261 const char *codeCompletionLocation =
nullptr;
271 std::vector<MatcherCompletion>
281 parser->contextStack.emplace_back(c, 0u);
286 void nextArg() { ++parser->contextStack.back().second; }
292 bool Parser::parseIdentifierPrefixImpl(
VariantValue *value) {
297 if (
auto namedValue = namedValues ? namedValues->lookup(nameToken.text)
305 if (!namedValue.isMatcher()) {
325 !sema->lookupMatcherCtor(nameToken.text)) {
343 std::optional<MatcherCtor> ctor = sema->lookupMatcherCtor(nameToken.text);
346 return parseMatcherExpressionImpl(nameToken, openToken, ctor, value);
349 bool Parser::parseChainedExpression(std::string &argument) {
363 !argumentToken.value.isString()) {
364 error->
addError(argumentToken.range,
375 argument = argumentToken.value.getString();
380 bool Parser::parseMatcherArgs(std::vector<ParserValue> &args,
MatcherCtor ctor,
381 const TokenInfo &nameToken, TokenInfo &endToken) {
382 ScopedContextEntry sce(
this, ctor);
401 ParserValue argValue;
406 if (!parseExpressionImpl(&argValue.value)) {
411 args.push_back(argValue);
419 bool Parser::parseMatcherExpressionImpl(
const TokenInfo &nameToken,
420 const TokenInfo &openToken,
421 std::optional<MatcherCtor> ctor,
422 VariantValue *value) {
429 std::vector<ParserValue> args;
434 if (!parseMatcherArgs(args, ctor.value_or(
nullptr), nameToken, endToken)) {
445 std::string functionName;
450 addCompletion(chainCallToken, MatcherCompletion(
"extract(\"",
"extract"));
456 error->
addError(chainCallToken.range,
462 !parseChainedExpression(functionName))
469 SourceRange matcherRange = nameToken.range;
470 matcherRange.end = endToken.range.end;
471 VariantMatcher result = sema->actOnMatcherExpression(
472 *ctor, matcherRange, functionName, args, error);
481 void Parser::addCompletion(
const TokenInfo &compToken,
482 const MatcherCompletion &completion) {
483 if (llvm::StringRef(completion.typedText).starts_with(compToken.text)) {
484 completions.emplace_back(completion.typedText.substr(compToken.text.size()),
485 completion.matcherDecl);
489 std::vector<MatcherCompletion>
494 std::vector<MatcherCompletion> result;
495 for (
const auto &entry : *namedValues) {
497 (entry.getValue().getTypeAsString() +
" " + entry.getKey()).str();
498 result.emplace_back(entry.getKey(), decl);
503 void Parser::addExpressionCompletions() {
509 for (
const auto &entry : contextStack) {
514 auto acceptedTypes = sema->getAcceptedCompletionTypes(contextStack);
515 for (
const auto &completion : sema->getMatcherCompletions(acceptedTypes)) {
516 addCompletion(compToken, completion);
519 for (
const auto &completion : getNamedValueCompletions(acceptedTypes)) {
520 addCompletion(compToken, completion);
525 bool Parser::parseExpressionImpl(VariantValue *value) {
531 return parseIdentifierPrefixImpl(value);
533 addExpressionCompletions();
555 llvm_unreachable(
"Unknown token kind.");
558 Parser::Parser(CodeTokenizer *tokenizer,
const Registry &matcherRegistry,
560 : tokenizer(tokenizer),
561 sema(std::make_unique<RegistrySema>(matcherRegistry)),
562 namedValues(namedValues), error(error) {}
566 std::optional<MatcherCtor>
593 Parser parser(&tokenizer, matcherRegistry, namedValues, error);
594 if (!parser.parseExpressionImpl(value))
606 std::vector<MatcherCompletion>
612 Parser parser(&tokenizer, matcherRegistry, namedValues, &error);
614 parser.parseExpressionImpl(&dummy);
616 return parser.completions;
620 llvm::StringRef &code,
const Registry &matcherRegistry,
623 if (!
parseExpression(code, matcherRegistry, namedValues, &value, error))
static std::vector< MatcherCompletion > getMatcherCompletions(ArrayRef< ArgKind > acceptedTypes, const Registry &matcherRegistry)
static std::vector< ArgKind > getAcceptedCompletionTypes(llvm::ArrayRef< std::pair< MatcherCtor, unsigned >> context)
static std::optional< MatcherCtor > lookupMatcherCtor(llvm::StringRef matcherName, const Registry &matcherRegistry)
static VariantMatcher constructMatcher(MatcherCtor ctor, internal::SourceRange nameRange, llvm::StringRef functionName, ArrayRef< ParserValue > args, internal::Diagnostics *error)
std::optional< DynMatcher > getDynMatcher() const
std::string getTypeAsString() const
const VariantMatcher & getMatcher() const
ArgStream addError(SourceRange range, ErrorType error)
TokenInfo consumeNextToken()
CodeTokenizer(llvm::StringRef matcherCode, Diagnostics *error, unsigned codeCompletionOffset)
TokenKind nextTokenKind() const
const TokenInfo & peekNextToken() const
CodeTokenizer(llvm::StringRef matcherCode, Diagnostics *error)
TokenInfo consumeNextTokenIgnoreNewlines()
std::optional< MatcherCtor > lookupMatcherCtor(llvm::StringRef matcherName) override
std::vector< MatcherCompletion > getMatcherCompletions(llvm::ArrayRef< ArgKind > acceptedTypes) override
std::vector< ArgKind > getAcceptedCompletionTypes(llvm::ArrayRef< std::pair< MatcherCtor, unsigned >> context) override
VariantMatcher actOnMatcherExpression(MatcherCtor Ctor, SourceRange NameRange, StringRef functionName, ArrayRef< ParserValue > Args, Diagnostics *Error) override
virtual std::vector< MatcherCompletion > getMatcherCompletions(llvm::ArrayRef< ArgKind > acceptedTypes)
virtual std::vector< ArgKind > getAcceptedCompletionTypes(llvm::ArrayRef< std::pair< MatcherCtor, unsigned >> Context)
static bool parseExpression(llvm::StringRef &code, const Registry &matcherRegistry, const NamedValueMap *namedValues, VariantValue *value, Diagnostics *error)
llvm::StringMap< VariantValue > NamedValueMap
static std::vector< MatcherCompletion > completeExpression(llvm::StringRef &code, unsigned completionOffset, const Registry &matcherRegistry, const NamedValueMap *namedValues)
static std::optional< DynMatcher > parseMatcherExpression(llvm::StringRef &matcherCode, const Registry &matcherRegistry, const NamedValueMap *namedValues, Diagnostics *error)
@ ParserChainedExprNoOpenParen
@ RegistryMatcherNotFound
@ ParserChainedExprInvalidArg
@ ParserMalformedChainedExpr
@ ParserChainedExprNoCloseParen
const internal::MatcherDescriptor * MatcherCtor
ScopedContextEntry(Parser *parser, MatcherCtor c)
static const char *const ID_Extract
void set(TokenKind newKind, llvm::StringRef newText)