sattline-parser
Standalone parser, AST, and transformer for ABB SattLine.
This package owns the Lark grammar, the strict single-file syntax behavior, the AST models, and the SLTransformer, all in one self-contained, installable package.
Features
- Lark LALR parser for SattLine sources (grammar in
grammar/sattline.lark) - Parses plain text and files (
.s,.g,.l,.x,.y,.zand any other extension; the parser is content-based, not extension-based) - Strict, no-silent-fallback parsing
- Structural comments (
(* ... *), nested) preserved as role-tagged AST nodes - Automatic compressed-source decoding (
preprocess_sl_text,is_compressed) - Error reporting with line/column locations in the original source (
describe_parse_error) - AST models in
sattline_parser.models SLTransformertree transformer insattline_parser.transformer- Standalone fuzz harness with timeout protection and corpus regression
- Zero runtime dependencies beyond
larkandregex
Install
pip install sattline-parser
Requires Python 3.13+.
Usage
Parse a source file
from pathlib import Path
from sattline_parser import parse_source_file
basepicture = parse_source_file(Path("program.s"))
Parse source text
from sattline_parser import parse_source_text
source = open("program.x", encoding="utf-8").read()
basepicture = parse_source_text(source)
parse_source_file and parse_source_text both return a BasePicture (the module-level model) with the full AST attached.
Choosing an entry point
parse_source_file is for when you have a path on disk. It handles the file I/O for you: it reads the file with an encoding fallback (utf-8, then cp1252, then latin-1) and passes the path along so error messages can name the source file.
parse_source_text is for when you already hold the source as a string: a snippet, an editor buffer, a response from an API, or content read by your own code. The two are interchangeable in behavior; parse_source_file(path) is equivalent to parse_source_text(path.read_text(...)) plus the encoding fallback and path-aware error reporting. Start with parse_source_file when you have a path, parse_source_text otherwise.
Both entry points handle cleanup automatically, so you do not need to pre-process the source:
- Comments are parsed structurally (
(* ... *), including nested ones) and preserved on the AST asCodeCommentnodes. - Compressed sources are detected and decoded automatically.
The exposed helpers below exist for the rare case where you are building tooling that needs the intermediate stages (for example, to tokenize, diff, or re-emit sources). For ordinary parsing you can ignore them.
For power users: handle compressed sources
from sattline_parser import is_compressed, preprocess_sl_text
if is_compressed(source):
decoded, mapping = preprocess_sl_text(source)
is_compressed answers whether the text uses the compressed encoding, and preprocess_sl_text decodes it, returning the decoded text plus a mapping back to the original. Since both parse entry points already detect and decode compressed sources, these are only needed by tooling that must decode without parsing (for example, saving a plain-text copy) or by the fuzz harness that drives preprocess_sl_text with adversarial inputs.
Report errors with source locations
from sattline_parser import create_parser, describe_parse_error, parse_source_text
parser = create_parser()
try:
parse_source_text(source, parser=parser)
except Exception as exc:
details = describe_parse_error(exc, source)
print(f"{details.line}:{details.column} {details.message}")
What is the AST good for?
parse_source_file and parse_source_text return a BasePicture, a tree of Python objects that mirrors the structure of the program. Once you have it, you can inspect and walk the program as data instead of as text.
For readers new to ASTs (abstract syntax trees): the parser does not give you the flat file back; it gives you structured objects. basepicture.program_name is the program name, basepicture.moduletype_defs is the list of type definitions, basepicture.submodules is the tree of nested modules, and so on. You can read fields, iterate lists, and check conditions directly in Python. For a small program this prints:
from pathlib import Path
from sattline_parser import parse_source_file
basepicture = parse_source_file(Path("program.s"))
print(basepicture.program_name)
print([submodule.header.name for submodule in basepicture.submodules])
print(len(basepicture.submodules), "submodules")
program
['Controller1', 'Controller2']
2 submodules
Think of the AST as a structured, machine-readable view of the program, that tools (a linter, a refactorer, an editor, a report generator) can walk without re-parsing the text. Since an AST is just nested objects, answering questions about the program becomes ordinary Python.
Development
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest tests/parser -q
ruff check src tests
pyright src tests
Project layout
src/sattline_parser/grammar/: Lark grammar and constantssrc/sattline_parser/models/: AST modelssrc/sattline_parser/transformer/: transformer mixins andSLTransformersrc/sattline_parser/api.py: public entry pointssrc/sattline_parser/fuzz_harness.py: standalone fuzzing
License
MIT. Copyright (c) 2025 Søren H. Johansen.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sattline_parser-2026.8.tar.gz.
File metadata
- Download URL: sattline_parser-2026.8.tar.gz
- Upload date:
- Size: 57.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9e5e09d1e72f9dae50773c1a2b0ab074f887253d3a3dd795a508f2251144db16
|
|
| MD5 |
3433e2a85229e32368fd10e739ff02dc
|
|
| BLAKE2b-256 |
f50017de2aa45922c94dafb8de667bb314762dcb8367128b0c224700b814ae25
|
Provenance
The following attestation bundles were made for sattline_parser-2026.8.tar.gz:
Publisher:
publish.yml on SorenHJohansen/sattline-parser
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sattline_parser-2026.8.tar.gz -
Subject digest:
9e5e09d1e72f9dae50773c1a2b0ab074f887253d3a3dd795a508f2251144db16 - Sigstore transparency entry: 2434676678
- Sigstore integration time:
-
Permalink:
SorenHJohansen/sattline-parser@8da2981d779c26f8d965cd7b3b4a73372dbfb718 -
Branch / Tag:
refs/tags/v2026.8 - Owner: https://github.com/SorenHJohansen
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8da2981d779c26f8d965cd7b3b4a73372dbfb718 -
Trigger Event:
push
-
Statement type:
File details
Details for the file sattline_parser-2026.8-py3-none-any.whl.
File metadata
- Download URL: sattline_parser-2026.8-py3-none-any.whl
- Upload date:
- Size: 66.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d83ec3eae0e6684736cd3b0f52dd27f1b965c272c1f6d4ac87349fa448afec67
|
|
| MD5 |
7bace3ef46d9bb66367c018959a7b091
|
|
| BLAKE2b-256 |
5a56178ef4304059b8ad88408132f00365d6f80fd15987482565b86c83a2b6c1
|
Provenance
The following attestation bundles were made for sattline_parser-2026.8-py3-none-any.whl:
Publisher:
publish.yml on SorenHJohansen/sattline-parser
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sattline_parser-2026.8-py3-none-any.whl -
Subject digest:
d83ec3eae0e6684736cd3b0f52dd27f1b965c272c1f6d4ac87349fa448afec67 - Sigstore transparency entry: 2434676962
- Sigstore integration time:
-
Permalink:
SorenHJohansen/sattline-parser@8da2981d779c26f8d965cd7b3b4a73372dbfb718 -
Branch / Tag:
refs/tags/v2026.8 - Owner: https://github.com/SorenHJohansen
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8da2981d779c26f8d965cd7b3b4a73372dbfb718 -
Trigger Event:
push
-
Statement type: