Registry / database / sly
library0.5pypypi✓ verified 23d ago

SLY is a 100% Python implementation of the lex and yacc tools, loosely based on the traditional compiler construction tools lex and yacc, implementing the LALR(1) parsing algorithm. It provides a bare-bones, yet fully capable, library for writing parsers in Python. The current version is 0.5. As of December 21, 2025, the project has been officially retired by its author, and no further maintenance is expected.

pip install sly
INSTALL
IMPORT
SIG · SLY
S
sly
databasepythonv0.5
Install
1.5s avg
Import
28ms
Disk
16MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v0.5 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.95 runs
installs and imports cleanly · install 0.0s · import 0.030s · 18MB
glibc
py 3.103.95 runs
installs and imports cleanly · install 1.5s · import 0.026s · 18MB
16MB installed
● package 16MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

Lexer
from sly import Lexer
Lexer is used to break input text into tokens.
Parser
from sly import Parser
Parser is used to recognize language syntax from a stream of tokens.

This quickstart demonstrates a simple calculator using SLY. It defines a lexer to tokenize input (numbers, IDs, operators) and a parser to build an abstract syntax tree and evaluate expressions, including variable assignments.

from sly import Lexer, Parser class CalcLexer(Lexer): tokens = { NUMBER, ID, PLUS, MINUS, TIMES, DIVIDE, ASSIGN, LPAREN, RPAREN } literals = { '=', '+', '-', '*', '/', '(', ')' } # String containing ignored characters ignore = ' \t' # Regular expression rules for tokens NUMBER = r'\d+' ID = r'[a-zA-Z_][a-zA-Z0-9_]*' # Special rules for tokens def NUMBER(self, t): t.value = int(t.value) return t def ID(self, t): t.value = str(t.value) return t def error(self, t): print(f"Illegal character '{t.value[0]}' at line {t.lineno}") self.index += 1 class CalcParser(Parser): tokens = CalcLexer.tokens precedence = ( ('left', PLUS, MINUS), ('left', TIMES, DIVIDE) ) def __init__(self): self.names = { } @_('ID ASSIGN expr') def statement(self, p): self.names[p.ID] = p.expr return p.expr @_('expr') def statement(self, p): return p.expr @_('expr PLUS expr') def expr(self, p): return p.expr0 + p.expr1 @_('expr MINUS expr') def expr(self, p): return p.expr0 - p.expr1 @_('expr TIMES expr') def expr(self, p): return p.expr0 * p.expr1 @_('expr DIVIDE expr') def expr(self, p): return p.expr0 / p.expr1 @_('LPAREN expr RPAREN') def expr(self, p): return p.expr @_('NUMBER') def expr(self, p): return p.NUMBER @_('ID') def expr(self, p): try: return self.names[p.ID] except LookupError: print(f"Undefined name '{p.ID}'") return 0 def error(self, p): if p: print(f"Syntax error at token {p.type}, value '{p.value}'") else: print("Syntax error at EOF") if __name__ == '__main__': lexer = CalcLexer() parser = CalcParser() while True: try: text = input('calc > ') if text.lower() == 'quit': break result = parser.parse(lexer.tokenize(text)) if result is not None: # Only print if there was a calculable result print(result) except EOFError: break except Exception as e: print(f"Error: {e}")
Debug
Known issues
breakingThe SLY project was officially retired by its author on December 21, 2025. No further maintenance or development is expected. Users are advised to consider other parsing libraries or fork the project for continued use.
fix
Migrate to an actively maintained parsing library (e.g., PLY, Lark) or fork SLY's source code if continued use is necessary.
affects: All versions (from December 21, 2025, onwards)
gotchaSLY is a modernization of the PLY project, but code written for PLY is generally not compatible with SLY. Direct migration of PLY code to SLY without modifications will likely fail.
fix
Rewrite PLY-based lexers and parsers to conform to SLY's API and conventions. Consult SLY's documentation for correct usage.
affects: All versions
gotchaSLY requires Python 3.6 or newer. It is not compatible with older Python versions.
fix
Ensure your project uses Python 3.6 or a more recent version.
affects: <0.5 (older Python versions)
gotchaLexer classes *must* define a `tokens` set specifying all possible token type names. Token names should generally be in all-caps. Incorrectly defined tokens or regex patterns are a common source of parsing issues.
fix
Always define `tokens` as a set of all-capitalized token names. Carefully review regular expressions and ensure they match the intended input. Utilize the `error` method in the Lexer for debugging unmatched characters.
affects: All versions
gotchaWhen defining parser rules, the `_()` decorator is crucial. Accessing parts of a rule (e.g., `expr PLUS expr`) requires careful indexing (e.g., `p.expr0`, `p.expr1`) if a symbol appears multiple times in a rule's right-hand side, or by name (e.g., `p.NUMBER`) otherwise.
fix
Refer to rule components using `p.symbolname` for unique symbols or `p.symbolnameN` (where N is a 0-indexed number) for repeated symbols. Consult the documentation for examples of `_()` decorator usage.
affects: All versions
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'sly'
The 'sly' library is not installed in the current Python environment.
fix
Run `pip install sly` in your terminal to install the library.
ImportError: cannot import name 'Lexer' from 'sly'
The `Lexer` class is part of the `sly.lex` submodule, and `Parser` is from `sly.yacc`, not directly available under the top-level 'sly' package.
fix
Change your import statements to `from sly.lex import Lexer` and `from sly.yacc import Parser`.
SyntaxError: Expected a list of tokens called 'tokens'
Every `sly.lex.Lexer` subclass must define a class attribute named `tokens`, which is a list of strings representing all valid token names.
fix
Add a `tokens = [...]` class attribute to your `Lexer` subclass, listing all token types (e.g., `tokens = ['NUMBER', 'PLUS']`).
SyntaxError: Expected a rule for token 'TOKEN_NAME'
A token name listed in the `tokens` list of your `Lexer` class does not have a corresponding regular expression rule (e.g., `t_TOKEN_NAME`) or a `t_ignore_TOKEN_NAME` rule defined for it.
fix
Define a `t_TOKEN_NAME = r'...'` attribute in your `Lexer` class for the missing token, or remove the token from the `tokens` list if it's not intended to be used.
SyntaxError: Parsing error. Unexpected token TOKEN_TYPE (VALUE) at line X, column Y
The `sly.yacc.Parser` encountered an input token that does not match any of the defined grammar rules (`p_NAME` methods) at the current parsing state.
fix
Review your parser's grammar rules (`p_NAME` methods) and the input string for any discrepancies, or implement a custom `p_error` method in your `Parser` class to handle or recover from syntax errors.
Upgrade
Version history
0.5latest on PyPI · released Oct 25, 2022
Audit
Dependencies

No dependency data recorded yet.

Agent activity
17 hits · last 30 days
node
12
Meta
1
Resources