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") {
229 }
else if (token ==
"false") {
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;
271std::vector<MatcherCompletion>
281 parser->contextStack.emplace_back(c, 0u);
292bool Parser::parseIdentifierPrefixImpl(
VariantValue *value) {
297 if (
auto namedValue = namedValues ? namedValues->lookup(nameToken.text)
305 if (!namedValue.isMatcher()) {
325 !sema->lookupMatcherCtor(nameToken.text)) {
333 tokenizer->skipNewlines();
336 TokenInfo openToken = tokenizer->consumeNextToken();
343 std::optional<MatcherCtor> ctor = sema->lookupMatcherCtor(nameToken.text);
346 return parseMatcherExpressionImpl(nameToken, openToken, ctor, value);
349bool Parser::parseChainedExpression(std::string &argument) {
353 const TokenInfo openToken = tokenizer->consumeNextToken();
354 const TokenInfo argumentToken = tokenizer->consumeNextTokenIgnoreNewlines();
355 const TokenInfo closeToken = tokenizer->consumeNextTokenIgnoreNewlines();
363 !argumentToken.value.isString()) {
364 error->addError(argumentToken.range,
380bool Parser::parseMatcherArgs(std::vector<ParserValue> &args,
MatcherCtor ctor,
387 endToken = tokenizer->consumeNextToken();
393 TokenInfo commaToken = tokenizer->consumeNextToken();
401 ParserValue argValue;
402 tokenizer->skipNewlines();
404 argValue.text = tokenizer->peekNextToken().text;
405 argValue.range = tokenizer->peekNextToken().range;
406 if (!parseExpressionImpl(&argValue.value)) {
410 tokenizer->skipNewlines();
411 args.push_back(argValue);
419bool Parser::parseMatcherExpressionImpl(
const TokenInfo &nameToken,
421 std::optional<MatcherCtor> ctor,
422 VariantValue *value) {
429 std::vector<ParserValue> args;
432 tokenizer->skipNewlines();
434 if (!parseMatcherArgs(args, ctor.value_or(
nullptr), nameToken, endToken)) {
445 std::string functionName;
447 tokenizer->consumeNextToken();
448 TokenInfo chainCallToken = tokenizer->consumeNextToken();
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);
481void 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);
489std::vector<MatcherCompletion>
490Parser::getNamedValueCompletions(llvm::ArrayRef<ArgKind> acceptedTypes) {
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);
503void Parser::addExpressionCompletions() {
504 const TokenInfo compToken = tokenizer->consumeNextTokenIgnoreNewlines();
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);
525bool Parser::parseExpressionImpl(VariantValue *value) {
526 switch (tokenizer->nextTokenKind()) {
528 *value = tokenizer->consumeNextToken().value;
531 return parseIdentifierPrefixImpl(value);
533 addExpressionCompletions();
536 error->addError(tokenizer->consumeNextToken().range,
549 const TokenInfo token = tokenizer->consumeNextToken();
555 llvm_unreachable(
"Unknown token kind.");
558Parser::Parser(
CodeTokenizer *tokenizer,
const Registry &matcherRegistry,
560 : tokenizer(tokenizer),
562 namedValues(namedValues), error(error) {}
566std::optional<MatcherCtor>
593 Parser parser(&tokenizer, matcherRegistry, namedValues, error);
594 if (!parser.parseExpressionImpl(value))
596 auto nextToken = tokenizer.peekNextToken();
599 error->addError(tokenizer.peekNextToken().range,
606std::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
const llvm::StringRef & getString() 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< ArgKind > getAcceptedCompletionTypes(llvm::ArrayRef< std::pair< MatcherCtor, unsigned > > context) override
std::vector< MatcherCompletion > getMatcherCompletions(llvm::ArrayRef< ArgKind > acceptedTypes) 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)
void set(TokenKind newKind, llvm::StringRef newText)
static const char *const idExtract