Created
April 11, 2014 21:35
-
-
Save kjr247/10503476 to your computer and use it in GitHub Desktop.
pascal compiler in C++ allowing concurrency without using semaphores
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Kyle Rebstock <[email protected]> Fri, Apr 11, 2014 at 1:10 PM | |
To : Kyle Rebstock <[email protected]> | |
// ------------------------------------------- | |
// Program: pascomp.cc (Version 1.8)//modified since 1.8 This is compiler before val/ref feature | |
// | |
// Description: This is a pascal like compiler with low-level code implementation. | |
// Student: Kyle Jackson Rebstock | |
// ID: 713599 | |
// Date: February 8, 2014 | |
// ------------------------------------------- | |
//#include <fstream.h> // for handling files | |
#include <ctype.h> | |
#include <stdlib.h> | |
#include <string> | |
#include <iomanip> | |
#include <iostream> | |
#include <stack> | |
// ------------------------------------------- | |
// These are some global definitions | |
// ------------------------------------------- | |
#define TRUE 1 | |
#define FALSE 0 | |
#define MAX_TABLE 500 | |
#define MAX_PCODE 1000 | |
#define MAX_SYMBOL 47 | |
#define MAX_SYM_SZ 20 | |
#define MAX_PRAMS 31 | |
#define MAX_STACK 1000 | |
// ------------------------------------------- | |
// These are some ERROR definitions | |
// ------------------------------------------- | |
#define ERROR_SEMICOLON 1 | |
#define ERROR_IDENT 2 | |
#define ERROR_UNKNOWN 3 | |
#define ERROR_ASSIGN 4 | |
#define ERROR_ASSIGN_PROC 5 | |
#define ERROR_PROCEDURE 6 | |
#define ERROR_END_SYM 7 | |
#define ERROR_DO_SYM 8 | |
#define ERROR_THEN_SYM 9 | |
#define ERROR_UNTIL_SYM 10 | |
#define ERROR_VARIABLE 11 | |
#define ERROR_OF_SYM 12 | |
#define ERROR_CONSTANT 13 | |
#define ERROR_COLON 14 | |
#define ERROR_RPAREN 15 | |
#define ERROR_IS_PROCEDURE 16 | |
#define ERROR_REL 17 | |
#define ERROR_PROG_SIZE 18 | |
#define ERROR_END_PROG 19 | |
#define ERROR_NUMBER 20 | |
#define ERROR_IDENT_VAR 22 | |
#define ERROR_LPAREN 23 | |
#define ERROR_UNTIL 25 | |
#define ERROR_TO_DOWNTO 26 | |
#define ERROR_OF 27 | |
#define ERROR_NUMBER_IDENT 28 | |
#define ERROR_CEND 29 | |
#define ERROR_NOPROCEDURE 30 | |
#define ERROR_VAR 31 | |
#define ERROR_ASSIGN 32 | |
//Begin Modified | |
#define ERROR_FUNC 33 | |
#define ERROR_FUNCLEVEL 34 | |
//End Modified | |
// ------------------------------------------- | |
// some enumerated data types | |
// ------------------------------------------- | |
typedef enum tag_symbol | |
{ | |
VARSYM, | |
CONSTSYM, | |
BEGINSYM, | |
ENDSYM, | |
CENDSYM, | |
PERIOD, | |
SEMICOLON, | |
COLON, | |
LPAREN, | |
RPAREN, | |
GRTHEN, | |
LSTHEN, | |
GREQL, | |
LSEQL, | |
EQL, | |
ASSIGN, | |
IFSYM, | |
IDENT, | |
NUMBER, | |
WRITESYM, | |
WRITELNSYM, | |
PROCSYM, | |
NOTEQL, | |
MINUS, | |
PLUS, | |
DIV, | |
MULT, | |
COMMA, | |
ODDSYM, | |
CALL, | |
ELSESYM, | |
THENSYM, | |
WHILESYM, | |
DOSYM, | |
REPEATSYM, | |
UNTILSYM, | |
CASESYM, | |
OFSYM, | |
CEND, | |
FOR, | |
DOWNTOSYM, | |
TOSYM, | |
FUNCSYM, | |
OR, | |
AND, | |
NOT, | |
COBEGIN, //MODIFIED COBEGIN" and "COEND | |
COEND //MODIFIED COBEGIN" and "COEND | |
}symbol; | |
// ------------------------------------------- | |
typedef enum tag_Objtype | |
{ | |
NOTYPE, | |
CONSTANT, | |
VARIABLE, | |
PROCEDURE, | |
FUNCTION //Modified | |
}Objtype; | |
// ------------------------------------------- | |
typedef enum tag_psyms | |
{ | |
OPR, | |
CAL, | |
INT, | |
JPC, | |
JMP, | |
LIT, | |
LOD, | |
STO, | |
CTS | |
}psyms; | |
typedef enum tag_intype | |
{ | |
ALPHA, | |
DIGIT, | |
EOL, | |
NONE, | |
PUNCT, | |
SPACE | |
}intype; | |
// ------------------------------------------- | |
typedef struct tag_symtable // Symbols Table Structure | |
{ | |
char name[MAX_SYM_SZ]; // Symbol name | |
Objtype kind; // Type of symbol | |
int value, // Value of symbol | |
level, // Level of symbol | |
adr; // Symbol address | |
}symtable; | |
// ------------------------------------------- | |
typedef struct tag_pcodetable // PCODE Table Structure | |
{ | |
psyms function; // pcode function | |
int level, // pcode level static link | |
adr; // pcode address number into table | |
}pcodetable;//used to save the compile code | |
// ------------------------------------------- | |
// These are some global variables | |
// ------------------------------------------- | |
int linelength, // line length | |
linecount, // line counter | |
charcount, // a character counter | |
codeinx, // pcode index counter inc everytime | |
codeinx0, // init pcode index | |
varcount0, // Init variable counter | |
number; | |
symbol prevsym; // holds the previous symbol | |
symbol toORdowntonsym; | |
symbol writesym; | |
symbol gensym; | |
symbol expsym; | |
symbol termsym; | |
symtable table[MAX_TABLE]; // table array | |
pcodetable pcode[MAX_PCODE]; // pcode table | |
char line[MAX_SYM_SZ]; // an identification string | |
char punc[MAX_SYM_SZ]; // punction array | |
char symstr[MAX_SYMBOL][MAX_SYM_SZ]; // symbols array | |
// ------------------------------------------- | |
// These are some function prototypes | |
// ------------------------------------------- | |
void block(symbol &, int, int); | |
void statement(symbol &, int, int); | |
void genexp(symbol &, int, int); | |
void expression(symbol &, int, int); | |
void term(symbol &, int, int); | |
void factor(symbol &, int, int); | |
char getchar(char &); | |
void getsym(symbol &); | |
intype chartype(char ch); | |
void enter(Objtype, char[], symbol &, int &, int, int &); | |
int base(int, int, int &); | |
void gen(psyms, int, int); | |
void interpret(void); | |
int position(int); | |
void showpcode(void); | |
void openfile(void); | |
void error(int); | |
// ------------------------------------------- | |
// This handles our system errors | |
// ------------------------------------------- | |
void error(int num) | |
{ | |
std::cout << std::endl; | |
switch (num) | |
{ | |
case ERROR_NOPROCEDURE: | |
std::cout << "Procedure not accepted here"; | |
break; | |
case ERROR_CEND: | |
std::cout << "cend sym expected"; | |
break; | |
case ERROR_NUMBER_IDENT: | |
std::cout << "number or ident expected"; | |
break; | |
case ERROR_OF: | |
std::cout << "of expected"; | |
break; | |
case ERROR_TO_DOWNTO: | |
std::cout << "to or downto expected"; | |
break; | |
case ERROR_UNTIL: | |
std::cout << "Until expected"; | |
break; | |
case ERROR_ASSIGN: | |
std::cout << "Assignment operator expected"; | |
break; | |
case ERROR_ASSIGN_PROC: | |
std::cout << "Assignment not allowed here"; | |
break; | |
case ERROR_COLON: | |
std::cout << "COLON Expected"; | |
break; | |
case ERROR_CONSTANT: | |
std::cout << "Constant Expected"; | |
break; | |
case ERROR_END_PROG: | |
std::cout << "Premature end of program"; | |
break; | |
case ERROR_DO_SYM: | |
std::cout << "DO symbol Expected"; | |
break; | |
case ERROR_END_SYM: | |
std::cout << "END symbol Expected"; | |
break; | |
case ERROR_REL: | |
std::cout << "Relational operator expected"; | |
break; | |
case ERROR_IDENT: | |
std::cout << "Identifier Expected"; | |
break; | |
case ERROR_IS_PROCEDURE: | |
std::cout << "Assignment to PROCEDURE not allowed"; | |
break; | |
case ERROR_NUMBER: | |
std::cout << "A number was Expected"; | |
break; | |
case ERROR_PROG_SIZE: | |
std::cout << "Program size is too large..."; | |
break; | |
case ERROR_OF_SYM: | |
std::cout << "OF symbol Expected"; | |
break; | |
case ERROR_RPAREN: | |
std::cout << "RIGHT Parenthesis Expected"; | |
break; | |
case ERROR_LPAREN: | |
std::cout << "LEFT Parenthesis Expected"; | |
break; | |
case ERROR_SEMICOLON: | |
std::cout << "Semicolon Expected"; | |
break; | |
case ERROR_THEN_SYM: | |
std::cout << "THEN symbol Expected"; | |
break; | |
case ERROR_UNKNOWN: | |
std::cout << "Unknown Identifier"; | |
break; | |
case ERROR_UNTIL_SYM: | |
std::cout << "UNTIL symbol Expected"; | |
break; | |
case ERROR_VARIABLE: | |
std::cout << "Variable or Expression Expected"; | |
break; | |
case ERROR_IDENT_VAR: | |
std::cout << "Ident - Variable Expected"; | |
break; | |
case ERROR_VAR: | |
std::cout << "VAR Expected"; | |
break; | |
//Begin Modified | |
case ERROR_FUNCLEVEL: | |
std::cout << "Must be inside function body"; | |
break; | |
case ERROR_FUNC: | |
std::cout << "Function Expected"; | |
break; | |
//End Modified | |
} | |
std::cout << std::endl; | |
exit(1); | |
} | |
// ------------------------------------------- | |
// Insert Block Identifier | |
// ------------------------------------------- | |
void enter(Objtype kind, char name[], symbol &sym, int &varcount, int level, int &tableinx) | |
{ | |
tableinx++; | |
strcpy(table[tableinx].name, name); | |
table[tableinx].kind = kind; | |
if (kind == CONSTANT) | |
{ | |
if (sym != IDENT) | |
error(ERROR_IDENT); | |
getsym(sym); | |
if (sym != EQL) | |
error(ERROR_ASSIGN); | |
getsym(sym); | |
if (sym != NUMBER) | |
error(ERROR_NUMBER); | |
table[tableinx].value = number;//for const only value matters | |
} | |
else if ((kind == VARIABLE)) | |
{ | |
if (sym != IDENT) | |
error(ERROR_IDENT); | |
table[tableinx].level = level; // store variable level for static link level | |
table[tableinx].adr = varcount++; // store address offset from base | |
} | |
else if (kind == PROCEDURE) | |
table[tableinx].level = level; // store procedure level | |
//Begin Modified | |
else if (kind == FUNCTION) | |
if (sym != IDENT) | |
error(ERROR_IDENT); | |
table[tableinx].level = level; // store funciton level | |
//End Modified | |
getsym(sym); | |
} | |
// ------------------------------------------- | |
// Locate Position | |
// ------------------------------------------- | |
int position(int tableinx) | |
{ | |
int i = tableinx; | |
for (strcpy(table[0].name, line); strcmp(table[i].name, line) != 0; i--); | |
return i; | |
} | |
// ------------------------------------------- | |
// Block | |
// ------------------------------------------- | |
void block(symbol &sym, int level, int tableinx) | |
{ //this is our dx, set to 3 for static link | |
int varcount = 3; //,dynamic link,and return address implicitly set | |
int count = 0; | |
// save symbol table count used to | |
int tableinx0 = tableinx; //fix after CONST,VAR,and PROCEDURES DECLARE | |
table[tableinx].adr = codeinx; // save pcode code index | |
gen(JMP, 0, 0); // Generate our init JMP Function,level,adr in pcode table | |
while (sym == CONSTSYM || sym == VARSYM || sym == PROCSYM || sym == FUNCSYM) | |
{ | |
if (sym == CONSTSYM) | |
{ | |
// ---- CONSTANT SYM ---- | |
getsym(sym); | |
enter(CONSTANT, line, sym, varcount, level, tableinx); | |
while (sym == COMMA) | |
{ | |
getsym(sym); | |
enter(CONSTANT, line, sym, varcount, level, tableinx);//int tableinx for all,set value of table line = name | |
} | |
if (sym != SEMICOLON) | |
error(ERROR_SEMICOLON); | |
getsym(sym); | |
} | |
// ---- VARIABLE SYM ---- | |
if (sym == VARSYM) | |
{ | |
getsym(sym); | |
enter(VARIABLE, line, sym, varcount, level, tableinx);//inc (dx) varcount and tableinx,used for INT 0,varcount | |
while (sym == COMMA) | |
{ | |
getsym(sym); | |
enter(VARIABLE, line, sym, varcount, level, tableinx); | |
} | |
if (sym != SEMICOLON) | |
error(ERROR_SEMICOLON); | |
getsym(sym); | |
} | |
// ---- PROCEDURE SYM ---- | |
//BEGIN MODIFIED | |
while (sym == PROCSYM || sym == FUNCSYM) //Procedure or Function | |
{ | |
prevsym = sym; //Save sym | |
getsym(sym); | |
if (sym != IDENT) | |
error(ERROR_IDENT); | |
//If sym = procedure then enter procedure | |
if (prevsym == PROCSYM){ | |
enter(PROCEDURE, line, sym, varcount, level, tableinx);//int tableinx and add level | |
} | |
//If sym = function enter function | |
if (prevsym == FUNCSYM){ | |
enter(FUNCTION, line, sym, varcount, level, tableinx);//int tableinx and add level | |
} | |
if (sym != SEMICOLON) | |
error(ERROR_SEMICOLON); | |
getsym(sym); | |
block(sym, level + 1, tableinx);//inc static link for functions inside of functions, table current pointer | |
if (sym != SEMICOLON) | |
error(ERROR_SEMICOLON); | |
getsym(sym); | |
} | |
//End Modified | |
} | |
pcode[table[tableinx0].adr].adr = codeinx;//tableinx0 is used to fix the original jump when u go into a block | |
table[tableinx0].adr = codeinx; | |
codeinx0 = codeinx; //fix proc addr in ST | |
gen(INT, 0, varcount);//inc the top of the stack by 3 + number of variable | |
statement(sym, level, tableinx); // ident can also now be a function and now stores variables and handles function storing | |
gen(OPR, 0, 0); | |
showpcode(); | |
} | |
// ------------------------------------------- | |
// Statement | |
// ------------------------------------------- | |
void statement(symbol &sym, int level, int tableinx) | |
{ | |
int i, i3, cx1, cx2, cx3, cx4, i2, cx5, cx6, cx7, cx8, cxa, cxb; | |
int first; | |
bool FirstCase = true; | |
int count = 0; | |
switch (sym) | |
{ | |
//COBEGIN | |
case COBEGIN: | |
gen(COBEGIN, level - table[i].level, table[i].adr); | |
int* arr[]; = new arr[n]; | |
//delete[] array; | |
getsym(); | |
do { | |
gen(COEND, level - table[i].level, table[i].adr); | |
arr[codeIndx] | |
getsym(sym); | |
getsym(sym); | |
getsym(sym); | |
} while{!COEND} | |
// IDENT | |
case IDENT: | |
i = position(tableinx); | |
if (i == 0) | |
error(ERROR_UNKNOWN); | |
switch (table[i].kind) | |
{ | |
case VARIABLE: | |
getsym(sym); | |
if (sym != ASSIGN) | |
error(ERROR_ASSIGN); | |
getsym(sym); | |
expression(sym, level, tableinx);//8 * B2 *example* put 8 and B2 onto stack and run OPR | |
gen(STO, level - table[i].level, table[i].adr); | |
break; | |
//Begin Modified | |
case FUNCTION: | |
getsym(sym); | |
if (sym != ASSIGN) | |
error(ERROR_ASSIGN); | |
getsym(sym); | |
expression(sym, level, tableinx);//8 * B2 *example* put 8 and B2 onto stack and run OPR | |
if (i == tableinx){ // if kind is function | |
gen(STO, 0, -1); // then STO 0, -1 | |
} | |
else | |
error(ERROR_FUNCLEVEL); | |
break; | |
default: | |
error(ERROR_ASSIGN_PROC); | |
//End Modified | |
} | |
break; | |
// PROCEDURE CALL | |
case CALL: | |
getsym(sym); | |
if (sym != IDENT) | |
error(ERROR_IDENT); | |
i = position(tableinx); | |
if (i == 0) | |
error(ERROR_UNKNOWN); | |
if (table[i].kind != PROCEDURE) | |
error(ERROR_PROCEDURE); | |
getsym(sym); | |
gen(CAL, level - table[i].level, table[i].adr); | |
break; | |
// BEGIN and END block | |
case BEGINSYM: | |
getsym(sym); | |
statement(sym, level, tableinx); | |
while (sym == SEMICOLON) | |
{ | |
getsym(sym); | |
statement(sym, level, tableinx); | |
} | |
if (sym != ENDSYM) | |
error(ERROR_END_SYM); | |
getsym(sym); | |
break; | |
// WHILE SYMBOL | |
case WHILESYM: | |
getsym(sym); | |
cx1 = codeinx; | |
genexp(sym, level, tableinx); | |
cx2 = codeinx; | |
gen(JPC, 0, 0); | |
if (sym != DOSYM) | |
error(ERROR_DO_SYM); | |
getsym(sym); | |
statement(sym, level, tableinx); | |
gen(JMP, 0, cx1); | |
pcode[cx2].adr = codeinx; | |
break; | |
// IF - THEN - ELSE //Modified | |
case IFSYM: | |
getsym(sym); | |
genexp(sym, level, tableinx); | |
cxa = codeinx; //Save cx1 | |
gen(JPC, 0, 0); // JPC 0,0 | |
if (sym != THENSYM) | |
error(ERROR_THEN_SYM); | |
getsym(sym); | |
statement(sym, level, tableinx); | |
pcode[cxa].adr = codeinx; //Fix JPC @ cx1 | |
/* add your code for ELSE here */ | |
if (sym == ELSESYM) // Begin Modified ----- | |
{ | |
getsym(sym); | |
cxb = codeinx; //Save cx2 | |
gen(JMP, 0, 0); //JMP 0,0 | |
pcode[cxa].adr = codeinx; //Fix JPC @ cx1 | |
statement(sym, level, tableinx); | |
pcode[cxb].adr = codeinx; //Fix JMP @ cx2 | |
} | |
//End Modified ------- | |
break; | |
case REPEATSYM: | |
/* add your code for REPEAT-UNTIL here */ | |
// Begin Modified ------- | |
cx1 = codeinx; //Save cx | |
do { | |
getsym(sym); | |
statement(sym, level, tableinx); | |
} while (sym == SEMICOLON); | |
if (sym != UNTILSYM) | |
error(ERROR_UNTIL_SYM); | |
getsym(sym); | |
genexp(sym, level, tableinx); | |
gen(JPC, 0, cx1); //JPC 0,cx | |
break; | |
case FOR: | |
/* add your code for FOR-DO here */ | |
getsym(sym); | |
if (sym != IDENT) | |
error(ERROR_IDENT_VAR); | |
i3 = position(tableinx); | |
if (i3 == 0) | |
error(ERROR_VAR); | |
if (table[i3].kind != VARIABLE) | |
error(ERROR_VAR); | |
getsym(sym); | |
if (sym != ASSIGN) | |
error(ERROR_ASSIGN); | |
getsym(sym); | |
expression(sym, level, tableinx); | |
gen(STO, level - table[i3].level, table[i3].adr); //STO | |
if (sym != TOSYM && sym != DOWNTOSYM) | |
error(ERROR_TO_DOWNTO); | |
toORdowntonsym = sym; //Save sym | |
getsym(sym); | |
expression(sym, level, tableinx); | |
//Modified | |
cx7 = codeinx; //Save cx7 | |
gen(CTS, 0, 0); //CTS 0,0 | |
gen(LOD, level - table[i3].level, table[i3].adr); //LOD | |
if (toORdowntonsym == TOSYM) //If sym is TO | |
gen(OPR, 0, 11); //OPR 0, >= | |
else if (toORdowntonsym == DOWNTOSYM) //If sym is DOWNTO | |
gen(OPR, 0, 13); //OPR 0, <= | |
cx8 = codeinx; //Save cx8 | |
gen(JPC, 0, 0); //JPC 0,0 | |
//End Mod | |
if (sym != DOSYM) | |
error(ERROR_DO_SYM); | |
getsym(sym); | |
statement(sym, level, tableinx); | |
//Modified | |
gen(LOD, level - table[i3].level, table[i3].adr); //LOD | |
gen(LIT, 0, 1); //LIT 0,1 | |
if (toORdowntonsym == TOSYM) //If sym is TO | |
gen(OPR, 0, 2); //OPR 0, + | |
else if (toORdowntonsym == DOWNTOSYM) //If sym is DOWNTO | |
gen(OPR, 0, 3); //OPR 0,- | |
gen(STO, level - table[i3].level, table[i3].adr); //STO | |
gen(JMP, 0, cx7); //JMP 0,cx7 | |
pcode[cx8].adr = codeinx; //fix JPC @ cx8 | |
gen(INT, 0, -1); //INT 0,-1 | |
//End Mod | |
break; | |
case CASESYM: | |
/* add your code for CASE here */ | |
//Begin Modified ------ | |
getsym(sym); | |
i2 = position(tableinx); | |
expression(sym, level, tableinx); | |
if (sym != OFSYM) | |
error(ERROR_OF_SYM); | |
getsym(sym); | |
while (sym == NUMBER || sym == IDENT) { | |
if (sym == IDENT) | |
{ | |
i2 = position(tableinx); | |
if (i2 == 0) | |
error(ERROR_VAR); | |
if (table[i2].kind != CONSTANT) | |
error(ERROR_CONSTANT); | |
} | |
//getsym(sym); | |
gen(CTS, 0, 0); // CTS 0,0 | |
if (sym == NUMBER) | |
gen(LIT, 0, number); //If Number then LIT 0,num | |
else if (sym == CONSTANT) | |
gen(LIT, 0, table[i2].value); //If constant then LIT 0, table[i].value | |
gen(OPR, 0, 8); //OPR 0,= | |
cx5 = codeinx; //Save cx5 | |
gen(JPC, 0, 0); // JPC 0,0 | |
getsym(sym); | |
if (sym != COLON) | |
error(ERROR_COLON); | |
getsym(sym); | |
statement(sym, level, tableinx); | |
if (sym != SEMICOLON) | |
error(ERROR_SEMICOLON); | |
if (FirstCase == true){ | |
cx6 = codeinx; //Save cx6 | |
gen(JMP, 0, 0); //JMP 0,0 | |
FirstCase = false; | |
} | |
else { | |
gen(JMP, 0, cx6); //JMP 0,cx6 | |
} | |
pcode[cx5].adr = codeinx; //fix JPC @ cx5 | |
getsym(sym); | |
} | |
if (sym != CENDSYM) | |
error(ERROR_CEND); | |
pcode[cx6].adr = codeinx; //fix JPC @ cx6 | |
gen(INT, 0, -1);// int 0,-1 | |
getsym(sym); | |
break; | |
//End Modified ------ | |
case WRITESYM: | |
/* add your code for WRITE here */ | |
//Begin Modified ------ | |
writesym = sym; //Save sym | |
getsym(sym); | |
if (sym != LPAREN) | |
error(ERROR_LPAREN); | |
do { | |
getsym(sym); | |
expression(sym, level, tableinx); | |
gen(OPR, 0, 14); //OPR 0,14 | |
} while (sym == COMMA); | |
if (sym != RPAREN) | |
error(ERROR_RPAREN); | |
getsym(sym); | |
/*if (prevsym == WRITELNSYM) | |
gen(OPR, 0, 15);*/ | |
// End Modified ------- | |
break; | |
case WRITELNSYM: | |
/* add your code for WRITELN here */ | |
// Begin Modified ------- | |
writesym = sym; //Save sym | |
getsym(sym); | |
if (sym != LPAREN) | |
error(ERROR_LPAREN); | |
do { | |
getsym(sym); | |
expression(sym, level, tableinx); | |
gen(OPR, 0, 14); //OPR 0,14 | |
} while (sym == COMMA); | |
if (sym != RPAREN) | |
error(ERROR_RPAREN); | |
getsym(sym); | |
//if (prevsym == WRITELNSYM) //If sym is writeln | |
gen(OPR, 0, 15); //OPR 0,15 | |
break; | |
// End Modified ------- | |
} // END of SWITCH | |
} | |
// ------------------------------------------- | |
// genexp | |
// ------------------------------------------- | |
//Modified from "condition" to "genexp" | |
void genexp(symbol &sym, int level, int tableinx) | |
{ | |
symbol gensym; | |
// ODD symbol | |
if (sym == ODDSYM) | |
{ | |
getsym(sym); | |
expression(sym, level, tableinx); | |
gen(OPR, 0, 6); | |
} | |
else | |
{ | |
expression(sym, level, tableinx); | |
if ((sym == EQL) || (sym == NOTEQL) || (sym == LSTHEN) || (sym == LSEQL) || (sym == GRTHEN) || (sym == GREQL)) | |
{ | |
gensym = sym; | |
getsym(sym); | |
expression(sym, level, tableinx); | |
switch (gensym) | |
{ | |
case EQL: | |
gen(OPR, 0, 8); | |
break; | |
case GREQL: | |
gen(OPR, 0, 11); | |
break; | |
case GRTHEN: | |
gen(OPR, 0, 12); | |
break; | |
case LSEQL: | |
gen(OPR, 0, 13); | |
break; | |
case LSTHEN: | |
gen(OPR, 0, 10); | |
break; | |
case NOTEQL: | |
gen(OPR, 0, 9); | |
break; | |
} | |
//may need to save sym, call expression, then gen(OPR, 0, symop)------------------------------------------? | |
} | |
//Modified | |
//General Experession doesn't have to be a relational operator, it can be nothing | |
//else error(ERROR_REL); | |
} | |
} | |
// ------------------------------------------- | |
// Expression | |
// ------------------------------------------- | |
void expression(symbol &sym, int level, int tableinx) | |
{ | |
symbol expsym; | |
if ((sym == PLUS) || (sym == MINUS)) | |
{ | |
expsym = sym; | |
getsym(sym); // save sym | |
term(sym, level, tableinx); | |
if (expsym == MINUS) | |
gen(OPR, 0, 1); | |
} | |
else | |
term(sym, level, tableinx); | |
//Begin Modified | |
//Add or sym | |
while (sym == PLUS || sym == MINUS || sym == OR) | |
{ | |
expsym = sym; | |
getsym(sym); | |
term(sym, level, tableinx); | |
if (expsym == MINUS) | |
gen(OPR, 0, 3); | |
else | |
gen(OPR, 0, 2);//Can be + or "OR" | |
} | |
//End modified | |
} | |
// ------------------------------------------- | |
// TERM | |
// ------------------------------------------- | |
void term(symbol &sym, int level, int tableinx) | |
{ | |
symbol termsym; | |
factor(sym, level, tableinx); | |
//Modified | |
while ((sym == MULT) || (sym == DIV) || (sym == AND)) | |
{ | |
termsym = sym; // save sym | |
getsym(sym); | |
factor(sym, level, tableinx); | |
if (termsym == DIV) | |
gen(OPR, 0, 5); | |
else // else if (sym == MULT) | |
gen(OPR, 0, 4);//Can be * or "AND" | |
//End Modified | |
} | |
} // End Void term | |
// ------------------------------------------- | |
// FACTOR | |
// ------------------------------------------- | |
void factor(symbol &sym, int level, int tableinx) | |
{ | |
int i; | |
int count = 0; | |
switch (sym) | |
{ | |
// IDENTIFER | |
case IDENT: | |
i = position(tableinx); | |
if (i == 0) | |
error(ERROR_UNKNOWN); | |
//Modified | |
if (table[i].kind == PROCEDURE || table[i].kind == FUNCTION) | |
error(ERROR_IS_PROCEDURE); | |
switch (table[i].kind) | |
{ | |
case VARIABLE: | |
gen(LOD, level - table[i].level, table[i].adr); | |
break; | |
case CONSTANT: | |
gen(LIT, 0, table[i].value); | |
break; | |
} | |
getsym(sym); | |
break; | |
// NUMBER | |
case NUMBER: | |
gen(LIT, 0, number); | |
getsym(sym); | |
break; | |
// LEFT PARENTHESE | |
case LPAREN: | |
getsym(sym); | |
genexp(sym, level, tableinx); | |
if (sym != RPAREN) | |
error(ERROR_RPAREN); | |
getsym(sym); | |
break; | |
case CALL: | |
getsym(sym); | |
i = position(tableinx); | |
if (i == 0) | |
error(ERROR_UNKNOWN); | |
/*if (sym != FUNCSYM || sym != PROCSYM) | |
error(ERROR_FUNC);*/ | |
if (sym != IDENT) | |
error(ERROR_IDENT); | |
if (table[i].kind != FUNCTION) | |
error(ERROR_FUNC); | |
gen(INT, 0, 1); //INT 0,1 | |
gen(CAL, level - table[i].level, table[i].adr);// Call | |
getsym(sym); | |
break; | |
case NOT: | |
getsym(sym); | |
factor(sym, level, tableinx); | |
gen(LIT, 0, 0); // Lit 0 and check inequality | |
gen(OPR, 0, 8); // opr, = | |
break; | |
default: | |
error(ERROR_VARIABLE); | |
} | |
//End Modified | |
} | |
// ------------------------------------------- | |
// Generate the PCODE | |
// ------------------------------------------- | |
void gen(psyms function, int level, int adr) | |
{ | |
if (codeinx > MAX_PCODE) | |
error(ERROR_PROG_SIZE); | |
pcode[codeinx].function = function; | |
pcode[codeinx].level = level; | |
pcode[codeinx].adr = adr; | |
codeinx++; | |
} | |
// ------------------------------------------- | |
// This is our GET CHARACTER function | |
// ------------------------------------------- | |
char getchar(char &ch) | |
{ | |
static char line[255]; // local array | |
if (charcount == linelength) | |
{ | |
charcount = linelength = 0; // zero out counters | |
std::cin.get(ch); | |
while (chartype(ch) != EOL && std::cin) | |
{ | |
line[linelength] = ch; | |
std::cin.get(ch); | |
linelength++; | |
} | |
if (linelength == 0 && charcount == 0 && !std::cin) | |
error(ERROR_END_PROG); | |
line[linelength] = 0; | |
std::cout << line << std::endl; | |
line[linelength] = ' '; | |
linecount++; // count lines | |
linelength++; // | |
} | |
ch = toupper(line[charcount]); | |
charcount++; // count characters | |
return ch; | |
} | |
// ------------------------------------------- | |
// This is our GETSYM | |
// ------------------------------------------- | |
void getsym(symbol &sym) | |
{ | |
char ch; | |
int index = 0; | |
do | |
getchar(ch); | |
while (chartype(ch) == SPACE || chartype(ch) == EOL); | |
if (chartype(ch) == ALPHA) | |
{ | |
do | |
{ | |
line[index++] = ch; | |
getchar(ch); | |
} while (chartype(ch) == ALPHA || chartype(ch) == DIGIT || ch == '_'); | |
line[index] = '\0'; | |
charcount--; | |
if (strcmp(line, "BEGIN") == 0) | |
sym = BEGINSYM; | |
else if (strcmp(line, "CALL") == 0) | |
sym = CALL; | |
else if (strcmp(line, "CASE") == 0) | |
sym = CASESYM; | |
else if (strcmp(line, "CONST") == 0) | |
sym = CONSTSYM; | |
else if (strcmp(line, "DO") == 0) | |
sym = DOSYM; | |
else if (strcmp(line, "CEND") == 0) | |
sym = CENDSYM; | |
else if (strcmp(line, "REPEAT") == 0) | |
sym = REPEATSYM; | |
else if (strcmp(line, "FOR") == 0) | |
sym = FOR; | |
else if (strcmp(line, "UNTIL") == 0) | |
sym = UNTILSYM; | |
else if (strcmp(line, "TO") == 0) | |
sym = TOSYM; | |
else if (strcmp(line, "ELSE") == 0) | |
sym = ELSESYM; | |
else if (strcmp(line, "DOWNTO") == 0) | |
sym = DOWNTOSYM; | |
else if (strcmp(line, "WRITELN") == 0) | |
sym = WRITELNSYM; | |
else if (strcmp(line, "WRITE") == 0) | |
sym = WRITESYM; | |
else if (strcmp(line, "END") == 0) | |
sym = ENDSYM; | |
else if (strcmp(line, "IF") == 0) | |
sym = IFSYM; | |
else if (strcmp(line, "ODD") == 0) | |
sym = ODDSYM; | |
else if (strcmp(line, "OF") == 0) | |
sym = OFSYM; | |
else if (strcmp(line, "PROCEDURE") == 0) | |
sym = PROCSYM; | |
else if (strcmp(line, "THEN") == 0) | |
sym = THENSYM; | |
else if (strcmp(line, "VAR") == 0) | |
sym = VARSYM; | |
else if (strcmp(line, "WHILE") == 0) | |
sym = WHILESYM; | |
else if (strcmp(line, "FUNCTION") == 0) | |
sym = FUNCSYM; | |
//MODIFIED | |
else if (strcmp(line, "AND") == 0) | |
sym = AND; | |
else if (strcmp(line, "OR") == 0) | |
sym = OR; | |
else if (strcmp(line, "NOT") == 0) | |
sym = NOT; | |
//END MODIFIED | |
else | |
sym = IDENT; | |
strcpy(symstr[sym], line); | |
return; | |
} | |
if (chartype(ch) == DIGIT) | |
{ | |
char strnum[10]; | |
sym = NUMBER; | |
number = 0; | |
do | |
{ | |
strnum[index++] = ch; | |
number = 10 * number + int(ch - 48); | |
getchar(ch); | |
} while (chartype(ch) == DIGIT); | |
charcount--; | |
strnum[index] = '\0'; | |
strcpy(symstr[sym], strnum); | |
return; | |
} | |
if (chartype(ch) == PUNCT) | |
{ | |
punc[index++] = ch; | |
if (ch == ':' || ch == '<' || ch == '>') | |
{ | |
getchar(ch); | |
if (chartype(ch) == PUNCT && (ch == '=') || (ch == '>')) | |
punc[index++] = ch; | |
else | |
charcount--; | |
} | |
punc[index] = '\0'; | |
if (strcmp(punc, ":=") == 0) | |
sym = ASSIGN; | |
else if (strcmp(punc, ":") == 0) | |
sym = COLON; | |
else if (strcmp(punc, ",") == 0) | |
sym = COMMA; | |
else if (strcmp(punc, "/") == 0) | |
sym = DIV; | |
else if (strcmp(punc, "=") == 0) | |
sym = EQL; | |
else if (strcmp(punc, ">=") == 0) | |
sym = GREQL; | |
else if (strcmp(punc, ">") == 0) | |
sym = GRTHEN; | |
else if (strcmp(punc, "(") == 0) | |
sym = LPAREN; | |
else if (strcmp(punc, "<=") == 0) | |
sym = LSEQL; | |
else if (strcmp(punc, "<") == 0) | |
sym = LSTHEN; | |
else if (strcmp(punc, "-") == 0) | |
sym = MINUS; | |
else if (strcmp(punc, "*") == 0) | |
sym = MULT; | |
else if (strcmp(punc, "<>") == 0) | |
sym = NOTEQL; | |
else if (strcmp(punc, ".") == 0) | |
sym = PERIOD; | |
else if (strcmp(punc, "+") == 0) | |
sym = PLUS; | |
else if (strcmp(punc, ")") == 0) | |
sym = RPAREN; | |
else if (strcmp(punc, ";") == 0) | |
sym = SEMICOLON; | |
strcpy(symstr[sym], punc); | |
return; | |
} | |
} | |
// ------------------------------------------- | |
// determine a character type | |
// ------------------------------------------- | |
intype chartype(char ch) | |
{ | |
if (ch == '\n' || ch == '\r') | |
return EOL; // character END-OF-LINE | |
if (isspace(ch)) | |
return SPACE; // character SPACE | |
if (isdigit(ch)) | |
return DIGIT; // character DIGIT | |
if (isalpha(ch)) | |
return ALPHA; // character ALPHA | |
if (ispunct(ch)) | |
return PUNCT; // character PUNCTUATION | |
return NONE; | |
} | |
// ------------------------------------------- | |
// Find the base | |
// ------------------------------------------- | |
int base(int lev, int basereg, int stack[stack[]]) | |
{ | |
int base1; | |
for (base1 = basereg; lev > 0; base1 = stack[base1], lev--); | |
return base1; | |
} | |
// ------------------------------------------- | |
// This is our Interpreter | |
// ------------------------------------------- | |
//You'll also need to change the top, base, and position variables inside of Interpret to be arrays too. Don't forget to change the stuff in your Base function. | |
void interpret(void) | |
{ | |
// You'll need to go into your Interpret() function and change everything to work through a stack of stacks. (stackz on stackz on stackz). | |
// So you'll have an array with 4 arrays inside of it, pretty much. Each of those will be a full "stack" unto itself. | |
int progreg[] = 0, basereg[] = 0, top[] = 0, stack[ stack[MAX_STACK] ] = { 0 }; | |
pcodetable inst; | |
std::cout << std::endl << "Start PL/0" << std::endl; | |
do | |
{ | |
inst = pcode[progreg]; | |
progreg++; | |
switch (inst.function) | |
{ | |
case LIT: | |
top++; | |
stack[top] = inst.adr; | |
continue; | |
case OPR: | |
switch (inst.adr) | |
{ | |
case 0: | |
top = basereg - 1; | |
basereg = stack[ stack[top + 2] ]; | |
progreg = stack[ stack[top + 3] ]; | |
continue; | |
case 1: | |
stack[ stack[top] ] = -stack[ stack[top] ]; | |
continue; | |
case 2: | |
top--; | |
stack[ stack[top] ] = stack[ stack[top] ] + stack[ stack[top + 1] ]; | |
continue; | |
case 3: | |
top--; | |
stack[ stack[top] ] = stack[ stack[top] ] - stack[ stack[top + 1] ]; | |
continue; | |
case 4: | |
top--; | |
stack[ stack[top] ] = stack[ stack[top] ] * stack[ stack[top + 1] ]; | |
continue; | |
case 5: | |
top--; | |
stack[ stack[top] ] = stack[ stack[top] ] / stack[ stack[top + 1] ]; | |
continue; | |
case 6: | |
stack[ stack[top] ] = (stack[ stack[top] % 2 > 0 ]); | |
continue; | |
case 8: | |
top--; | |
stack[ stack[top] ] = (stack[ stack[top] ] == stack[ stack[top + 1] ]); | |
continue; | |
case 9: | |
top--; | |
stack[ stack[top] ] = (stack[ stack[top] ] != stack[ stack[top + 1] ]); | |
continue; | |
case 10: | |
top--; | |
stack[ stack[top] ] = (stack[ stack[top] ] < stack[ stack[top + 1] ]); | |
continue; | |
case 11: | |
top--; | |
stack[ stack[top] ] = (stack[ stack[top] ] >= stack[ stack[top + 1] ]); | |
continue; | |
case 12: | |
top--; | |
stack[ stack[top] ] = (stack[ stack[top] ] > stack[ stack[top + 1] ]); | |
continue; | |
case 13: | |
top--; | |
stack[top] = (stack[top] <= stack[top + 1]); | |
continue; | |
// Begin Modified ------- | |
case 14: | |
std::cout << stack[top] << " "; | |
top--; | |
continue; | |
case 15: | |
std::cout << std::endl; | |
//top--; | |
continue; | |
// End Modified ------- | |
} | |
continue; | |
case LOD: | |
top++; | |
stack[top] = stack[base(inst.level, basereg, stack) + inst.adr]; | |
continue; | |
case STO: | |
stack[base(inst.level, basereg, stack) + inst.adr] = stack[top]; | |
top--; | |
continue; | |
case CAL: | |
stack[top + 1] = base(inst.level, basereg, stack); | |
stack[top + 2] = basereg; | |
stack[top + 3] = progreg; | |
basereg = top + 1; | |
progreg = inst.adr; | |
continue; | |
case INT: | |
top = top + inst.adr; | |
continue; | |
case JMP: | |
progreg = inst.adr; | |
continue; | |
case JPC: | |
if (stack[top] == inst.level) | |
progreg = inst.adr; | |
top--; | |
continue; | |
case CTS: | |
top++; | |
stack[top] = stack[top - 1]; | |
continue; | |
} | |
} while (progreg != 0); | |
std::cout << "End PL/0\n"; | |
} | |
// ------------------------------------------- | |
// This shows our PCODE | |
// ------------------------------------------- | |
void showpcode(void) | |
{ | |
int startpoint; | |
startpoint = codeinx0; | |
std::cout << std::endl; | |
for (int i = startpoint; i < codeinx; ++i) | |
{ | |
std::cout << i << " "; | |
switch (pcode[i].function) | |
{ | |
case CAL: | |
std::cout << "CAL "; | |
break; | |
case INT: | |
std::cout << "INT "; | |
break; | |
case JMP: | |
std::cout << "JMP "; | |
break; | |
case JPC: | |
std::cout << "JPC "; | |
break; | |
case LIT: | |
std::cout << "LIT "; | |
break; | |
case LOD: | |
std::cout << "LOD "; | |
break; | |
case OPR: | |
std::cout << "OPR "; | |
break; | |
case STO: | |
std::cout << "STO "; | |
break; | |
case CTS: | |
std::cout << "CTS "; | |
break; | |
} | |
std::cout << pcode[i].level << ' ' << pcode[i].adr << std::endl; | |
} | |
} | |
// ------------------------------------------- | |
// This is our main program entry | |
// ------------------------------------------- | |
int main(int argc, char* argv[]) | |
{ | |
symbol sym; | |
int i; | |
char filen[40]; | |
FILE *stream; | |
// Initialize some variables | |
linelength = 0; | |
charcount = 0; | |
linecount = 0; | |
codeinx = 0; | |
freopen_s(&stream, "Output.txt", "w", stdout); | |
getsym(sym); // get the first symbol | |
block(sym, 0, 0); // start processing | |
std::cout << "\nSuccessful compilation!\n"; | |
interpret(); | |
return 0; | |
} | |
On Thu, Apr 10, 2014 at 8:08 PM, Kyle Rebstock <[email protected]> wrote : | |
// ------------------------------------------- | |
// Program: pascomp.cc (Version 1.8)//modified since 1.8 This is compiler before val/ref feature | |
// | |
// Description: This is a pascal like compiler with low-level code implementation. | |
// Student: Kyle Jackson Rebstock | |
// ID: 713599 | |
// Date: February 8, 2014 | |
// ------------------------------------------- | |
//#include <fstream.h> // for handling files | |
#include <ctype.h> | |
#include <stdlib.h> | |
#include <string> | |
#include <iomanip> | |
#include <iostream> | |
// ------------------------------------------- | |
// These are some global definitions | |
// ------------------------------------------- | |
#define TRUE 1 | |
#define FALSE 0 | |
#define MAX_TABLE 500 | |
#define MAX_PCODE 1000 | |
#define MAX_SYMBOL 47 | |
#define MAX_SYM_SZ 20 | |
#define MAX_PRAMS 31 | |
#define MAX_STACK 1000 | |
// ------------------------------------------- | |
// These are some ERROR definitions | |
// ------------------------------------------- | |
#define ERROR_SEMICOLON 1 | |
#define ERROR_IDENT 2 | |
#define ERROR_UNKNOWN 3 | |
#define ERROR_ASSIGN 4 | |
#define ERROR_ASSIGN_PROC 5 | |
#define ERROR_PROCEDURE 6 | |
#define ERROR_END_SYM 7 | |
#define ERROR_DO_SYM 8 | |
#define ERROR_THEN_SYM 9 | |
#define ERROR_UNTIL_SYM 10 | |
#define ERROR_VARIABLE 11 | |
#define ERROR_OF_SYM 12 | |
#define ERROR_CONSTANT 13 | |
#define ERROR_COLON 14 | |
#define ERROR_RPAREN 15 | |
#define ERROR_IS_PROCEDURE 16 | |
#define ERROR_REL 17 | |
#define ERROR_PROG_SIZE 18 | |
#define ERROR_END_PROG 19 | |
#define ERROR_NUMBER 20 | |
#define ERROR_IDENT_VAR 22 | |
#define ERROR_LPAREN 23 | |
#define ERROR_UNTIL 25 | |
#define ERROR_TO_DOWNTO 26 | |
#define ERROR_OF 27 | |
#define ERROR_NUMBER_IDENT 28 | |
#define ERROR_CEND 29 | |
#define ERROR_NOPROCEDURE 30 | |
#define ERROR_VAR 31 | |
#define ERROR_ASSIGN 32 | |
//Begin Modified | |
#define ERROR_FUNC 33 | |
#define ERROR_FUNCLEVEL 34 | |
//End Modified | |
// ------------------------------------------- | |
// some enumerated data types | |
// ------------------------------------------- | |
typedef enum tag_symbol | |
{ | |
VARSYM, | |
CONSTSYM, | |
BEGINSYM, | |
ENDSYM, | |
CENDSYM, | |
PERIOD, | |
SEMICOLON, | |
COLON, | |
LPAREN, | |
RPAREN, | |
GRTHEN, | |
LSTHEN, | |
GREQL, | |
LSEQL, | |
EQL, | |
ASSIGN, | |
IFSYM, | |
IDENT, | |
NUMBER, | |
WRITESYM, | |
WRITELNSYM, | |
PROCSYM, | |
NOTEQL, | |
MINUS, | |
PLUS, | |
DIV, | |
MULT, | |
COMMA, | |
ODDSYM, | |
CALL, | |
ELSESYM, | |
THENSYM, | |
WHILESYM, | |
DOSYM, | |
REPEATSYM, | |
UNTILSYM, | |
CASESYM, | |
OFSYM, | |
CEND, | |
FOR, | |
DOWNTOSYM, | |
TOSYM, | |
FUNCSYM, | |
OR, | |
AND, | |
NOT, | |
COBEGIN, //MODIFIED COBEGIN" and "COEND | |
COEND //MODIFIED COBEGIN" and "COEND | |
}symbol; | |
// ------------------------------------------- | |
typedef enum tag_Objtype | |
{ | |
NOTYPE, | |
CONSTANT, | |
VARIABLE, | |
PROCEDURE, | |
FUNCTION //Modified | |
}Objtype; | |
// ------------------------------------------- | |
typedef enum tag_psyms | |
{ | |
OPR, | |
CAL, | |
INT, | |
JPC, | |
JMP, | |
LIT, | |
LOD, | |
STO, | |
CTS | |
}psyms; | |
typedef enum tag_intype | |
{ | |
ALPHA, | |
DIGIT, | |
EOL, | |
NONE, | |
PUNCT, | |
SPACE | |
}intype; | |
// ------------------------------------------- | |
typedef struct tag_symtable // Symbols Table Structure | |
{ | |
char name[MAX_SYM_SZ]; // Symbol name | |
Objtype kind; // Type of symbol | |
int value, // Value of symbol | |
level, // Level of symbol | |
adr; // Symbol address | |
}symtable; | |
// ------------------------------------------- | |
typedef struct tag_pcodetable // PCODE Table Structure | |
{ | |
psyms function; // pcode function | |
int level, // pcode level static link | |
adr; // pcode address number into table | |
}pcodetable;//used to save the compile code | |
// ------------------------------------------- | |
// These are some global variables | |
// ------------------------------------------- | |
int linelength, // line length | |
linecount, // line counter | |
charcount, // a character counter | |
codeinx, // pcode index counter inc everytime | |
codeinx0, // init pcode index | |
varcount0, // Init variable counter | |
number; | |
symbol prevsym; // holds the previous symbol | |
symbol toORdowntonsym; | |
symbol writesym; | |
symbol gensym; | |
symbol expsym; | |
symbol termsym; | |
symtable table[MAX_TABLE]; // table array | |
pcodetable pcode[MAX_PCODE]; // pcode table | |
char line[MAX_SYM_SZ]; // an identification string | |
char punc[MAX_SYM_SZ]; // punction array | |
char symstr[MAX_SYMBOL][MAX_SYM_SZ]; // symbols array | |
// ------------------------------------------- | |
// These are some function prototypes | |
// ------------------------------------------- | |
void block(symbol &, int, int); | |
void statement(symbol &, int, int); | |
void genexp(symbol &, int, int); | |
void expression(symbol &, int, int); | |
void term(symbol &, int, int); | |
void factor(symbol &, int, int); | |
char getchar(char &); | |
void getsym(symbol &); | |
intype chartype(char ch); | |
void enter(Objtype, char[], symbol &, int &, int, int &); | |
int base(int, int, int &); | |
void gen(psyms, int, int); | |
void interpret(void); | |
int position(int); | |
void showpcode(void); | |
void openfile(void); | |
void error(int); | |
// ------------------------------------------- | |
// This handles our system errors | |
// ------------------------------------------- | |
void error(int num) | |
{ | |
std::cout << std::endl; | |
switch (num) | |
{ | |
case ERROR_NOPROCEDURE: | |
std::cout << "Procedure not accepted here"; | |
break; | |
case ERROR_CEND: | |
std::cout << "cend sym expected"; | |
break; | |
case ERROR_NUMBER_IDENT: | |
std::cout << "number or ident expected"; | |
break; | |
case ERROR_OF: | |
std::cout << "of expected"; | |
break; | |
case ERROR_TO_DOWNTO: | |
std::cout << "to or downto expected"; | |
break; | |
case ERROR_UNTIL: | |
std::cout << "Until expected"; | |
break; | |
case ERROR_ASSIGN: | |
std::cout << "Assignment operator expected"; | |
break; | |
case ERROR_ASSIGN_PROC: | |
std::cout << "Assignment not allowed here"; | |
break; | |
case ERROR_COLON: | |
std::cout << "COLON Expected"; | |
break; | |
case ERROR_CONSTANT: | |
std::cout << "Constant Expected"; | |
break; | |
case ERROR_END_PROG: | |
std::cout << "Premature end of program"; | |
break; | |
case ERROR_DO_SYM: | |
std::cout << "DO symbol Expected"; | |
break; | |
case ERROR_END_SYM: | |
std::cout << "END symbol Expected"; | |
break; | |
case ERROR_REL: | |
std::cout << "Relational operator expected"; | |
break; | |
case ERROR_IDENT: | |
std::cout << "Identifier Expected"; | |
break; | |
case ERROR_IS_PROCEDURE: | |
std::cout << "Assignment to PROCEDURE not allowed"; | |
break; | |
case ERROR_NUMBER: | |
std::cout << "A number was Expected"; | |
break; | |
case ERROR_PROG_SIZE: | |
std::cout << "Program size is too large..."; | |
break; | |
case ERROR_OF_SYM: | |
std::cout << "OF symbol Expected"; | |
break; | |
case ERROR_RPAREN: | |
std::cout << "RIGHT Parenthesis Expected"; | |
break; | |
case ERROR_LPAREN: | |
std::cout << "LEFT Parenthesis Expected"; | |
break; | |
case ERROR_SEMICOLON: | |
std::cout << "Semicolon Expected"; | |
break; | |
case ERROR_THEN_SYM: | |
std::cout << "THEN symbol Expected"; | |
break; | |
case ERROR_UNKNOWN: | |
std::cout << "Unknown Identifier"; | |
break; | |
case ERROR_UNTIL_SYM: | |
std::cout << "UNTIL symbol Expected"; | |
break; | |
case ERROR_VARIABLE: | |
std::cout << "Variable or Expression Expected"; | |
break; | |
case ERROR_IDENT_VAR: | |
std::cout << "Ident - Variable Expected"; | |
break; | |
case ERROR_VAR: | |
std::cout << "VAR Expected"; | |
break; | |
//Begin Modified | |
case ERROR_FUNCLEVEL: | |
std::cout << "Must be inside function body"; | |
break; | |
case ERROR_FUNC: | |
std::cout << "Function Expected"; | |
break; | |
//End Modified | |
} | |
std::cout << std::endl; | |
exit(1); | |
} | |
// ------------------------------------------- | |
// Insert Block Identifier | |
// ------------------------------------------- | |
void enter(Objtype kind, char name[], symbol &sym, int &varcount, int level, int &tableinx) | |
{ | |
tableinx++; | |
strcpy(table[tableinx].name, name); | |
table[tableinx].kind = kind; | |
if (kind == CONSTANT) | |
{ | |
if (sym != IDENT) | |
error(ERROR_IDENT); | |
getsym(sym); | |
if (sym != EQL) | |
error(ERROR_ASSIGN); | |
getsym(sym); | |
if (sym != NUMBER) | |
error(ERROR_NUMBER); | |
table[tableinx].value = number;//for const only value matters | |
} | |
else if ((kind == VARIABLE)) | |
{ | |
if (sym != IDENT) | |
error(ERROR_IDENT); | |
table[tableinx].level = level; // store variable level for static link level | |
table[tableinx].adr = varcount++; // store address offset from base | |
} | |
else if (kind == PROCEDURE) | |
table[tableinx].level = level; // store procedure level | |
//Begin Modified | |
else if (kind == FUNCTION) | |
if (sym != IDENT) | |
error(ERROR_IDENT); | |
table[tableinx].level = level; // store funciton level | |
//End Modified | |
getsym(sym); | |
} | |
// ------------------------------------------- | |
// Locate Position | |
// ------------------------------------------- | |
int position(int tableinx) | |
{ | |
int i = tableinx; | |
for (strcpy(table[0].name, line); strcmp(table[i].name, line) != 0; i--); | |
return i; | |
} | |
// ------------------------------------------- | |
// Block | |
// ------------------------------------------- | |
void block(symbol &sym, int level, int tableinx) | |
{ //this is our dx, set to 3 for static link | |
int varcount = 3; //,dynamic link,and return address implicitly set | |
int count = 0; | |
// save symbol table count used to | |
int tableinx0 = tableinx; //fix after CONST,VAR,and PROCEDURES DECLARE | |
table[tableinx].adr = codeinx; // save pcode code index | |
gen(JMP, 0, 0); // Generate our init JMP Function,level,adr in pcode table | |
while (sym == CONSTSYM || sym == VARSYM || sym == PROCSYM || sym == FUNCSYM) | |
{ | |
if (sym == CONSTSYM) | |
{ | |
// ---- CONSTANT SYM ---- | |
getsym(sym); | |
enter(CONSTANT, line, sym, varcount, level, tableinx); | |
while (sym == COMMA) | |
{ | |
getsym(sym); | |
enter(CONSTANT, line, sym, varcount, level, tableinx);//int tableinx for all,set value of table line = name | |
} | |
if (sym != SEMICOLON) | |
error(ERROR_SEMICOLON); | |
getsym(sym); | |
} | |
// ---- VARIABLE SYM ---- | |
if (sym == VARSYM) | |
{ | |
getsym(sym); | |
enter(VARIABLE, line, sym, varcount, level, tableinx);//inc (dx) varcount and tableinx,used for INT 0,varcount | |
while (sym == COMMA) | |
{ | |
getsym(sym); | |
enter(VARIABLE, line, sym, varcount, level, tableinx); | |
} | |
if (sym != SEMICOLON) | |
error(ERROR_SEMICOLON); | |
getsym(sym); | |
} | |
// ---- PROCEDURE SYM ---- | |
//BEGIN MODIFIED | |
while (sym == PROCSYM || sym == FUNCSYM) //Procedure or Function | |
{ | |
prevsym = sym; //Save sym | |
getsym(sym); | |
if (sym != IDENT) | |
error(ERROR_IDENT); | |
//If sym = procedure then enter procedure | |
if (prevsym == PROCSYM){ | |
enter(PROCEDURE, line, sym, varcount, level, tableinx);//int tableinx and add level | |
} | |
//If sym = function enter function | |
if (prevsym == FUNCSYM){ | |
enter(FUNCTION, line, sym, varcount, level, tableinx);//int tableinx and add level | |
} | |
if (sym != SEMICOLON) | |
error(ERROR_SEMICOLON); | |
getsym(sym); | |
block(sym, level + 1, tableinx);//inc static link for functions inside of functions, table current pointer | |
if (sym != SEMICOLON) | |
error(ERROR_SEMICOLON); | |
getsym(sym); | |
} | |
//End Modified | |
} | |
pcode[table[tableinx0].adr].adr = codeinx;//tableinx0 is used to fix the original jump when u go into a block | |
table[tableinx0].adr = codeinx; | |
codeinx0 = codeinx; //fix proc addr in ST | |
gen(INT, 0, varcount);//inc the top of the stack by 3 + number of variable | |
statement(sym, level, tableinx); // ident can also now be a function and now stores variables and handles function storing | |
gen(OPR, 0, 0); | |
showpcode(); | |
} | |
// ------------------------------------------- | |
// Statement | |
// ------------------------------------------- | |
void statement(symbol &sym, int level, int tableinx) | |
{ | |
int i, i3, cx1, cx2, cx3, cx4, i2, cx5, cx6, cx7, cx8, cxa, cxb; | |
int first; | |
bool FirstCase = true; | |
int count = 0; | |
switch (sym) | |
{ | |
// IDENT | |
case IDENT: | |
i = position(tableinx); | |
if (i == 0) | |
error(ERROR_UNKNOWN); | |
switch (table[i].kind) | |
{ | |
case VARIABLE: | |
getsym(sym); | |
if (sym != ASSIGN) | |
error(ERROR_ASSIGN); | |
getsym(sym); | |
expression(sym, level, tableinx);//8 * B2 *example* put 8 and B2 onto stack and run OPR | |
gen(STO, level - table[i].level, table[i].adr); | |
break; | |
//Begin Modified | |
case FUNCTION: | |
getsym(sym); | |
if (sym != ASSIGN) | |
error(ERROR_ASSIGN); | |
getsym(sym); | |
expression(sym, level, tableinx);//8 * B2 *example* put 8 and B2 onto stack and run OPR | |
if (i == tableinx){ // if kind is function | |
gen(STO, 0, -1); // then STO 0, -1 | |
} | |
else | |
error(ERROR_FUNCLEVEL); | |
break; | |
default: | |
error(ERROR_ASSIGN_PROC); | |
//End Modified | |
} | |
break; | |
// PROCEDURE CALL | |
case CALL: | |
getsym(sym); | |
if (sym != IDENT) | |
error(ERROR_IDENT); | |
i = position(tableinx); | |
if (i == 0) | |
error(ERROR_UNKNOWN); | |
if (table[i].kind != PROCEDURE) | |
error(ERROR_PROCEDURE); | |
getsym(sym); | |
gen(CAL, level - table[i].level, table[i].adr); | |
break; | |
// BEGIN and END block | |
case BEGINSYM: | |
getsym(sym); | |
statement(sym, level, tableinx); | |
while (sym == SEMICOLON) | |
{ | |
getsym(sym); | |
statement(sym, level, tableinx); | |
} | |
if (sym != ENDSYM) | |
error(ERROR_END_SYM); | |
getsym(sym); | |
break; | |
// WHILE SYMBOL | |
case WHILESYM: | |
getsym(sym); | |
cx1 = codeinx; | |
genexp(sym, level, tableinx); | |
cx2 = codeinx; | |
gen(JPC, 0, 0); | |
if (sym != DOSYM) | |
error(ERROR_DO_SYM); | |
getsym(sym); | |
statement(sym, level, tableinx); | |
gen(JMP, 0, cx1); | |
pcode[cx2].adr = codeinx; | |
break; | |
// IF - THEN - ELSE //Modified | |
case IFSYM: | |
getsym(sym); | |
genexp(sym, level, tableinx); | |
cxa = codeinx; //Save cx1 | |
gen(JPC, 0, 0); // JPC 0,0 | |
if (sym != THENSYM) | |
error(ERROR_THEN_SYM); | |
getsym(sym); | |
statement(sym, level, tableinx); | |
pcode[cxa].adr = codeinx; //Fix JPC @ cx1 | |
/* add your code for ELSE here */ | |
if (sym == ELSESYM) // Begin Modified ----- | |
{ | |
getsym(sym); | |
cxb = codeinx; //Save cx2 | |
gen(JMP, 0, 0); //JMP 0,0 | |
pcode[cxa].adr = codeinx; //Fix JPC @ cx1 | |
statement(sym, level, tableinx); | |
pcode[cxb].adr = codeinx; //Fix JMP @ cx2 | |
} | |
//End Modified ------- | |
break; | |
case REPEATSYM: | |
/* add your code for REPEAT-UNTIL here */ | |
// Begin Modified ------- | |
cx1 = codeinx; //Save cx | |
do { | |
getsym(sym); | |
statement(sym, level, tableinx); | |
} while (sym == SEMICOLON); | |
if (sym != UNTILSYM) | |
error(ERROR_UNTIL_SYM); | |
getsym(sym); | |
genexp(sym, level, tableinx); | |
gen(JPC, 0, cx1); //JPC 0,cx | |
break; | |
case FOR: | |
/* add your code for FOR-DO here */ | |
getsym(sym); | |
if (sym != IDENT) | |
error(ERROR_IDENT_VAR); | |
i3 = position(tableinx); | |
if (i3 == 0) | |
error(ERROR_VAR); | |
if (table[i3].kind != VARIABLE) | |
error(ERROR_VAR); | |
getsym(sym); | |
if (sym != ASSIGN) | |
error(ERROR_ASSIGN); | |
getsym(sym); | |
expression(sym, level, tableinx); | |
gen(STO, level - table[i3].level, table[i3].adr); //STO | |
if (sym != TOSYM && sym != DOWNTOSYM) | |
error(ERROR_TO_DOWNTO); | |
toORdowntonsym = sym; //Save sym | |
getsym(sym); | |
expression(sym, level, tableinx); | |
//Modified | |
cx7 = codeinx; //Save cx7 | |
gen(CTS, 0, 0); //CTS 0,0 | |
gen(LOD, level - table[i3].level, table[i3].adr); //LOD | |
if (toORdowntonsym == TOSYM) //If sym is TO | |
gen(OPR, 0, 11); //OPR 0, >= | |
else if (toORdowntonsym == DOWNTOSYM) //If sym is DOWNTO | |
gen(OPR, 0, 13); //OPR 0, <= | |
cx8 = codeinx; //Save cx8 | |
gen(JPC, 0, 0); //JPC 0,0 | |
//End Mod | |
if (sym != DOSYM) | |
error(ERROR_DO_SYM); | |
getsym(sym); | |
statement(sym, level, tableinx); | |
//Modified | |
gen(LOD, level - table[i3].level, table[i3].adr); //LOD | |
gen(LIT, 0, 1); //LIT 0,1 | |
if (toORdowntonsym == TOSYM) //If sym is TO | |
gen(OPR, 0, 2); //OPR 0, + | |
else if (toORdowntonsym == DOWNTOSYM) //If sym is DOWNTO | |
gen(OPR, 0, 3); //OPR 0,- | |
gen(STO, level - table[i3].level, table[i3].adr); //STO | |
gen(JMP, 0, cx7); //JMP 0,cx7 | |
pcode[cx8].adr = codeinx; //fix JPC @ cx8 | |
gen(INT, 0, -1); //INT 0,-1 | |
//End Mod | |
break; | |
case CASESYM: | |
/* add your code for CASE here */ | |
//Begin Modified ------ | |
getsym(sym); | |
i2 = position(tableinx); | |
expression(sym, level, tableinx); | |
if (sym != OFSYM) | |
error(ERROR_OF_SYM); | |
getsym(sym); | |
while (sym == NUMBER || sym == IDENT) { | |
if (sym == IDENT) | |
{ | |
i2 = position(tableinx); | |
if (i2 == 0) | |
error(ERROR_VAR); | |
if (table[i2].kind != CONSTANT) | |
error(ERROR_CONSTANT); | |
} | |
//getsym(sym); | |
gen(CTS, 0, 0); // CTS 0,0 | |
if (sym == NUMBER) | |
gen(LIT, 0, number); //If Number then LIT 0,num | |
else if (sym == CONSTANT) | |
gen(LIT, 0, table[i2].value); //If constant then LIT 0, table[i].value | |
gen(OPR, 0, 8); //OPR 0,= | |
cx5 = codeinx; //Save cx5 | |
gen(JPC, 0, 0); // JPC 0,0 | |
getsym(sym); | |
if (sym != COLON) | |
error(ERROR_COLON); | |
getsym(sym); | |
statement(sym, level, tableinx); | |
if (sym != SEMICOLON) | |
error(ERROR_SEMICOLON); | |
if (FirstCase == true){ | |
cx6 = codeinx; //Save cx6 | |
gen(JMP, 0, 0); //JMP 0,0 | |
FirstCase = false; | |
} | |
else { | |
gen(JMP, 0, cx6); //JMP 0,cx6 | |
} | |
pcode[cx5].adr = codeinx; //fix JPC @ cx5 | |
getsym(sym); | |
} | |
if (sym != CENDSYM) | |
error(ERROR_CEND); | |
pcode[cx6].adr = codeinx; //fix JPC @ cx6 | |
gen(INT, 0, -1);// int 0,-1 | |
getsym(sym); | |
break; | |
//End Modified ------ | |
case WRITESYM: | |
/* add your code for WRITE here */ | |
//Begin Modified ------ | |
writesym = sym; //Save sym | |
getsym(sym); | |
if (sym != LPAREN) | |
error(ERROR_LPAREN); | |
do { | |
getsym(sym); | |
expression(sym, level, tableinx); | |
gen(OPR, 0, 14); //OPR 0,14 | |
} while (sym == COMMA); | |
if (sym != RPAREN) | |
error(ERROR_RPAREN); | |
getsym(sym); | |
/*if (prevsym == WRITELNSYM) | |
gen(OPR, 0, 15);*/ | |
// End Modified ------- | |
break; | |
case WRITELNSYM: | |
/* add your code for WRITELN here */ | |
// Begin Modified ------- | |
writesym = sym; //Save sym | |
getsym(sym); | |
if (sym != LPAREN) | |
error(ERROR_LPAREN); | |
do { | |
getsym(sym); | |
expression(sym, level, tableinx); | |
gen(OPR, 0, 14); //OPR 0,14 | |
} while (sym == COMMA); | |
if (sym != RPAREN) | |
error(ERROR_RPAREN); | |
getsym(sym); | |
//if (prevsym == WRITELNSYM) //If sym is writeln | |
gen(OPR, 0, 15); //OPR 0,15 | |
break; | |
// End Modified ------- | |
} // END of SWITCH | |
} | |
// ------------------------------------------- | |
// genexp | |
// ------------------------------------------- | |
//Modified from "condition" to "genexp" | |
void genexp(symbol &sym, int level, int tableinx) | |
{ | |
symbol gensym; | |
// ODD symbol | |
if (sym == ODDSYM) | |
{ | |
getsym(sym); | |
expression(sym, level, tableinx); | |
gen(OPR, 0, 6); | |
} | |
else | |
{ | |
expression(sym, level, tableinx); | |
if ((sym == EQL) || (sym == NOTEQL) || (sym == LSTHEN) || (sym == LSEQL) || (sym == GRTHEN) || (sym == GREQL)) | |
{ | |
gensym = sym; | |
getsym(sym); | |
expression(sym, level, tableinx); | |
switch (gensym) | |
{ | |
case EQL: | |
gen(OPR, 0, 8); | |
break; | |
case GREQL: | |
gen(OPR, 0, 11); | |
break; | |
case GRTHEN: | |
gen(OPR, 0, 12); | |
break; | |
case LSEQL: | |
gen(OPR, 0, 13); | |
break; | |
case LSTHEN: | |
gen(OPR, 0, 10); | |
break; | |
case NOTEQL: | |
gen(OPR, 0, 9); | |
break; | |
} | |
//may need to save sym, call expression, then gen(OPR, 0, symop)------------------------------------------? | |
} | |
//Modified | |
//General Experession doesn't have to be a relational operator, it can be nothing | |
//else error(ERROR_REL); | |
} | |
} | |
// ------------------------------------------- | |
// Expression | |
// ------------------------------------------- | |
void expression(symbol &sym, int level, int tableinx) | |
{ | |
symbol expsym; | |
if ((sym == PLUS) || (sym == MINUS)) | |
{ | |
expsym = sym; | |
getsym(sym); // save sym | |
term(sym, level, tableinx); | |
if (expsym == MINUS) | |
gen(OPR, 0, 1); | |
} | |
else | |
term(sym, level, tableinx); | |
//Begin Modified | |
//Add or sym | |
while (sym == PLUS || sym == MINUS || sym == OR) | |
{ | |
expsym = sym; | |
getsym(sym); | |
term(sym, level, tableinx); | |
if (expsym == MINUS) | |
gen(OPR, 0, 3); | |
else | |
gen(OPR, 0, 2);//Can be + or "OR" | |
} | |
//End modified | |
} | |
// ------------------------------------------- | |
// TERM | |
// ------------------------------------------- | |
void term(symbol &sym, int level, int tableinx) | |
{ | |
symbol termsym; | |
factor(sym, level, tableinx); | |
//Modified | |
while ((sym == MULT) || (sym == DIV) || (sym == AND)) | |
{ | |
termsym = sym; // save sym | |
getsym(sym); | |
factor(sym, level, tableinx); | |
if (termsym == DIV) | |
gen(OPR, 0, 5); | |
else // else if (sym == MULT) | |
gen(OPR, 0, 4);//Can be * or "AND" | |
//End Modified | |
} | |
} // End Void term | |
// ------------------------------------------- | |
// FACTOR | |
// ------------------------------------------- | |
void factor(symbol &sym, int level, int tableinx) | |
{ | |
int i; | |
int count = 0; | |
switch (sym) | |
{ | |
// IDENTIFER | |
case IDENT: | |
i = position(tableinx); | |
if (i == 0) | |
error(ERROR_UNKNOWN); | |
//Modified | |
if (table[i].kind == PROCEDURE || table[i].kind == FUNCTION) | |
error(ERROR_IS_PROCEDURE); | |
switch (table[i].kind) | |
{ | |
case VARIABLE: | |
gen(LOD, level - table[i].level, table[i].adr); | |
break; | |
case CONSTANT: | |
gen(LIT, 0, table[i].value); | |
break; | |
} | |
getsym(sym); | |
break; | |
// NUMBER | |
case NUMBER: | |
gen(LIT, 0, number); | |
getsym(sym); | |
break; | |
// LEFT PARENTHESE | |
case LPAREN: | |
getsym(sym); | |
genexp(sym, level, tableinx); | |
if (sym != RPAREN) | |
error(ERROR_RPAREN); | |
getsym(sym); | |
break; | |
case CALL: | |
getsym(sym); | |
i = position(tableinx); | |
if (i == 0) | |
error(ERROR_UNKNOWN); | |
/*if (sym != FUNCSYM || sym != PROCSYM) | |
error(ERROR_FUNC);*/ | |
if (sym != IDENT) | |
error(ERROR_IDENT); | |
if (table[i].kind != FUNCTION) | |
error(ERROR_FUNC); | |
gen(INT, 0, 1); //INT 0,1 | |
gen(CAL, level - table[i].level, table[i].adr);// Call | |
getsym(sym); | |
break; | |
case NOT: | |
getsym(sym); | |
factor(sym, level, tableinx); | |
gen(LIT, 0, 0); // Lit 0 and check inequality | |
gen(OPR, 0, 8); // opr, = | |
break; | |
default: | |
error(ERROR_VARIABLE); | |
} | |
//End Modified | |
} | |
// ------------------------------------------- | |
// Generate the PCODE | |
// ------------------------------------------- | |
void gen(psyms function, int level, int adr) | |
{ | |
if (codeinx > MAX_PCODE) | |
error(ERROR_PROG_SIZE); | |
pcode[codeinx].function = function; | |
pcode[codeinx].level = level; | |
pcode[codeinx].adr = adr; | |
codeinx++; | |
} | |
// ------------------------------------------- | |
// This is our GET CHARACTER function | |
// ------------------------------------------- | |
char getchar(char &ch) | |
{ | |
static char line[255]; // local array | |
if (charcount == linelength) | |
{ | |
charcount = linelength = 0; // zero out counters | |
std::cin.get(ch); | |
while (chartype(ch) != EOL && std::cin) | |
{ | |
line[linelength] = ch; | |
std::cin.get(ch); | |
linelength++; | |
} | |
if (linelength == 0 && charcount == 0 && !std::cin) | |
error(ERROR_END_PROG); | |
line[linelength] = 0; | |
std::cout << line << std::endl; | |
line[linelength] = ' '; | |
linecount++; // count lines | |
linelength++; // | |
} | |
ch = toupper(line[charcount]); | |
charcount++; // count characters | |
return ch; | |
} | |
// ------------------------------------------- | |
// This is our GETSYM | |
// ------------------------------------------- | |
void getsym(symbol &sym) | |
{ | |
char ch; | |
int index = 0; | |
do | |
getchar(ch); | |
while (chartype(ch) == SPACE || chartype(ch) == EOL); | |
if (chartype(ch) == ALPHA) | |
{ | |
do | |
{ | |
line[index++] = ch; | |
getchar(ch); | |
} while (chartype(ch) == ALPHA || chartype(ch) == DIGIT || ch == '_'); | |
line[index] = '\0'; | |
charcount--; | |
if (strcmp(line, "BEGIN") == 0) | |
sym = BEGINSYM; | |
else if (strcmp(line, "CALL") == 0) | |
sym = CALL; | |
else if (strcmp(line, "CASE") == 0) | |
sym = CASESYM; | |
else if (strcmp(line, "CONST") == 0) | |
sym = CONSTSYM; | |
else if (strcmp(line, "DO") == 0) | |
sym = DOSYM; | |
else if (strcmp(line, "CEND") == 0) | |
sym = CENDSYM; | |
else if (strcmp(line, "REPEAT") == 0) | |
sym = REPEATSYM; | |
else if (strcmp(line, "FOR") == 0) | |
sym = FOR; | |
else if (strcmp(line, "UNTIL") == 0) | |
sym = UNTILSYM; | |
else if (strcmp(line, "TO") == 0) | |
sym = TOSYM; | |
else if (strcmp(line, "ELSE") == 0) | |
sym = ELSESYM; | |
else if (strcmp(line, "DOWNTO") == 0) | |
sym = DOWNTOSYM; | |
else if (strcmp(line, "WRITELN") == 0) | |
sym = WRITELNSYM; | |
else if (strcmp(line, "WRITE") == 0) | |
sym = WRITESYM; | |
else if (strcmp(line, "END") == 0) | |
sym = ENDSYM; | |
else if (strcmp(line, "IF") == 0) | |
sym = IFSYM; | |
else if (strcmp(line, "ODD") == 0) | |
sym = ODDSYM; | |
else if (strcmp(line, "OF") == 0) | |
sym = OFSYM; | |
else if (strcmp(line, "PROCEDURE") == 0) | |
sym = PROCSYM; | |
else if (strcmp(line, "THEN") == 0) | |
sym = THENSYM; | |
else if (strcmp(line, "VAR") == 0) | |
sym = VARSYM; | |
else if (strcmp(line, "WHILE") == 0) | |
sym = WHILESYM; | |
else if (strcmp(line, "FUNCTION") == 0) | |
sym = FUNCSYM; | |
//MODIFIED | |
else if (strcmp(line, "AND") == 0) | |
sym = AND; | |
else if (strcmp(line, "OR") == 0) | |
sym = OR; | |
else if (strcmp(line, "NOT") == 0) | |
sym = NOT; | |
//END MODIFIED | |
else | |
sym = IDENT; | |
strcpy(symstr[sym], line); | |
return; | |
} | |
if (chartype(ch) == DIGIT) | |
{ | |
char strnum[10]; | |
sym = NUMBER; | |
number = 0; | |
do | |
{ | |
strnum[index++] = ch; | |
number = 10 * number + int(ch - 48); | |
getchar(ch); | |
} while (chartype(ch) == DIGIT); | |
charcount--; | |
strnum[index] = '\0'; | |
strcpy(symstr[sym], strnum); | |
return; | |
} | |
if (chartype(ch) == PUNCT) | |
{ | |
punc[index++] = ch; | |
if (ch == ':' || ch == '<' || ch == '>') | |
{ | |
getchar(ch); | |
if (chartype(ch) == PUNCT && (ch == '=') || (ch == '>')) | |
punc[index++] = ch; | |
else | |
charcount--; | |
} | |
punc[index] = '\0'; | |
if (strcmp(punc, ":=") == 0) | |
sym = ASSIGN; | |
else if (strcmp(punc, ":") == 0) | |
sym = COLON; | |
else if (strcmp(punc, ",") == 0) | |
sym = COMMA; | |
else if (strcmp(punc, "/") == 0) | |
sym = DIV; | |
else if (strcmp(punc, "=") == 0) | |
sym = EQL; | |
else if (strcmp(punc, ">=") == 0) | |
sym = GREQL; | |
else if (strcmp(punc, ">") == 0) | |
sym = GRTHEN; | |
else if (strcmp(punc, "(") == 0) | |
sym = LPAREN; | |
else if (strcmp(punc, "<=") == 0) | |
sym = LSEQL; | |
else if (strcmp(punc, "<") == 0) | |
sym = LSTHEN; | |
else if (strcmp(punc, "-") == 0) | |
sym = MINUS; | |
else if (strcmp(punc, "*") == 0) | |
sym = MULT; | |
else if (strcmp(punc, "<>") == 0) | |
sym = NOTEQL; | |
else if (strcmp(punc, ".") == 0) | |
sym = PERIOD; | |
else if (strcmp(punc, "+") == 0) | |
sym = PLUS; | |
else if (strcmp(punc, ")") == 0) | |
sym = RPAREN; | |
else if (strcmp(punc, ";") == 0) | |
sym = SEMICOLON; | |
strcpy(symstr[sym], punc); | |
return; | |
} | |
} | |
// ------------------------------------------- | |
// determine a character type | |
// ------------------------------------------- | |
intype chartype(char ch) | |
{ | |
if (ch == '\n' || ch == '\r') | |
return EOL; // character END-OF-LINE | |
if (isspace(ch)) | |
return SPACE; // character SPACE | |
if (isdigit(ch)) | |
return DIGIT; // character DIGIT | |
if (isalpha(ch)) | |
return ALPHA; // character ALPHA | |
if (ispunct(ch)) | |
return PUNCT; // character PUNCTUATION | |
return NONE; | |
} | |
// ------------------------------------------- | |
// Find the base | |
// ------------------------------------------- | |
int base(int lev, int basereg, int stack[]) | |
{ | |
int base1; | |
for (base1 = basereg; lev > 0; base1 = stack[base1], lev--); | |
return base1; | |
} | |
// ------------------------------------------- | |
// This is our Interpreter | |
// ------------------------------------------- | |
void interpret(void) | |
{ | |
int progreg = 0, basereg = 0, top = 0, stack[MAX_STACK] = { 0 }; | |
pcodetable inst; | |
std::cout << std::endl << "Start PL/0" << std::endl; | |
do | |
{ | |
inst = pcode[progreg]; | |
progreg++; | |
switch (inst.function) | |
{ | |
case LIT: | |
top++; | |
stack[top] = inst.adr; | |
continue; | |
case OPR: | |
switch (inst.adr) | |
{ | |
case 0: | |
top = basereg - 1; | |
basereg = stack[top + 2]; | |
progreg = stack[top + 3]; | |
continue; | |
case 1: | |
stack[top] = -stack[top]; | |
continue; | |
case 2: | |
top--; | |
stack[top] = stack[top] + stack[top + 1]; | |
continue; | |
case 3: | |
top--; | |
stack[top] = stack[top] - stack[top + 1]; | |
continue; | |
case 4: | |
top--; | |
stack[top] = stack[top] * stack[top + 1]; | |
continue; | |
case 5: | |
top--; | |
stack[top] = stack[top] / stack[top + 1]; | |
continue; | |
case 6: | |
stack[top] = (stack[top] % 2 > 0); | |
continue; | |
case 8: | |
top--; | |
stack[top] = (stack[top] == stack[top + 1]); | |
continue; | |
case 9: | |
top--; | |
stack[top] = (stack[top] != stack[top + 1]); | |
continue; | |
case 10: | |
top--; | |
stack[top] = (stack[top] < stack[top + 1]); | |
continue; | |
case 11: | |
top--; | |
stack[top] = (stack[top] >= stack[top + 1]); | |
continue; | |
case 12: | |
top--; | |
stack[top] = (stack[top] > stack[top + 1]); | |
continue; | |
case 13: | |
top--; | |
stack[top] = (stack[top] <= stack[top + 1]); | |
continue; | |
// Begin Modified ------- | |
case 14: | |
std::cout << stack[top] << " "; | |
top--; | |
continue; | |
case 15: | |
std::cout << std::endl; | |
//top--; | |
continue; | |
// End Modified ------- | |
} | |
continue; | |
case LOD: | |
top++; | |
stack[top] = stack[base(inst.level, basereg, stack) + inst.adr]; | |
continue; | |
case STO: | |
stack[base(inst.level, basereg, stack) + inst.adr] = stack[top]; | |
top--; | |
continue; | |
case CAL: | |
stack[top + 1] = base(inst.level, basereg, stack); | |
stack[top + 2] = basereg; | |
stack[top + 3] = progreg; | |
basereg = top + 1; | |
progreg = inst.adr; | |
continue; | |
case INT: | |
top = top + inst.adr; | |
continue; | |
case JMP: | |
progreg = inst.adr; | |
continue; | |
case JPC: | |
if (stack[top] == inst.level) | |
progreg = inst.adr; | |
top--; | |
continue; | |
case CTS: | |
top++; | |
stack[top] = stack[top - 1]; | |
continue; | |
} | |
} while (progreg != 0); | |
std::cout << "End PL/0\n"; | |
} | |
// ------------------------------------------- | |
// This shows our PCODE | |
// ------------------------------------------- | |
void showpcode(void) | |
{ | |
int startpoint; | |
startpoint = codeinx0; | |
std::cout << std::endl; | |
for (int i = startpoint; i < codeinx; ++i) | |
{ | |
std::cout << i << " "; | |
switch (pcode[i].function) | |
{ | |
case CAL: | |
std::cout << "CAL "; | |
break; | |
case INT: | |
std::cout << "INT "; | |
break; | |
case JMP: | |
std::cout << "JMP "; | |
break; | |
case JPC: | |
std::cout << "JPC "; | |
break; | |
case LIT: | |
std::cout << "LIT "; | |
break; | |
case LOD: | |
std::cout << "LOD "; | |
break; | |
case OPR: | |
std::cout << "OPR "; | |
break; | |
case STO: | |
std::cout << "STO "; | |
break; | |
case CTS: | |
std::cout << "CTS "; | |
break; | |
} | |
std::cout << pcode[i].level << ' ' << pcode[i].adr << std::endl; | |
} | |
} | |
// ------------------------------------------- | |
// This is our main program entry | |
// ------------------------------------------- | |
int main(int argc, char* argv[]) | |
{ | |
symbol sym; | |
int i; | |
char filen[40]; | |
FILE *stream; | |
// Initialize some variables | |
linelength = 0; | |
charcount = 0; | |
linecount = 0; | |
codeinx = 0; | |
freopen_s(&stream, "Output.txt", "w", stdout); | |
getsym(sym); // get the first symbol | |
block(sym, 0, 0); // start processing | |
std::cout << "\nSuccessful compilation!\n"; | |
interpret(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment