Compilers class, fun times! Minor update about what I've been doing.
Project 1 was to build our scanner function, which is used to produce tokens from our input file and hand them over to the parser.
That one was interesting, as it was my first time implementing a FSA as a table, and using a driver to go from state to state.
Today, I wrapped up the first 1/2 of my 2nd project - building a Top down parser.
Currently, it is a set of functions based on BNF productions. They are all VOID at the moment, but later this week I will have to modify them to build a parse tree.
Some snippets of code:
Code
struct parseNode {
int productionInstance;
token_t token;
struct parseNode *child1, *child2, *child3;
};
Code
struct token_t {
int tokenInstance;
std::string tokenID;
int lineNum;
};
(from scanner)
Code
/*
* Preprocessor function.
* Takes a single character to work on, and the current file stream.
* Keeps track of line numbers, normalizes case sensitivity,
* handles comment processing. Returns a tuple containing
* line # and our character back to the scanner.
*/
charTuple* preprocessor(char c, FILE *fp) {
static int lineNum = 1;
charTuple *tuple = new charTuple;
if (c == '#') {
while (1) {
c = getc(fp);
if (c == '\n') {
lineNum++;
c = ' ';
break;
}
}
}
if (c == '\n') {
lineNum++;
}
if (isalpha(c)) {
tuple->character = tolower(c);
} else {
tuple->character = c;
}
tuple->line = lineNum;
return tuple;
}
(from parser)
Code
void parser(FILE *fp) {
token_t *token = scanner(fp);
program_NT(token, fp);
if (token->tokenInstance == EOFtk) {
printf("Parse OKAY!\n");
} else {
printf("Parser Error: Source code found after 'return' token. Expected EOF.\n");
exit(1);
}
return;
}
void program_NT(token_t *token, FILE *fp) {
var_NT(token, fp);
if (token->tokenInstance == DOtk) {
delete token;
token = scanner(fp);
block_NT(token, fp);
if (token->tokenInstance == RETURNtk) {
delete token;
token = scanner(fp);
} else {
parserError(token, "return");
}
} else {
parserError(token, "do");
}
return;
}
void var_NT(token_t *token, FILE *fp) {
if (token->tokenInstance == VARtk) {
delete token;
token = scanner(fp);
if (token->tokenInstance == IDtk) {
delete token;
token = scanner(fp);
mvars_NT(token, fp);
if (token->tokenInstance == DELIMtk && token->tokenID[0] == '.') {
delete token;
token = scanner(fp);
return;
} else {
parserError(token, ".");
}
} else {
parserError(token, "ID");
}
} else {
return;
}
}
void block_NT(token_t *token, FILE *fp) {
if (token->tokenInstance == STARTtk) {
delete token;
token = scanner(fp);
var_NT(token, fp);
stats_NT(token, fp);
if (token->tokenInstance == FINISHtk) {
delete token;
token = scanner(fp);
} else {
parserError(token, "finish");
}
} else {
parserError(token, "start");
}
return;
}
(test input file we used)
Code
#test 2
var x : y .
do
start
var x .
print 2 - x .
start
var x .
print 1 .
finish
repeat [ x == 0]
start
print 2.
finish
finish
return
This post was edited by Eep on Nov 6 2014 01:29am