2012-09-21 09:05:50 -05:00
|
|
|
//Lexical analyser
|
|
|
|
#include <algorithm>
|
|
|
|
#include "Scanner.h"
|
|
|
|
|
|
|
|
namespace pim
|
|
|
|
{
|
|
|
|
namespace compiler
|
|
|
|
{
|
|
|
|
Scanner::Scanner(std::stringstream & source_) :
|
|
|
|
source(source_)
|
|
|
|
{
|
|
|
|
nextCharacter();
|
|
|
|
}
|
|
|
|
|
|
|
|
Token Scanner::NextToken()
|
|
|
|
{
|
|
|
|
//Read whitespace, newlines and comments
|
|
|
|
while(
|
|
|
|
cChar == ' ' || cChar == '\t' ||
|
|
|
|
cChar == '\r' || cChar == '\n' ||
|
|
|
|
cChar == '/')
|
|
|
|
{
|
|
|
|
if(cChar == '/')
|
|
|
|
{
|
|
|
|
nextCharacter();
|
|
|
|
if(cChar == '/')
|
|
|
|
{
|
|
|
|
while(cChar != '\n' && cChar != '\r')
|
|
|
|
nextCharacter();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return Token(Token::DivideSymbol, "/", cLine);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(cChar == '\r')
|
|
|
|
{
|
|
|
|
nextCharacter();
|
|
|
|
if(cChar == '\n')
|
|
|
|
cLine++;
|
|
|
|
else
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if(cChar == '\n')
|
|
|
|
cLine++;
|
|
|
|
|
|
|
|
nextCharacter();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(std::isalpha(cChar)) //Read alphanumeric symbols
|
|
|
|
{
|
|
|
|
cToken.clear();
|
|
|
|
while(std::isalpha(cChar) || std::isdigit(cChar))
|
|
|
|
{
|
|
|
|
cToken.push_back(cChar);
|
|
|
|
nextCharacter();
|
|
|
|
}
|
|
|
|
|
|
|
|
std::transform(cToken.begin(), cToken.end(), cToken.begin(), ::tolower);
|
|
|
|
|
|
|
|
for(int i = 0; i < Token::SymbolNumber; i++)
|
|
|
|
if(Token::SymbolNames[i] == cToken)
|
|
|
|
return Token(i, cToken, cLine);
|
|
|
|
return Token(Token::Identifier, cToken, cLine);
|
|
|
|
}
|
|
|
|
else if(std::isdigit(cChar)) //Read numeric constants
|
|
|
|
{
|
|
|
|
bool decimal = false;
|
|
|
|
cToken.clear();
|
|
|
|
while(std::isdigit(cChar))
|
|
|
|
{
|
|
|
|
cToken.push_back(cChar);
|
|
|
|
nextCharacter();
|
|
|
|
}
|
|
|
|
if(cChar == '.')
|
|
|
|
{
|
|
|
|
decimal = true;
|
|
|
|
cToken.push_back(cChar);
|
|
|
|
nextCharacter();
|
|
|
|
while(std::isdigit(cChar))
|
|
|
|
{
|
|
|
|
cToken.push_back(cChar);
|
|
|
|
nextCharacter();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(decimal)
|
|
|
|
return Token(Token::DecimalConstant, cToken, cLine);
|
|
|
|
return Token(Token::IntegerConstant, cToken, cLine);
|
|
|
|
}
|
|
|
|
else if(cChar == '=')
|
|
|
|
{
|
|
|
|
nextCharacter();
|
|
|
|
if(cChar == '=')
|
|
|
|
{
|
|
|
|
nextCharacter();
|
|
|
|
return Token(Token::EqualSymbol, "==", cLine);
|
|
|
|
}
|
|
|
|
return Token(Token::AssignSymbol, "=", cLine);
|
|
|
|
}
|
|
|
|
else if(cChar == '!')
|
|
|
|
{
|
|
|
|
nextCharacter();
|
|
|
|
if(cChar == '=')
|
|
|
|
return Token(Token::NotEqualSymbol, "==", cLine);
|
|
|
|
}
|
|
|
|
else if(cChar == '(')
|
|
|
|
{
|
|
|
|
nextCharacter();
|
|
|
|
return Token(Token::LeftBracket, "(", cLine);
|
|
|
|
}
|
|
|
|
else if(cChar == ')')
|
|
|
|
{
|
|
|
|
nextCharacter();
|
|
|
|
return Token(Token::RightBracket, ")", cLine);
|
|
|
|
}
|
|
|
|
else if(cChar == '/')
|
|
|
|
{
|
|
|
|
nextCharacter();
|
|
|
|
return Token(Token::DivideSymbol, "/", cLine);
|
|
|
|
}
|
|
|
|
else if(cChar == '*')
|
|
|
|
{
|
|
|
|
nextCharacter();
|
|
|
|
return Token(Token::MultiplySymbol, "*", cLine);
|
|
|
|
}
|
|
|
|
else if(cChar == '+')
|
|
|
|
{
|
|
|
|
nextCharacter();
|
|
|
|
return Token(Token::PlusSymbol, "+", cLine);
|
|
|
|
}
|
|
|
|
else if(cChar == '-')
|
|
|
|
{
|
|
|
|
nextCharacter();
|
|
|
|
return Token(Token::MinusSymbol, "-", cLine);
|
|
|
|
}
|
|
|
|
else if(cChar == '%')
|
|
|
|
{
|
|
|
|
nextCharacter();
|
|
|
|
return Token(Token::ModuloSymbol, "%", cLine);
|
|
|
|
}
|
|
|
|
else if(cChar == '<')
|
|
|
|
{
|
|
|
|
nextCharacter();
|
|
|
|
if(cChar == '=')
|
|
|
|
{
|
|
|
|
return Token(Token::LessEqualSymbol, "<=", cLine);
|
|
|
|
}
|
|
|
|
return Token(Token::LessSymbol, "<", cLine);
|
|
|
|
}
|
|
|
|
else if(cChar == '>')
|
|
|
|
{
|
|
|
|
nextCharacter();
|
|
|
|
if(cChar == '=')
|
|
|
|
{
|
|
|
|
return Token(Token::GreaterEqualSymbol, ">=", cLine);
|
|
|
|
}
|
|
|
|
return Token(Token::GreaterSymbol, ">", cLine);
|
|
|
|
}
|
|
|
|
else if(cChar == ',')
|
|
|
|
{
|
|
|
|
nextCharacter();
|
|
|
|
return Token(Token::CommaSymbol, ",", cLine);
|
|
|
|
}
|
2012-09-21 15:21:03 -05:00
|
|
|
else if(cChar == '.')
|
|
|
|
{
|
|
|
|
nextCharacter();
|
|
|
|
return Token(Token::DotSymbol, ".", cLine);
|
|
|
|
}
|
2012-09-21 09:05:50 -05:00
|
|
|
else
|
|
|
|
{
|
|
|
|
nextCharacter();
|
|
|
|
return Token(Token::InvalidSymbol, std::string(1, cChar), cLine);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Scanner::nextCharacter()
|
|
|
|
{
|
|
|
|
if(source.good())
|
|
|
|
cChar = source.get();
|
|
|
|
else
|
|
|
|
cChar = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|