Documentation · PyPI · GitHub
syntactes
A simpler Python parser generator.
The name is derived from Greek συντάκτης (/sin'daktis/) meaning editor/composer.
Features
- Parsing table creation (LR0, SLR and LR1)
- Token parsing, with callbacks or grammar primitives (
add(1,3) % expr -> expr PLUS expr) that compute values on each reduction - Grammars written as text, one rule per line
Installation
> pip install syntactes
Quick start
Creating a parsing table
from syntactes import Grammar, Rule, SLRGenerator, Symbol
EOF = Symbol.eof()
S = Symbol("S", is_terminal=False)
E = Symbol("E", False)
T = Symbol("T", False)
x = Symbol("x", True)
PLUS = Symbol("+", True)
symbols = {EOF, S, E, T, x, PLUS}
# 0. S -> E $
# 1. E -> T + E
# 2. E -> T
# 3. T -> x
rule_1 = Rule(0, S, E, EOF)
rule_2 = Rule(1, E, T, PLUS, E)
rule_3 = Rule(2, E, T)
rule_4 = Rule(3, T, x)
rules = (rule_1, rule_2, rule_3, rule_4)
grammar = Grammar(rule_1, rules, symbols)
generator = SLRGenerator(grammar)
parsing_table = generator.generate()
print(parsing_table.pretty_str())
Running the above example produces this output:
GRAMMAR RULES
-------------
0. S -> E $
1. E -> T + E
2. E -> T
3. T -> x
-------------
SLR PARSING TABLE
-------------------------------------------------
| | $ | + | E | S | T | x |
-------------------------------------------------
| 1 | -- | -- | s2 | -- | s3 | s4 |
-------------------------------------------------
| 2 | a | -- | -- | -- | -- | -- |
-------------------------------------------------
| 3 | r2 | s5 | -- | -- | -- | -- |
-------------------------------------------------
| 4 | r3 | r3 | -- | -- | -- | -- |
-------------------------------------------------
| 5 | -- | -- | s6 | -- | s3 | s4 |
-------------------------------------------------
| 6 | r1 | -- | -- | -- | -- | -- |
-------------------------------------------------
Parsing
from syntactes import Grammar, Rule, Symbol, Token
from syntactes.parser import Location, SLRParser, UnexpectedTokenError
EOF = Symbol.eof()
S = Symbol("S", is_terminal=False)
E = Symbol("E", False)
T = Symbol("T", False)
x = Symbol("x", True)
PLUS = Symbol("+", True)
symbols = {EOF, S, E, T, x, PLUS}
# 0. S -> E $
# 1. E -> T + E
# 2. E -> T
# 3. T -> x
rule_1 = Rule(0, S, E, EOF)
rule_2 = Rule(1, E, T, PLUS, E)
rule_3 = Rule(2, E, T)
rule_4 = Rule(3, T, x)
rules = (rule_1, rule_2, rule_3, rule_4)
grammar = Grammar(rule_1, rules, symbols)
parser = SLRParser.from_grammar(grammar)
@parser.execute_on(rule_1)
def result(e):
# The starting rule's callback gets every right-hand side token except $.
# Its return value is returned by parse().
return e.value
@parser.execute_on(rule_2)
def add(t, plus, e):
# One token per right-hand side symbol, in order. A non-terminal's value is
# whatever the callback of the rule that produced it returned.
# A non-terminal's token starts where its first token does.
print(f"column {t.location.column}: reducing by {rule_2}: {t.value} + {e.value}")
return t.value + e.value
@parser.execute_on(rule_3)
def term(t):
return t.value
@parser.execute_on(rule_4)
def number(x_token):
# Terminals carry the value they were created with.
return x_token.value
def lex(text):
# One token per character but spaces, located at its offset on line 1.
for offset, char in enumerate(text):
location = Location(offset, 1, offset + 1)
if char == "+":
yield Token(PLUS, location)
elif char != " ":
yield Token(x, location, int(char))
yield Token(EOF, Location(len(text), 1, len(text) + 1))
print("Parsing: 1 + 2 + 3\n")
print("result:", parser.parse(lex("1 + 2 + 3")))
print("\nParsing: 1 +\n")
try:
parser.parse(lex("1 +"))
except UnexpectedTokenError as e:
print(f"column {e.received_token.location.column}: {e}")
Running the above example produces this output:
Parsing: 1 + 2 + 3
column 5: reducing by E -> T + E: 2 + 3
column 1: reducing by E -> T + E: 1 + 5
result: 6
Parsing: 1 +
column 4: Received token: $; expected one of: ['x']
Learn more
The documentation covers the rest:
- Grammars: writing grammars as text with
Grammar.from_text, building them fromSymbols andRules, empty rules, and the errors and warnings for malformed grammars. - Parsing tables: the LR0, SLR and LR1
generators, reading
pretty_str(), and finding conflicts. - Parsing: callbacks, primitives,
ParserErrors, and how the parser resolves conflicts. - API reference.
Metadata
Release files for syntactes 0.11.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| syntactes-0.11.0.tar.gz | 26.1 kB | Without provenance | Details for syntactes-0.11.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| syntactes-0.11.0-py3-none-any.whl | Python 3 | none | any | Details for syntactes-0.11.0-py3-none-any.whl |
Total release size: 56.5 kB
Release files / syntactes-0.11.0.tar.gz
| Download URL | syntactes-0.11.0.tar.gz |
|---|---|
| Size | 26.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e0b9534a895c8102b162877d3f826df00f9acbc67cf8a83d2733254ac99d9d56
|
|
BLAKE2b-256 checksum How to use checksums |
15b8779484900852dda0e8b469121ec26bbf3d9dc6eec89f4acf19f589bd102f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Linux Mint","version":"21.3","id":"virginia","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / syntactes-0.11.0-py3-none-any.whl
| Download URL | syntactes-0.11.0-py3-none-any.whl |
|---|---|
| Size | 30.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5160f7e24a0d1c7ec5e94ec9d4b7d50ba0bfc049cff369f56200a135ccd3e063
|
|
BLAKE2b-256 checksum How to use checksums |
2c6f69848404f0f6a0a8e0dfa77b07f53699752cdb9b2c33eb465acc76eadf65
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Linux Mint","version":"21.3","id":"virginia","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for syntactes 0.11.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.