Skip to content

Template Generator

Benedict Albrecht edited this page May 20, 2026 · 7 revisions

Template Generator

The Crodox Template Generator is a Python script that produces starter Crodox grammar definitions for supported programming languages.

Usage

python crodox_template_generator.py <language>
python crodox_template_generator.py <language> --output <file>

Examples

# Print Python definition to stdout
python crodox_template_generator.py python

# Write to a file
python crodox_template_generator.py python --output python.crodox

Supported Languages

Language Command
Python python crodox_template_generator.py python

Adding New Languages

To add a new language, edit crodox_template_generator.py:

  1. Create a new generator function:

    def generate_mylang() -> str:
        lines = [
            '<~"FROM".ext~>',
            '    # ... your objects here ...',
            '<~>',
        ]
        return '\n'.join(lines) + '\n'
  2. Register it in the LANGUAGES dictionary:

    LANGUAGES: dict[str, Callable[[], str]] = {
        "python": generate_python,
        "mylang": generate_mylang,
    }
  3. Run it:

    python crodox_template_generator.py mylang

Full Script

Save the following as crodox_template_generator.py:

Click to expand the full script
"""
Crodox Template Generator

Generates starter Crodox grammar definition files for supported programming languages.

Usage:
    python crodox_template_generator.py <language> [--output <file>]

Example:
    python crodox_template_generator.py python
    python crodox_template_generator.py python --output python.crodox
"""

import argparse
from typing import Callable


def generate_python() -> str:
    tq = '"""'
    sq = "'''"
    lines = [
        '<~"FROM".py~>',
        '',
        '    <*comment_line*> # -->> \\n <*>',
        f'    <*comment_block*> <| {tq} -->> {tq} <||> {sq} -->> {sq} |> <*>',
        '',
        '    <*()*> ( <---> ) <*>',
        '    <*[]*> [ <---> ] <*>',
        '    <*{}*> { <---> } <*>',
        '',
        '    <:import:>',
        '        import <<name:up>> <| as <<name:up>> <||> |> \\n',
        '    <:>',
        '',
        '    <:from_import:>',
        '        from <<"FROM">> import <| <<name:up>> <||> ( <? <<name:up>> <| , <||> |> ?> ) |> \\n',
        '    <:>',
        '',
        '    <:decorator:>',
        "        @ <<'name'>> <| ( <? <| <<'name'>> <||> ' <<'name'>> ' <||> \" <<'name'>> \" <||> <<name>> |> <| , <||> |> ?> ) <||> |> \\n",
        '    <:>',
        '',
        '    <:variable:>',
        "        <<name>> <| : <<'name'>> <||> |> = -->> \\n",
        '    <:>',
        '',
        '    <:parameter:>',
        "        <<name>> <| : <<'name'>> <||> |> <| = -->> <| , <||> ) |> <||> <| , <||> ) |> |>",
        '    <:>',
        '',
        '    <:function:>',
        "        <| async <||> |> def <<name:up>> ( <? <-{parameter}-> ?> ) <| -> <<'name'>> <||> |> : <--->",
        '    <:>',
        '',
        '    <:class:>',
        "        class <<name:up>> <| ( <? <<'name'>> <| , <||> |> ?> ) <||> |> : <-function->",
        '    <:>',
        '',
        '    <:return:>',
        '        return -->> \\n',
        '    <:>',
        '',
        '    <:raise:>',
        "        raise <<'name'>> ( -->> ) \\n",
        '    <:>',
        '',
        '    <:if:>        if -->> : <--->',
        '    <:>',
        '',
        '    <:elif:>        elif -->> : <--->',
        '    <:>',
        '',
        '    <:else:>        else : <--->',
        '    <:>',
        '',
        '    <:for:>        for <<name>> in -->> : <--->',
        '    <:>',
        '',
        '    <:while:>        while -->> : <--->',
        '    <:>',
        '',
        '    <:try:>        try : <--->',
        '    <:>',
        '',
        '    <:except:>',
        "        except <| <<'name'>> <| as <<name>> <||> |> <||> |> : <--->",
        '    <:>',
        '',
        '    <:finally:>        finally : <--->',
        '    <:>',
        '',
        '    <:with:>        with -->> as <<name>> : <--->',
        '    <:>',
        '',
        '    <:assert:>        assert -->> \\n',
        '    <:>',
        '',
        '    <:pass:>        pass \\n',
        '    <:>',
        '',
        '<~>',
    ]
    return '\\n'.join(lines) + '\\n'


def generate_tsql() -> str:
    lines = [
        '<~"FROM".sql~>',
        '',
        '    <*comment_line*> -- -->> \\n <*>',
        '    <*comment_block*> /* -->> */ <*>',
        '',
        '    <*()*> ( <---> ) <*>',
        '',
        '    <:use:>',
        '        USE <<name>> \\n',
        '    <:>',
        '',
        '    <:go:>',
        '        GO \\n',
        '    <:>',
        '',
        '    <:declare:>',
        "        DECLARE <<name>> <<'name'>> <| = -->> <| , <||> \\n |> <||> <| , <||> \\n |> |>",
        '    <:>',
        '',
        '    <:set:>',
        "        SET <<'name'>> = -->> <| ; <||> \\n |>",
        '    <:>',
        '',
        '    <:exec:>',
        "        <| EXEC <||> EXECUTE |> <<'name'>> <? <<name>> <| , <||> |> ?> <| ; <||> \\n |>",
        '    <:>',
        '',
        '    <:join:>',
        "        <| INNER <||> LEFT <||> RIGHT <||> FULL <||> CROSS <||> |> JOIN <| <<'name'>> <||> <<name>> |> <| <| AS <||> |> <<name>> <||> |> ON -->> \\n",
        '    <:>',
        '',
        '    <:select:>',
        "        SELECT <| TOP <<name>> <||> |> <? <| <<'name'>> <||> <<name>> |> <| <| AS <||> |> <<name>> <||> |> <| , <||> |> ?>",
        "        <| FROM <? <| <<'name'>> <||> <<name>> |> <| <| AS <||> |> <<name>> <||> |> <| , <||> |> ?> <||> |>",
        '        <? <-{join}-> ?>',
        '        <| WHERE -->> \\n <||> |>',
        "        <| GROUP BY <? <<'name'>> <| , <||> |> ?> <||> |>",
        '        <| HAVING -->> \\n <||> |>',
        "        <| ORDER BY <? <<'name'>> <| ASC <||> DESC <||> |> <| , <||> |> ?> <||> |>",
        '        <| ; <||> \\n |>',
        '    <:>',
        '',
        '    <:insert:>',
        "        INSERT INTO <<'name'>> <| ( <? <<'name'>> <| , <||> |> ?> ) <||> |>",
        '        <| VALUES ( -->> ) <||> |>',
        '        <| ; <||> \\n |>',
        '    <:>',
        '',
        '    <:update:>',
        "        UPDATE <<'name'>>",
        "        SET <? <<'name'>> = -->> <| , <||> \\n |> ?>",
        '        <| WHERE -->> \\n <||> |>',
        '        <| ; <||> \\n |>',
        '    <:>',
        '',
        '    <:delete:>',
        "        DELETE FROM <<'name'>>",
        '        <| WHERE -->> \\n <||> |>',
        '        <| ; <||> \\n |>',
        '    <:>',
        '',
        '    <:if:>',
        '        IF -->> BEGIN <---> END <| ELSE BEGIN <---> END <||> |>',
        '    <:>',
        '',
        '    <:while:>',
        '        WHILE -->> BEGIN <---> END',
        '    <:>',
        '',
        '    <:begin_try:>',
        '        BEGIN TRY <---> END TRY',
        '        BEGIN CATCH <---> END CATCH',
        '    <:>',
        '',
        '    <:return:>',
        '        RETURN <| -->> <| ; <||> \\n |> <||> <| ; <||> \\n |> |>',
        '    <:>',
        '',
        '    <:print:>',
        '        PRINT -->> <| ; <||> \\n |>',
        '    <:>',
        '',
        '    <:column_def:>',
        "        <<name>> <<'name'>> <| ( <<name>> ) <||> |>",
        '        <| NOT NULL <||> NULL <||> |>',
        '        <| DEFAULT -->> \\n <||> |>',
        '        <| PRIMARY KEY <||> |>',
        '        <| IDENTITY ( <<name>> , <<name>> ) <||> |>',
        "        <| REFERENCES <<'name'>> ( <<'name'>> ) <||> |>",
        '        <| , <||> |>',
        '    <:>',
        '',
        '    <:create_table:>',
        '        CREATE TABLE <<name:up>> ( <? <-{column_def}-> ?> ) <| ; <||> \\n |>',
        '    <:>',
        '',
        '    <:alter_table:>',
        "        ALTER TABLE <<'name'>>",
        '        <| ADD -->> <| ; <||> \\n |>',
        "        <||> DROP COLUMN <<'name'>> <| ; <||> \\n |>",
        '        <||> ALTER COLUMN -->> <| ; <||> \\n |>',
        '        |>',
        '    <:>',
        '',
        '    <:drop_table:>',
        "        DROP TABLE <| IF EXISTS <||> |> <<'name'>> <| ; <||> \\n |>",
        '    <:>',
        '',
        '    <:param:>',
        "        <<name>> <<'name'>> <| = -->> <| , <||> \\n |> <||> |> <| OUTPUT <||> |> <| , <||> |>",
        '    <:>',
        '',
        '    <:create_proc:>',
        '        CREATE <| OR ALTER <||> |> PROCEDURE <<name:up>>',
        '        <? <-{param}-> ?>',
        '        AS BEGIN <---> END <| ; <||> \\n |>',
        '    <:>',
        '',
        '    <:create_function:>',
        '        CREATE <| OR ALTER <||> |> FUNCTION <<name:up>> (',
        '        <? <-{param}-> ?>',
        "        ) RETURNS <<'name'>> <| ( <<name>> ) <||> |>",
        '        AS BEGIN <---> END <| ; <||> \\n |>',
        '    <:>',
        '',
        '    <:create_view:>',
        '        CREATE <| OR ALTER <||> |> VIEW <<name:up>>',
        '        AS <| ; <||> \\n |>',
        '    <:>',
        '',
        '    <:create_index:>',
        '        CREATE <| UNIQUE <||> |> <| CLUSTERED <||> NONCLUSTERED <||> |> INDEX <<name:up>>',
        "        ON <<'name'>> ( <? <<'name'>> <| ASC <||> DESC <||> |> <| , <||> |> ?> )",
        '        <| ; <||> \\n |>',
        '    <:>',
        '',
        '    <:create_trigger:>',
        '        CREATE <| OR ALTER <||> |> TRIGGER <<name:up>>',
        "        ON <<'name'>>",
        '        <| AFTER <||> INSTEAD OF |> <? <| INSERT <||> UPDATE <||> DELETE |> <| , <||> |> ?>',
        '        AS BEGIN <---> END <| ; <||> \\n |>',
        '    <:>',
        '',
        '<~>',
    ]
    return '\\n'.join(lines) + '\\n'


LANGUAGES: dict[str, Callable[[], str]] = {
    "python": generate_python,
    "tsql": generate_tsql,
}


def main() -> None:
    parser = argparse.ArgumentParser(
        description="Generate a starter Crodox grammar definition for a programming language.",
    )
    parser.add_argument(
        "language",
        choices=sorted(LANGUAGES.keys()),
        help="Target language for the Crodox definition",
    )
    parser.add_argument(
        "--output", "-o",
        help="Output file path (default: stdout)",
    )

    args = parser.parse_args()
    template = LANGUAGES[args.language]()

    if args.output:
        with open(args.output, "w", encoding="utf-8") as f:
            f.write(template)
        print(f"Wrote Crodox definition to {args.output}")
    else:
        print(template)


if __name__ == "__main__":
    main()

Alternatively, clone the wiki repo to get the script directly:

git clone https://crodox-software-gmbh.ghe.com/crodox/Wiki.wiki.git

Clone this wiki locally