Is there any solution to create language completion from grammar?

Is there any code which can complete from grammar? I got to this example, but its not completing FROM and SELECT keywords. I didn’t find anything so I guess there is no solution and it has to be taken care of manually.

import { EditorView, basicSetup } from "codemirror";
import { EditorState } from "@codemirror/state";
import { Language, syntaxTree } from "@codemirror/language";
import { LRLanguage, LanguageSupport } from "@codemirror/language";
import { styleTags, tags as t } from "@lezer/highlight";
import { autocompletion } from "@codemirror/autocomplete";
import { buildParser } from '@lezer/generator';

/* sample grammar and completion for
FROM table select field1, field2
*/

    const tableSpecs = [
      { tablename: "users", fields: ["id", "name", "email"] },
      { tablename: "orders", fields: ["order_id", "user_id", "date"] }
    ];

    // Lezer grammar for the DSL
    const grammar = `
      @top Query { "FROM" TableName "SELECT" FieldList }
      TableName { identifier }
      FieldList { Field ("," Field)* }
      Field { identifier }

    @tokens {
      identifier { std.asciiLetter+ }
      whitespace { std.whitespace+ }
    }
@skip { whitespace }
    `;
    const parser = buildParser(grammar);

    // Completion source
    function sqlCompletion(context: any) {
      console.log(`context ${context}`);
      let { state, pos } = context;
      let tree = state.tree;
      let node = tree.resolve(pos, -1); // Innermost node at cursor

      // Check if we're in an Identifier node
      if (node.type.name === "TableName" && node.parent) {

          let word = context.matchBefore(/\w*/);
          if (!word) return null;
          let options = tableSpecs.map(spec => ({ label: spec.tablename }));
          options = options.filter(opt => opt.label.startsWith(word.text));
          return {
            from: word.from,
            options
          };
      }

    if (node.type.name === "Field" && node.parent) {
        console.log("=== Field");
        // Find the Query node by traversing up
        let current = node.parent;
        while (current && current.type.name !== "Query") {
            current = current.parent;
        }

        if (!current) return null;

        // Get the TableName node under Query
        let tableNameNode = current.getChildren("TableName")[0];
        if (!tableNameNode) return null;

        // Extract table name text
        let tableName = state.doc.sliceString(tableNameNode.from, tableNameNode.to);
        console.log(tableName);
        let tableSpec = tableSpecs.find(spec => spec.tablename === tableName);
        if (!tableSpec) return null;

        let word = context.matchBefore(/\w*/);
        if (!word) return null;
        let options = tableSpec.fields.map(field => ({ label: field }));
        options = options.filter(opt => opt.label.startsWith(word.text));
        return {
            from: word.from,
            options
        };
    }
      return null;
    }



const sqlLang = LRLanguage.define({
  parser: parser.configure({
    props: [
      styleTags({
        TableName: t.variableName,
        FieldName: t.propertyName,
        "SELECT FROM": t.keyword,
      }),
    ],
  }),
});

export function example() {
  return new LanguageSupport(sqlLang, [
     sqlLang.data.of({autocomplete: sqlCompletion})
  ])
}


;(window as any).view = new EditorView({
  doc: 'FROM u' ,
  extensions: [
    basicSetup,
    example(),
    autocompletion({ override: [sqlCompletion] })
  ],
  parent: document.body
})

Indeed, providing good completion from a grammar is tricky, and it wouldn’t really give you more than keyword completion, so there’s no such feature, and people write completion separate from the grammar (though possibly using syntax tree context to make it more specific).