Search
Categories
Documents
Language::Basic - Perl Module to interpret BASIC
Language::Basic - Perl Module to interpret BASIC
use Language::Basic;
my $Program = new Language::Basic::Program;
$Program->input("program.bas"); # Read lines from a file
$Program->parse; # Parse the Program
$Program->implement; # Run the Program
$Program->output_perl; # output Program as a Perl program
$Program->line("20 PRINT X"); # add one line to existing Program
Featured scripts:
- basic.pl
-
Runs BASIC programs from the command line.
- termbasic.pl
-
Term::Readline program. Input one line of BASIC at a time, then run the
program.
- basic2pl.pl
-
Outputs a Perl program that does the same thing as the input BASIC program.
This module lets you run any BASIC programs you may have lying around, or
may inspire you to write new ones!
The aspects of the language that are supported are described below. Note
that I was pretty much aiming for Applesoft BASIC (tm) ca. 1985, not some
modern BASIC with real subroutines.
This class handles a whole program. A Program is just a bunch of Lines,
each of which has one or more Statements on it. Running the program
involves moving through the lines, usually in numerical order, and
implementing each line.
Methods:
- current_program
-
Returns the program currently being parsed/implemented/whatever
- set_current_program
-
Sets arg0 to be the Current Program
- current_line
-
Returns the LB::line currently being parsed/implemented/whatever
- set_current_line
-
Sets the current line in Program arg0 to be line number arg1
- first_line_number
-
Returns (not surprisingly) the first line number in Program arg0
- current_line_number
-
What line number in Program arg0 are we currently on?
- input
-
This method reads in a program from a file, whose name is the string arg0. It
doesn't do any parsing, except for taking the line number out of the line.
- line
-
This method takes a line of BASIC (arg1, already chomped), forms a new LB::Line
with it, and adds it to the Program (arg0). It doesn't do any parsing,
except for taking the line number out of the line.
- parse
-
This method parses the program, which just involves looping over the lines
in the program and parsing each line.
- implement
-
This method actually runs the program. That is, it starts on the first line,
and implements statements one at a time. It performs the statements on a
line in order, and goes from line to line in numerical order, unless a GOTO,
NEXT, etc. sends it somewhere else. It stops when it hits an END statement or
``falls off'' the end of the program.
- start
-
This method erases program stack and moves line pointer to beginning of program
-
It should be called any time we start going through the program.
(Either implement or output_perl.)
- goto_line
-
Continue Program execution at the first Statement on line number arg1.
- goto_after_statement
-
Kind of like goto_line, except go to the Statement after Statement arg1.
(Or the first statement on the line just after Statement arg1, if it's the last
Statement on its line.) E.g., when you RETURN from a GOSUB, you want to return
to the GOSUB line but start execution after the GOSUB. Same with FOR.
The following methods are called from LB::Statement parse or implement
methods to implement various BASIC commands.
- push_stack
-
(GOSUB) Call a subroutine, i.e. push the current Statement::Gosub onto the
Program's calling stack
- pop_stack
-
(RETURN) Return from a subroutine, i.e., pop the top Statement::Gosub off of
the Program's calling stack
- store_for
-
(FOR) Store a Statement::For arg1, so that when we get to the corresponding
Statement::Next, we know where to go back to
- pop_stack
-
(NEXT) Get the Statement::For corresponding to Statement::Next arg1
- add_data
-
(DATA) Add a piece of data to the Program's data storage, to be accessed
later.
- get_data
-
(READ) Get a piece of data that was stored earlier.
Finally, there are methods for translating a Program to Perl.
- output_perl
-
This method translates a program to Perl and outputs it. It does so by
looping through the Lines of the program in order, and calling output_perl on
each one. It also prints some pre- and post- data, such as any subroutines it
needs to declare (e.g., subs that imitate BASIC functionality, as well as subs
that correspond to BASIC DEF statements).
-
It attempts to print everything out nicely, with added whitespace et al. to
make the code somewhat readable. (Note that all of the subpackages'
output_perl methods return strings rather than printing them, so we can
handle all of the printing, indenting, etc. here.)
- need_sub
-
Tells the Program that it needs to use the sub named arg0 (whose definition
is in arg1). This is used for outputting a Perl translation of a BASIC
program, so that you only write ``sub mid_str {...}'' if MID$ is used in
the BASIC program.
This class handles one line of a BASIC program, which has one or more
Statements on it.
This class has no implement method. The reason is that sometimes, you'll
jump to the middle of a line. (E.g., returning from the GOSUBs in
10 FOR A=1 TO 10: GOSUB 1000: NEXT A)
Methods:
- get_next
-
Returns the Line's line number
- get_next
-
Returns the next line number in the Program
- set_next
-
Sets the next line number in the Program to be arg1.
- parse
-
This method breaks the line up into Statements (and removes whitespace, except
in strings), then parses the Statements in order.
- output_perl
-
This method simply calls output_perl on each of the Line's Statements in
order.
This is a (hopefully current) description of what Language::Basic supports.
For each command, I give an example use of that command, and possible
a comment or two about it.
Also see the Language::Basic::Syntax manpage, which describes
the exact syntax for each statement, expressions, variable names, etc.
- DATA
-
DATA 1,2,``HI''. These will be read sequentially by READ statements. Note
that currently all string constants must be quoted.
- DEF
-
DEF FNA(X)= INT(X + .5).
- DIM
-
DIM A(20), B(10,10). Arrays default to size 10 (or actually 11 since they
start at zero.)
- END
-
END.
- FOR
-
FOR I = 1 TO 10 STEP 3. STEP defaults to 1 if not given, and may be negative.
(For loops are always implemented at least once.)
- GOTO
-
GOTO 30. Note that GOTO 30+(X*3) is also supported.
- GOSUB
-
GOSUB 10+X. Gosub is just like GOTO, except that when the program gets to
a RETURN statement, it will come back to the statement just after the GOSUB.
- IF
-
IF X > Y THEN 30 ELSE X = X + 1. ELSE is not required. In a THEN or ELSE,
a lone number means GOTO that number (also known as an implied GOTO).
- INPUT
-
INPUT A$, B$. Also allowed is INPUT ``FOO''; BAR. This prints ``FOO?'' instead of
just ``?'' as the input prompt.
- LET
-
LET X=4. The word ``LET'' isn't required; i.e. X=4 is just like LET X=4.
- NEXT
-
NEXT I. Increment I by STEP, test against its limit, go back to the FOR
statement if it's not over (or under, for a descending loop) its limit.
- ON
-
ON X-3 GOSUB 10,20. This is equivalent to:
IF X-3 = 1 THEN GOSUB 10
IF X-3 = 2 THEN GOSUB 20
-
ON ... GOTO is also allowed.
- PRINT
-
PRINT FOO; BAR$, 6*BLAH. semicolon means no space (or one space after printing
numbers!), comma is like a 14-character tab (or \n past column 56).
Print \n after the last expression unless there's a semicolon after it.
- READ
-
READ A, B(I), C$. Reads data from DATA statements into variables
- REM
-
REM WHATEVER. Anything after the REM is ignored (including colons and
succeeding statements!)
- RETURN
-
RETURN. Return to the statement after the last GOSUB.
The following functions are currently supported:
Numeric Functions: INT (like Perl's int), RND (rand), ASC (ord),
LEN (length), VAL (turn a string into a number; in Perl you just + 0 :))
RND just calls Perl's rand; you can't seed it or anything.
String functions: CHR$, MID$, STR$
Multiple statements can appear on one line, separated by colons. E.g.:
10 FOR I = 1 TO 10: PRINT I: NEXT I, or 20 FOR A = 1 TO 4: GOSUB 3000: NEXT A.
Note that after a THEN, all statements are considered part of the THEN,
until a statement starting with ELSE, after which all remaining statements are
part of the ELSE. A REM slurps up everything until the end of the line,
including colons.
Hopefully your code doesn't have many bugs, because there isn't
much error checking.
Everything except string constants is converted to upper case, so 'a' and 'A'
are the same variable. (But note that the string ``Yes'' <> ``YES'', at least
for now.)
Spaces are (currently) required around various pieces of the program, like
THEN, ELSE, GOTO. That is, GOTO20 won't work. This may or may not change
in the future.
When you use basic.pl (&LB::Program::input), the lines in the input file must
be in numerical order. When using termbasic.pl (&LB::Program::line), this
rule doesn't apply.
This is an alpha release and likely contains many bugs; these are merely
the known ones.
If you use multiple Language::Basic::Program objects in a Perl program,
functions and variables can leak over from one to another.
It is possible to get some Perl warnings; for example, if you input a string
into a numerical variable and then do something with it.
PRINT and so forth all go to the select-ed output handle; there really
ought to be a way to set for a Program the output handle.
There needs to be better and consistent error handling, and a more
extensive test suite.
Amir Karger (akarger@cpan.org)
David Glasser gave ideas and feedback, hunted down bugs, and sent in a major
patch to help the LB guts.
Copyright (c) Amir Karger 2000
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
BASIC stands for Beginner's All-purpose Symbolic Instruction Code. Since it
was considered pretty hot stuff in the early 80's, it's the first language that
I and a lot of folks my age learned, so it holds a special place in my heart.
Which is the only reason I spent so many hours writing an interpreter for it
long after it was superseded by real interpreted languages that had subroutines
and didn't rely quite so much on GOTO.
I originally wrote this interpreter in C, as the final project for my first
C programming class in college. Its name at that point was COMPLEX, which
stood for ``C-Oriented Major Project which did not use LEX''.
When I learned Perl, I felt like its string handling capabilities would be
much better for an interpreter, so eventually I ported and expanded it.
(Incidentally, I was right. I had surpassed the original program's
functionality in less than a week, and I was able to run wumpus in 2.)
A big goal for the Perl port is to support enough of the language that I can
run wumpus, another legacy from my childhood. The interpreter's name could be
changed from COMPLEX to ``Perl Eclectic Retro interpreter which did not use
Parse::LEX'', or PERPLEX, but I settled for Language::Basic instead.
All of the the Language::Basic::* manpages associated with Language::Basic sub-modules
the Language::Basic::Syntax manpage, which describes the syntax supported by
the Language::Basic module
perl(1), wump(6)
Information
|
This site is currently in testing, it is not yet operating using the full database. Until it is officially launched you may wish to visit Help-Site Computer Manuals. After launch, this site (HelpSpy) will replace Help-Site. Information about the spider which is currently trawling the Internet looking for links to add to this directory can be found here. |
|
|