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
-