summaryrefslogtreecommitdiff
path: root/src/pim/Scanner.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/pim/Scanner.cpp')
-rw-r--r--src/pim/Scanner.cpp178
1 files changed, 178 insertions, 0 deletions
diff --git a/src/pim/Scanner.cpp b/src/pim/Scanner.cpp
new file mode 100644
index 0000000..32e64d0
--- /dev/null
+++ b/src/pim/Scanner.cpp
@@ -0,0 +1,178 @@
+//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);
+ }
+ else
+ {
+ nextCharacter();
+ return Token(Token::InvalidSymbol, std::string(1, cChar), cLine);
+ }
+ }
+
+ void Scanner::nextCharacter()
+ {
+ if(source.good())
+ cChar = source.get();
+ else
+ cChar = 0;
+ }
+ }
+} \ No newline at end of file