//
// scanner.cpp
//
// Copyright (C) 1996 by Dan Saks.
// May be copied for private, non-commercial use,
// provided this copyright notice remains intact.
// All other rights reserved.
//
#include <ctype.h>
#include <iostream>
#include <string.h>
#include "scanner.h"
#define DIM(a) (sizeof(a)/sizeof(a[0]))
scanner::pair const scanner::keyword[] =
{
{ "bool", token::TYPE_KEYWORD },
{ "char", token::TYPE_KEYWORD },
{ "const", token::CONST },
{ "double", token::TYPE_KEYWORD },
{ "float", token::TYPE_KEYWORD },
{ "int", token::TYPE_KEYWORD },
{ "void", token::TYPE_KEYWORD },
{ "volatile", token::VOLATILE },
{ "wchar_t", token::TYPE_KEYWORD }
};
token scanner::get()
{
if (next_token.kind() != token::NO_VALUE)
{
current_token = next_token;
next_token = token();
}
else
{
previous_token = current_token;
current_token = scan();
}
return current_token;
}
token scanner::unget()
{
next_token = current_token;
return current_token = previous_token;
}
token scanner::scan()
{
int c;
token::category kind;
string text;
while (isspace(c = in_stream.get()))
;
//
// scan an integer-literal
//
if (isdigit(c))
{
kind = token::INT_LITERAL;
do
{
text += char(c);
c = in_stream.get();
}
while (isdigit(c));
in_stream.putback(c);
}
//
// scan an identifier, a name, or a type-keyword
//
else if (isalpha(c) || c == '_')
{
kind = token::IDENTIFIER;
do
{
text += char(c);
c = in_stream.get();
}
while (isalnum(c) || c == '_');
in_stream.putback(c);
if (isupper(text[0]))
kind = token::NAME;
else
for (int i = 0; i < DIM(keyword); ++i)
if (text == keyword[i].text)
{
kind = keyword[i].kind;
break;
}
}
//
// scan a scope-resolution operator
//
else if (c == ':')
{
if ((c = in_stream.get()) != ':')
{
in_stream.putback(c);
kind = token::NO_SUCH;
text = ":";
}
else
{
kind = token::SCOPE;
text = "::";
}
}
//
// scan a single-character operator
//
else if (strchr("*&[]();,", c) != 0)
{
kind = token::category(c);
text = char(c);
}
//
// scan end-of-file
//
else if (c == EOF)
kind = token::NO_MORE;
//
// there's no such token
//
else
{
kind = token::NO_SUCH;
text = char(c);
}
return token(kind, text);
}
const char *image(token::category tc)
{
switch (tc)
{
case token::AMPERSAND:
return "&";
case token::COMMA:
return ",";
case token::LEFT_BRACKET:
return "[";
case token::LEFT_PAREN:
return "(";
case token::RIGHT_BRACKET:
return "]";
case token::RIGHT_PAREN:
return ")";
case token::SEMICOLON:
return ";";
case token::STAR:
return "*";
case token::NO_MORE:
return "end of input";
case token::SCOPE:
return "::";
case token::INT_LITERAL:
return "int literal";
case token::IDENTIFIER:
return "identifier";
case token::NAME:
return "name";
case token::TYPE_KEYWORD:
return "type keyword";
case token::CONST:
return "const";
case token::VOLATILE:
return "volatile";
}
return "no such token";
}