// COMPILER.CPP // // // PROGRAM BY LOUIS GUZIK STUDENT #58831 SPRING 1995 // // // // GRADE:_____ // // // // COMMENTS:_______________________________________________________________ // // _______________________________________________________________ // // _______________________________________________________________ // // _______________________________________________________________ // // _______________________________________________________________ // // ///////////////////////////////////////////////////////////////////////////// #define LINE_MAX 40 // MAX CHARACTERS PER LINE #include #include #include "hashtbl.h" HashTable SymbolTbl; #include "arraytbl.h" ArrayTable StringTbl; #include "token.h" Token *TokenList; #include "list.h" List *ErrorList; // FUNCTIONS Token *Lex( char LineBuff[ 256 ], int LineNumb ); void Gen_Code( void ); void Execute( void ); void Accept( void ); void Reject( int code ); Token *Read( Token * ); void S( void ); void S_Special( void ); // if ? = ? READ, WRITE, ASSIGN void A( void ); // VARIABLES int LineNumb = 0; // LINE NUMBER COUNTER int WarnCount = 0; int ErrorCount = 0; int Parser_Error = 0; int Statement_Error = -1; static Token *inp; // POINTER TO A TOKEN char ErrorTable[ 20 ][ 80 ]; int DEBUG = 0; int PC = 36; // Program Counter int Accum; // accumalator const MEM_END = 150; int Memory[ MEM_END ]; /*/ MY STATIC MEMORY ---------------------------- | 0 - 9 : 10 CONSTANTS | |--------------------------| | 10 - 35 : 26 VARS | |--------------------------| | 36 : START of CODE | |--------------------------| | MEM_END : END of MEM | ---------------------------- /*/ void main() { // **** DECLARE VARIABLES FILE *fpinput; Token *tptr; // POINTER TO A TOKEN int i; char inflname[ 16 ]; char LineBuff[ 256 ]; // USED FOR GETTING STRING FROM KEYBOARD // INIT MEMORY for( i=0; i> LineBuff; if( LineBuff[0] == 'Y' || LineBuff[0] == 'y' ) DEBUG = 1; cout << "\n Input Source File =>" << inflname << "<= Is this OK (Y or N) ?\b"; fflush( stdin ); cin >> LineBuff; if( LineBuff[ 0 ] == 'N' || LineBuff[ 0 ] == 'n' ) { cout << " Enter new file ==>"; cin >> LineBuff; strcpy( inflname, LineBuff ); } if( (fpinput = fopen( inflname, "r" )) != (FILE *) NULL ) cout << "\n Input Source File =>" << inflname << "<= \n\n"; else { cout << " BAD FILE OPEN =>" << inflname << "<= \n\n"; cout << "\nEnd of Compiler. Louis Guzik Spring 1995 \n\n"; exit( 1 ); } // BEGIN - SINGLE PASS COMPILER // // **** SCAN INPUT FILE LINE BY LINE rewind( fpinput ); while( (fgets( LineBuff, 256, fpinput )) != (char *) NULL ) { LineNumb++; TokenList = Lex( LineBuff, LineNumb ); // IF NOT BLANK LINE if( TokenList ) { if( DEBUG ) TokenList->Print(); // BEGIN - RECURSIVE DESCENT PARSER CODE !!! // Statement_Error = 0; inp = TokenList; S(); if( inp == NULL && !Statement_Error ) Accept(); else if( inp != NULL && !Statement_Error ) Reject( 8 ); // // END - RECURSIVE DESCENT PARSER CODE !!! // if there are NO parser errors Gen Code if( ! Parser_Error ) { Gen_Code(); } } // if( TokenList ) // **** DELETE OLD TOKEN LIST while( TokenList ) { tptr = TokenList; TokenList = TokenList->Next; delete tptr; } } // while( (fgets( LineBuff, 256, fpinput )) != (char *) NULL ) // // END - SINGLE PASS COMPILER if( DEBUG ) { cout << "\n\nSYMBOL TABLE"; SymbolTbl.PrintAll(); cout << "\n\nSTRING TABLE"; StringTbl.PrintAll(); } cout << "\n Total Lex Warnings: " << WarnCount << "\n"; while( ErrorList ) { ErrorCount++; ErrorList->Print(); ErrorList = ErrorList->Next; } cout << "\n Total Parser Errors: " << ErrorCount << "\n"; // **** CLEAN UP fclose( fpinput ); cout << "\nEnd of Compiler. Louis Guzik Spring 1995 \n\n"; // BEGIN - EXECUTION // // if there are no parser errors if( ! Parser_Error ) { Gen_Code(); // MAKE HALT THE LAST OPCODE Execute(); } // // END - EXCUTION exit( 0 ); } // ** MAIN //////////////////////////////////////////////////////////////////////////// void Execute( void ) { int i; // DUMP MEMORY if( DEBUG ) { cout << "\nEXECUTE RUN-TIME \n ADDRESS MEMORY DUMP BEFORE EXECUTE\n\t -----------------\n"; for( i=0; i> Accum; PC = PC + 2; if( DEBUG ) cout << "\nPC=" << PC << " A=" << Accum << " "; break; case 4: // WRITE cout << Accum; PC = PC + 2; if( DEBUG ) cout << "\nPC=" << PC << " A=" << Accum << " "; break; case 5: // PRINT StringTbl.Print( Accum ); PC = PC + 2; if( DEBUG ) cout << "\nPC=" << PC << " A=" << Accum << " "; break; case 6: // CMP EQUAL PC++; i = Accum - Memory[ Memory[PC] ]; if( DEBUG ) cout << "\nPC=" << PC << " A=" << Accum << " "; if( i == 0 ) // EQUAL PC = PC + 3; else PC++; if( DEBUG ) cout << "\nPC=" << PC << " A=" << Accum << " "; break; case 7: // NOT EQUAL PC++; i = Accum - Memory[ Memory[PC] ]; if( DEBUG ) cout << "\nPC=" << PC << " A=" << Accum << " "; if( i != 0 ) // NOT EQUAL PC = PC + 3; else PC++; if( DEBUG ) cout << "\nPC=" << PC << " A=" << Accum << " "; break; case 8: // ADD PC++; Accum = Accum + Memory[ Memory[PC] ]; PC++; if( DEBUG ) cout << "\nPC=" << PC << " A=" << Accum << " "; break; case 9: // SUB PC++; if( DEBUG ) cout << "\nPC=" << PC << " A=" << Accum << " "; Accum = Accum - Memory[ Memory[PC] ]; PC++; if( DEBUG ) cout << "\nPC=" << PC << " A=" << Accum << " "; break; case 10: // MUL PC++; if( DEBUG ) cout << "\nPC=" << PC << " A=" << Accum << " "; Accum = Accum * Memory[ Memory[PC] ]; PC++; if( DEBUG ) cout << "\nPC=" << PC << " A=" << Accum << " "; break; case 11: // DIV PC++; if( DEBUG ) cout << "\nPC=" << PC << " A=" << Accum << " "; if( Memory[ Memory[PC] ] != 0 ) // CANNOT DIVIDE BY ZERO { Accum = Accum / Memory[ Memory[PC] ]; PC++; } else { cout << "\n\n ERROR at RUN TIME: DIVIDE BY ZERO ERROR \n"; cout << " PC = " << PC << "\n"; PC = MEM_END; } if( DEBUG ) cout << "\nPC=" << PC << " A=" << Accum << " "; break; case 12: // JUMP PC++; if( DEBUG ) cout << "\nPC=" << PC << " A=" << Accum << " "; i = Memory[ PC ]; PC = i; if( DEBUG ) cout << "\nPC=" << PC << " A=" << Accum << " "; break; default: PC = PC + 2; //if( DEBUG ) cout << "\nEXE... PC=" << PC << " A=" << Accum << " "; break; } // switch( Memory[ PC ] } // while( Memory[ PC ] != 13 ) // while not halt if( DEBUG ) cout << "\nPC=" << PC << " A=" << Accum << " "; cout << "\n\n Program End! \n"; // //// END - EXECUTION if( DEBUG ) { cout << "\n RUN-TIME \n ADDRESS MEMORY DUMP AFTER EXECUTE\n\t -----------------\n"; for( i=0; i ASSIGN id = A; // 2 S --> COMPUTE id = A oper A; // 3 S --> WRITE id | string; // 4 S --> READ id; // 5 S --> S* // 6 S --> IF A = A S_Special; // 7 A --> id | constant; // 8 S_Special --> ASSIGN id = A; | WRITE id | string; | READ id; /* Code OpCode Operand Comment ---------------------------------------------------------------------------- 1 Load Var | Const ; Load Accumulator with address 2 Store Var ; Store from Accum. to Address 3 Read --- ; Read from Keyboard to Accum 4 Write --- ; Write Addr in Accum to CRT Screen 5 Print Str ; Print Addr of Str in Accum to CRT Screen 6 Cmp Var ; Compare Var to Accum, if Accum == Var do stmt. 7 Not Var ; Compare Var to Accum, if Accum != Var do stmt. 8 Add Var ; Add; Accum = Accum + Var 9 Sub Var ; Subtract; Accum = Accum - Var 10 Mul Var : Multiply; Accum = Accum * VAr 11 Div Var ; Divide; Accum = Accum / Var 12 Jmp Label ; Jump to a label 13 Halt --- ; End of program */ void Gen_Code( void ) { int Target; char LookaHead; Token *Tptr = TokenList; switch( Tptr->Vname[ 0 ] ) { case 'A': // ASSIGN { Memory[ PC ] = 1; // LOAD ACCUMULATOR PC++; Tptr = Tptr->Next; // Tptr now points to var Target = SymbolTbl.Get( Tptr->Vname ); // Target = Addr of Var Tptr = Tptr->Next->Next; // Tptr point to var | constant Memory[ PC ] = Tptr->Value; PC++; Memory[ PC ] = 2; // STORE from Accum PC++; Memory[ PC ] = Target; // to ADDRESS of Var PC++; break; } // case 'A': // ASSIGN case 'C': // COMPUTE { Memory[ PC ] = 1; // LOAD ACCUMULATOR PC++; Tptr = Tptr->Next; // Tptr now points to target var Target = SymbolTbl.Get( Tptr->Vname ); // Target = Addr of Var Tptr = Tptr->Next->Next; // Tptr point to source1 Memory[ PC ] = Tptr->Value; // Addr of source1 PC++; Tptr = Tptr->Next; // Tptr point to operator switch( Tptr->Vname[ 0 ] ) { case '+': Memory[ PC ] = 8; // ADD break; case '-': Memory[ PC ] = 9; // SUBTRACT break; case '*': Memory[ PC ] = 10; // MULTIPLY break; case '/': Memory[ PC ] = 11; // DIVIDE break; } PC++; Tptr = Tptr->Next; // Tptr point to source2 Memory[ PC ] = Tptr->Value; // Addr of source2 PC++; Memory[ PC ] = 2; // STORE from Accum PC++; Memory[ PC ] = Target; // to ADDRESS of Var PC++; break; } // case 'C': // COMPUTE case 'W': // WRITE { Memory[ PC ] = 1; // LOAD ACCUMULATOR PC++; Tptr = Tptr->Next; // Tptr now points to var if( Tptr->Type == 2 ) // WRITE VAR { Target = Tptr->Value; // Target = Addr of Var Memory[ PC ] = Target; // PUT ADDR IN ACCUM PC++; Memory[ PC ] = 4; // WRITE VAR whos ADDR is in Accum } else if( Tptr->Type == 5 ) // WRITE STRING { Target = Tptr->Value; // Target = Addr of String in StringTbl Memory[ PC ] = i; // PUT ADDR IN ACCUM Memory[ PC ] = Target; // PUT ADDR IN ACCUM PC++; Memory[ PC ] = 5; // PRINT STR whos ADDR is in Accum } PC++; Memory[ PC ] = 99; // LOCATION NOT USED FOR WRITE NOR FOR PRINT PC++; break; } // case 'W': // WRITE case 'R': // READ { Memory[ PC ] = 3; // READ FROM KEYBOARD TO ACCUM PC++; Memory[ PC ] = 99; // LOCATION NOT USED FOR READ PC++; Tptr = Tptr->Next; // Tptr now points to var Target = SymbolTbl.Get( Tptr->Vname ); // Target = Addr of Var Memory[ PC ] = 2; // STORE from Accum PC++; Memory[ PC ] = Target; // to ADDRESS of Var PC++; break; } // case 'R': // READ case 'I': // IF { Memory[ PC ] = 1; // LOAD ACCUMULATOR PC++; Tptr = Tptr->Next; // Tptr now points to Source var Memory[ PC ] = Tptr->Value; // addrs of the var PC++; Tptr = Tptr->Next; // Tptr point to operator switch( Tptr->Vname[ 0 ] ) { case '=': Memory[ PC ] = 6; // EQUAL break; case '!': Memory[ PC ] = 7; // NOT EQUAL break; } PC++; Tptr = Tptr->Next; // Tptr point to source2 Memory[ PC ] = Tptr->Value; // Addr of source2 PC++; LookaHead = Tptr->Next->Vname[0]; // look at what statement to execute if true Memory[ PC ] = 12; // jump if false PC++; Memory[ PC ] = PC + 5; // 4 memory locations PC++; switch( LookaHead ) { case 'W': // WRITE Memory[ PC ] = 1; // LOAD ACCUMULATOR PC++; Tptr = Tptr->Next->Next; // Tptr now points to var if( Tptr->Type == 2 ) // WRITE VAR { Target = Tptr->Value; // Target = Addr of Var Memory[ PC ] = Target; // PUT ADDR IN ACCUM PC++; Memory[ PC ] = 4; // WRITE VAR whos ADDR is in Accum } else if( Tptr->Type == 5 ) // WRITE STRING { Target = Tptr->Value; // Target = Addr of String in StringTbl Memory[ PC ] = i; // PUT ADDR IN ACCUM Memory[ PC ] = Target; // PUT ADDR IN ACCUM PC++; Memory[ PC ] = 5; // PRINT STR whos ADDR is in Accum } PC++; Memory[ PC ] = 99; // LOCATION NOT USED FOR WRITE NOR FOR PRINT PC++; break; case 'R': // READ Memory[ PC ] = 3; // READ FROM KEYBOARD TO ACCUM PC++; Memory[ PC ] = 99; // LOCATION NOT USED FOR READ PC++; Tptr = Tptr->Next->Next; // Tptr now points to var Target = SymbolTbl.Get( Tptr->Vname ); // Target = Addr of Var Memory[ PC ] = 2; // STORE from Accum PC++; Memory[ PC ] = Target; // to ADDRESS of Var PC++; break; case 'A': // ASSIGN Memory[ PC ] = 1; // LOAD ACCUMULATOR PC++; Tptr = Tptr->Next->Next; // Tptr now points to var Target = SymbolTbl.Get( Tptr->Vname ); // Target = Addr of Var Tptr = Tptr->Next->Next; // Tptr point to var | constant Memory[ PC ] = Tptr->Value; PC++; Memory[ PC ] = 2; // STORE from Accum PC++; Memory[ PC ] = Target; // to ADDRESS of Var PC++; break; } break; } // case 'I': // IF default: { Memory[ PC ] = 13; // HALT PC = 36; break; } } // switch( inp->Vname[ 0 ] ) } // Gen_Code() //////////////////////////////////////////////////////////////////////////// // RECURSIVE DESCENT PARSER CODE !!! // void Accept( void ) { Statement_Error = 0; } void Reject( int code ) { Parser_Error = 1; Statement_Error = code; if( ErrorList == NULL ) ErrorList = new List( LineNumb, code, ErrorTable[ code ] ); else ErrorList->Add( LineNumb, code, ErrorTable[ code ] ); } Token *Read( Token *inp ) { return( inp->Next ); } void A( void ) // ID | CONSTANT // RULE 8 { if( inp == NULL ) Reject( 10 ); else if( inp->Type == 2 || inp->Type == 4 ) inp = Read( inp ); else Reject( 8 ); } // TYPE // 1 = Keyword; Assign, Compute, If, Write, Print, Read // 2 = ID Variable // 3 = Operator // 4 = Numb Constant // 5 = String // 6 = EOLN // LANG. RULE // 1 S --> ASSIGN id = A; // 2 S --> COMPUTE id = A oper A; // 3 S --> WRITE id | string // 4 S --> READ id; // 5 S --> S* // 6 S --> IF A = A S_Special; // 7 A --> id | constant // 8 S_Special --> ASSIGN id = A; | WRITE id | string; | READ id; void S( void ) { if( inp->Type == 1 ) // KEYWORD { switch( inp->Vname[ 0 ] ) { case 'A': // ASSIGN // RULE 1 { inp = Read( inp ); if( inp == NULL ) Reject( 9 ); else if( strcmp(inp->Tname, "ID") == 0 ) { inp = Read( inp ); if( inp == NULL ) Reject( 9 ); else if( inp->Vname[0] == '=' ) { inp = Read( inp ); A(); if( inp == NULL ) Reject( 9 ); else if( inp->Vname[0] == ';' ) inp = Read( inp ); else Reject( 1 ); } else Reject( 1 ); } break; } // case 'A': // ASSIGN // RULE 1 case 'C': // COMPUTE // RULE 2 { inp = Read( inp ); if( inp == NULL ) Reject( 9 ); else if( strcmp(inp->Tname, "ID") == 0 ) { inp = Read( inp ); if( inp == NULL ) Reject( 9 ); else if( inp->Vname[0] == '=' ) { inp = Read( inp ); A(); if( inp == NULL ) Reject( 9 ); else if( strcmp(inp->Tname, "Oper") == 0 ) { inp = Read( inp ); A(); if( inp == NULL ) Reject( 9 ); else if( inp->Vname[0] == ';' ) inp = Read( inp ); else Reject( 2 ); } else Reject( 2 ); } else Reject( 2 ); } break; } // case 'C': // COMPUTE // RULE 2 case 'W': // WRITE // RULE 3 { inp = Read( inp ); if( inp == NULL ) Reject( 9 ); else if( strcmp(inp->Tname, "ID") == 0 || strcmp(inp->Tname, "String") == 0 ) { inp = Read( inp ); if( inp == NULL ) Reject( 9 ); else if( inp->Vname[0] == ';' ) inp = Read( inp ); else Reject( 3 ); } else Reject( 3 ); break; } // case 'W': // WRITE // RULE 3 case 'R': // READ // RULE 4 { inp = Read( inp ); if( inp == NULL ) Reject( 9 ); else if( strcmp(inp->Tname, "ID") == 0 ) { inp = Read( inp ); if( inp == NULL ) Reject( 9 ); else if( inp->Vname[0] == ';' ) inp = Read( inp ); else Reject( 4 ); } else Reject( 4 ); break; } // case 'R': // READ // RULE 4 case 'I': // IF // RULE 6 { inp = Read( inp ); A(); if( inp == NULL ) Reject( 9 ); else if( inp->Vname[0] == '=' || inp->Vname[0] == '!' ) { inp = Read( inp ); A(); S_Special(); } else Reject( 6 ); break; } // case 'I': // IF // RULE 6 default: // RULE 5 Reject( 5 ); break; } // switch inp->Vname } // if( inp->Type == 1 ) else Reject( 9 ); } // void S( void ) void S_Special( void ) { if( inp->Type == 1 ) // KEYWORD { switch( inp->Vname[ 0 ] ) { case 'A': // ASSIGN // RULE 1 { inp = Read( inp ); if( inp == NULL ) Reject( 9 ); else if( strcmp(inp->Tname, "ID") == 0 ) { inp = Read( inp ); if( inp == NULL ) Reject( 9 ); else if( inp->Vname[0] == '=' ) { inp = Read( inp ); A(); if( inp == NULL ) Reject( 9 ); else if( inp->Vname[0] == ';' ) inp = Read( inp ); else Reject( 1 ); } else Reject( 1 ); } break; } // case 'A': // ASSIGN // RULE 1 case 'W': // WRITE // RULE 3 { inp = Read( inp ); if( inp == NULL ) Reject( 9 ); else if( strcmp(inp->Tname, "ID") == 0 || strcmp(inp->Tname, "String") == 0 ) { inp = Read( inp ); if( inp == NULL ) Reject( 9 ); else if( inp->Vname[0] == ';' ) inp = Read( inp ); else Reject( 3 ); } else Reject( 3 ); break; } // case 'W': // WRITE // RULE 3 case 'R': // READ // RULE 4 { inp = Read( inp ); if( inp == NULL ) Reject( 9 ); else if( strcmp(inp->Tname, "ID") == 0 ) { inp = Read( inp ); if( inp == NULL ) Reject( 9 ); else if( inp->Vname[0] == ';' ) inp = Read( inp ); else Reject( 4 ); } else Reject( 4 ); break; } // case 'R': // READ // RULE 4 default: // RULE 5 Reject( 5 ); break; } // switch inp->Vname } // if( inp->Type == 1 ) else Reject( 9 ); } // void S_Special( void ) // //////////////////////////////////////////////////////////////////////////// Token *Lex( char LineBuff[ 256 ], int LineNumb ) { Token *Tptr; // TEMP TOKEN POINTER char Buffer[ LINE_MAX+1 ]; // +1 FOR '\0' NULL TERMINATION char Str[ LINE_MAX+1 ]; int i; int BuffEmpty; // FLAG, ARE THERE MORE CHARS IN BUFFER int Index; int StartIndex; int State; Tptr = NULL; // **** FILL BUFFER WITH NULLS for( i=0; i < LINE_MAX+1; i++ ) Buffer[ i ] = '\0'; // PREPROCESSING STRIP OUT LEADING WHITE SPACES Index = 0; while( LineBuff[ Index ] == ' ' || LineBuff[ Index ] == '\t' ) Index++; // **** LOAD BUFFER i = 0; while( LineBuff[ Index ] != '\n' && Index < LINE_MAX ) { Buffer[ i ] = LineBuff[ Index ]; Index++; i++; } // **** ARE THERE CHARS IN THE BUFFER if( Buffer[ 0 ] == '\0' ) BuffEmpty = 1; // BUFFER EMPTY else BuffEmpty = 0; // MORE CHARS // **** WHILE BUFFER IS NOT EMPTY PROCESS MORE TOKENS Index = 0; StartIndex = 0; State = 0; while( ! BuffEmpty ) // **** SCAN BUFFER CHAR BY CHAR { switch( State ) // **** SWITCH FROM HELL { // **** KEYWORDS case 0: // ** STATE 0 switch( toupper(Buffer[ Index ]) ) { case 'A': // ** STATE 1 State = 1; Index++; break; case 'C': // ** STATE 8 State = 8; Index++; break; case 'I': // ** STATE 16 State = 16; Index++; break; case 'W': // ** STATE 19 State = 19; Index++; break; case 'R': // ** STATE 25 State = 25; Index++; break; case ' ' : case '\t': State = 0; Index++; StartIndex = Index; // **** ARE THERE MORE CHARS IN THE BUFFER if( Buffer[ Index ] == '\0' ) BuffEmpty = 1; // BUFFER EMPTY break; default: State = 30; } // ** CASE 0 break; case 1: // ** STATE 1 if( toupper(Buffer[ Index ]) == 'S' ) { State = 2; Index++; } else { State = 30; Index = StartIndex; } break; case 2: // ** STATE 2 if( toupper(Buffer[ Index ]) == 'S' ) { State = 3; Index++; } else { State = 30; Index = StartIndex; } break; case 3: // ** STATE 3 if( toupper(Buffer[ Index ]) == 'I' ) { State = 4; Index++; } else { State = 30; Index = StartIndex; } break; case 4: // ** STATE 4 if( toupper(Buffer[ Index ]) == 'G' ) { State = 5; Index++; } else { State = 30; Index = StartIndex; } break; case 5: // ** STATE 5 if( toupper(Buffer[ Index ]) == 'N' ) { State = 6; Index++; } else { State = 30; Index = StartIndex; } break; case 6: // ** STATE 6 if( Buffer[ Index ] == ' ' ) { State = 7; Index++; } else { State = 30; Index = StartIndex; } break; case 7: // ** STATE 7 State = 0; StartIndex = Index; if( Tptr ) Tptr->AddToken( "KeyWord", "ASSIGN", LineNumb ); else Tptr = new Token( "KeyWord", "ASSIGN", LineNumb ); // **** ARE THERE MORE CHARS IN THE BUFFER if( Buffer[ Index ] == '\0' ) BuffEmpty = 1; // BUFFER EMPTY break; case 8: // ** STATE 8 if( toupper(Buffer[ Index ]) == 'O' ) { State = 9; Index++; } else { State = 30; Index = StartIndex; } break; case 9: // ** STATE 9 if( toupper(Buffer[ Index ]) == 'M' ) { State = 10; Index++; } else { State = 30; Index = StartIndex; } break; case 10: // ** STATE 10 if( toupper(Buffer[ Index ]) == 'P' ) { State = 11; Index++; } else { State = 30; Index = StartIndex; } break; case 11: // ** STATE 11 if( toupper(Buffer[ Index ]) == 'U' ) { State = 12; Index++; } else { State = 30; Index = StartIndex; } break; case 12: // ** STATE 12 if( toupper(Buffer[ Index ]) == 'T' ) { State = 13; Index++; } else { State = 30; Index = StartIndex; } break; case 13: // ** STATE 13 if( toupper(Buffer[ Index ]) == 'E' ) { State = 14; Index++; } else { State = 30; Index = StartIndex; } break; case 14: // ** STATE 14 if( Buffer[ Index ] == ' ' ) { State = 15; Index++; } else { State = 30; Index = StartIndex; } break; case 15: // ** STATE 15 State = 0; StartIndex = Index; if( Tptr ) Tptr->AddToken( "KeyWord", "COMPUTE", LineNumb ); else Tptr = new Token( "KeyWord", "COMPUTE", LineNumb ); // **** ARE THERE MORE CHARS IN THE BUFFER if( Buffer[ Index ] == '\0' ) BuffEmpty = 1; // BUFFER EMPTY break; case 16: // ** STATE 16 if( toupper(Buffer[ Index ]) == 'F' ) { State = 17; Index++; } else { State = 30; Index = StartIndex; } break; case 17: // ** STATE 17 if( toupper(Buffer[ Index ]) == ' ' ) { State = 18; Index++; } else { State = 30; Index = StartIndex; } break; case 18: // ** STATE 18 State = 0; StartIndex = Index; if( Tptr ) Tptr->AddToken( "KeyWord", "IF", LineNumb ); else Tptr = new Token( "KeyWord", "IF", LineNumb ); // **** ARE THERE MORE CHARS IN THE BUFFER if( Buffer[ Index ] == '\0' ) BuffEmpty = 1; // BUFFER EMPTY break; case 19: // ** STATE 19 if( toupper(Buffer[ Index ]) == 'R' ) { State = 20; Index++; } else { State = 30; Index = StartIndex; } break; case 20: // ** STATE 20 if( toupper(Buffer[ Index ]) == 'I' ) { State = 21; Index++; } else { State = 30; Index = StartIndex; } break; case 21: // ** STATE 21 if( toupper(Buffer[ Index ]) == 'T' ) { State = 22; Index++; } else { State = 30; Index = StartIndex; } break; case 22: // ** STATE 22 if( toupper(Buffer[ Index ]) == 'E' ) { State = 23; Index++; } else { State = 30; Index = StartIndex; } break; case 23: // ** STATE 23 if( Buffer[ Index ] == ' ' ) { State = 24; Index++; } else { State = 30; Index = StartIndex; } break; case 24: // ** STATE 24 State = 0; StartIndex = Index; if( Tptr ) Tptr->AddToken( "KeyWord", "WRITE", LineNumb ); else Tptr = new Token( "KeyWord", "WRITE", LineNumb ); // **** ARE THERE MORE CHARS IN THE BUFFER if( Buffer[ Index ] == '\0' ) BuffEmpty = 1; // BUFFER EMPTY break; case 25: // ** STATE 25 if( toupper(Buffer[ Index ]) == 'E' ) { State = 26; Index++; } else { State = 30; Index = StartIndex; } break; case 26: // ** STATE 26 if( toupper(Buffer[ Index ]) == 'A' ) { State = 27; Index++; } else { State = 30; Index = StartIndex; } break; case 27: // ** STATE 27 if( toupper(Buffer[ Index ]) == 'D' ) { State = 28; Index++; } else { State = 30; Index = StartIndex; } break; case 28: // ** STATE 28 if( Buffer[ Index ] == ' ' ) { State = 29; Index++; } else { State = 30; Index = StartIndex; } break; case 29: // ** STATE 29 State = 0; StartIndex = Index; if( Tptr ) Tptr->AddToken( "KeyWord", "READ", LineNumb ); else Tptr = new Token( "KeyWord", "READ", LineNumb ); // **** ARE THERE MORE CHARS IN THE BUFFER if( Buffer[ Index ] == '\0' ) BuffEmpty = 1; // BUFFER EMPTY break; // **** INDENTIFIERS case 30: // ** STATE 30 if( toupper(Buffer[ Index ]) >= 'A' && toupper(Buffer[ Index ]) <= 'Z' ) { State = 31; StartIndex = Index; } else { State = 32; } break; case 31: // ** STATE 31 Str[ 0 ] = toupper( Buffer[ Index ] ); Str[ 1 ] = '\0'; if( Tptr ) Tptr->AddToken( "ID", Str, LineNumb ); else Tptr = new Token( "ID", Str, LineNumb ); Index++; StartIndex = Index; State = 0; // **** ARE THERE MORE CHARS IN THE BUFFER if( Buffer[ Index ] == '\0' ) BuffEmpty = 1; // BUFFER EMPTY break; // **** OPERATORS case 32: // ** STATE 32 switch( Buffer[ Index ] ) { case '+': case '-': case '*': case '/': case '=': case '!': State = 33; break; default: State = 34; } // ** STATE 32 break; case 33: // ** STATE 33 Str[ 0 ] = Buffer[ Index ]; Str[ 1 ] = '\0'; if( Tptr ) Tptr->AddToken( "Oper", Str, LineNumb ); else Tptr = new Token( "Oper", Str, LineNumb ); Index++; StartIndex = Index; State = 0; // **** ARE THERE MORE CHARS IN THE BUFFER if( Buffer[ Index ] == '\0' ) BuffEmpty = 1; // BUFFER EMPTY break; // **** NUMERIC CONSTANTS case 34: // ** STATE 34 if( Buffer[ Index ] >= '0' && Buffer[ Index ] <= '9' ) { State = 35; StartIndex = Index; } else { State = 36; } break; case 35: // ** STATE 35 Str[ 0 ] = Buffer[ Index ]; Str[ 1 ] = '\0'; if( Tptr ) Tptr->AddToken( "Numb", Str, LineNumb ); else Tptr = new Token( "Numb", Str, LineNumb ); Index++; StartIndex = Index; State = 0; // **** ARE THERE MORE CHARS IN THE BUFFER if( Buffer[ Index ] == '\0' ) BuffEmpty = 1; // BUFFER EMPTY break; // **** STRINGS case 36: // ** STATE 36 if( Buffer[ Index ] == '"' ) { State = 37; Index++; i = 0; StartIndex = Index; } else { State = 39; } break; case 37: // ** STATE 37 if( Buffer[ Index ] != '"' && Buffer[ Index ] != '\0' ) { Str[ i ] = Buffer[ Index ]; Index++; i++; } else if( Buffer[ Index ] == '\0' ) { cout << "\n Lex WARNING ! MISSING CHAR \" Line Number: " << LineNumb << "\n" ; WarnCount++; State = 38; } else if( Buffer[ Index ] == '"' ) State = 38; break; case 38: Str[ i ] = '\0'; if( Tptr ) Tptr->AddToken( "String", Str, LineNumb ); else Tptr = new Token( "String", Str, LineNumb ); // **** ARE THERE MORE CHARS IN THE BUFFER if( Buffer[ Index ] == '\0' ) BuffEmpty = 1; // BUFFER EMPTY Index++; StartIndex = Index; State = 0; // **** ARE THERE MORE CHARS IN THE BUFFER if( Buffer[ Index ] == '\0' ) BuffEmpty = 1; // BUFFER EMPTY break; // **** EOLN DELIMITER case 39: // ** STATE 39 if( Buffer[ Index ] == ';' ) { State = 40; StartIndex = Index; } else { State = 41; } break; case 40: // ** STATE 40 Str[ 0 ] = Buffer[ Index ]; Str[ 1 ] = '\0'; if( Tptr ) Tptr->AddToken( "EOLN", Str, LineNumb ); else Tptr = new Token( "EOLN", Str, LineNumb ); Index++; StartIndex = Index; State = 0; // **** ARE THERE MORE CHARS IN THE BUFFER if( Buffer[ Index ] == '\0' ) BuffEmpty = 1; // BUFFER EMPTY break; case 41: // ERROR STATE WarnCount++; cout << "\n Lex WARNING ! ILLEGAL CHAR " << Buffer[ Index ] << " Line Number: " << LineNumb << "\n" ; Index++; StartIndex = Index; State = 0; // **** ARE THERE MORE CHARS IN THE BUFFER if( Buffer[ Index ] == '\0' ) BuffEmpty = 1; // BUFFER EMPTY break; default: // THIS IS A SAFETY, FOR ANYTHING I FORGOT. cout << "\n hell DEFAULT ERR, Buff==>" << Buffer[ Index ] << "<== State = " << State << "\n" ; Index++; // **** ARE THERE MORE CHARS IN THE BUFFER if( Buffer[ Index ] == '\0' ) BuffEmpty = 1; // BUFFER EMPTY exit(99); break; } // SWITCH FROM HELL } // while( ! BuffEmpty ) return( Tptr ); } // ** Lex() // ** COMPILER.CPP ////////////////////////////////////////////////////////////////////////////