/* Lex.cpp - Very simple lexical analyzer for an equally simple * 'desk calculator' language. * * Essentially breaks the input stream up into a series of tokens, * returning the token code */ #include #include #include using namespace std; #include "Lex.h" namespace Lex { // Code for end of file const int ENDOFFILE = -1; // Code for a numeric constant (cur_val() returns the value) const int NUMBER = 128; // Code for a symbol (cur_sym() returns the name) const int SYMBOL = 129; // Keyword token codes const int SET_KW = 130; const int FUN_KW = 131; // State information static double val = 0.0; static string sym; static int token = 0; const string & cur_sym() { // Return current symbol, token==SYMBOL return sym; } int cur_tok() { // Return current token return token; } double cur_val() { // Return current value, token==NUMBER return val; } int get_next(istream &input) // Get next token from input { char ch; double intpart=0; double exponent=1; int after=0; // # of digits after decimal point int before=0; // # of digits before decimal point sym = ""; // Reset the state as needed val = 0.0; input.get(ch); // Get first character while (ch <= ' ' && ch != '\n') { // Skip whitespace if (!input.good()) { return (token = ENDOFFILE); } input.get(ch); } switch (ch) { case '+': // Characters (not all are supported) case '-': case '*': case '/': case '(': case ')': case '}': case '{': case '=': case '>': case '<': case '\n': return (token = ch); default: if (ch >= 'a' && ch <= 'z') { // Symbol or keyword while (ch >= 'a' && ch <= 'z') { sym += ch; input.get(ch); } input.putback(ch); if (sym == "fun") { return (token = FUN_KW); } if (sym == "set") { return (token = SET_KW); } return (token = SYMBOL); } else if (ch >= '0' && ch <= '9') { // Numeric constant intpart = 0; exponent = 0; while (ch >= '0' && ch <= '9') { intpart = (intpart * 10) + (ch - '0'); // Convert from ASCII before++; input.get(ch); } if (ch == '.') { // Is there a fractional part? input.get(ch); while (ch >= '0' && ch <= '9') { // Gather fraction intpart = (intpart * 10) + (ch - '0'); // Convert from ASCII after++; input.get(ch); } } if (ch == 'e' || ch == 'E') { // Is there an exponent? input.get(ch); while (ch >= '0' && ch <= '9') { // Gather exponent exponent = (exponent * 10) + (ch - '0'); input.get(ch); } } if (after > 0) { exponent -= after; } if (after + before < 1) { cerr << "Need at least one digit in number\n"; } val = intpart * pow(10, exponent); input.putback(ch); return (token = NUMBER); } else { cerr << "Illegal input character: " << (int)ch << endl; return (token = 0); // Illegal value } break; } } } /* End namespace */