Link to home
Start Free TrialLog in
Avatar of morales7_0
morales7_0

asked on

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)
Avatar of jkr
jkr
Flag of Germany image

Could you provide a sample "token.txt"? It's hard to test that without an input file...
Avatar of morales7_0
morales7_0

ASKER

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

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
ASKER CERTIFIED SOLUTION
Avatar of jkr
jkr
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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