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)