{"id":1853,"library":"parsimonious","title":"Parsimonious","description":"Parsimonious is a pure-Python library for creating parsers based on Parsing Expression Grammars (PEGs). It aims for speed and usability, allowing users to define grammars using a simplified EBNF notation. It is designed for applications requiring efficient parsing of structured text, such as configuration files or domain-specific languages. The current version is 0.11.0.","status":"active","version":"0.11.0","language":"en","source_language":"en","source_url":"https://github.com/erikrose/parsimonious","tags":["parsing","PEG","grammar","parser","DSL","AST"],"install":[{"cmd":"pip install parsimonious","lang":"bash","label":"Install stable version"}],"dependencies":[],"imports":[{"symbol":"Grammar","correct":"from parsimonious.grammar import Grammar"},{"note":"Used for structured traversal and transformation of the parse tree.","symbol":"NodeVisitor","correct":"from parsimonious.nodes import NodeVisitor"}],"quickstart":{"code":"from parsimonious.grammar import Grammar\nfrom parsimonious.nodes import NodeVisitor\n\n# 1. Define your grammar\ngrammar = Grammar(\n    \"\"\"\n    expression = term ((\"+\" / \"-\") term)*\n    term       = factor ((\"*\" / \"/\") factor)*\n    factor     = \"(\" expression \")\" / number\n    number     = ~\"[0-9]+\"\n    \"\"\"\n)\n\n# 2. Parse an input string\ninput_string = \"(10 + 20) * 3\"\ntry:\n    tree = grammar.parse(input_string)\n    print(f\"Successfully parsed: {input_string}\")\n    # print(tree.prettily())\n\n    # 3. (Optional) Process the parse tree using a NodeVisitor\n    class CalculatorVisitor(NodeVisitor):\n        def visit_number(self, node, visited_children):\n            return int(node.text)\n\n        def visit_factor(self, node, visited_children):\n            if len(visited_children) == 3: # ( expression )\n                _, expr, _ = visited_children\n                return expr\n            return visited_children[0] # number\n\n        def visit_term(self, node, visited_children):\n            result = visited_children[0]\n            for i in range(1, len(visited_children), 2):\n                op = visited_children[i][0].text # Access the operator node's text\n                num = visited_children[i+1]\n                if op == '*':\n                    result *= num\n                elif op == '/':\n                    result /= num\n            return result\n\n        def visit_expression(self, node, visited_children):\n            result = visited_children[0]\n            for i in range(1, len(visited_children), 2):\n                op = visited_children[i][0].text # Access the operator node's text\n                num = visited_children[i+1]\n                if op == '+':\n                    result += num\n                elif op == '-':\n                    result -= num\n            return result\n\n        def generic_visit(self, node, visited_children):\n            return visited_children or node\n\n    calculator = CalculatorVisitor()\n    result = calculator.visit(tree)\n    print(f\"Result: {result}\")\n\nexcept Exception as e:\n    print(f\"Error parsing: {e}\")\n","lang":"python","description":"This quickstart demonstrates how to define a simple arithmetic grammar, parse an input string, and then process the resulting parse tree using a `NodeVisitor` to evaluate the expression. This pattern of grammar definition followed by a visitor for tree manipulation is central to using Parsimonious effectively."},"warnings":[{"fix":"Always pin your `parsimonious` dependency to a specific version (e.g., `parsimonious==0.11.0`) to ensure stability. Consult the GitHub changelog for specific migration details between versions.","message":"Parsimonious is pre-1.0, and API changes have occurred in previous versions (e.g., 0.5). While 0.11.0 doesn't have explicitly documented breaking changes from 0.10.x, it's generally advised to pin exact versions to avoid unexpected behavior changes in future minor releases.","severity":"breaking","affected_versions":"<1.0"},{"fix":"Adhere strictly to Parsimonious's regex syntax (`~\"pattern\"`). Be aware that future versions might change how regexes are defined or preferred. For complex character classes, explicit regexes are currently efficient.","message":"The library's internal regex handling uses the `regex` library (not Python's built-in `re`) and employs a specific `~\"regex\"` syntax. The author has also indicated a potential future deprecation of explicit regexes in favor of dynamically built primitives.","severity":"gotcha","affected_versions":"All"},{"fix":"For very large files or data streams, consider pre-processing to break them into smaller, manageable chunks, or evaluate if a stream-based parsing library is more suitable for your specific use case. Parsimonious is best suited for inputs that fit comfortably in memory.","message":"Parsimonious is a 'Collection parser' rather than a 'stream parser'. This means it loads the entire input (e.g., a string or file content) into memory before parsing. For extremely large inputs, this can lead to high memory consumption.","severity":"gotcha","affected_versions":"All"},{"fix":"For any non-trivial processing of the parse tree, implement a `NodeVisitor` subclass. This provides an organized, maintainable, and less error-prone way to traverse and transform the tree.","message":"While direct manipulation of `Node` objects is possible, the recommended and most robust way to process the Abstract Syntax Tree (AST) after parsing is to create a subclass of `NodeVisitor`.","severity":"gotcha","affected_versions":"All"}],"env_vars":null,"last_verified":"2026-04-09T00:00:00.000Z","next_check":"2026-07-08T00:00:00.000Z"}