#ifndef _scan_h_ #define _scan_h_ #include #include #include #include "util.h" using namespace std; /* * Token scanner object for the recursive descent parser. Breaks the input * stream into the tokens described below, essentially identifiers, integer * constants, and some operators. */ /* A token has a code number and the string it actually represents. */ class Scanner { public: /* These are code numbers for each token type. */ enum tok_code { tok_id, // An identifier, L(L|D)* tok_lit, // A literal: an unsigned integer number. tok_left, // A left paren. tok_right, // A right paren tok_splat, // An asterisk tok_slash, // A slash tok_plus, // A plus sign tok_minus, // A minus sign or dash tok_asst, // An assignment symbol, := tok_semi, // A semicolon. tok_EOF // END-of-file. }; // The tokens returned by the scanner are of this type. class Token: public ParserObject { public: tok_code code() const { return m_code; } string text() const { return m_text; } void pr(ostream &s, int indent) const { s << spaces(indent) << m_codenames[m_code] << "(" << m_text << ")"; } Token(): m_code(tok_EOF), m_text("Uninitialized") { } Token(tok_code c, string t): m_code(c), m_text(t) { } private: tok_code m_code; string m_text; }; /* Get the current token. */ const Token & curr_tok() const { return m_curr; } /* Move forward one token, and return the new current token. */ const Token & next_tok(); /* Create the scanner. Remembers the stream, and reads the first token from it, which can be recovered with curr_token(). */ Scanner(istream &strm): m_in(strm) { next_tok(); } private: /* Reference to the underlying input stream. */ istream &m_in; /* Current token. */ Token m_curr; /* String names to correspond to the token codes */ static const char *m_codenames[]; }; // Class for scanner execeptions. class BadInputCharacter: public runtime_error { public: BadInputCharacter(char ch): runtime_error("Bad input character '" + ch_to_str(ch) + "'") { } private: string ch_to_str(char ch) { char ret[2] = { ch, 0 }; return ret; } }; #endif