Skip to main content

Trishula - The modern parser combinator for Python 3

Trishula is a parser combinator library extended PEG syntaxes, inspired by Parsimmon(ES) and boost::spirit::qi(C++).

Trishula supports python version >= 3.7.0

Examples

grammar = (
    Value("aaa")
    >> (Value("bbb") | Value("ccc"))
    >> (+Value("eee") >= (lambda x: "modified"))
    >> -Value("f")
    >> Value("g")
    >> Regexp(r"a+")
    >> Not(Value("hhh"))
)
# This works
print(vars(Parser().parse(grammar, "aaaccceeeeeeeeeeeefgaaa")))

# {
#      'status': <Status.SUCCEED: 1>,
#      'index': 23,
#      'value': [[[[[['aaa', 'ccc'], 'modified'], 'f'], 'g'], 'aaa'], None]
# }

You can see examples in "example" directory (execute it under example directory).

Description

Grammers can be defined by Value and Regexp primitive and operators. Below we describe operators.

Operators

As mentioned above, Trishula uses many operator overloads to make definition of parsers be easier.

operator result
>> Sequence
| OrderedChoise
~ ZeroOrMore
+ OneOrMore
- Optional
>= Map
@ NamedParser

and we have classes named Not and And, which are made for prediction.

Recursion

Trishula supports recursion with Ref. Recursion can be written like this:

def grammar():
   return (
        (Value("[]") >= (lambda x: [])) |
        ((
            Value("[") >>
            Ref(grammar) >>
            Value("]")
        ) >= (lambda x: [x[0][1]]))
    )

def main():
    result = Parser().parse(grammar(), "[[[]]]")
    print(vars(result))
    # => {'status': <Status.SUCCEED: 1>, 'index': 6, 'value': [[[]]]}

Be aware that Ref executes function only once so that parser can be memorized.

Namespace

Namespace is one of Trishula's powerful features. You can name your parser and retrieve values with map (as dict).

Usage is simple. Mark the parser with @ operator like parser @ "name" and surround with Namespace(parser). Then you can grab values with Namespace(parser) => fn. fn is a callable taking dict type and returns new value.

import trishula as T


def main():
    grammar = T.Namespace(
        T.Value("[") >> (T.Regexp(r"[0-9]+") >= (float)) @ "value" >> T.Value("]")
    ) >= (lambda a_dict: a_dict["value"])
    result = T.Parser().parse(grammar, "[12345]")
    print(vars(result))
    # ==> {'status': <Status.SUCCEED: 1>, 'index': 7, 'value': 12345.0, 'namespace': {}}


main()

Note that after mapped function called, internal namespace is cleaned up with empty dict.

Conditional parsing

You can do something like this:

def main():
    def cond(value):
        d = {
            "(": ")",
            "{": "}",
            "[": "]",
        }
        return T.Value(d.get(value[0]))


    grammar = T.Namespace(
        T.Value("[")
        >> +(T.Regexp(r"[a-z]") | T.Value("\n")) @ "value"
        >> T.Conditional(cond)
    )
    result = T.Parser().parse(grammar, "[abcd\n\nefg]")
    print(result)


main()

Conditional take one argument that receive a value and return parser. It runs dynamically so that you can choose a parser at runtime.

Utils

There are sep_by, sep_by1, and index.

Generator

import trishula as T


@T.define_parser
def parser():
    yield T.Value("aaa")
    v = yield T.Value("bbb")
    yield T.Value("ccc")
    # Do not forget to return a value
    yield v

print(T.Parser().parse(parser, "aaabbbccc"))
# ==> <Success index='9' value='bbb' namespace='{}'>

Metadata

Release files for trishula 0.0.9

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for trishula 0.0.9
File Size Uploaded
trishula-0.0.9.tar.gz 4.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for trishula 0.0.9
File Interpreter ABI Platform
trishula-0.0.9-py3-none-any.whl Python 3 none any Details

Total release size: 10.0 kB

Release files / trishula-0.0.9.tar.gz

Download URL trishula-0.0.9.tar.gz
Size 4.7 kB
Tags Source
SHA-256 checksum
How to use checksums
fa3339924a972e1dd6646d93d5f946443b7a3cb5f8cbdb39c59914df04a0549d
BLAKE2b-256 checksum
How to use checksums
caba3a2265fbb9a83c3ab5080aeb1164c710b73234fd4ce16526aebfbccd257c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.13.0 pkginfo/1.5.0.1 requests/2.21.0 setuptools/39.0.1 requests-toolbelt/0.9.1 tqdm/4.31.1 CPython/3.7.0

Release files / trishula-0.0.9-py3-none-any.whl

Download URL trishula-0.0.9-py3-none-any.whl
Size 5.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
30d5326d06c2b596b2091ce077f3b08c319ecbb91ee84b8aae1567f1dd71fc0f
BLAKE2b-256 checksum
How to use checksums
0356ecaed45ecf5f36f158a40c02762452d4c2f61677542d5c1268705b0071be
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.13.0 pkginfo/1.5.0.1 requests/2.21.0 setuptools/39.0.1 requests-toolbelt/0.9.1 tqdm/4.31.1 CPython/3.7.0

Release history Release notifications | RSS feed

This release

0.0.9 This release

2 release files

0.0.8

2 release files

0.0.7

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

3 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page