Name | spectrum-basic JSON |
Version |
0.4.2
JSON |
| download |
home_page | None |
Summary | A parser and language tool for ZX Spectrum BASIC |
upload_time | 2024-12-17 20:58:34 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.10 |
license | MIT |
keywords |
zx-spectrum
basic
retro
compiler
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# Spectrum BASIC Tools
A Python toolkit for parsing, transforming, and manipulating ZX Spectrum BASIC programs. This tool can help you work with both classic Spectrum BASIC and an enhanced dialect that supports modern programming constructs.
## Features
- Full parser for ZX Spectrum BASIC
- Support for an enhanced dialect with:
- Optional line numbers
- Labels (e.g., `@loop:`)
- Label references in expressions and GOTOs
- Program transformations:
- Line numbering and renumbering
- Variable name minimization
- Label elimination (for Spectrum compatibility)
- Detailed variable analysis
- Pretty printing with authentic Spectrum BASIC formatting
- TAP file generation for loading programs on a real Spectrum
- Run a subset of BASIC programs locally for algorithm testing
## Installation
For developer mode, clone the repository and install the package in editable mode:
```bash
git clone https://github.com/imneme/spectrum-basic.git
cd spectrum-basic
pip install -e .
```
Install from PyPI:
```bash
pip install speccy-basic
```
Requires Python 3.10 or later.
## Usage
### Command Line
The package installs a command-line tool called `speccy-basic`:
```bash
# Show the parsed and pretty-printed program
speccy-basic program.bas --show
# Number unnumbered lines and remove labels
speccy-basic program.bas --delabel
# Minimize variable names
speccy-basic program.bas --minimize
# Combine transformations
speccy-basic program.bas --delabel --minimize
# Analyze variables
speccy-basic program.bas --find-vars
# Generate a TAP file
speccy-basic program.bas --tap output.tap --tap-name "My Program"
# Run a program locally
speccy-basic program.bas --run
```
### As a Library
```python
from spectrum_basic import parse_file, number_lines, minimize_variables, make_program_tap, write_tap
# Parse a program
program = parse_file("my_program.bas")
# Apply transformations
number_lines(program, remove_labels=True)
minimize_variables(program)
# Output the result
str(program)
# Program image and tape generation
binary_code = bytes(program)
tap = make_program_tap(binary_code, name="My Program", autostart=9000)
write_tap(tap, "output.tap")
```
## Enhanced BASIC Features
The tool supports an enhanced dialect of BASIC that's compatible with ZX Spectrum BASIC. Additional features include:
### Labels
```basic
@loop:
FOR I = 1 TO 10
PRINT I
NEXT I
GOTO @loop
```
Label names are written `@identifier`. Lines are labeled by putting the label at the start of the line, followed by a colon. They can be used anywhere where you would write a line number, including:
- `GOTO`/`GOSUB` statements
- Arithmetic expressions (e.g., `(@end - @start)/10`)
## Working with the AST
If you want to analyze or transform BASIC programs, you'll need to work with the Abstract Syntax Tree (AST) that represents the program's structure. Import the AST nodes from the ast module:
```python
from spectrum_basic.ast import Variable, Number, Label, BuiltIn
```
The AST nodes have attributes that correspond to the fields of the original BASIC code. For example:
```text
>>> from spectrum_basic import *
>>> prog = parse_string('10 PRINT "Hello World!";')
>>> len(prog.lines)
1
>>> (stmt := prog.lines[0].statements[0])
PRINT "Hello World!";
>>> (arg := stmt.args[0])
"Hello World!";
>>> arg.value
"Hello World!"
>>> arg.sep
';'
```
However, for many applications where you want to traverse syntax tree, you may prefer to use the AST walking API described below.
### AST Walking
The AST can be traversed using the `walk()` generator, which yields tuples of `(event, node)`. Events are:
```python
class Walk(Enum):
ENTERING = auto() # Entering a compound node
VISITING = auto() # At a leaf node or simple value
LEAVING = auto() # Leaving a compound node
```
Example usage:
```python
def find_variables(program):
"""Find all variables in a program"""
variables = set()
for event, obj in walk(program):
if event == Walk.VISITING and isinstance(obj, Variable):
variables.add(obj.name)
return sorted(variables)
```
You can control traversal by sending `Walk.SKIP` back to the generator to skip processing a node's children. You can also just abandon the generator at any time.
### Key AST Nodes
Common patterns for matching AST nodes:
```python
# Basic nodes
Variable(name=str) # Variable reference (e.g., "A" or "A$")
Number(value=int|float) # Numeric literal
Label(name=str) # Label reference (e.g., "@loop")
# Built-in commands/functions (most statements)
BuiltIn(action=str, # Command name (e.g., "PRINT", "GOTO")
args=tuple) # Command arguments
# Statements that don't just take expressions usually have their own AST nodes
# for example:
Let(var=Variable|ArrayRef, # Assignment statement
expr=Expression) # Expression to assign
# Program structure
Program(lines=list) # Complete program
SourceLine( # Single line of code
line_number=int|None,
label=Label|None,
statements=list)
```
Example pattern matching:
```python
match obj:
case BuiltIn(action="GOTO", args=[target]) if isinstance(target, Number):
# Handle simple GOTO with numeric line number
line_num = target.value
...
case Variable(name=name) if name.endswith("$"):
# Handle string variable
...
```
## License
MIT License. Copyright (c) 2024 Melissa O'Neill
## Requirements
- Python 3.10 or later
- TextX parsing library
Raw data
{
"_id": null,
"home_page": null,
"name": "spectrum-basic",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": null,
"keywords": "zx-spectrum, basic, retro, compiler",
"author": null,
"author_email": "\"Melissa E. O'Neill\" <oneill@acm.org>",
"download_url": "https://files.pythonhosted.org/packages/eb/2d/890d8b62c37cd3943abd53a7a201c5e7af45031c77c0b0b71594e2b3ccb9/spectrum_basic-0.4.2.tar.gz",
"platform": null,
"description": "# Spectrum BASIC Tools\n\nA Python toolkit for parsing, transforming, and manipulating ZX Spectrum BASIC programs. This tool can help you work with both classic Spectrum BASIC and an enhanced dialect that supports modern programming constructs.\n\n## Features\n\n- Full parser for ZX Spectrum BASIC\n- Support for an enhanced dialect with:\n - Optional line numbers\n - Labels (e.g., `@loop:`)\n - Label references in expressions and GOTOs\n- Program transformations:\n - Line numbering and renumbering\n - Variable name minimization\n - Label elimination (for Spectrum compatibility)\n- Detailed variable analysis\n- Pretty printing with authentic Spectrum BASIC formatting\n- TAP file generation for loading programs on a real Spectrum\n- Run a subset of BASIC programs locally for algorithm testing\n\n## Installation\n\nFor developer mode, clone the repository and install the package in editable mode:\n\n```bash\ngit clone https://github.com/imneme/spectrum-basic.git\ncd spectrum-basic\npip install -e .\n```\n\nInstall from PyPI:\n\n```bash\npip install speccy-basic\n``` \n\n\nRequires Python 3.10 or later. \n\n## Usage\n\n### Command Line\n\nThe package installs a command-line tool called `speccy-basic`:\n\n```bash\n# Show the parsed and pretty-printed program\nspeccy-basic program.bas --show\n\n# Number unnumbered lines and remove labels\nspeccy-basic program.bas --delabel\n\n# Minimize variable names\nspeccy-basic program.bas --minimize\n\n# Combine transformations\nspeccy-basic program.bas --delabel --minimize\n\n# Analyze variables\nspeccy-basic program.bas --find-vars\n\n# Generate a TAP file\nspeccy-basic program.bas --tap output.tap --tap-name \"My Program\"\n\n# Run a program locally\nspeccy-basic program.bas --run\n```\n\n### As a Library\n\n```python\nfrom spectrum_basic import parse_file, number_lines, minimize_variables, make_program_tap, write_tap\n\n# Parse a program\nprogram = parse_file(\"my_program.bas\")\n\n# Apply transformations\nnumber_lines(program, remove_labels=True)\nminimize_variables(program)\n\n# Output the result\nstr(program)\n\n# Program image and tape generation\nbinary_code = bytes(program)\ntap = make_program_tap(binary_code, name=\"My Program\", autostart=9000)\nwrite_tap(tap, \"output.tap\")\n```\n\n## Enhanced BASIC Features\n\nThe tool supports an enhanced dialect of BASIC that's compatible with ZX Spectrum BASIC. Additional features include:\n\n### Labels\n```basic\n@loop:\nFOR I = 1 TO 10\n PRINT I\nNEXT I\nGOTO @loop\n```\n\nLabel names are written `@identifier`. Lines are labeled by putting the label at the start of the line, followed by a colon. They can be used anywhere where you would write a line number, including:\n\n- `GOTO`/`GOSUB` statements\n- Arithmetic expressions (e.g., `(@end - @start)/10`)\n\n\n## Working with the AST\n\nIf you want to analyze or transform BASIC programs, you'll need to work with the Abstract Syntax Tree (AST) that represents the program's structure. Import the AST nodes from the ast module:\n\n```python\nfrom spectrum_basic.ast import Variable, Number, Label, BuiltIn\n```\n\nThe AST nodes have attributes that correspond to the fields of the original BASIC code. For example:\n\n```text\n>>> from spectrum_basic import *\n>>> prog = parse_string('10 PRINT \"Hello World!\";')\n>>> len(prog.lines)\n1\n>>> (stmt := prog.lines[0].statements[0])\nPRINT \"Hello World!\";\n>>> (arg := stmt.args[0])\n\"Hello World!\";\n>>> arg.value\n\"Hello World!\"\n>>> arg.sep\n';'\n```\n\nHowever, for many applications where you want to traverse syntax tree, you may prefer to use the AST walking API described below.\n\n### AST Walking\n\nThe AST can be traversed using the `walk()` generator, which yields tuples of `(event, node)`. Events are:\n\n```python\nclass Walk(Enum):\n ENTERING = auto() # Entering a compound node\n VISITING = auto() # At a leaf node or simple value\n LEAVING = auto() # Leaving a compound node\n```\n\nExample usage:\n\n```python\ndef find_variables(program):\n \"\"\"Find all variables in a program\"\"\"\n variables = set()\n for event, obj in walk(program):\n if event == Walk.VISITING and isinstance(obj, Variable):\n variables.add(obj.name)\n return sorted(variables)\n```\n\nYou can control traversal by sending `Walk.SKIP` back to the generator to skip processing a node's children. You can also just abandon the generator at any time.\n\n### Key AST Nodes\n\nCommon patterns for matching AST nodes:\n\n```python\n# Basic nodes\nVariable(name=str) # Variable reference (e.g., \"A\" or \"A$\")\nNumber(value=int|float) # Numeric literal\nLabel(name=str) # Label reference (e.g., \"@loop\")\n\n# Built-in commands/functions (most statements)\nBuiltIn(action=str, # Command name (e.g., \"PRINT\", \"GOTO\")\n args=tuple) # Command arguments\n\n# Statements that don't just take expressions usually have their own AST nodes\n# for example:\nLet(var=Variable|ArrayRef, # Assignment statement\n expr=Expression) # Expression to assign\n\n# Program structure\nProgram(lines=list) # Complete program\nSourceLine( # Single line of code\n line_number=int|None,\n label=Label|None,\n statements=list)\n```\n\nExample pattern matching:\n\n```python\nmatch obj:\n case BuiltIn(action=\"GOTO\", args=[target]) if isinstance(target, Number):\n # Handle simple GOTO with numeric line number\n line_num = target.value\n ...\n case Variable(name=name) if name.endswith(\"$\"):\n # Handle string variable\n ...\n```\n\n## License\n\nMIT License. Copyright (c) 2024 Melissa O'Neill\n\n## Requirements\n\n- Python 3.10 or later\n- TextX parsing library\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A parser and language tool for ZX Spectrum BASIC",
"version": "0.4.2",
"project_urls": {
"Bug Tracker": "https://github.com/imneme/spectrum-basic/issues",
"Documentation": "https://github.com/imneme/spectrum-basic#readme",
"Homepage": "https://github.com/imneme/spectrum-basic"
},
"split_keywords": [
"zx-spectrum",
" basic",
" retro",
" compiler"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "a463ecc4fdce1a994f481526d5c8677875a94083be2dfa317b6e39767efafce1",
"md5": "7ec007393a90d36f587d19556aa7ac13",
"sha256": "221a652ec3a820f2fc190fce47371c9ca91e9af9939ef9923264fe7c5dd74f91"
},
"downloads": -1,
"filename": "spectrum_basic-0.4.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "7ec007393a90d36f587d19556aa7ac13",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 37459,
"upload_time": "2024-12-17T20:58:31",
"upload_time_iso_8601": "2024-12-17T20:58:31.904437Z",
"url": "https://files.pythonhosted.org/packages/a4/63/ecc4fdce1a994f481526d5c8677875a94083be2dfa317b6e39767efafce1/spectrum_basic-0.4.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "eb2d890d8b62c37cd3943abd53a7a201c5e7af45031c77c0b0b71594e2b3ccb9",
"md5": "320eb9c0455da2d7655f249d9f70818c",
"sha256": "e266aa9a53f945aceabfee3c21c005fa2334f1136bbec963bafee19e6ebe373b"
},
"downloads": -1,
"filename": "spectrum_basic-0.4.2.tar.gz",
"has_sig": false,
"md5_digest": "320eb9c0455da2d7655f249d9f70818c",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 35721,
"upload_time": "2024-12-17T20:58:34",
"upload_time_iso_8601": "2024-12-17T20:58:34.399039Z",
"url": "https://files.pythonhosted.org/packages/eb/2d/890d8b62c37cd3943abd53a7a201c5e7af45031c77c0b0b71594e2b3ccb9/spectrum_basic-0.4.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-12-17 20:58:34",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "imneme",
"github_project": "spectrum-basic",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "spectrum-basic"
}