2022-10-17 22:26:36 -03:00
|
|
|
#include "lexer.h"
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
2023-02-13 23:03:31 -03:00
|
|
|
obelisk::Lexer::Lexer(const std::string& sourceFile)
|
2022-10-17 22:26:36 -03:00
|
|
|
{
|
2023-02-13 23:03:31 -03:00
|
|
|
fileStream_.open(sourceFile, std::ifstream::in);
|
|
|
|
if (!fileStream_)
|
|
|
|
{
|
|
|
|
throw obelisk::LexerException("could not open source file " + sourceFile);
|
|
|
|
}
|
|
|
|
}
|
2022-10-17 22:26:36 -03:00
|
|
|
|
2023-02-13 23:03:31 -03:00
|
|
|
obelisk::Lexer::~Lexer()
|
|
|
|
{
|
|
|
|
fileStream_.close();
|
|
|
|
fileStream_.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
int obelisk::Lexer::getToken()
|
|
|
|
{
|
2022-10-17 22:26:36 -03:00
|
|
|
while (isspace(lastChar))
|
|
|
|
{
|
2023-02-13 23:03:31 -03:00
|
|
|
lastChar = fileStream_.get();
|
2022-10-17 22:26:36 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (isalpha(lastChar))
|
|
|
|
{
|
|
|
|
eraseIdentifier();
|
|
|
|
appendIdentifier(lastChar);
|
2023-02-13 23:03:31 -03:00
|
|
|
while (isalnum((lastChar = fileStream_.get())))
|
2022-10-17 22:26:36 -03:00
|
|
|
{
|
|
|
|
appendIdentifier(lastChar);
|
|
|
|
}
|
|
|
|
|
2022-11-04 11:19:30 -03:00
|
|
|
if (getIdentifier() == "fact")
|
|
|
|
{
|
|
|
|
return Token::kTokenFact;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (getIdentifier() == "rule")
|
|
|
|
{
|
|
|
|
return Token::kTokenFact;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (getIdentifier() == "action")
|
|
|
|
{
|
|
|
|
return Token::kTokenAction;
|
|
|
|
}
|
|
|
|
|
2022-10-17 22:26:36 -03:00
|
|
|
if (getIdentifier() == "def")
|
|
|
|
{
|
|
|
|
return Token::kTokenDef;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (getIdentifier() == "extern")
|
|
|
|
{
|
|
|
|
return kTokenExtern;
|
|
|
|
}
|
|
|
|
|
|
|
|
return kTokenIdentifier;
|
|
|
|
}
|
|
|
|
|
2022-11-30 22:44:08 -03:00
|
|
|
if (isdigit(lastChar))
|
2022-10-17 22:26:36 -03:00
|
|
|
{
|
2022-11-30 22:44:08 -03:00
|
|
|
bool firstPeriod = false;
|
2022-10-17 22:26:36 -03:00
|
|
|
std::string numberStr;
|
|
|
|
do
|
|
|
|
{
|
2022-11-30 22:44:08 -03:00
|
|
|
if (firstPeriod && lastChar == '.')
|
|
|
|
{
|
|
|
|
throw obelisk::LexerException("invalid double value");
|
|
|
|
}
|
|
|
|
else if (!firstPeriod && lastChar == '.')
|
|
|
|
{
|
|
|
|
firstPeriod = true;
|
|
|
|
}
|
2022-10-17 22:26:36 -03:00
|
|
|
numberStr += lastChar;
|
2023-02-13 23:03:31 -03:00
|
|
|
lastChar = fileStream_.get();
|
2022-10-17 22:26:36 -03:00
|
|
|
}
|
|
|
|
while (isdigit(lastChar) || lastChar == '.');
|
|
|
|
|
|
|
|
setNumberValue(strtod(numberStr.c_str(), nullptr));
|
|
|
|
|
|
|
|
return kTokenNumber;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lastChar == '#')
|
|
|
|
{
|
|
|
|
commentLine(&lastChar);
|
|
|
|
|
|
|
|
if (lastChar != EOF)
|
|
|
|
{
|
|
|
|
return getToken();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (lastChar == '/')
|
|
|
|
{
|
2023-02-13 23:03:31 -03:00
|
|
|
lastChar = fileStream_.get();
|
2022-10-17 22:26:36 -03:00
|
|
|
if (lastChar == '/')
|
|
|
|
{
|
|
|
|
commentLine(&lastChar);
|
|
|
|
|
|
|
|
if (lastChar != EOF)
|
|
|
|
{
|
|
|
|
return getToken();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lastChar == EOF)
|
|
|
|
{
|
|
|
|
return kTokenEof;
|
|
|
|
}
|
|
|
|
|
|
|
|
int thisChar = lastChar;
|
2023-02-13 23:03:31 -03:00
|
|
|
lastChar = fileStream_.get();
|
2022-10-17 22:26:36 -03:00
|
|
|
return thisChar;
|
|
|
|
}
|
|
|
|
|
|
|
|
void obelisk::Lexer::commentLine(int* lastChar)
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
2023-02-13 23:03:31 -03:00
|
|
|
*lastChar = fileStream_.get();
|
2022-10-17 22:26:36 -03:00
|
|
|
}
|
|
|
|
while (*lastChar != EOF && *lastChar != '\n' && *lastChar != '\r');
|
|
|
|
}
|
|
|
|
|
2022-11-04 11:19:30 -03:00
|
|
|
const std::string& obelisk::Lexer::getIdentifier()
|
2022-10-17 22:26:36 -03:00
|
|
|
{
|
|
|
|
return identifier_;
|
|
|
|
}
|
|
|
|
|
2022-11-04 11:19:30 -03:00
|
|
|
void obelisk::Lexer::setIdentifier(const std::string& identifier)
|
2022-10-17 22:26:36 -03:00
|
|
|
{
|
|
|
|
identifier_ = identifier;
|
|
|
|
}
|
|
|
|
|
|
|
|
void obelisk::Lexer::eraseIdentifier()
|
|
|
|
{
|
|
|
|
identifier_ = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
void obelisk::Lexer::appendIdentifier(int lastChar)
|
|
|
|
{
|
|
|
|
identifier_ += lastChar;
|
|
|
|
}
|
|
|
|
|
|
|
|
double obelisk::Lexer::getNumberValue()
|
|
|
|
{
|
|
|
|
return numberValue_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void obelisk::Lexer::setNumberValue(double numberValue)
|
|
|
|
{
|
|
|
|
numberValue_ = numberValue;
|
|
|
|
}
|