Website Summary Files Commits Branches @commit @diff @stats
path: root / JSImpl
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
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.
6 files changed, 187 insertions, 263 deletions
-rw-r--r--JSImpl/src/Lexer.cpp129
-rw-r--r--JSImpl/src/Lexer.h7
-rw-r--r--JSImpl/src/main.cpp9
-rw-r--r--JSImpl/test/CodeGenerationTests.cpp27
-rw-r--r--JSImpl/test/LexerTests.cpp233
-rw-r--r--JSImpl/test/ParserTests.cpp45
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));
diff --git a/JSImpl/test/CodeGenerationTests.cpp b/JSImpl/test/CodeGenerationTests.cpp
index d341562..a6ebc6e 100644
--- a/JSImpl/test/CodeGenerationTests.cpp
+++ b/JSImpl/test/CodeGenerationTests.cpp
@@ -9,9 +9,8 @@
TEST(CodeGen, Empty)
{
- IPLVector<Token> tokens;
IPLString source = "";
- Tokenize(source.c_str(), tokens);
+ IPLVector<Token> tokens = Tokenize(source.c_str()).tokens;
auto ast = Parse(tokens);
auto asmb = GenerateByteCode(ast, source,
ByteCodeGeneratorOptions(ByteCodeGeneratorOptions::OptimizationsType::None, false));
@@ -23,9 +22,8 @@ TEST(CodeGen, Empty)
TEST(CodeGen, VarDeclations)
{
- IPLVector<Token> tokens;
IPLString source = "var a;";
- Tokenize(source.c_str(), tokens);
+ IPLVector<Token> tokens = Tokenize(source.c_str()).tokens;
auto ast = Parse(tokens);
auto asmb = GenerateByteCode(ast, source,
ByteCodeGeneratorOptions(ByteCodeGeneratorOptions::OptimizationsType::None, false));
@@ -37,9 +35,8 @@ TEST(CodeGen, VarDeclations)
TEST(CodeGen, VarDeclationsWithValue)
{
- IPLVector<Token> tokens;
IPLString source = "var a = 5;";
- Tokenize(source.c_str(), tokens);
+ IPLVector<Token> tokens = Tokenize(source.c_str()).tokens;
auto ast = Parse(tokens);
auto asmb = GenerateByteCode(ast, source,
ByteCodeGeneratorOptions(ByteCodeGeneratorOptions::OptimizationsType::None, false));
@@ -53,9 +50,8 @@ TEST(CodeGen, VarDeclationsWithValue)
TEST(CodeGen, VarDeclationsBinaryExpre)
{
- IPLVector<Token> tokens;
IPLString source = "var a = 5 + 6;";
- Tokenize(source.c_str(), tokens);
+ IPLVector<Token> tokens = Tokenize(source.c_str()).tokens;
auto ast = Parse(tokens);
auto asmb = GenerateByteCode(ast, source,
ByteCodeGeneratorOptions(ByteCodeGeneratorOptions::OptimizationsType::None, false));
@@ -72,9 +68,8 @@ TEST(CodeGen, VarDeclationsBinaryExpre)
TEST(CodeGen, VariableAssignment)
{
- IPLVector<Token> tokens;
IPLString source = "var a; a = 5;";
- Tokenize(source.c_str(), tokens);
+ IPLVector<Token> tokens = Tokenize(source.c_str()).tokens;
auto ast = Parse(tokens);
auto asmb = GenerateByteCode(ast, source,
ByteCodeGeneratorOptions(ByteCodeGeneratorOptions::OptimizationsType::None, false));
@@ -89,9 +84,8 @@ TEST(CodeGen, VariableAssignment)
TEST(CodeGen, MultiVariableAssignment)
{
- IPLVector<Token> tokens;
IPLString source = "var a; var b = 6; a = b;";
- Tokenize(source.c_str(), tokens);
+ IPLVector<Token> tokens = Tokenize(source.c_str()).tokens;
auto ast = Parse(tokens);
auto asmb = GenerateByteCode(ast, source,
ByteCodeGeneratorOptions(ByteCodeGeneratorOptions::OptimizationsType::None, false));
@@ -107,9 +101,8 @@ TEST(CodeGen, MultiVariableAssignment)
TEST(CodeGen, SimpleIf)
{
- IPLVector<Token> tokens;
IPLString source = "var a = 5; if (a < 1) { a = 7}";
- Tokenize(source.c_str(), tokens);
+ IPLVector<Token> tokens = Tokenize(source.c_str()).tokens;
auto ast = Parse(tokens);
auto asmb = GenerateByteCode(ast, source,
ByteCodeGeneratorOptions(ByteCodeGeneratorOptions::OptimizationsType::None, false));
@@ -129,9 +122,8 @@ TEST(CodeGen, SimpleIf)
TEST(CodeGen, SimpleIfElse)
{
- IPLVector<Token> tokens;
IPLString source = "var a = 5; if (a < 1) { a = 3; } else { a = 7; }";
- Tokenize(source.c_str(), tokens);
+ IPLVector<Token> tokens = Tokenize(source.c_str()).tokens;
auto ast = Parse(tokens);
auto asmb = GenerateByteCode(ast, source,
ByteCodeGeneratorOptions(ByteCodeGeneratorOptions::OptimizationsType::None, false));
@@ -154,9 +146,8 @@ TEST(CodeGen, SimpleIfElse)
TEST(CodeGen, SimpleFor)
{
- IPLVector<Token> tokens;
IPLString source = "var a = 0; for (var i = 0; i < 5; i++ ){ a = a + i; }";
- Tokenize(source.c_str(), tokens);
+ IPLVector<Token> tokens = Tokenize(source.c_str()).tokens;
auto ast = Parse(tokens);
auto asmb = GenerateByteCode(ast, source,
ByteCodeGeneratorOptions(ByteCodeGeneratorOptions::OptimizationsType::None, false));
diff --git a/JSImpl/test/LexerTests.cpp b/JSImpl/test/LexerTests.cpp
index 2f13916..a1a25d3 100644
--- a/JSImpl/test/LexerTests.cpp
+++ b/JSImpl/test/LexerTests.cpp
@@ -5,211 +5,210 @@
TEST(Lexer, Less)
{
- IPLVector<Token> tokens;
- Tokenize("<", tokens);
+ IPLVector<Token> tokens = Tokenize("<").tokens;
ASSERT_EQ(tokens.size(), 2u);
- ASSERT_EQ(tokens[0].Type, TokenType::Less);
+ ASSERT_EQ(tokens[0].Type, TokenType::Less);
}
TEST(Lexer, Number)
{
- IPLVector<Token> tokens;
- Tokenize("213434.24", tokens);
+ IPLVector<Token> tokens = Tokenize("213434.24").tokens;
ASSERT_EQ(tokens.size(), 2u);
- ASSERT_EQ(tokens[0].Type, TokenType::Number);
- ASSERT_EQ(tokens[0].Number, 213434.24);
+ ASSERT_EQ(tokens[0].Type, TokenType::Number);
+ ASSERT_EQ(tokens[0].Number, 213434.24);
}
TEST(Lexer, HexNumber)
{
- IPLVector<Token> tokens;
- auto result = Tokenize("0x10", tokens);
+ const auto res = Tokenize("0x10");
+ const auto& tokens = res.tokens;
- ASSERT_TRUE(result.IsSuccessful);
+ ASSERT_TRUE(res.IsSuccessful);
ASSERT_EQ(tokens.size(), 2u);
- ASSERT_EQ(tokens[0].Type, TokenType::Number);
- ASSERT_EQ(tokens[0].Number, 16);
+ ASSERT_EQ(tokens[0].Type, TokenType::Number);
+ ASSERT_EQ(tokens[0].Number, 16);
}
TEST(Lexer, ScientificNotationNumber)
{
- IPLVector<Token> tokens;
- auto result = Tokenize("1e2", tokens);
+ const auto res = Tokenize("1e2");
+ const auto& tokens = res.tokens;
- ASSERT_TRUE(result.IsSuccessful);
+ ASSERT_TRUE(res.IsSuccessful);
ASSERT_EQ(tokens.size(), 2u);
- ASSERT_EQ(tokens[0].Type, TokenType::Number);
- ASSERT_EQ(tokens[0].Number, 100);
+ ASSERT_EQ(tokens[0].Type, TokenType::Number);
+ ASSERT_EQ(tokens[0].Number, 100);
}
TEST(Lexer, NumberStartWithNine)
{
- IPLVector<Token> tokens;
- Tokenize("999", tokens);
+ IPLVector<Token> tokens = Tokenize("999").tokens;
ASSERT_EQ(tokens.size(), 2u);
- ASSERT_EQ(tokens[0].Type, TokenType::Number);
- ASSERT_EQ(tokens[0].Number, 999);
+ ASSERT_EQ(tokens[0].Type, TokenType::Number);
+ ASSERT_EQ(tokens[0].Number, 999);
}
TEST(Lexer, NumberStartWithZero)
{
- IPLVector<Token> tokens;
- Tokenize("0999", tokens);
+ IPLVector<Token> tokens = Tokenize("0999").tokens;
ASSERT_EQ(tokens.size(), 2u);
- ASSERT_EQ(tokens[0].Type, TokenType::Number);
- ASSERT_EQ(tokens[0].Number, 999);
+ ASSERT_EQ(tokens[0].Type, TokenType::Number);
+ ASSERT_EQ(tokens[0].Number, 999);
}
TEST(Lexer, SpaceNewLineSpace)
{
- IPLVector<Token> tokens;
- Tokenize(" \n var a = 4; ", tokens);
- ASSERT_TRUE(tokens.size() == 6 && tokens[0].Type == TokenType::Var &&
- tokens[1].Type == TokenType::Identifier &&
- tokens[2].Type == TokenType::Equal &&
- tokens[3].Type == TokenType::Number &&
- tokens[4].Type == TokenType::Semicolon);
+ IPLVector<Token> tokens = Tokenize(" \n var a = 4; ").tokens;
+ ASSERT_TRUE(tokens.size() == 6 && tokens[0].Type == TokenType::Var);
+ ASSERT_TRUE(tokens[1].Type == TokenType::Identifier);
+ ASSERT_TRUE(tokens[2].Type == TokenType::Equal);
+ ASSERT_TRUE(tokens[3].Type == TokenType::Number);
+ ASSERT_TRUE(tokens[4].Type == TokenType::Semicolon);
}
TEST(Lexer, String)
{
- IPLVector<Token> tokens;
- Tokenize("\"alabala\"", tokens);
+ IPLVector<Token> tokens = Tokenize("\"alabala\"").tokens;
ASSERT_TRUE(tokens.size() == 2 && tokens[0].Type == TokenType::String
- && tokens[0].Lexeme == "\"alabala\"");
+ && tokens[0].Lexeme == "\"alabala\"");
}
TEST(Lexer, StringSingleQuotedStrings)
{
- IPLVector<Token> tokens;
- Tokenize("'alabala'", tokens);
+ IPLVector<Token> tokens = Tokenize("'alabala'").tokens;
ASSERT_TRUE(tokens.size() == 2 && tokens[0].Type == TokenType::String && tokens[0].Lexeme == "'alabala'");
}
TEST(Lexer, KeyWord)
{
- IPLVector<Token> tokens;
- Tokenize("for", tokens);
+ IPLVector<Token> tokens = Tokenize("for").tokens;
ASSERT_TRUE(tokens.size() == 2 && tokens[0].Type == TokenType::For);
}
TEST(Lexer, VariableDeclaration)
{
- IPLVector<Token> tokens;
- Tokenize("var pesho = 10", tokens);
+ IPLVector<Token> tokens = Tokenize("var pesho = 10").tokens;
- ASSERT_TRUE(tokens.size() == 5 && tokens[0].Type == TokenType::Var
- && tokens[1].Type == TokenType::Identifier
- && tokens[2].Type == TokenType::Equal
- && tokens[3].Type == TokenType::Number
- && tokens[4].Type == TokenType::Eof);
+ ASSERT_TRUE(tokens.size() == 5 && tokens[0].Type == TokenType::Var);
+ ASSERT_TRUE(tokens[1].Type == TokenType::Identifier);
+ ASSERT_TRUE(tokens[2].Type == TokenType::Equal);
+ ASSERT_TRUE(tokens[3].Type == TokenType::Number);
+ ASSERT_TRUE(tokens[4].Type == TokenType::Eof);
}
TEST(Lexer, StringError)
{
- IPLVector<Token> tokens;
- const auto& res = Tokenize("\" aaaa", tokens);
+ const auto res = Tokenize("\" aaaa");
ASSERT_TRUE(!res.IsSuccessful && res.Error.Row == 0 && res.Error.Column == 6);
}
TEST(Lexer, TestWhiteSpaceTokens)
{
- IPLVector<Token> tokens;
- const auto& res = Tokenize(" 1\n2 abc\n \n", tokens, { true, false });
- ASSERT_TRUE(res.IsSuccessful
- && tokens.size() == 8
- && tokens[0].Type == TokenType::Whitespace
- && tokens[0].Lexeme == " "
- && tokens[1].Type == TokenType::Number
- && tokens[1].Number == 1
- && tokens[2].Type == TokenType::Whitespace
- && tokens[2].Lexeme == "\n"
- && tokens[3].Type == TokenType::Number
- && tokens[3].Number == 2
- && tokens[4].Type == TokenType::Whitespace
- && tokens[4].Lexeme == " "
- && tokens[5].Type == TokenType::Identifier
- && tokens[5].Lexeme == "abc"
- && tokens[6].Type == TokenType::Whitespace
- && tokens[6].Lexeme == "\n \n"
- && tokens[7].Type == TokenType::Eof);
+ const auto res = Tokenize(" 1\n2 abc\n \n", { true, false });
+ const auto& tokens = res.tokens;
+ ASSERT_TRUE(res.IsSuccessful);
+ ASSERT_TRUE(tokens.size() == 11);
+ ASSERT_TRUE(tokens[0].Type == TokenType::Whitespace);
+ ASSERT_TRUE(tokens[0].Lexeme == "");
+ ASSERT_TRUE(tokens[1].Type == TokenType::Number);
+ ASSERT_TRUE(tokens[1].Number == 1);
+ ASSERT_TRUE(tokens[2].Type == TokenType::NewLine);
+ ASSERT_TRUE(tokens[2].Lexeme == "");
+ ASSERT_TRUE(tokens[3].Type == TokenType::Number);
+ ASSERT_TRUE(tokens[3].Number == 2);
+ ASSERT_TRUE(tokens[4].Type == TokenType::Whitespace);
+ ASSERT_TRUE(tokens[4].Lexeme == "");
+ ASSERT_TRUE(tokens[5].Type == TokenType::Whitespace);
+ ASSERT_TRUE(tokens[5].Lexeme == "");
+ ASSERT_TRUE(tokens[6].Type == TokenType::Identifier);
+ ASSERT_TRUE(tokens[6].Lexeme == "abc");
+ ASSERT_TRUE(tokens[7].Type == TokenType::NewLine);
+ ASSERT_TRUE(tokens[7].Lexeme == "");
+ ASSERT_TRUE(tokens[8].Type == TokenType::Whitespace);
+ ASSERT_TRUE(tokens[8].Lexeme == "");
+ ASSERT_TRUE(tokens[9].Type == TokenType::NewLine);
+ ASSERT_TRUE(tokens[9].Lexeme == "");
+ ASSERT_TRUE(tokens[10].Type == TokenType::Eof);
}
TEST(Lexer, SimpleComment)
{
- IPLVector<Token> tokens;
- const auto& res = Tokenize("//comment", tokens, { false, true });
- ASSERT_TRUE(res.IsSuccessful
- && tokens.size() == 2
- && tokens[0].Type == TokenType::Comment
- && tokens[0].Lexeme == "//comment"
- && tokens[1].Type == TokenType::Eof);
+ const auto res = Tokenize("//comment", { false, true });
+ const auto& tokens = res.tokens;
+ ASSERT_TRUE(res.IsSuccessful);
+ ASSERT_TRUE(tokens.size() == 2);
+ ASSERT_TRUE(tokens[0].Type == TokenType::Comment);
+ ASSERT_TRUE(tokens[0].Lexeme == "//comment");
+ ASSERT_TRUE(tokens[1].Type == TokenType::Eof);
}
TEST(Lexer, SimpleMultiLineComment)
{
- IPLVector<Token> tokens;
- const auto& res = Tokenize("/*comment\ncomment*/", tokens, { false, true });
- ASSERT_TRUE(res.IsSuccessful
- && tokens.size() == 2
- && tokens[0].Type == TokenType::Comment
- && tokens[0].Lexeme == "/*comment\ncomment*/"
- && tokens[1].Type == TokenType::Eof);
+ const auto res = Tokenize("/*comment\ncomment*/", { false, true });
+ const auto& tokens = res.tokens;
+ ASSERT_TRUE(res.IsSuccessful);
+ ASSERT_TRUE(tokens.size() == 2);
+ ASSERT_TRUE(tokens[0].Type == TokenType::Comment);
+ ASSERT_TRUE(tokens[0].Lexeme == "/*comment\ncomment*/");
+ ASSERT_TRUE(tokens[1].Type == TokenType::Eof);
}
TEST(Lexer, ConsecutiveMultiLineComment)
{
- IPLVector<Token> tokens;
- const auto& res = Tokenize("/*comment1\ncomment1*//*comment2\ncomment2*/", tokens, { false, true });
- ASSERT_TRUE(res.IsSuccessful
- && tokens.size() == 3
- && tokens[0].Type == TokenType::Comment
- && tokens[0].Lexeme == "/*comment1\ncomment1*/"
- && tokens[1].Type == TokenType::Comment
- && tokens[1].Lexeme == "/*comment2\ncomment2*/"
- && tokens[2].Type == TokenType::Eof);
+ const auto res = Tokenize("/*comment1\ncomment1*//*comment2\ncomment2*/", { false, true });
+ const auto& tokens = res.tokens;
+ ASSERT_TRUE(res.IsSuccessful);
+ ASSERT_TRUE(tokens.size() == 3);
+ ASSERT_TRUE(tokens[0].Type == TokenType::Comment);
+ ASSERT_TRUE(tokens[0].Lexeme == "/*comment1\ncomment1*/");
+ ASSERT_TRUE(tokens[1].Type == TokenType::Comment);
+ ASSERT_TRUE(tokens[1].Lexeme == "/*comment2\ncomment2*/");
+ ASSERT_TRUE(tokens[2].Type == TokenType::Eof);
}
TEST(Lexer, ConsecutiveMultiLineCommentWithSpace)
{
- IPLVector<Token> tokens;
- const auto& res = Tokenize("/*comment1\ncomment1*/\n\n\n/*comment2\ncomment2*/", tokens, { false, true });
- ASSERT_TRUE(res.IsSuccessful
- && tokens.size() == 3
- && tokens[0].Type == TokenType::Comment
- && tokens[0].Lexeme == "/*comment1\ncomment1*/"
- && tokens[1].Type == TokenType::Comment
- && tokens[1].Lexeme == "/*comment2\ncomment2*/"
- && tokens[2].Type == TokenType::Eof);
+ const auto res = Tokenize("/*comment1\ncomment1*/\n\n\n/*comment2\ncomment2*/", { false, true });
+ const auto& tokens = res.tokens;
+ ASSERT_TRUE(res.IsSuccessful);
+ ASSERT_TRUE(tokens.size() == 3);
+ ASSERT_TRUE(tokens[0].Type == TokenType::Comment);
+ ASSERT_TRUE(tokens[0].Lexeme == "/*comment1\ncomment1*/");
+ ASSERT_TRUE(tokens[1].Type == TokenType::Comment);
+ ASSERT_TRUE(tokens[1].Lexeme == "/*comment2\ncomment2*/");
+ ASSERT_TRUE(tokens[2].Type == TokenType::Eof);
}
TEST(Lexer, ConsecutiveMultiLineCommentWithSpaceWithTokens)
{
- IPLVector<Token> tokens;
- const auto& res = Tokenize("//comment1\n/*comment2\ncomment2*/\n\n\n/*comment3\ncomment3*/", tokens, { true, true });
- ASSERT_TRUE(res.IsSuccessful
- && tokens.size() == 6
- && tokens[0].Type == TokenType::Comment
- && tokens[0].Lexeme == "//comment1"
- && tokens[1].Type == TokenType::Whitespace
- && tokens[1].Lexeme == "\n"
- && tokens[2].Type == TokenType::Comment
- && tokens[2].Lexeme == "/*comment2\ncomment2*/"
- && tokens[3].Type == TokenType::Whitespace
- && tokens[3].Lexeme == "\n\n\n"
- && tokens[4].Type == TokenType::Comment
- && tokens[4].Lexeme == "/*comment3\ncomment3*/"
- && tokens[5].Type == TokenType::Eof);
+ const auto res = Tokenize("//comment1\n/*comment2\ncomment2*/\n\n\n/*comment3\ncomment3*/", { true, true });
+ const auto& tokens = res.tokens;
+ ASSERT_TRUE(res.IsSuccessful);
+ ASSERT_TRUE(tokens.size() == 8);
+ ASSERT_TRUE(tokens[0].Type == TokenType::Comment);
+ ASSERT_TRUE(tokens[0].Lexeme == "//comment1");
+ ASSERT_TRUE(tokens[1].Type == TokenType::NewLine);
+ ASSERT_TRUE(tokens[1].Lexeme == "");
+ ASSERT_TRUE(tokens[2].Type == TokenType::Comment);
+ ASSERT_TRUE(tokens[2].Lexeme == "/*comment2\ncomment2*/");
+ ASSERT_TRUE(tokens[3].Type == TokenType::NewLine);
+ ASSERT_TRUE(tokens[3].Lexeme == "");
+ ASSERT_TRUE(tokens[4].Type == TokenType::NewLine);
+ ASSERT_TRUE(tokens[4].Lexeme == "");
+ ASSERT_TRUE(tokens[5].Type == TokenType::NewLine);
+ ASSERT_TRUE(tokens[5].Lexeme == "");
+ ASSERT_TRUE(tokens[6].Type == TokenType::Comment);
+ ASSERT_TRUE(tokens[6].Lexeme == "/*comment3\ncomment3*/");
+ ASSERT_TRUE(tokens[7].Type == TokenType::Eof);
}
TEST(Lexer, CommentError)
{
- IPLVector<Token> tokens;
- const auto& res = Tokenize(" aa\n /*", tokens);
+ auto res = Tokenize(" aa\n /*");
ASSERT_TRUE(!res.IsSuccessful && res.Error.Row == 1 &&
- res.Error.Column == 3);
+ res.Error.Column == 3);
}
diff --git a/JSImpl/test/ParserTests.cpp b/JSImpl/test/ParserTests.cpp
index a5b0c99..91534c5 100644
--- a/JSImpl/test/ParserTests.cpp
+++ b/JSImpl/test/ParserTests.cpp
@@ -10,8 +10,7 @@
TEST(Parser, ParseUnaryExpr)
{
- IPLVector<Token> tokens;
- Tokenize("function pesho() { var a = 0; return a; } var a = \"3\";", tokens);
+ IPLVector<Token> tokens = Tokenize("function pesho() { var a = 0; return a; } var a = \"3\";").tokens;
// TODO make actual test :D
auto expr = Parse(tokens);
@@ -23,8 +22,7 @@ TEST(Parser, ParseUnaryExpr)
TEST(Parser, VariableDeclaration)
{
- IPLVector<Token> tokens;
- Tokenize("var s = 0;", tokens);
+ IPLVector<Token> tokens = Tokenize("var s = 0;").tokens;
auto expr = Parse(tokens);
std::ostringstream output;
@@ -36,8 +34,7 @@ TEST(Parser, VariableDeclaration)
TEST(Parser, Assignment)
{
- IPLVector<Token> tokens;
- Tokenize("var s = 0; s = 100;", tokens);
+ IPLVector<Token> tokens = Tokenize("var s = 0; s = 100;").tokens;
auto expr = Parse(tokens);
std::ostringstream output;
@@ -49,8 +46,7 @@ TEST(Parser, Assignment)
TEST(Parser, VariableDeclarationAdditionOfLiterals)
{
- IPLVector<Token> tokens;
- Tokenize("var s = 5 + 6;", tokens);
+ IPLVector<Token> tokens = Tokenize("var s = 5 + 6;").tokens;
auto expr = Parse(tokens);
std::ostringstream output;
@@ -62,8 +58,7 @@ TEST(Parser, VariableDeclarationAdditionOfLiterals)
TEST(Parser, VariableDeclarationAdditionOfVariables)
{
- IPLVector<Token> tokens;
- Tokenize("var a = 5; var b = 4; var c = a + b;", tokens);
+ IPLVector<Token> tokens = Tokenize("var a = 5; var b = 4; var c = a + b;").tokens;
auto expr = Parse(tokens);
std::ostringstream output;
@@ -79,8 +74,7 @@ TEST(Parser, VariableDeclarationAdditionOfVariables)
TEST(Parser, VariableDeclarationMultiplicationOfLiterals)
{
- IPLVector<Token> tokens;
- Tokenize("var s = 5 * 6;", tokens);
+ IPLVector<Token> tokens = Tokenize("var s = 5 * 6;").tokens;
auto expr = Parse(tokens);
std::ostringstream output;
@@ -92,8 +86,7 @@ TEST(Parser, VariableDeclarationMultiplicationOfLiterals)
TEST(Parser, VariableDeclarationMultiplicationOfVariables)
{
- IPLVector<Token> tokens;
- Tokenize("var a = 5; var b = 4; var c = a * b;", tokens);
+ IPLVector<Token> tokens = Tokenize("var a = 5; var b = 4; var c = a * b;").tokens;
auto expr = Parse(tokens);
std::ostringstream output;
@@ -110,8 +103,7 @@ TEST(Parser, VariableDeclarationMultiplicationOfVariables)
TEST(Parser, Unary)
{
- IPLVector<Token> tokens;
- Tokenize("var a = 5; a++; var b = 6; --b;", tokens);
+ IPLVector<Token> tokens = Tokenize("var a = 5; a++; var b = 6; --b;").tokens;
auto expr = Parse(tokens);
std::ostringstream output;
@@ -127,8 +119,7 @@ TEST(Parser, Unary)
TEST(Parser, If)
{
{
- IPLVector<Token> tokens;
- Tokenize("var a = 5; var b = 3; if(a == 5){a++; b++;} b++;", tokens);
+ IPLVector<Token> tokens = Tokenize("var a = 5; var b = 3; if(a == 5){a++; b++;} b++;").tokens;
auto expr = Parse(tokens);
std::ostringstream output;
@@ -140,8 +131,7 @@ TEST(Parser, If)
ASSERT_DOUBLE_EQ(i.ModifyVariable("b"), 5.0);
}
{
- IPLVector<Token> tokens;
- Tokenize("var a = 5; var b = 3; if(a == 5)a++; b++; b++;", tokens);
+ IPLVector<Token> tokens = Tokenize("var a = 5; var b = 3; if(a == 5)a++; b++; b++;").tokens;
auto expr = Parse(tokens);
std::ostringstream output;
@@ -154,8 +144,7 @@ TEST(Parser, If)
}
{
- IPLVector<Token> tokens;
- Tokenize("var a = 5; var b = 3; if(a != 5)a++; b++; b++;", tokens);
+ IPLVector<Token> tokens = Tokenize("var a = 5; var b = 3; if(a != 5)a++; b++; b++;").tokens;
auto expr = Parse(tokens);
std::ostringstream output;
@@ -168,8 +157,7 @@ TEST(Parser, If)
}
{
- IPLVector<Token> tokens;
- Tokenize("var a = 5; var b = 3; if(a != 5){a++;} else { b++;}b++;", tokens);
+ IPLVector<Token> tokens = Tokenize("var a = 5; var b = 3; if(a != 5){a++;} else { b++;}b++;").tokens;
auto expr = Parse(tokens);
std::ostringstream output;
@@ -182,8 +170,7 @@ TEST(Parser, If)
}
{
- IPLVector<Token> tokens;
- Tokenize("var a = 5; var b = 3; if(a == 5){a++;} else { b++;}b++;", tokens);
+ IPLVector<Token> tokens = Tokenize("var a = 5; var b = 3; if(a == 5){a++;} else { b++;}b++;").tokens;
auto expr = Parse(tokens);
std::ostringstream output;
@@ -199,8 +186,7 @@ TEST(Parser, If)
TEST(Parser, For)
{
{
- IPLVector<Token> tokens;
- Tokenize("var i = 0; for (var j = 0; j < 10; j++) { i = i + j; }", tokens);
+ IPLVector<Token> tokens = Tokenize("var i = 0; for (var j = 0; j < 10; j++) { i = i + j; }").tokens;
auto expr = Parse(tokens);
std::ostringstream output;
@@ -210,8 +196,7 @@ TEST(Parser, For)
ASSERT_DOUBLE_EQ(i.ModifyVariable("i"), 45.0);
}
{
- IPLVector<Token> tokens;
- Tokenize("var i = 0; for (var j = 0; j < 10; j++) i = i + j;", tokens);
+ IPLVector<Token> tokens = Tokenize("var i = 0; for (var j = 0; j < 10; j++) i = i + j;").tokens;
auto expr = Parse(tokens);
std::ostringstream output;
ASTInterpreter i;