Website Summary Files Commits Branches @commit @diff @stats
path: root / JSImpl / src
diff options
context:
space:
mode:
Commita7575e08c67ab6e4f3c5a48b302c42a17d2500c2 (patch)
Author
 martin dobrev <martindobrev0@gmail.com>
2020-10-12 22:56:16 +0300
Committer
 martin dobrev <martindobrev0@gmail.com>
2020-10-12 22:56:16 +0300
Filesab3caa138c0048a0140af070d0dbbdd0d686f15c /JSImpl/src
IPL-a7575e08c67ab6e4f3c5a48b302c42a17d2500c2.tar
IPL-a7575e08c67ab6e4f3c5a48b302c42a17d2500c2.tar.gz
IPL-a7575e08c67ab6e4f3c5a48b302c42a17d2500c2.zip
Parentd9183dd25685297d0b9278591b910bb753bc93ed (diff)
Add support for new lines and tabs in tokenizer.
Improve tests verbosity. Replace white spaces with tabs.
3 files changed, 47 insertions, 98 deletions
-rw-r--r--JSImpl/src/Lexer.cpp129
-rw-r--r--JSImpl/src/Lexer.h7
-rw-r--r--JSImpl/src/main.cpp9
diff --git a/JSImpl/src/Lexer.cpp b/JSImpl/src/Lexer.cpp
index dbbf92d..8607480 100644
--- a/JSImpl/src/Lexer.cpp
+++ b/JSImpl/src/Lexer.cpp
@@ -35,7 +35,7 @@ inline bool IsStringBound(char c)
inline bool IsWhiteSpace(char c)
{
- return c == ' ' || c == '\t';
+ return c == ' ';
}
inline bool IsNewLine(char c)
@@ -72,7 +72,7 @@ class Tokenizer
{
public:
Tokenizer(const char* code, const LexerSettings& settings);
- LexerResult Tokenize(IPLVector<Token>& tokens);
+ LexerResult Tokenize();
private:
Token NextToken();
@@ -81,9 +81,11 @@ private:
inline Token ProduceToken(TokenType type);
inline Token ProduceToken(TokenType type, IPLString lexeme, double number);
inline Token ProduceErrorToken();
+ inline Token ProduceInvalidToken();
+
+ bool FilterToken(TokenType type);
IPLString ParseComment();
- IPLString ParseWhitespaces();
double ParseNumber();
IPLString ParseString();
Keyword ParseKeyword();
@@ -94,8 +96,6 @@ private:
void SetError(const IPLString& what);
- bool SkipWhiteSpaces();
- bool SkipNewLine();
bool Match(const char c);
inline void NextSymbol();
@@ -112,21 +112,19 @@ private:
State m_GenerationState;
LexerSettings m_Settings;
- bool m_SkipNextToken;
IPLUnorderedMap<IPLString, TokenType> m_KeyWordsTable;
};
-LexerResult Tokenize(const char* code, IPLVector<Token>& tokens, const LexerSettings& settings)
+LexerResult Tokenize(const char* code, const LexerSettings& settings)
{
Tokenizer tokenizer(code, settings);
-
- return tokenizer.Tokenize(tokens);
+ return tokenizer.Tokenize();
}
-LexerResult Tokenize(const char * code, IPLVector<Token>& tokens)
+LexerResult Tokenize(const char * code)
{
- return Tokenize(code, tokens, { false, false });
+ return Tokenize(code, { false, false });
}
Tokenizer::Tokenizer(const char* code, const LexerSettings& settings)
@@ -138,7 +136,6 @@ Tokenizer::Tokenizer(const char* code, const LexerSettings& settings)
, m_Error()
, m_GenerationState(State::Success)
, m_Settings(settings)
- , m_SkipNextToken(false)
{
m_KeyWordsTable["break"] = TokenType::Break;
m_KeyWordsTable["case"] = TokenType::Case;
@@ -180,60 +177,49 @@ Tokenizer::Tokenizer(const char* code, const LexerSettings& settings)
m_KeyWordsTable["false"] = TokenType::False;
}
-LexerResult Tokenizer::Tokenize(IPLVector<Token>& tokens)
+LexerResult Tokenizer::Tokenize()
{
+ LexerResult result{ true, IPLError() };
+ Token token;
do
{
- Token token;
- do
- {
- token = NextToken();
- } while (m_SkipNextToken);
+ token = NextToken();
if (m_GenerationState == State::Error)
{
- return LexerResult{ false, IPLError(m_Error) };
+ result.IsSuccessful = false;
+ result.Error = IPLError(m_Error);
+ return result;
}
+ if (FilterToken(token.Type))
+ {
+ result.tokens.emplace_back(token);
+ }
+ } while (token.Type != TokenType::Eof);
- tokens.emplace_back(token);
- } while (tokens.back().Type != TokenType::Eof);
-
- return LexerResult{ true, IPLError() };
+ return result;
}
-bool Tokenizer::SkipWhiteSpaces()
+bool Tokenizer::FilterToken(TokenType type)
{
- const auto old = m_Current;
- while (IsWhiteSpace(m_Code[m_Current]))
+ if (type == TokenType::Comment)
{
- NextSymbol();
+ return m_Settings.CreateCommentTokens;
}
- return old != m_Current;
-}
-
-bool Tokenizer::SkipNewLine()
-{
- const auto old = m_Current;
- while (IsNewLine(m_Code[m_Current]))
+ else if (type == TokenType::Whitespace ||
+ type == TokenType::Tab ||
+ type == TokenType::NewLine)
{
- NextLine();
+ return m_Settings.CreateWhitespaceTokens;
}
- return old != m_Current;
+ return true;
}
bool Tokenizer::Match(const char c)
{
if (c == m_Code[m_Current])
{
- if (!IsNewLine(m_Code[m_Current]))
- {
- NextSymbol();
- }
- else
- {
- NextLine();
- }
-
+ NextSymbol();
return true;
}
return false;
@@ -359,6 +345,11 @@ inline Token Tokenizer::ProduceErrorToken()
return ProduceToken(TokenType::Invalid, "");
}
+inline Token Tokenizer::ProduceInvalidToken()
+{
+ return ProduceToken(TokenType::Invalid, "");
+}
+
IPLString Tokenizer::ParseComment()
{
auto start = m_Current;
@@ -395,33 +386,6 @@ IPLString Tokenizer::ParseComment()
RETURN_ERROR(IPLString());
}
-IPLString Tokenizer::ParseWhitespaces()
-{
- if (!IsWhiteSpace(m_Code[m_Current]) && !IsNewLine(m_Code[m_Current]))
- {
- RETURN_FAIL(IPLString());
- }
-
- auto start = m_Current;
- while (1)
- {
- if (IsWhiteSpace(m_Code[m_Current]))
- {
- NextSymbol();
- }
- else if (IsNewLine(m_Code[m_Current]))
- {
- NextLine();
- }
- else
- {
- break;
- }
- }
-
- RETURN_SUCCESS(IPLString(m_Code + start, m_Code + m_Current));
-}
-
double Tokenizer::ParseNumber()
{
if (!IsDigit(m_Code[m_Current]))
@@ -531,8 +495,6 @@ void Tokenizer::SetError(const IPLString& what)
Token Tokenizer::NextToken()
{
- m_SkipNextToken = false;
-
if (IsEnd(m_Code[m_Current]))
{
return ProduceToken(TokenType::Eof);
@@ -545,25 +507,9 @@ Token Tokenizer::NextToken()
}
if (IsStateSuccess())
{
- if (!m_Settings.CreateCommentTokens)
- {
- m_SkipNextToken = true;
- return ProduceSkipToken();
- }
return ProduceToken(TokenType::Comment, comment);
}
- const auto& spaces = ParseWhitespaces();
- if (IsStateSuccess())
- {
- if (!m_Settings.CreateWhitespaceTokens)
- {
- m_SkipNextToken = true;
- return ProduceSkipToken();
- }
- return ProduceToken(TokenType::Whitespace, spaces);
- }
-
// Single Char
switch (m_Code[m_Current])
{
@@ -592,6 +538,9 @@ Token Tokenizer::NextToken()
case '[': NextSymbol(); return ProduceToken(TokenType::LeftSquareBracket);
case ']': NextSymbol(); return ProduceToken(TokenType::RightSquareBracket);
case '\\': NextSymbol(); return ProduceToken(TokenType::Backslash);
+ case '\n': NextLine(); return ProduceToken(TokenType::NewLine);
+ case ' ': NextSymbol(); return ProduceToken(TokenType::Whitespace);
+ case '\t': NextSymbol(); return ProduceToken(TokenType::Tab);
default:
break;
}
diff --git a/JSImpl/src/Lexer.h b/JSImpl/src/Lexer.h
index 3c0c785..00acc7a 100644
--- a/JSImpl/src/Lexer.h
+++ b/JSImpl/src/Lexer.h
@@ -100,6 +100,8 @@ enum class TokenType
False,
Whitespace,
+ Tab,
+ NewLine,
Comment,
Eof,
@@ -119,6 +121,7 @@ struct LexerResult
{
bool IsSuccessful;
IPLError Error;
+ IPLVector<Token> tokens;
};
struct LexerSettings
@@ -127,5 +130,5 @@ struct LexerSettings
bool CreateCommentTokens;
};
-LexerResult Tokenize(const char* code, IPLVector<Token>& tokens, const LexerSettings& settings);
-LexerResult Tokenize(const char* code, IPLVector<Token>& tokens); \ No newline at end of file
+LexerResult Tokenize(const char* code, const LexerSettings& settings);
+LexerResult Tokenize(const char* code); \ No newline at end of file
diff --git a/JSImpl/src/main.cpp b/JSImpl/src/main.cpp
index 90f6023..ef5ac1b 100644
--- a/JSImpl/src/main.cpp
+++ b/JSImpl/src/main.cpp
@@ -15,9 +15,8 @@
void RunParseCalc()
{
- IPLVector<Token> tokens;
//Tokenize("var a = 0; var b = a + 123;a+b;", tokens);
- Tokenize("var a = 5; if(a == 5){a++;}", tokens);
+ auto tokens = Tokenize("var a = 5; if(a == 5){a++;}").tokens;
// TODO make actual test :D
auto expr = Parse(tokens);
@@ -60,8 +59,7 @@ void InteractiveInterpreter()
i.Print(p);
continue;
}
- IPLVector<Token> tokens;
- Tokenize(command, tokens);
+ auto tokens = Tokenize(command).tokens;
auto result = i.Run(Parse(tokens).get());
while (!result.empty()) {
std::cout << result.back() << std::endl;
@@ -72,7 +70,6 @@ void InteractiveInterpreter()
void Generate()
{
- IPLVector<Token> tokens;
//Tokenize("var a = 0; var b = a + 123;a+b;", tokens);
/*Tokenize("var a; if(a < 4) { a = 8; if(a < 7) {var b = 4;}} else { a = 2} ", tokens);*/
IPLString source = "var i = 0; \n"
@@ -80,7 +77,7 @@ void Generate()
"{\n"
" i = i + j;\n"
"}";
- Tokenize(source.c_str(), tokens);
+ auto tokens = Tokenize(source.c_str()).tokens;
auto asmb = GenerateByteCode(Parse(tokens), source,
ByteCodeGeneratorOptions(ByteCodeGeneratorOptions::OptimizationsType::None, true));