This is the primary code of the Basic interpreter, where the listing of the last section is extracted to extract GET_TOKEN () and generation value get_exp (int * result) function.
The code in this section is simpler, which is to get the Token assembly that you want to get. If you get_token, if you use print, you will call a get_token will promise the next token, it is very simple, maybe you can get it. of.
In the next section, I will give you a complete C encapsulated source code. / 1 Tiny Basic Interpreter * /
#include
#define Num_Lab 100 # Define Lab_LEN 10 # define for_nest 25 # define Sub_Nest 25 # Define Prog_size 10000 # Define Delimiter 1 # Define Variable 2 # Define Number 3 # Define Command 4 # define string 5 # define quote 6
#define print 2 # Define IF3 # Define The 4 # define for 5 # define next 6 # define to 7 # define goto 8 # define eol 9 # define finished 10 # define gosub 11 # define return 12 # define END 13
Char * prog; / * HOLDS Expression to be analyzed * / jmp_buf e_buf; / * Hold Environment for longjmp () * /
Int variables [26] = {/ * 26 USER VARIABLES, AZ * / 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
Struct Commands {/ * keyword lookup table * / char command [20]; char tok;} Table [] = {/ * Command Must be entered LowerCase * / "Print", Print, / * in this table * / "input" , INPUT, "IF", IF, "THEN", "Goto", Goto, "For", For, "Next", Next, "To", To, "Gosub", Gosub, "Return", Return , "End", end, null, end};
CHAR token [80]; char token_type, tok;
Struct label {char name [lab_len]; char * p; / * Point to place to go in source * /};
Struct label label_table [num_lab]; char * find_label (), * gpop ();
Struct for_stack {int var; / * counter variable * / int target; / * target value * / char * Loc;} fstack [for_nest]; / * stack for for / next loop * / struct for_stack fpop (); char * gstack [SUB_NEST]; / * stack for gosub * / int ftos; / * index to top of for stack * / int gtos; / * index to top of gosub * /
Void Print (), scan_labels (), FIND_EOL (), EXEC_GOTO (); Void gosub (), greturn (), gpush (), label_init (), fpush ();
/ * LOAD a program * / load_program (char * p, char * fname) {file * fp; INT i = 0; if (! (Fp = fopen (fp = fopen (rab ")) RETURN 0;
i = 0; do {* p = getc (fp); p ; i ;} while (! feof (fp) && i / * Assign a variable a value * / assignment () {Int var, value; / * Getthe variable name * / get_token (); if (! isalpha (* token)) {SERROR (4); return;} VAR = Toupper (* token) - 'a'; / * get the equals sign * / get_token (); if (* token! = '=') {SERROR (3); return;} / * Get the value to assign to var * / get_exp (& value); / * Assign the value * / variables [var] = value;} / * EXECUTE A Simple Version of the Basic Print Statement * / Void Print () {INT Answer; INT LEN = 0, Spaces; Char Last_Delim; Do {Get_Token (); / * Get next List item * / if (tok == EOL || tok == finished) Break; if (token_type == quote) {/ * is string * / printf ("% s", token); len = strlen (token); get_token ();} else {/ * Is Expression * / Putback (); get_exp (& answer); get_token (); len = printf ("% d", answer);} last_delim = * token; if (* token == ',') {/ * compute Number of move to next tab * / space = 8- (len% 8); len = spaces; / * add in the tabbing position * / while (spaces) {printf (""); spaces ---;}} else IF (* token == ';') {printf ("");} else if (tok! = eol && tok! = finished) serror (0);} while (* token == ';' || * token == ','); IF (tok == eol || tok == finished) {if (Last_Delim! = ';' && last_delim! = ',') Printf ("/ n");} else serror (0); / * error is not OR; * /} / * Find all labels * / void scan_labels () {int Addr; char * TEMP; Label_init (); / * zero all labels * / temp = prog; / * save poiter to top of program * / / * if the first token in the nEKE is a label * / get_token (); if (token_type == number) {structure (label_table [0] .name, token); label_table [0] .p = prog;} find_eol ); Do {get_token (); if (token_type == Number) {addr = get_next_label (token); if (addr == - 1 || Addr == - 2) {(addr == - 1)? SERROR (5 : SERROR (6);} STRCPY (label_table [addr] .name, token); label_table [addr] .p = prog; / * current point in program * /} / * if not on A Blank line, Find Next Line * / If (tok! = Eol) Find_eol ();} while (tok! = Finished); prog = Temp; / * restore to Original * /} / * Find the start of next line * / void find_eol () {while (* prog! = '/ n' && * prog! = '/ 0') prog; if (* prog) PROG ;} / * RETURN INDEX of Next Free Posion In The Label Array -1 Is Returned IF The Array Is Full. -2 Is Returned When DuPlicate Label Is Found. * / Get_Next_Label (Char * S) {Register Int T For (t = 0; t / * Find location of given label. A Null is returned if Label is not found; OHTHERWISE A POINTER TO The position of the label is returned. * / char * find_label (char * s) {register Int T; For (t = 0; t / * EXECUTE A goto statement. * / void exec_goto () {char * LOC; GET_TOKEN (); / * get label to go to * / / * find the location of label * / loc = find_label (token); if (LOC == '/ 0') SERROR (7); / * label not defined * / else prog = loc;.. / * start program running at that time * /} / * initialize the array that holds the labels by convention, a null label name indicates that array posiiton is unused * / void label_init () {register int T; For (t = 0; t / * EXECUTE An if statement * / void exec_if () {INT X, Y, COND; CHAR OP; Get_exp (& x); / * get left exapression * / GET_TOKEN (); / * get the operator * / if (! strcmp ("<>", * token) {serror (0); / * not a leagal oprator * / return;} OP = * token; get_exp (& y ); / * GET Right Expression * / / * DETERMINE THECOME * / COND = 0; Switch (OP) {CASE '<': if (x / * EXECUTE a for loop * / void exec_for () {structure for_stack i; int value; GET_TOKEN (); / * read the control variable * / if (! isalpha (* token) {serror (4); return;} I.VAR = Toupper (* token) - 'a'; / * save its index * / GET_TOKEN (); / * read the equal signal * / if (* token! = '=') {serror (3); return;} get_exp (& value); / * get initial value * / variables [i.var] = Value; GET_TOKEN (); IF (tok! = to) SERROR (9); / * read an discard the to * / get_exp (& i.target); / * get target value * / / * if Loop Can Execute At Least ONCE, PUSH INTO ON Stack * / IF (Value <= i.target) {i.loc = PROG; FPUSH (i);} else / * OtherWise, Skip loop code altogether * / while (tok! = next) get_token (); / * execute a next statement * / void next () {struct for_stack i; i = fpop (); / * read the loop info * / Variables [i.var] ; / * incrtainted variable * / if (variables [i.var]> i.target) return; / * all done * / fpush (i); / * Otherwise, returnire INFO * / PrOG = i.loc; / * loop * /} / * push function for the for stack * / void fpush (struct for_stack i) {if (ftos> for_nest) SERROR (10); fstack [ftos] = i; ftos ;} Struct for_stack fpop () {ftos ---; IF (ftos <0) SERROR (11); return (fstack [ftos]);} / * EXEC A Simple Form Of Basic Input Command * / Void Input () {Char Str [80], Var; INT I; GET_TOKEN (); / * See if prompt string id = s present * / if (token_type == quote) {printf (token); / * if so, print it and check for command * / get_token (); if (* token ! = ',') SERROR (1); get_token ();} else printf ("?"); / * OtherWise, Prompt with / * / var = Toupper (* token) - 'a'; / * get the input Var * / Scanf ("% d", & i); / * read input * / variables [var] = i; / * store it * /} / * EXECUTE A Gosub Command * / Void Gosub () {char * Loc; get_token (); / * Find the label to call * / loc = find_label (token); if (LOC == '/ 0') SERROR (7 ); / * Label not defined * / else {gpush (prog); / * save place to return to * / prog = Loc; / * start program running at this lock * /}} / * return.com gosub * / void greturn () {prog = gpop (); / * Gosub stack push function * / void gpush (char * s) {gtos ; IF (gtos == Sub_Nest) {SERROR (12); Return;} gstack [gtos] = s;} / * Gosub stack pop function * / char * gpop () {if (gtos == 0) {serror (13); return 0;} return gstack [gtos--];} Main (int Argc, char * argv []) {char in [80]; int Answer; char * p_buf; char * t; IF (argc! = 2) {Printf ("USAGE: RUN / * Allocate Memory for the program * / if (! (p_buf = (char *) malloc (prog_size))) {Printf ("allocation failure); exit (1);} / * Load the program to execute * / if (! loading_program (p_buf, argv [1])) EXIT (1); IF (setjmp (e_buf)) EXIT (1); / * Initialize the long jump * /