SkillAgentSearch skills...

TatSu

竜 TatSu generates Python parsers from grammars in a variation of EBNF

Install / Use

/learn @neogeny/TatSu
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

.. Copyright (c) 2017-2026 Juancarlo Añez (apalala@gmail.com) .. SPDX-License-Identifier: BSD-4-Clause

.. |dragon| unicode:: 0x7ADC .. unicode dragon .. |nbsp| unicode:: 0xA0 .. non breakable space .. |TatSu| replace:: |dragon|\ |nbsp|\ TatSu .. |TatSu-LTS| replace:: |dragon|\ |nbsp|\ TatSu-LTS .. _RELEASES: https://github.com/neogeny/TatSu/releases

| |license| ​ |pyversions| | |fury| ​ |actions| ​ |docs| ​ |installs| ​ |codspeed| | |sponsor| |

|TatSu|

*At least for the people who send me mail about a new language that
they're designing, the general advice is: do it to learn about how
to write a compiler. Don't have any expectations that anyone will
use it, unless you hook up with some sort of organization in a
position to push it hard. It's a lottery, and some can buy a lot of
the tickets. There are plenty of beautiful languages (more beautiful
than C) that didn't catch on. But someone does win the lottery, and
doing a language at least teaches you something.*

`Dennis Ritchie`_ (1941-2011) Creator of the C_ programming
language and of Unix_

|TatSu| is a tool that takes grammars in extended EBNF_ as input, and outputs memoizing_ (Packrat) PEG parsers in Python. The classic variations of EBNF (Tomassetti, EasyExtend, Wirth) and ISO EBNF_ are supported as input grammar formats.

Why use a PEG_ parser generator?

Regular expressions are “memory-less”—they excel at finding flat patterns like email addresses or phone numbers, but they fail once data becomes hierarchical. Regular expressions cannot "count" or balance demarcations (a regex cannot reliably validate whether opening and closing parenthesis are matched in a nested math equation).

Parsing is the essential step up when you need to understand the logic and structure of information rather than just its appearance. Parsing constructs an Abstract Syntax Tree (AST_) of the input, a hierarchical map that represents how different parts of a sequence relate to one another.

  • Recursive Structures: Whenever a piece of data can contain a version of itself (like a folder inside a folder, or a conditional if statement inside another if), you need a parser to track the depth and scope.

  • Translating Formats: When converting one format into another, a parser ensures that the meaning of the original structure is preserved, preventing the "data soup" that occurs when using simple find-and-replace tools.

  • Ambiguity Resolution: In complex sequences, the same sub-sequence might mean different things depending on where it sits in the tree. A parser uses the surrounding context to decide how to treat that sequence, whereas a regex treats every match in isolation.

  • Domain-Specific Languages (DSL): Parsing allows the creation of specialized "mini-languages" tailored to a specific field, such as hardware description, music notation, or complex business rules.

  • Executable Logic: While a regex can tell you if a string looks like a command, a parser turns that string into an object that a computer can actually execute, ensuring the order of operations and dependencies are strictly followed.

|TatSu| can compile a grammar stored in a string into a Grammar object that can be used to parse any given input (much like the re_ module does with regular expressions). |TatSu| can also generate a Python_ module that implements the parser.

|TatSu| supports left-recursive_ rules in PEG_ grammars using the algorithm_ by Laurent and Mens. The generated AST_ has the expected left associativity.

Compatibility

|TatSu| expects a maintained_ version of Python (>=3.13), but currently all tests run in versions of Python down to Python 3.12. |TatSu| is also compatible with the current pre-release version of Python 3.15.

For older versions of Python, you may consider TatSu-LTS_, a friendly fork of |TatSu| aimed at compatibility.

.. _algorithm: http://norswap.com/pubs/sle2016.pdf .. _TatSu-LTS: https://pypi.org/project/TatSu-LTS/

Installation

.. code-block:: bash

$ pip install TatSu

Using the Tool

|TatSu| can be used as a library, much like Python's re, by embedding grammars as strings and generating grammar models instead of generating Python code.

This compiles the grammar and generates an in-memory parser that can subsequently be used for parsing input with:

.. code-block:: python

parser = tatsu.compile(grammar)

Compiles the grammar and parses the given input producing an AST_ as result:

.. code-block:: python

ast = tatsu.parse(grammar, input)

The result is equivalent to calling:

.. code-block:: python

parser = compile(grammar)
ast = parser.parse(input)

Compiled grammars are cached for efficiency.

This compiles the grammar to the Python_ source code that implements the parser:

.. code-block:: python

parser_source = tatsu.to_python_sourcecode(grammar)

This is an example of how to use |TatSu| as a library:

.. code-block:: python

GRAMMAR = '''
    start:  expression $

    expression:
        | expression '+' term
        | expression '-' term
        | term

    term:
        | term '*' factor
        | term '/' factor
        | factor

    factor:
        | '(' expression ')'
        | number

    number: /\d+/
'''


if __name__ == '__main__':
    import json
    from tatsu import parse
    from tatsu.util import asjson

    ast = parse(GRAMMAR, '3 + 5 * ( 10 - 20 )')
    print(ast.asjsons())

..

|TatSu| will use the first rule defined in the grammar as the start rule.

This is the output:

.. code-block:: console

[
  "3",
  "+",
  [
    "5",
    "*",
    [
      "10",
      "-",
      "20"
    ]
  ]
]

Documentation

For a detailed explanation of what |TatSu| is capable of, please see the documentation_.

.. _documentation: http://tatsu.readthedocs.io/

Questions?

Please use the [tatsu]_ tag on StackOverflow_ for general Q&A, and limit GitHub issues to bugs, enhancement proposals, and feature requests.

.. _[tatsu]: https://stackoverflow.com/tags/tatsu/info

Changes

See the RELEASES_ for details.

License

You may use |TatSu| under the terms of the BSD-style license described in the enclosed LICENSE file. If your project requires different licensing please email_.

For Fun

This is a diagram of the grammar for |TatSu|'s own grammar language:

.. code:: console

start ●─grammar─■

grammar[Grammar] ●─ [title](`TATSU`)──┬→───────────────────────────────────┬── [`rules`]+(rule)──┬→───────────────────────────────┬──⇥$
                                      ├→──┬─ [`directives`]+(directive)─┬──┤                     ├→──┬─ [`rules`]+(rule)───────┬──┤
                                      │   └─ [`keywords`]+(keyword)─────┘  │                     │   └─ [`keywords`]+(keyword)─┘  │
                                      └───────────────────────────────────<┘                     └───────────────────────────────<┘

directive ●─'@@'─ !['keyword'] ✂ ───┬─ [name](──┬─'comments'─────┬─) ✂ ─'::' ✂ ─ [value](regex)────────────┬─ ✂ ──■
                                    │           └─'eol_comments'─┘                                         │
                                    ├─ [name]('whitespace') ✂ ─'::' ✂ ─ [value](──┬─regex───┬─)────────────┤
                                    │                                             ├─string──┤              │
                                    │                                             ├─'None'──┤              │
                                    │                                             ├─'False'─┤              │
                                    │                                             └─`None`──┘              │
                                    ├─ [name](──┬─'nameguard'──────┬─) ✂ ───┬─'::' ✂ ─ [value](boolean)─┬──┤
                                    │           ├─'ignorecase'─────┤        └─ [value](`True`)──────────┘  │
                                    │           ├─'left_recursion'─┤                                       │
                                    │           ├─'parseinfo'──────┤                                       │
                                    │           └─'memoization'────┘                                       │
                                    ├─ [name]('grammar') ✂ ─'::' ✂ ─ [value](word)─────────────────────────┤
                                    └─ [name]('namechars') ✂ ─'::' ✂ ─ [value](string)─────────────────────┘

keywords ●───┬─keywords─┬───■
             └─────────<┘

keyword ●─'@@keyword' ✂ ─'::' ✂ ───┬→──────────────────────────────────┬───■
                                   ├→ @+(──┬─word───┬─)─ ![──┬─':'─┬─]─┤
                                   │       └─string─┘        └─'='─┘   │
                                   └──────────────────────────────────<┘

the_params_at_last ●───┬─ [kwparams](kwparams)─────────────────────────┬──■
                       ├─ [params](params)',' ✂ ─ [kwparams](kwparams)─┤
                       └─ [params](params)─────────────────────────────┘

paramdef ●───┬─'[' ✂ ─ >(the_params_at_last) ']'─┬──■
             ├─'(' ✂ ─ >(the_params_at_last) ')'─┤
             └─'::' ✂ ─ [params](params)─────────┘

rule[Rule] ●─ [decorators](──┬→──────────┬──) [name](name) ✂ ───┬─→ >(paramdef) ─┬───┬─→'<' ✂ ─ [base](known_name)─┬───┬─'='──┬─ ✂ ─ [exp](expre)ENDRULE ✂ ──■
                             ├→decorator─┤                      └─→──────────────┘   └─→───────────────────────────┘   ├─':='─┤
                             └───
View on GitHub
GitHub Stars439
CategoryDevelopment
Updated1h ago
Forks54

Languages

Python

Security Score

85/100

Audited on Mar 27, 2026

No findings