I have written this Parser for a formal grammar, to me it looks like it should be ok but when i tried to run it a Segmentation Error comes up - i have run valgrind its got leaks but it does come up with an error.
Can anyone spot what i am overlooking!?
Thanks very much.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ERROR(PHRASE) {fprintf(stderr, "Fatal Error %s occured in %s, line %d\n",PHRASE, __FILE__, __LINE__); exit(2);}
typedef enum {plus, minus, times, slash, lparen, rparen, fwsym, ltsym, rtsym, dosym, setsym, fromsym, tosym, alpha, number, becomes, semicolon} Symbol;
int p = 0, sizecnt;
char* str;
Symbol sym;
void getsym(void){
while(str[p] == ' ' || str[p] == '\n' || str[p] == '\r' || str[p] == '\r'){
p++;
}
switch(str[p]){
case '+':
p = p + 1;
sym = plus;
return;
case '-':
p = p + 1;
sym = minus;
return;
case '*':
p = p + 1;
sym = times;
return;
case '/':
p = p + 1;
sym = slash;
return;
case '{':
p = p + 1;
sym = lparen;
return;
case '}':
p = p + 1;
sym = rparen;
return;
case 'F':
if(str[p+1] == 'W'){
sym = fwsym;
return;
}
if(str[p+1] == 'R' && str[p+2] == 'O' && str[p+3] == 'M'){
p = p+4;
sym = fromsym;
return;
}
case 'L':
if(str[p+1] == 'T'){
p = p+2;
sym = ltsym;
return;
}
case 'R':
if(str[p+1] == 'T'){
p = p + 2;
sym = rtsym;
return;
}
case 'D':
if(str[p+1] == 'O'){
p = p + 2;
sym = dosym;
return;
}
case 'S':
if(str[p+1] == 'E' && str[p+2] == 'T'){
p = p + 3;
sym = setsym;
return;
}
case 'T':
if(str[p+1] == 'O'){
p = p + 2;
sym = tosym;
return;
}
case ':':
if(str[p+1] == '='){
p = p + 2;
sym = becomes;
return;
}
case ';':
p = p + 1;
sym = semicolon;
return;
}
if(str[p] >= 'A' && str[p] <= 'Z'){
p = p + 1;
sym = alpha;
return;
}
if(str[p] >= 0 && str[p] <= '9'){
sym = number;
return;
}
}
int accept (Symbol s){
if (sym == s){
getsym();
return 1;
}
ERROR("Unexpected Symbol");
return 0;
}
int expect (Symbol s){
if (accept(s)){
return 1;
}
ERROR("Unexpected Symbol");
return 0;
}
void var(void){
expect(alpha);
return;
}
void varnum(void){
if (accept(number)){
return;
}
else {
var();
return;
}
}
void polish (void){
if(accept(semicolon)){
return;
}
varnum();
polish();
}
void set(void){
var();
expect(becomes);
polish();
return;
}
void todo(void){
var();
expect(fromsym);
varnum();
expect(tosym);
varnum();
expect(lparen);
return;
}
void instruct(void){
getsym();
if(accept(fwsym)){
getsym();
varnum();
return;
}
else if(accept(ltsym)){
getsym();
varnum();
return;
}
else if(accept(rtsym)){
getsym();
varnum();
return;
}
else if(accept(dosym)){
getsym();
todo();
return;
}
else if(accept(setsym)){
getsym();
set();
return;
}
else{ERROR("Not A Valid Instruction");
}
}
void instructlst(void){
if(accept(rparen)){
return;
}
instruct();
instructlst();
}
void parseStart(void){
getsym();
expect(lparen);
instructlst();
}
void op(void){
expect(sym == plus || sym == minus || sym == times || sym == slash);
return;
}
int main (int argc, char *argv[]){
FILE *fin;
int c, sizecnt;
if (argc != 2){
printf ("cannot open %s <filename>\n", argv[0]);
exit(2);
}
fin = (fopen(argv[1], "r"));
if ((fin = NULL)){
ERROR("In File Input");
exit(2);
}
while(1){
c = fgetc(fin);
if (c != EOF){
sizecnt++;
}
else {
break;
}
}
str = malloc(sizecnt);
rewind(fin);
while (fscanf(fin, "%s", str/*[i++]*/) != EOF){
}
parseStart();
printf("Parsed OK");
return 0;
}