Skip to main content

The modern PEG parser combinator for python

Project description

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='{}'>

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

trishula-0.0.9.tar.gz (4.7 kB view details)

Uploaded Source

Built Distribution

trishula-0.0.9-py3-none-any.whl (5.3 kB view details)

Uploaded Python 3

File details

Details for the file trishula-0.0.9.tar.gz.

File metadata

  • Download URL: trishula-0.0.9.tar.gz
  • Upload date:
  • Size: 4.7 kB
  • Tags: Source
  • Uploaded using 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

File hashes

Hashes for trishula-0.0.9.tar.gz
Algorithm Hash digest
SHA256 fa3339924a972e1dd6646d93d5f946443b7a3cb5f8cbdb39c59914df04a0549d
MD5 8112df3f7e1ec88d25070f38c041c423
BLAKE2b-256 caba3a2265fbb9a83c3ab5080aeb1164c710b73234fd4ce16526aebfbccd257c

See more details on using hashes here.

File details

Details for the file trishula-0.0.9-py3-none-any.whl.

File metadata

  • Download URL: trishula-0.0.9-py3-none-any.whl
  • Upload date:
  • Size: 5.3 kB
  • Tags: Python 3
  • Uploaded using 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

File hashes

Hashes for trishula-0.0.9-py3-none-any.whl
Algorithm Hash digest
SHA256 30d5326d06c2b596b2091ce077f3b08c319ecbb91ee84b8aae1567f1dd71fc0f
MD5 80ab7ec4d7fd16728b1c3d0bd1393182
BLAKE2b-256 0356ecaed45ecf5f36f158a40c02762452d4c2f61677542d5c1268705b0071be

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page