Metadata-Version: 2.4
Name: grammar-school
Version: 0.5.0
Summary: A lightweight framework for building tiny LLM-friendly DSLs
Author-email: Conceptual Machines <romagnoli.luca@gmail.com>
License-Expression: MIT
Keywords: dsl,domain-specific-language,llm,parser,interpreter,grammar
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Software Development :: Interpreters
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: lark>=1.1.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
Requires-Dist: pytest-xdist>=3.0.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Requires-Dist: mypy>=1.0.0; extra == "dev"
Requires-Dist: pre-commit>=3.0.0; extra == "dev"
Requires-Dist: openai>=1.0.0; extra == "dev"
Provides-Extra: docs
Requires-Dist: mkdocs>=1.5.0; extra == "docs"
Requires-Dist: mkdocs-material>=9.0.0; extra == "docs"
Requires-Dist: mkdocstrings[python]>=0.23.0; extra == "docs"
Requires-Dist: pymdown-extensions>=10.0.0; extra == "docs"

# Grammar School - Python Implementation

A lightweight framework for building tiny LLM-friendly DSLs in Python.

## Installation

```bash
pip install grammar-school
```

For development:

```bash
pip install -e ".[dev]"
```

## Quick Start

```python
from grammar_school import Grammar, method

class MyGrammar(Grammar):
    @method
    def greet(self, name):
        # @method contains the actual implementation
        # You can do anything here - side effects, state changes, etc.
        print(f"Hello, {name}!")

# No runtime needed - methods execute directly!
grammar = MyGrammar()
grammar.execute('greet(name="World")')

# Methods can maintain state using self
class MyGrammarWithState(Grammar):
    def __init__(self):
        super().__init__()
        self.greetings = []  # State managed in the grammar instance

    @method
    def greet(self, name):
        self.greetings.append(name)
        print(f"Hello, {name}!")

grammar = MyGrammarWithState()
grammar.execute('greet(name="World")')
print(grammar.greetings)  # ['World']
```

## Understanding the Architecture

Grammar School provides a **unified interface**:

1. **Grammar + @method**: Methods contain their implementation directly
2. **Framework handles the rest**: Parsing, interpretation, and execution happen automatically

**Benefits:**
- Simple and intuitive - just write methods with your logic
- No need to separate concerns - methods can do anything
- State management via `self` attributes
- The Grammar/Runtime split is handled internally but hidden from you

## Streaming Execution

For large DSL programs or real-time processing, you can stream method executions:

```python
grammar = MyGrammar()

# Stream method executions one at a time (memory efficient)
for _ in grammar.stream('greet(name="A").greet(name="B").greet(name="C")'):
    # Methods execute as they're called
    pass
```

This is useful for:
- **Large programs**: Don't load all method calls into memory at once
- **Real-time processing**: Start executing methods before parsing completes
- **Memory efficiency**: Process methods incrementally

## Functional Programming Support

Grammar School supports functional programming paradigms through the `FunctionalMixin`:

```python
from grammar_school import Grammar, FunctionalMixin, method

class MyGrammar(Grammar, FunctionalMixin):
    @method
    def square(self, x):
        return x * x

    @method
    def is_even(self, x):
        return x % 2 == 0

grammar = MyGrammar()
# Use functional operations with function references
grammar.execute('map(@square, data)')
grammar.execute('filter(@is_even, data)')
grammar.execute('map(@square, data).filter(@is_even, data)')
```

**Available functional operations:**
- `map(@function, data)` - Map a function over data
- `filter(@predicate, data)` - Filter data using a predicate
- `reduce(@function, data, initial)` - Reduce data using a function
- `compose(@f, @g, @h)` - Compose multiple functions
- `pipe(data, @f, @g, @h)` - Pipe data through functions

**Function references:** Use `@function_name` syntax to pass functions as arguments.

## Examples

See the `examples/` directory for complete DSL implementations.

## API Reference

### Core Types

- `Value`: AST value node (number, string, identifier, bool)
- `Arg`: Named argument
- `Call`: Function call with arguments
- `CallChain`: Chain of calls (method chaining)
### Decorators

- `@method`: Mark a method as a DSL handler (contains implementation)
- `@rule`: Define grammar rules (for custom grammars)

### Classes

- `Grammar`: Main grammar class that orchestrates parsing and interpretation
- `Interpreter`: Interprets CallChain AST into Actions
- `LarkBackend`: Lark-based parser backend
