My program compiles but does not run to completion.

Here's my code for my program.  I get a source code from a text file, retrieve the tokens from the file, and see what type they are.  What my program should do is print the type and the token to another text file.  My program compiles, but when it executes I only see the messages on the screen that the file to be read and the file to written wear openned with no problem.  Then the program stops and I get an execution error which I have no clue what it means.  I've never got the chance to see if it does what it suppose to do.  Can anyone please look over my code and see what might be wrong.  Any advice or comments would be greatly appreciated!  Thanks!!!!

/*********************************************************************/
/* Marco A Morales  CS 380 Compilers 30 Nov 04                       */
/*                                                                   */
/* Parse program for the Tiny program                                */
/*                                                                   */
/*********************************************************************/
#include<ctype.h>
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<fstream>

using std::ofstream;
using std::ifstream;
using std::cout;
using std::cin;
using std::endl;

#define BMAX 256 //maximum length for the input buffer
#define MAXTL 40 //maximum lentgth of the token
#define MAXRESERVED 8

//the six states that the scanner can be in
typedef enum {START,INASSIGN,INCOMMENT,INNUM,INID,DONE}
State;

typedef enum
{ENDFILE, ERROR, // book-keeping tokens
IF, THEN, ELSE, END, REPEAT, UNTIL, READ, WRITE, // reserved words
ID, NUM, // multicharacter tokens
ASSIGN, EQ, LT, GT, PLUS, MINUS, TIMES, OVER, LPAREN, RPAREN, SEMI} // special symbols
TokenType;

static char lineBuf[BMAX]; //array to hold the a line of the Tiny file

static int linenum = 0; //counter to track the number of lines
static int bufsz = 0; //current length of array
static int EoFflag = false; //end of file flag
static int linepos = 0; //marker for the array of "lineBuf"

//modiffied functions from instructor's code
int getNxChar(); //function to get next character from  
void ungetNxChar(); //fucntion to go back if not the end of Tiny file
void getTok(); //function to determine token
void classToken ( TokenType );
void printToFile();
 
static char tokString[MAXTL+1];
 
//pointers for input and output files
FILE *tokfile, *symbfile;


//main program to use the functions from instructor's code
int main()
{
      if((tokfile = fopen("tokens.txt","rt")) == NULL) //open Tiny file
            {
                  cout<<"Error..."<<endl; //give error message if file cannot open
                  exit(0);
            }
      else
            cout<<"No Error"<<endl; //give message that file was able to be open

      if(( symbfile = fopen("symbols.txt","wt")) == NULL) //open tokens file
            {
                  cout<<"Error..."<<endl; //give error message if file cannot open
                  exit(0);
            }
      else
            cout<<"No Error"<<endl; //give message that file was able to be open
      
      while(!feof(tokfile))
      {

            getNxChar();
            ungetNxChar();
            getTok();
 
      
 
      }
            
      return 0;

} //end of main
 
//function to get token from file
int getNxChar()
{
       if(!(linepos < bufsz))
       {
             linenum++;
             
             if(fgets(lineBuf, BMAX-1, tokfile))
             {
                   fprintf(symbfile,"%4d: %s",linenum,lineBuf);
                   bufsz = strlen(lineBuf);
                   linepos = 0;
                   return lineBuf[linepos++];
             }
             else
             {
                   EoFflag = true;
                   return EOF;
             }
       }
             
       else
       {
             return lineBuf[linepos++];
       }
 
} //end of getNxChar function


//fucntion to go back if it is not the end of the Tiny file and decrement the position in array
 void ungetNxChar()
 {
             if(!EoFflag)
              linepos--;
 
 } //end of ungetNxChar function

 static struct
{ char* str;
TokenType token;
} reservedWords[MAXRESERVED]
= {{"if", IF},{"else", ELSE},{"end", END},
{"repeat", REPEAT},{"until", UNTIL},
{"read", READ},{"write", WRITE}};

//lookup identifier to see if it is a reserved word
static TokenType tokenLookUpTable (char * t)
{
      int i;
      for (i=0; i<MAXRESERVED; i++)
            if(!strcmp(t, reservedWords[i].str))
                  return reservedWords[i].token;
            return ID;
}

 //function to match up tokens
void getTok()
 {
       int tokStrInd = 0;
       TokenType currentToken;
       State state = START;
      
       bool keep, noKeep;

       noKeep = false;
      
       while (state != DONE)
       {
             int a = getNxChar();
             keep = true;

             switch(state)
             {
             case START:
                   if(isdigit(a))
                         state = INNUM;
                   else if(isalpha(a))
                         state = INID;
                   else if(a == ':')
                         state = INASSIGN;
                   else if((a == ' ')||(a == '\t')||(a == '\n'))
                         keep = false;
                   else if(a == '{')
                   {
                         keep = false;
                         state = INCOMMENT;
                   }
                   else
                   {
                         state = DONE;
                         
                         switch(a)
                         {
                         case EOF:
                               keep = false;
                               currentToken = ENDFILE;
                               break;
                         case'=':
                               currentToken = EQ;
                               break;
                         case'<':
                               currentToken = LT;
                               break;
                         case'>':
                               currentToken = GT;
                               break;
                         case'(':
                               currentToken = LPAREN;
                               break;
                         case')':
                               currentToken = RPAREN;
                               break;
                         case';':
                               currentToken = SEMI;
                               break;
                         case'+':
                               currentToken = PLUS;
                               break;
                         case'-':
                               currentToken = MINUS;
                               break;
                         case'*':
                               currentToken = TIMES;
                               break;
                         case'/':
                               currentToken = OVER;
                               break;
                         default:
                               currentToken = ERROR;
                               break;
                         }
                   }
                   break;
                                                             
             case INCOMMENT:
                   keep = false;
                   if(a == '}')
                         state = START;
                   break;
             case INASSIGN:
                   state = DONE;
                   if(a == '=')
                   currentToken = ASSIGN;
                   else
                   {
                         ungetNxChar();
                         keep = false;
                         currentToken = ERROR;
                   }
                  
                   break;
             case INNUM:
                   if(!isdigit(a))
                   {
                         ungetNxChar();
                         keep = false;
                         state = DONE;
                         currentToken = NUM;
                   }
                   break;
             case INID:
                   if(!isalpha(a))
                   {
                         ungetNxChar();
                         keep = false;
                         state = DONE;
                         currentToken = ID;
                   }
                   break;
             case DONE:
             default:
                   fprintf(symbfile,"Scanner Bug: state= %d\n", state);
                   state = DONE;
                   currentToken = ERROR;
                   break;
             }

            if((keep) && (tokStrInd <= MAXTL))
                  tokString[tokStrInd++] = (char)a;
             if(state == DONE)
             {
                   tokString[tokStrInd] = '\0';
                  
                   if(currentToken == ID)
                   {
                         currentToken = tokenLookUpTable(tokString);
                   }
                       classToken(currentToken);
                  
             }

                         
             if (noKeep)
             {
                   fprintf(tokfile,"%s","Error in source file line number:");
                   fprintf(tokfile,"%d\n",linenum);
             }

             
      }

} //end of getTok function
 

void classToken (TokenType token)
{      
 
      switch ( token)
                        {
                        case IF:
                        case THEN:
                        case ELSE:
                        case END:
                        case REPEAT:
                        case UNTIL:
                        case READ:
                        case WRITE:
                              fprintf (symbfile, "reserved word: %s\n",tokString);
                              break;
                        case ASSIGN: fprintf (symbfile, "operator: =\n"); break;
                        case LT: fprintf (symbfile, "operator: <\n"); break;
                        case GT: fprintf (symbfile, "operator: >\n"); break;
                        case EQ: fprintf (symbfile, "operator: ==\n"); break;
                        case LPAREN: fprintf (symbfile, "operator: (\n"); break;
                        case RPAREN: fprintf (symbfile, "operator: )\n"); break;
                        case SEMI: fprintf (symbfile, "operator: ;\n"); break;
                        case PLUS: fprintf (symbfile, "operator: +\n"); break;
                        case MINUS: fprintf (symbfile, "operator: -\n"); break;
                        case TIMES: fprintf (symbfile, "operator: *\n"); break;
                        case OVER: fprintf (symbfile, "operator: /\n"); break;
                        case ENDFILE: fprintf (symbfile, "operator: EOF\n"); break;
                        case NUM:
                              fprintf (symbfile, "NUM, val= %s\n", tokString);
                              break;
                        case ID:
                              fprintf (symbfile, "ID, name= %s\n", tokString);
                              break;
                        case ERROR:
                              fprintf (symbfile, "ERROR: %s\n", tokString);
                              break;
                        default: fprintf (symbfile, "Unknown token: %d\n", token);
                        }
      
      
}// end classToken (TokenType token)
morales7_0Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

jkrCommented:
Could you provide a sample "token.txt"? It's hard to test that without an input file...
0
morales7_0Author Commented:
This is a copy of the file "tokens.txt"  which are only a list of tokens.

read
x
;
if
0
<
x
then
fact
:=
1
;
repeat
fact
:=
fact
*
x
;
x
:=
x
-
1
until
x
=
0
;
write
fact
end

0
morales7_0Author Commented:
Here is a copy of the source code from the original program.  At first, the program took the tokens from this code and gave the reasult in the "tokens.txt" you see above.  After I made some modifications to dictate what type these tokens were is when the program stopped working.  

This is the "Tiny.txt" file that was used to come up with the  "tokens.txt" file.  

{ Sample program
  in TINY language-
  computes factorial
}
read x; { input an integer }
if 0 < x then { don't compute if x <= 0 }
  fact := 1;
  repeat
    fact := fact * x;
      x := x - 1
      until x = 0;
      write fact { output factorial of x }
end
0
jkrCommented:
There are two problems

- you had

#define MAXRESERVED 8

and only 7 elements in the array:

static struct
{ char* str;
TokenType token;
} reservedWords[MAXRESERVED]
= {{"if", IF},{"else", ELSE},{"end", END},
{"repeat", REPEAT},{"until", UNTIL},
{"read", READ},{"write", WRITE}};

make that

#define MAXRESERVED 7

- additionally, the lookup function nedds to be

//lookup identifier to see if it is a reserved word
static TokenType tokenLookUpTable (char * t)
{
    int i;
    for (i=0; i<MAXRESERVED-1; i++) // '-1' since indices are zero-based
         if(!strcmp(t, reservedWords[i].str))
              return reservedWords[i].token;
         return ID;
}
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
jkrCommented:
BTW, with the above changes, it does not crash and produces

   1: read
reserved word: read
   2: x
ID, name= x
   3: ;
operator: ;
   4: if
reserved word: if
   5: 0
NUM, val= 0
   6: <
operator: <
   7: x
ID, name= x
   8: then
ID, name= then
   9: fact
ID, name= fact
  10: :=
operator: =
  11: 1
NUM, val= 1
  12: ;
operator: ;
  13: repeat
reserved word: repeat
  14: fact
ID, name= fact
  15: :=
operator: =
  16: fact
ID, name= fact
  17: *
operator: *
  18: x
ID, name= x
  19: ;
operator: ;
  20: x
ID, name= x
  21: :=
operator: =
  22: x
ID, name= x
  23: -
operator: -
  24: 1
NUM, val= 1
  25: until
reserved word: until
  26: x
ID, name= x
  27: =
operator: ==
  28: 0
NUM, val= 0
  29: ;
operator: ;
  30: write
ID, name= write
  31: fact
ID, name= fact
  32: endreserved word: end
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.