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;
}

1. Learn how to indent code.

2. Learn how to use a debugger.
The debugger would trap the segfault, AND then allow you to explore the code at the point the trap happened. From that you might get more of an idea as to where it's going wrong than simply staring at the command prompt again.
It'll also allow you to single-step the code, examine data as you go, etc etc.
Truly vital you figure out how to debug your own code.

3. if(str[p] >= 0 && str[p] <= '9')
So not '0' then?

Thanks for the advice. I use Valgrind (with line numbers switched on in exe) and it has said the memory error is on line 289 (c = fgetc(fin);) any ideas?

Again thank you for any help

The Valgrind also came up as reading a NULL at address 0x0, which suggests a error in opening the file.

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;
}

Hello

As you have given the program plz try to give its output as well so that it will be easy to find the mistake
Generally SEGMENTATION FAULT oxxurs if there is mistake in a loop
so check out all loops in a program.....

while(str[p] == ' ' || str[p] == '\n' || str[p] == '\r' || str[p] == '\r'){
p++;
}


Shouldn't you also verify the end of string character? -> '\0'

This article has been dead for over six months. Start a new discussion instead.