ext/ply/ply/lex.py: ext/ply/ply/yacc.py: ext/ply/CHANGES: ext/ply/README: ext/ply/TODO: ext/ply/doc/ply.html: ext/ply/example/ansic/clex.py: ext/ply/example/ansic/cparse.py: ext/ply/example/calc/calc.py: ext/ply/example/hedit/hedit.py: ext/ply/example/optcalc/calc.py: ext/ply/test/README: ext/ply/test/calclex.py: ext/ply/test/lex_doc1.exp: ext/ply/test/lex_doc1.py: ext/ply/test/lex_dup1.exp: ext/ply/test/lex_dup1.py: ext/ply/test/lex_dup2.exp: ext/ply/test/lex_dup2.py: ext/ply/test/lex_dup3.exp: ext/ply/test/lex_dup3.py: ext/ply/test/lex_empty.py: ext/ply/test/lex_error1.py: ext/ply/test/lex_error2.py: ext/ply/test/lex_error3.exp: ext/ply/test/lex_error3.py: ext/ply/test/lex_error4.exp: ext/ply/test/lex_error4.py: ext/ply/test/lex_hedit.exp: ext/ply/test/lex_hedit.py: ext/ply/test/lex_ignore.exp: ext/ply/test/lex_ignore.py: ext/ply/test/lex_re1.exp: ext/ply/test/lex_re1.py: ext/ply/test/lex_rule1.py: ext/ply/test/lex_token1.py: ext/ply/test/lex_token2.py: ext/ply/test/lex_token3.py: ext/ply/test/lex_token4.py: ext/ply/test/lex_token5.exp: ext/ply/test/lex_token5.py: ext/ply/test/yacc_badargs.exp: ext/ply/test/yacc_badargs.py: ext/ply/test/yacc_badprec.exp: ext/ply/test/yacc_badprec.py: ext/ply/test/yacc_badprec2.exp: ext/ply/test/yacc_badprec2.py: ext/ply/test/yacc_badrule.exp: ext/ply/test/yacc_badrule.py: ext/ply/test/yacc_badtok.exp: ext/ply/test/yacc_badtok.py: ext/ply/test/yacc_dup.exp: ext/ply/test/yacc_dup.py: ext/ply/test/yacc_error1.exp: ext/ply/test/yacc_error1.py: ext/ply/test/yacc_error2.exp: ext/ply/test/yacc_error2.py: ext/ply/test/yacc_error3.exp: ext/ply/test/yacc_error3.py: ext/ply/test/yacc_inf.exp: ext/ply/test/yacc_inf.py: ext/ply/test/yacc_missing1.exp: ext/ply/test/yacc_missing1.py: ext/ply/test/yacc_nodoc.exp: ext/ply/test/yacc_nodoc.py: ext/ply/test/yacc_noerror.exp: ext/ply/test/yacc_noerror.py: ext/ply/test/yacc_nop.exp: ext/ply/test/yacc_nop.py: ext/ply/test/yacc_notfunc.exp: ext/ply/test/yacc_notfunc.py: ext/ply/test/yacc_notok.exp: ext/ply/test/yacc_notok.py: ext/ply/test/yacc_rr.exp: ext/ply/test/yacc_rr.py: ext/ply/test/yacc_simple.exp: ext/ply/test/yacc_simple.py: ext/ply/test/yacc_sr.exp: ext/ply/test/yacc_sr.py: ext/ply/test/yacc_term1.exp: ext/ply/test/yacc_term1.py: ext/ply/test/yacc_unused.exp: ext/ply/test/yacc_unused.py: ext/ply/test/yacc_uprec.exp: ext/ply/test/yacc_uprec.py: Import patch ply.diff src/arch/isa_parser.py: everything is now within the ply package --HG-- rename : ext/ply/lex.py => ext/ply/ply/lex.py rename : ext/ply/yacc.py => ext/ply/ply/yacc.py extra : convert_revision : fca8deabd5c095bdeabd52a1f236ae1404ef106e
79 lines
2.5 KiB
Text
79 lines
2.5 KiB
Text
Inspired by a September 14, 2006 Salon article "Why Johnny Can't Code" by
|
|
David Brin (http://www.salon.com/tech/feature/2006/09/14/basic/index.html),
|
|
I thought that a fully working BASIC interpreter might be an interesting,
|
|
if not questionable, PLY example. Uh, okay, so maybe it's just a bad idea,
|
|
but in any case, here it is.
|
|
|
|
In this example, you'll find a rough implementation of 1964 Dartmouth BASIC
|
|
as described in the manual at:
|
|
|
|
http://www.bitsavers.org/pdf/dartmouth/BASIC_Oct64.pdf
|
|
|
|
See also:
|
|
|
|
http://en.wikipedia.org/wiki/Dartmouth_BASIC
|
|
|
|
This dialect is downright primitive---there are no string variables
|
|
and no facilities for interactive input. Moreover, subroutines and functions
|
|
are brain-dead even more than they usually are for BASIC. Of course,
|
|
the GOTO statement is provided.
|
|
|
|
Nevertheless, there are a few interesting aspects of this example:
|
|
|
|
- It illustrates a fully working interpreter including lexing, parsing,
|
|
and interpretation of instructions.
|
|
|
|
- The parser shows how to catch and report various kinds of parsing
|
|
errors in a more graceful way.
|
|
|
|
- The example both parses files (supplied on command line) and
|
|
interactive input entered line by line.
|
|
|
|
- It shows how you might represent parsed information. In this case,
|
|
each BASIC statement is encoded into a Python tuple containing the
|
|
statement type and parameters. These tuples are then stored in
|
|
a dictionary indexed by program line numbers.
|
|
|
|
- Even though it's just BASIC, the parser contains more than 80
|
|
rules and 150 parsing states. Thus, it's a little more meaty than
|
|
the calculator example.
|
|
|
|
To use the example, run it as follows:
|
|
|
|
% python basic.py hello.bas
|
|
HELLO WORLD
|
|
%
|
|
|
|
or use it interactively:
|
|
|
|
% python basic.py
|
|
[BASIC] 10 PRINT "HELLO WORLD"
|
|
[BASIC] 20 END
|
|
[BASIC] RUN
|
|
HELLO WORLD
|
|
[BASIC]
|
|
|
|
The following files are defined:
|
|
|
|
basic.py - High level script that controls everything
|
|
basiclex.py - BASIC tokenizer
|
|
basparse.py - BASIC parser
|
|
basinterp.py - BASIC interpreter that runs parsed programs.
|
|
|
|
In addition, a number of sample BASIC programs (.bas suffix) are
|
|
provided. These were taken out of the Dartmouth manual.
|
|
|
|
Disclaimer: I haven't spent a ton of time testing this and it's likely that
|
|
I've skimped here and there on a few finer details (e.g., strictly enforcing
|
|
variable naming rules). However, the interpreter seems to be able to run
|
|
the examples in the BASIC manual.
|
|
|
|
Have fun!
|
|
|
|
-Dave
|
|
|
|
|
|
|
|
|
|
|
|
|