""" Base class for DSL definitions. DSLDefinition provides the interface for defining domain-specific languages that can be used with the DslEditor control and CodeMirror. """ from abc import ABC, abstractmethod from functools import cached_property from typing import List, Dict, Any from myfasthtml.core.dsl.lark_to_simple_mode import extract_completions_from_grammar from myfasthtml.core.utils import make_safe_id class DSLDefinition(ABC): """ Base class for DSL definitions. Subclasses must implement get_grammar() to provide the Lark grammar. The Lezer grammar and completions are automatically derived. Attributes: name: Human-readable name of the DSL. """ name: str = "DSL" @abstractmethod def get_grammar(self) -> str: """ Return the Lark grammar string for this DSL. Returns: The Lark grammar as a string. """ pass @cached_property def completions(self) -> Dict[str, List[str]]: """ Return completion items extracted from the grammar. This is cached after first computation. Returns: Dictionary with completion categories: - 'keywords': Language keywords (if, not, and, etc.) - 'operators': Comparison and arithmetic operators - 'functions': Function-like constructs (style, format, etc.) - 'types': Type names (number, date, boolean, etc.) - 'literals': Literal values (True, False, etc.) """ return extract_completions_from_grammar(self.get_grammar()) @cached_property def simple_mode_config(self) -> Dict[str, Any]: """ Return the CodeMirror 5 Simple Mode configuration for syntax highlighting. This is cached after first computation. Returns: Dictionary with Simple Mode rules: { "start": [ {"regex": "...", "token": "keyword"}, {"regex": "...", "token": "string"}, ... ] } """ from myfasthtml.core.dsl.lark_to_simple_mode import lark_to_simple_mode return lark_to_simple_mode(self.get_grammar()) def get_editor_config(self) -> Dict[str, Any]: """ Return the configuration for the DslEditor JavaScript initialization. Returns: Dictionary with: - 'simpleModeConfig': The CodeMirror Simple Mode configuration - 'completions': The completion items - 'name': The DSL name """ return { "name": self.name, "simpleModeConfig": self.simple_mode_config, "completions": self.completions, } def get_id(self): return make_safe_id(self.name)