Skip to content
Snippets Groups Projects
Commit bae2db4f authored by Ronald Charles Moore's avatar Ronald Charles Moore
Browse files

removed leftover

parent c4342872
Branches
Tags
No related merge requests found
// This code made available to his students by
// Prof. Ronald Moore
// https://fbi.h-da.de/personen/ronald-moore/
// mailto:ronald.moore@h-da.de
// with no warranties whatsoever!
#include <cassert>
#include <cctype> // for isspace
#include <cstdlib> // for strtod
#include <iostream>
#include <fstream>
#include <string>
// include <vector>
// ===================
// LEXICAL ANALYSIS
// The following are taken to be tokens:
// left and right parenthesis, the plus and minus characters,
// as well as asterisk and forward slash -- and numbers.
// In the script, substraction and division are not supported,
// but it seems like time to add them.
// Preliminaries and Utilities
// ============================
// Utility Types
typedef double numberType; // feel fee to change this to something else like int or float or bigint....
typedef enum Token {
tok_number = 'n',
tok_lparen = '(',
tok_rparen = ')',
tok_plus = '+',
tok_minus = '-',
tok_times = '*',
tok_div = '/',
tok_eof = 'E',
bad_tok = 'X'
} Token;
// global variables -- sue me if you don't like that!
static std::istream *input = &(std::cin); // until proven otherwise
static std::string currentLine( "" );
static int currentLineNumber = -1;
static int currentColumnNumber = 0;
static int currentTokenLength = 0;
static Token next_token; // again with the global variables...
static numberType currentNumber; // = zero....
static void printErrorMsg( const std::string Error )
{
std::cout << "ERROR on line " << currentLineNumber
<< ", column " << currentColumnNumber << " : "
<< Error << std::endl;
std::cout << currentLine;
for ( int col = 0; col < currentColumnNumber-1; col++ )
std::cout << '-';
std::cout << '^' << std::endl;
} // end printErrorMsg
// The Lexer
// ==========
static bool skippedWhiteSpace( ) { // return true if not at EOF, i.e. if skipped
while ( true ) {
int currentLineLength = currentLine.length();
while ( currentColumnNumber < currentLineLength )
if ( isspace( currentLine[ currentColumnNumber ] ) )
currentColumnNumber++;
else // if NOT isspace()
return true;
// if we're here, we're at the end of a line.
std::getline( *input, currentLine );
currentLineNumber++;
currentColumnNumber = 0;
if ( ! *input ) // EOF!!
return false;
// else, repeat!
// Which is the same as
// return skippedWhiteSpace() -- i.e. tail recursion.
};
};
static Token gettok( ) {
assert( input ); // we assume nullptr != input
if ( ! *input ) return bad_tok;
// else, we can read from input
// Skip white space, going to next line as necessary
if ( ! skippedWhiteSpace( ) ) return tok_eof;
// We're have visible text in front of us.
char currentChar = currentLine[ currentColumnNumber ];
currentColumnNumber++; // usually, but see num...
switch ( currentChar ) {
case '(' : return tok_lparen;
case ')' : return tok_rparen;
case '+' : return tok_plus;
case '-' : return tok_minus;
case '*' : return tok_times;
case '/' : return tok_div;
default :
// either we have a number in front of us, or we don't
assert( 0 < currentColumnNumber );
char *alpha = &(currentLine[ currentColumnNumber-1 ]);
// minus one because we incremented it before the switch
char *omega = nullptr; // until we call strtod...
double tmpValue = strtod( alpha, &omega );
if ( alpha == omega ) {
return bad_tok; // !!!
};
// else if strtod found a real number (or at least a double)
currentNumber = tmpValue; // let C++ do the converison
currentColumnNumber += (omega - alpha) -1;
// minus one because we incremented it before the switch
return tok_number;
}; // end switch
assert( false ); // we should never get here!
return bad_tok;
} // end gettok
// PARSING!!!
// ===========
//
// The grammar we are going to parse here is:
// Grammar:
// E → T E´
// E´ → + T E´ | - T E´ | ε
// T → F T´
// T´ → * F T´ | / F T´ | ε
// F → ( E ) | num
// Note that the recursive descent function for (e.g.) E´
// is nameded "E2ndHalf"-
// Forward Declarations
static numberType E();
static numberType E2ndHalf();
static numberType T();
static numberType T2ndHalf();
static numberType F();
// E → T E´
numberType E() { return T() + E2ndHalf(); }
// T → F T´
numberType T() { return F() * T2ndHalf(); }
// E´ → + T E´ | - T E´ | ε
numberType E2ndHalf() {
switch ( next_token ) {
case tok_plus :
next_token = gettok(); // eat +
return T() + E2ndHalf();
case tok_minus :
next_token = gettok(); // eat -
return (-1.0 * T()) + E2ndHalf();
default :
return 0.0;
};
} // end E2ndHalf
// T´ → * F T´ | / F T´ | ε
numberType T2ndHalf() {
numberType tmp, rhs, acc;
switch ( next_token ) {
case tok_times :
next_token = gettok(); // eat *
return F() * T2ndHalf();
case tok_div :
next_token = gettok(); // eat /
tmp = F();
if ( 0.0 != tmp )
return (1.0/tmp) * T2ndHalf();
// else if T() returned zero
printErrorMsg( "Division by zero!" );
// fall through to default return one
default :
return 1.0;
};
} // end T2ndHalf
// F → ( E ) | num
numberType F() {
numberType result = 0;
switch ( next_token ) {
case tok_lparen :
next_token = gettok(); // eat lparen
result = E();
if ( tok_rparen == next_token ) {
next_token = gettok(); // eat rparen
return result;
};
// else if rparen not found
printErrorMsg( "Expected Right Parenthesis" );
return 0.0;
case tok_number :
result = currentNumber; // side-effect of last gettok()
next_token = gettok(); // eat id
return result;
default :
printErrorMsg( "Expected Left Parenthesis or number" );
return 0.0;
};
}
// main (!)
// =========
int main( int argc, char **argv ) {
if (2 != argc) {
std::cerr << "Usage: " << argv[0] << " <fileName>.\n"
<< "You provided " << argc-1 << " arguments, we take exactly one (only).\n";
return( -1 );
};
// else if 1 == argc ....
std::string fileName( argv[1] );
if ( "-" != fileName ) {
static std::ifstream ifs( fileName );
input = &ifs;
}
// Prime the pump!
next_token = gettok( );
// get tokens and dump them...
while ( tok_eof != next_token ) {
std::cout << currentLineNumber << ":"
<< currentLine << std::endl;
numberType value = E( );
std::cout << "INTERPRETER: " << value << std::endl;
};
std::cout << "End Of File!" << std::endl;
return 0; // Alles klar!!!
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment