fx92-interpreter/fx92.py

136 lines
3.5 KiB
Python
Executable File

#! /usr/bin/python3
import os
import sys
import getopt
from fx92.parser import Parser
from fx92.lexer import UrlLexer, TextLexer
from fx92.printer import print_ast
from fx92.drawing import Window, InterruptException
from fx92.interpreter import Context
from fx92.keyseq import print_key_sequence
#---
# Main program
#---
usage_string = """
usage: {} [-s|-u] <file> [options...]
If "-" is specified as input, stdin is read.
Input mode (default is -s):
-s Input file is an ASCII script ("GOTO 12, 35")
-u Input file is a wes.casio.com URL ("https://...F908313200333500")
Output options:
--quiet Do not show the SDL window
--save=<file> Save a copy of the screen output in a bitmap file
--scale=<n> Window scale up (default 4, max 16)
--stream=<dir> Capture rendering in real time, outputs a series of bitmaps
--keyseq Output key sequence for Aditya02's hardware mod
""".format(sys.argv[0]).strip()
def usage(exitcode=None):
print(usage_string, file=sys.stderr)
if exitcode is not None:
sys.exit(exitcode)
def main():
# Read command-line arguments
try:
opts, args = getopt.gnu_getopt(sys.argv[1:], "hus",
["help", "quiet", "keyseq", "save=", "scale=", "debug=", "stream="])
opts = dict(opts)
if len(sys.argv) == 1 or "-h" in opts or "--help" in opts:
usage(0)
if "-u" in opts and "-s" in opts:
raise getopt.GetoptError("-s (script input) and -u (URL input) "
"are exclusive")
if len(args) < 1:
usage(1)
if len(args) > 1:
raise getopt.GetoptError("only one input file can be specified")
except getopt.GetoptError as e:
print("error:", e, file=sys.stderr)
print("Try '{} --help' for details.".format(sys.argv[0]), file=sys.stderr)
sys.exit(1)
# Other parameters
quiet = "--quiet" in opts
out = opts.get("--save", None)
debug = opts.get("--debug", None)
stream = opts.get("--stream", False)
keyseq = opts.get("--keyseq", None)
scale = int(opts.get("--scale", "4"))
if scale < 1:
scale = 1
if scale > 16:
scale = 16
# Read the input program
file = args[0]
if file == "-":
program = sys.stdin.read()
else:
with open(file, "r") as fp:
program = fp.read()
# URL mode
if "-u" in opts:
lexer = UrlLexer(program)
# Default, script mode
else:
lexer = TextLexer(program)
# Lexer debug mode, just print the token stream
if debug == "lexer":
lexer.dump()
return 0
parser = Parser(lexer)
ast = parser.parse_program()
ast = ast.simplify()
# Parser debug mode, print the AST
if debug == "parser":
print_ast(ast, lang="ast")
return 0
# Key sequence mode, print a key sequence
if keyseq is not None:
print_key_sequence(ast)
return 0
# Create the folder for streaming capture
if stream:
try:
os.mkdir(stream)
except FileExistsError:
print("error: folder {} already exists, avoiding overwrite".format(
stream))
return 1
with Window(width=192, height=47, scale=scale, quiet=quiet,
stream=stream) as w:
ctx = Context(w)
try:
ctx.run(ast)
if out is not None:
w.save(out)
w.wait()
except InterruptException:
print("[interpreter] Interrupted.", file=sys.stderr)
return 0
if __name__ == "__main__":
sys.exit(main())