Skip to content

Specification

This document provides the complete specification for Grammar School. All implementations (Python, Go, and future languages) must follow this conceptual design.

Overview

Grammar School is a lightweight, multi-language framework for creating small, precise, LLM-friendly domain-specific languages (DSLs). It provides:

  • A way to define grammar rules (via strings or structured combinators)
  • A way to map DSL verbs to semantic handlers
  • A parser → AST → interpreter → actions → runtime pipeline
  • Independent implementations in Python and Go (and potentially TypeScript)

Grammar School does not require interop between languages. Each implementation is standalone but follows the same conceptual model.

Core Concepts

DSL Program

A DSL program is a plain string, typically generated by an LLM under CFG constraints:

track(name="Drums").add_clip(start=0, length=8)
Cmaj7(1,1), Fmaj7(2,1)
tracks().filter(name~="FX").mute()

Abstract Syntax Tree (AST)

Grammar School uses the following conceptual AST types:

Value:
  kind: "number" | "string" | "identifier" | "bool"
  value: any

Arg:
  name: string
  value: Value

Call:
  name: string
  args: Map<string,Value>

CallChain:
  calls: Call[]

Each implementation represents these using native language types (e.g., Python dataclasses, Go structs).

Actions (Interpreter Output)

Semantic evaluation produces Action objects:

Action:
  kind: string           # e.g. "create_track", "add_clip", "note"
  payload: Map<String,Any>

These are runtime instructions executed later by a domain-specific runtime.

Lifecycle

Every implementation follows the same pipeline:

DSL code (string)
   → Parse
       → CallChain (AST)
           → Interpret
               → []Action (plan)
                   → Execute (runtime)

Python Specification

See the Python API documentation for the complete Python implementation specification.

Go Specification

See the Go API documentation for the complete Go implementation specification.

Equality of Implementations

  • Python and Go implementations must follow the same conceptual design.
  • They do not share code.
  • They do not depend on each other.
  • They do not need to interoperate.
  • They simply implement the same grammar → AST → actions flow.

This gives: consistency, flexibility, multi-runtime choice, no forced coupling.

What's Not in Scope

  • Not a full compiler toolkit
  • Not intended to replace ANTLR, LALR tools, or PEG frameworks
  • No static type inference
  • No necessity for Rust, C++, WASM, or cross-language FFI
  • No cross-language runtime communication by default

Each implementation stands on its own.