{"id":2769,"library":"sly","title":"SLY - Sly Lex Yacc","description":"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.","status":"abandoned","version":"0.5","language":"python","source_language":"en","source_url":"https://github.com/dabeaz/sly","tags":["lexer","parser","compiler","LALR(1)","language tools","abandoned"],"install":[{"cmd":"pip install sly","lang":"bash","label":"Install stable version"}],"dependencies":[],"imports":[{"note":"Lexer is used to break input text into tokens.","symbol":"Lexer","correct":"from sly import Lexer"},{"note":"Parser is used to recognize language syntax from a stream of tokens.","symbol":"Parser","correct":"from sly import Parser"}],"quickstart":{"code":"from sly import Lexer, Parser\n\nclass CalcLexer(Lexer):\n    tokens = { NUMBER, ID, PLUS, MINUS, TIMES, DIVIDE, ASSIGN, LPAREN, RPAREN }\n    literals = { '=', '+', '-', '*', '/', '(', ')' }\n\n    # String containing ignored characters\n    ignore = ' \\t'\n\n    # Regular expression rules for tokens\n    NUMBER = r'\\d+'\n    ID = r'[a-zA-Z_][a-zA-Z0-9_]*'\n\n    # Special rules for tokens\n    def NUMBER(self, t):\n        t.value = int(t.value)\n        return t\n\n    def ID(self, t):\n        t.value = str(t.value)\n        return t\n\n    def error(self, t):\n        print(f\"Illegal character '{t.value[0]}' at line {t.lineno}\")\n        self.index += 1\n\nclass CalcParser(Parser):\n    tokens = CalcLexer.tokens\n\n    precedence = (\n        ('left', PLUS, MINUS),\n        ('left', TIMES, DIVIDE)\n    )\n\n    def __init__(self):\n        self.names = { }\n\n    @_('ID ASSIGN expr')\n    def statement(self, p):\n        self.names[p.ID] = p.expr\n        return p.expr\n\n    @_('expr')\n    def statement(self, p):\n        return p.expr\n\n    @_('expr PLUS expr')\n    def expr(self, p):\n        return p.expr0 + p.expr1\n\n    @_('expr MINUS expr')\n    def expr(self, p):\n        return p.expr0 - p.expr1\n\n    @_('expr TIMES expr')\n    def expr(self, p):\n        return p.expr0 * p.expr1\n\n    @_('expr DIVIDE expr')\n    def expr(self, p):\n        return p.expr0 / p.expr1\n\n    @_('LPAREN expr RPAREN')\n    def expr(self, p):\n        return p.expr\n\n    @_('NUMBER')\n    def expr(self, p):\n        return p.NUMBER\n\n    @_('ID')\n    def expr(self, p):\n        try:\n            return self.names[p.ID]\n        except LookupError:\n            print(f\"Undefined name '{p.ID}'\")\n            return 0\n\n    def error(self, p):\n        if p:\n            print(f\"Syntax error at token {p.type}, value '{p.value}'\")\n        else:\n            print(\"Syntax error at EOF\")\n\nif __name__ == '__main__':\n    lexer = CalcLexer()\n    parser = CalcParser()\n    while True:\n        try:\n            text = input('calc > ')\n            if text.lower() == 'quit':\n                break\n            result = parser.parse(lexer.tokenize(text))\n            if result is not None: # Only print if there was a calculable result\n                print(result)\n        except EOFError:\n            break\n        except Exception as e:\n            print(f\"Error: {e}\")","lang":"python","description":"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."},"warnings":[{"fix":"Migrate to an actively maintained parsing library (e.g., PLY, Lark) or fork SLY's source code if continued use is necessary.","message":"The 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.","severity":"breaking","affected_versions":"All versions (from December 21, 2025, onwards)"},{"fix":"Rewrite PLY-based lexers and parsers to conform to SLY's API and conventions. Consult SLY's documentation for correct usage.","message":"SLY 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.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure your project uses Python 3.6 or a more recent version.","message":"SLY requires Python 3.6 or newer. It is not compatible with older Python versions.","severity":"gotcha","affected_versions":"<0.5 (older Python versions)"},{"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.","message":"Lexer 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.","severity":"gotcha","affected_versions":"All versions"},{"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.","message":"When 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.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"search_vec":"'0.5':53 '1':31,78 '100':8 '2025':58 '21':57 'abandon':81 'algorithm':33 'author':67 'bare':38 'bare-bon':37 'base':18 'bone':39 'capabl':42 'compil':22,76 'construct':23 'current':50 'decemb':56 'expect':73 'fulli':41 'implement':10,28 'lalr':30,77 'languag':79 'lex':3,13,25 'lexer':74 'librari':43 'loos':17 'mainten':71 'offici':63 'pars':32 'parser':46,75 'project':60 'provid':35 'python':9,48 'retir':64 'sli':1,2,5 'tool':16,24,80 'tradit':21 'version':51 'write':45 'yacc':4,15,27 'yet':40","created_at":"2026-04-11T01:42:01.804188+00:00","updated_at":"2026-04-16T21:50:08.179489+00:00","problems":[{"fix":"Run `pip install sly` in your terminal to install the library.","cause":"The 'sly' library is not installed in the current Python environment.","error":"ModuleNotFoundError: No module named 'sly'"},{"fix":"Change your import statements to `from sly.lex import Lexer` and `from sly.yacc import Parser`.","cause":"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.","error":"ImportError: cannot import name 'Lexer' from 'sly'"},{"fix":"Add a `tokens = [...]` class attribute to your `Lexer` subclass, listing all token types (e.g., `tokens = ['NUMBER', 'PLUS']`).","cause":"Every `sly.lex.Lexer` subclass must define a class attribute named `tokens`, which is a list of strings representing all valid token names.","error":"SyntaxError: Expected a list of tokens called 'tokens'"},{"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.","cause":"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.","error":"SyntaxError: Expected a rule for token 'TOKEN_NAME'"},{"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.","cause":"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.","error":"SyntaxError: Parsing error. Unexpected token TOKEN_TYPE (VALUE) at line X, column Y"}],"ecosystem":"pypi","meta_description":null,"install_score":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":"0.5","cli_name":"","cli_version":null,"type":"library","homepage":null,"github":"https://github.com/dabeaz/sly","docs":null,"changelog":null,"pypi":"https://pypi.org/project/sly/","npm":null,"openapi_spec":null,"status_page":null,"smithery":null,"categories":["database"],"base_url":null,"auth_type":null,"provenance":{"verified_status":"passing","verified_at":"2026-06-28","last_verified":"2026-08-28","next_check":"2026-07-28","install_tag":null}}