University of Calgary

tiny basic help

Tiny Basic Interpreter HELP
created by: Katrin Becker, 1999
adapted from: ACM programming contest problem set
Still confused?????
Here's some help.........[note that code is in C++, but the basic idea is the same for Java]
CONTENTS of THIS PAGE...
The Scanner
The Interpreter

 

Main Program:
- get args to main
- open file
- if open successful
Scanner.LoadProgram()
CPU.ExecuteProgram()
- close file

Scanner: Outline
#ifndef ScannerClass_h
#define ScannerClass_h
/******************************************************
FILE: "ScannerClass.h"

Tine Basic Interpreter

Scanner Class

K.Becker
Feb. 10 2000
Tiny Basic Scanner

*****************************************************/
class ScannerClass
{
public:

ScannerClass(int l=1, int t=0):line_no(l), t_no(t) {}
// program starts at line 1

// MODIFY FUNCTIONS
void LoadProgram( int& status ); // load whole program into memory

// ACCESS FUNCTIONS

private:
// DATA MEMBERS
int line_no; // what line are we on?
int t_no;    // which descriptor in memory on current line (i.e. which column?)

DescriptorClass descriptor; // the current one

// INTERNAL METHODS
int WhatKind( char ch );
// based on first char, what kind of descriptor could it be?

void ReadString( char& ch, char* token, int kind, int& status);
// read all of a string (number or word)

void GetNext( int& status );
// read next token, convert to descriptor triple

void ParseExpression( int& status ); // do whole expression
void ParseStatement( int& status ); // do the whole program
};
#endif
//-------------------------------------------------------------------
// END ScannerClass.h
//-------------------------------------------------------------------
int WhatKind ( char ch );
- find out what kind/type of token it might be based on the value of the first character
if ch is digit
NUMBER
else if A-Z
LETTER
else if =
EQUALS
else if + | >
OPERATOR
else if '\n'
EOLN
else
ERROR
 
void Readstring( char& ch, char* token, int kind, int& status );
- called only when 'ch' was LETTER or NUMBER to get the rest of the token;
- all other tokens are single characters
 
while WhatKind(ch) == kind & OK
read chars into token
set status from file
if ch is '\n' we've hit end-of-line so
status = EOLN
else put the char back for the next guy to read
 
Void GetNext( int& status );
- read the next token, find out what it is, and set up the descriptor
 
clear the token
get the next char
if it's a blank then skip_blanks (which leaves nextchar = next available non-blank
if file still OK
switch( WhatKind( nextchar ) )
NUMBER: ReadString
descr.SetAll(NUMBER, NUM, atoi(token))
EQUALS: descr.SetAll(EQUALS, '=', 0)
OPERATOR: descr.SetAll( OPERATOR, nextchar, 0)
LETTER: ReadString
if "LET" descr.SetName(LET)
if "PRINT" descr.SetName(PRINT)
if "GOTO" descr.SetName(GOTO)
if "IF" descr.SetName(IF)
if "STOP" descr.SetName(STOP)
else descr.SetName(token[0]) // the only char
descr.SetType(VARIABLE)
 
if I didn't already set Type to VARIABLE it must be RESERVED_WORD
EOLN: descr.SetAll(EOLN, ENDLINE, 0)
else descr.SetAll(ERROR, BAD, 0)
 
void ParseExpression( int Start, int& status);
- do an entire expression, no matter where it came from
 
GetNext
- will be first OPERAND so Store it in memory at [line][start]
if we're not at EOLN yet
GetNext
- will be operator so Store in memory at [line][start+1]
GetNext
- will be other operand so Stroe in memory at [line][start+2]
 
void ParseStatement( int& status )
- do an entire statement starting after line number (like in the language definition)
GetNext
- will be RESERVED_WORD so Store it in memory at [line][0]
switch (descr.Name())
LET: GetNext & Store in memory at [line][1]
GetNext - it's the = we don't need it
ParseExpression(2,status) // expression starts in column 2
PRINT: GetNext & store it in memory at [line][1]
GOTO: ParseExpression(1,status)
IF: ParserExpression(1,status)
STOP: -------
 
void LoadProgram
GetNext - this is the line number
while (not EOF)
line = descr.Value()
ParseStatement()
GetNext - the next line number

Interpreter: Outline
#ifndef InterpreterClass_h
#define InterpreterClass_h
/******************************************************
FILE: "InterpreterClass.h"

Tine Basic Interpreter

Interpreter Class

K.Becker
Feb. 10 2000
Tiny Basic Interpreter

*****************************************************/
class InterpreterClass
{
public:
// set up new interpreter
InterpreterClass(int p=1): prog_counter(p) {}

// MODIFY FUNCTIONS
void ExecuteProgram(); // DO IT

private:
// DATA MEMBERS
DescriptorClass instr_reg; // holds reserved word of current instruction
DescriptorClass addr_reg; // holds target, as in LET A=1 {holds the A}

int accumulator; // just like a really real accumulator
int prog_counter; // holds next instruction to execute
int reg1; // general register 1
int reg2; // general register 2

// INTERNAL METHODS
void EvaluateExpression( int instr, int first );
// evaluate expression in memory at line "instr"
//expr start at "first" descriptor
};
#endif
//-------------------------------------------------------------------
// END InterpreterClass.h
//-------------------------------------------------------------------
 
void EvaluateExpression( line, col )
A1 gets descriptor Fetched from memory at [line][col] // first operand
A2 gets descriptor Fetched from memory at [line][col+2] // second operand
OP gets descriptor Fetched from memory at [line][col+1] // the operator
- this works because memory exists in those locations even if the descriptor there is "null"
 
if A1 is VARIABLE
reg1 = current value of variable (A1.Name()) in memory
else it's a number
reg1 = A1.Value()
if OP.Type() is OPERAND
then it wasn't null so
if A2 is VARIABLE
reg2 = current value of variable (A2.Name()) in memory
else it's a number
reg2 = A2.Value()
switch on OP.Name()
+ : accumulator = reg1 + reg2
> : accumulator = reg1 > reg2 ? 1 : 0
else there was only one argument in th expression and we already have its value in reg1
accumulator = reg1
 
void ExecuteProgram
program counter = 1
while ( 1 ) // do forever
instruction register gets res-word Fetched from memory at [program counter][0]
current = program counter
increment program counter
switch on (instruction register Name())
LET: EvaluateExpression( current, 2 )
address register gets var name Fetched from memory at [current][1]
set variable( addressregister Name()) in memory to accumulator
PRINT: address register gets var name Fetched from memory at [current][1]
print out the Name() and Value()
GOTO: EvaluateExpression( current, 1 )
set program counter to acumulator
IF: EvaluateExpression( current, 1 )
if accumulator is 0 increment program counter
STOP: say BYE
return - this is better than exit here

Updated: August 5, 2005 06:56 PM