------------------------------------------------------------------------------
MC logo
Scanner Defintion
[^] Recursive Descent Parser
------------------------------------------------------------------------------
scan.h
#ifndef _scan_h_
#define _scan_h_

#include <stdexcept>
#include <iostream>
#include <string>
#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. */
        Token curr_tok() const { return m_curr; }

        /* Move forward one token, and return the new current token. */
        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