Website Summary Files Commits Branches @commit @diff @stats
path: root / JSImpl / src
diff options
context:
space:
mode:
Commit560a585091f1948efb47d58c82dede281ebef54d (patch)
Author
 martin dobrev <martindobrev0@gmail.com>
2018-09-07 19:00:01 +0300
Committer
 martin dobrev <martindobrev0@gmail.com>
2018-09-07 19:00:01 +0300
Filese62ac68d4fe03881be70b7ce6f400fb0a63060a9 /JSImpl/src
IPL-560a585091f1948efb47d58c82dede281ebef54d.tar
IPL-560a585091f1948efb47d58c82dede281ebef54d.tar.gz
IPL-560a585091f1948efb47d58c82dede281ebef54d.zip
Parent23067c0e3a92d452c1f8f3519c64d970a27732e3 (diff)
Introduce Parser and Expression hierarchy.
5 files changed, 371 insertions, 0 deletions
-rw-r--r--JSImpl/src/Expression.cpp100
-rw-r--r--JSImpl/src/Expression.h71
-rw-r--r--JSImpl/src/Parser.cpp182
-rw-r--r--JSImpl/src/Parser.h7
-rw-r--r--JSImpl/src/main.cpp11
diff --git a/JSImpl/src/Expression.cpp b/JSImpl/src/Expression.cpp
new file mode 100644
index 0000000..8626578
--- /dev/null
+++ b/JSImpl/src/Expression.cpp
@@ -0,0 +1,100 @@
+#include "Expression.h"
+
+BinaryExpression::BinaryExpression(IPLSharedPtr<Expression> exprLeft, IPLSharedPtr<Expression> exprRight, TokenType op)
+: m_Left(exprLeft)
+, m_Right(exprRight)
+, m_Operator(op)
+{}
+
+IPLString BinaryExpression::GetBinaryTypeAsString()
+{
+ // TODO: Implement
+ return "Binary";
+}
+
+void BinaryExpression::Print(std::ostream& os)
+{
+ os << "{ \n";
+ os << " Expression Type: Binary";
+ os << " Left expr: ";
+ m_Left->Print(os);
+
+ os << " Right expr:";
+ m_Right->Print(os);
+
+ os << " Operator Type: " << GetBinaryTypeAsString();
+ os << "\n}\n";
+}
+
+
+
+UnaryExpression::UnaryExpression(IPLSharedPtr<Expression> expr, TokenType op, bool suffix)
+ : m_Expr(expr)
+ , m_Operator(op)
+ , m_Suffix(suffix)
+{
+}
+
+void UnaryExpression::Print(std::ostream& os)
+{
+ os << "{ \n";
+ os << " Expression Type: Unary";
+ os << " Expr: ";
+ m_Expr->Print(os);
+
+ os << " Operator Type: " << GetBinaryTypeAsString() << std::endl;
+ os << "\n}\n";
+}
+
+IPLString UnaryExpression::GetBinaryTypeAsString()
+{
+ // TODO: Implement
+ return "Unary";
+}
+
+LiteralExpression::LiteralExpression(double v)
+ :m_Type(LiteralType::Number)
+ , m_NumValue(v)
+{}
+
+LiteralExpression::LiteralExpression(IPLString& v)
+ : m_Type(LiteralType::String)
+ , m_StringValue(v)
+{}
+
+LiteralExpression::LiteralExpression(bool v)
+ : m_Type(LiteralType::Boolean)
+ , m_BooleanValue(v)
+{}
+
+LiteralExpression::LiteralExpression(LiteralType type)
+ : m_Type(type)
+{}
+
+void LiteralExpression::Print(std::ostream& os)
+{
+ os << "{ \n";
+ os << " Literal Type: Unary";
+ os << " Literal value: ";
+ switch (m_Type)
+ {
+ case LiteralType::Number:
+ os << m_NumValue;
+ break;
+ case LiteralType::String:
+ os << m_StringValue;
+ break;
+ case LiteralType::Boolean:
+ os << m_BooleanValue;
+ break;
+ case LiteralType::Null:
+ os << "null";
+ case LiteralType::Undefined:
+ os << "undefined";
+ break;
+ default:
+ break;
+ }
+
+ os << "\n}\n";
+}
diff --git a/JSImpl/src/Expression.h b/JSImpl/src/Expression.h
new file mode 100644
index 0000000..f2ad3e6
--- /dev/null
+++ b/JSImpl/src/Expression.h
@@ -0,0 +1,71 @@
+#pragma once
+
+#include "CommonTypes.h"
+#include "Lexer.h"
+
+class Expression : public IPLEnableShared<Expression>
+{
+
+ public:
+ virtual ~Expression() {}
+ virtual void Print(std::ostream& os) {};
+};
+
+using ExpressionPtr = IPLSharedPtr<Expression>;
+
+// binary:= expression operator expression
+class BinaryExpression : public Expression
+{
+public:
+ virtual ~BinaryExpression() {}
+ BinaryExpression(IPLSharedPtr<Expression> exprLeft, IPLSharedPtr<Expression> exprRight, TokenType op);
+ virtual void Print(std::ostream& os);
+private:
+ IPLString GetBinaryTypeAsString();
+private:
+ IPLSharedPtr<Expression> m_Left;
+ IPLSharedPtr<Expression> m_Right;
+ TokenType m_Operator;
+};
+
+// binary:= expression operator |
+// operator expression
+class UnaryExpression : public Expression
+{
+public:
+ virtual ~UnaryExpression() {}
+ UnaryExpression(IPLSharedPtr<Expression> expr, TokenType op, bool suffix);
+ virtual void Print(std::ostream& os);
+private:
+ IPLString GetBinaryTypeAsString();
+private:
+ IPLSharedPtr<Expression> m_Expr;
+ TokenType m_Operator;
+ bool m_Suffix;
+};
+
+// literal:= number | string | true | false | null | undefined
+class LiteralExpression : public Expression
+{
+public:
+ enum LiteralType
+ {
+ Number,
+ String,
+ Boolean,
+ Null,
+ Undefined,
+ };
+ virtual ~LiteralExpression() {}
+ LiteralExpression(double);
+ LiteralExpression(IPLString&);
+ LiteralExpression(bool);
+ LiteralExpression(LiteralType type);
+ virtual void Print(std::ostream& os);
+private:
+ double m_NumValue;
+ IPLString m_StringValue;
+ bool m_BooleanValue;
+ LiteralType m_Type;
+};
+
diff --git a/JSImpl/src/Parser.cpp b/JSImpl/src/Parser.cpp
new file mode 100644
index 0000000..1eceb7f
--- /dev/null
+++ b/JSImpl/src/Parser.cpp
@@ -0,0 +1,182 @@
+#include "Parser.h"
+
+class Parser
+{
+public:
+ Parser(IPLVector<Token>& tokens, const std::function<void()>& onError = {});
+ ExpressionPtr Parse();
+private:
+ bool MatchOneOf(IPLVector<TokenType> types);
+ bool Match(TokenType type);
+ ExpressionPtr Unary();
+ ExpressionPtr LeftSideExpression();
+ ExpressionPtr SimpleExpression();
+
+ Token& Prev() { return m_Tokens[m_Current - 1]; }
+ std::function<void()> OnError;
+ unsigned m_Current;
+ IPLVector<Token> m_Tokens;
+};
+
+Parser::Parser(IPLVector<Token>& tokens, const std::function<void()>& onError)
+ : m_Tokens(tokens)
+ , OnError(onError)
+ , m_Current(0)
+{
+}
+
+bool Parser::MatchOneOf(IPLVector<TokenType> types)
+{
+ for (auto t : types)
+ {
+ if (t == m_Tokens[m_Current].Type)
+ {
+ ++m_Current;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Parser::Match(TokenType type)
+{
+ if (type == m_Tokens[m_Current].Type)
+ {
+ ++m_Current;
+ return true;
+ }
+ return false;
+}
+
+ExpressionPtr Parser::SimpleExpression()
+{
+ //SimpleExpression
+ // this
+ // | null
+ // | true
+ // | false
+ // | Number
+ // | String
+ // | Identifier
+ // | RegularExpression
+ // | ParenthesizedExpression
+ // | ArrayLiteral
+ if (Match({TokenType::Number}))
+ {
+ return IPLMakeSharePtr<LiteralExpression>(Prev().Number);
+ }
+ else if (Match({ TokenType::String }))
+ {
+ return IPLMakeSharePtr<LiteralExpression>(Prev().Lexeme);
+ }
+ else
+ {
+ // TODO implement
+ return ExpressionPtr();
+ }
+}
+
+ExpressionPtr Parser::LeftSideExpression()
+{
+ //LeftSideExpression ->
+ // CallExpression
+ // | ShortNewExpression
+
+ // CallExpression ->
+ // PrimaryExpression
+ // | FullNewExpression
+ // | CallExpression MemberOperator
+ // | CallExpression Arguments
+
+ // FullNewExpression -> new FullNewSubexpression Arguments
+
+ // ShortNewExpression -> new ShortNewSubexpression
+
+ // FullNewSubexpression ->
+ // PrimaryExpressionnormal
+ // | FullNewExpression
+ // | FullNewSubexpression MemberOperator
+
+ // ShortNewSubexpression ->
+ // FullNewSubexpression
+ // | ShortNewExpression
+
+ // MemberOperator ->
+ // [Expressionnormal, allowIn]
+ //| .Identifier
+
+ // Arguments ->
+ // ()
+ // | (ArgumentList)
+
+ // ArgumentList ->
+ // AssignmentExpressionnormal, allowIn
+ // | ArgumentList, AssignmentExpressionnormal, allowIn
+ return SimpleExpression();
+}
+
+ExpressionPtr Parser::Unary()
+{
+
+ //UnaryExpression
+ // PostfixExpression
+ // | delete LeftSideExpressionnormal
+ // | ++LeftSideExpressionnormal
+ // | --LeftSideExpressionnormal
+ // | void UnaryExpressionnormal
+ // | typeof UnaryExpressionnormal
+ // | +UnaryExpressionnormal
+ // | -UnaryExpressionnormal
+ // | ~UnaryExpressionnormal
+ // | !UnaryExpressionnormal
+ if (MatchOneOf({
+ TokenType::Delete,
+ TokenType::MinusMinus,
+ TokenType::PlusPlus,
+ }))
+ {
+ auto ls = LeftSideExpression();
+ auto suffix = false;
+ return IPLMakeSharePtr<UnaryExpression>(ls, Prev().Type, suffix);
+ }
+ else if (MatchOneOf({
+ TokenType::Void,
+ TokenType::Typeof,
+ TokenType::Plus,
+ TokenType::Minus,
+ TokenType::BitwiseNot,
+ TokenType::Bang,
+ }))
+ {
+ auto ls = Unary();
+ auto suffix = false;
+ return IPLMakeSharePtr<UnaryExpression>(ls, Prev().Type, suffix);
+ }
+ else
+ {
+ //PostfixExpression
+ // LeftSideExpression
+ // | LeftSideExpression++
+ // | LeftSideExpression--
+ auto leftSide = LeftSideExpression();
+ if (MatchOneOf({ TokenType::PlusPlus, TokenType::MinusMinus }))
+ {
+ auto suffix = true;
+ return IPLMakeSharePtr<UnaryExpression>(leftSide, Prev().Type, suffix);
+ }
+ return leftSide;
+ }
+}
+
+ExpressionPtr Parser::Parse()
+{
+ // TODO implement full grammar
+ return Unary();
+}
+
+
+ExpressionPtr Parse(IPLVector<Token>& tokens, const std::function<void()>& onError)
+{
+ Parser p(tokens, onError);
+ return p.Parse();
+} \ No newline at end of file
diff --git a/JSImpl/src/Parser.h b/JSImpl/src/Parser.h
new file mode 100644
index 0000000..15b8a2f
--- /dev/null
+++ b/JSImpl/src/Parser.h
@@ -0,0 +1,7 @@
+#pragma
+
+#include "CommonTypes.h"
+#include "Expression.h"
+#include "Lexer.h"
+
+ExpressionPtr Parse(IPLVector<Token>&, const std::function<void()>& onError = {}); \ No newline at end of file
diff --git a/JSImpl/src/main.cpp b/JSImpl/src/main.cpp
index 1b345c3..43c063d 100644
--- a/JSImpl/src/main.cpp
+++ b/JSImpl/src/main.cpp
@@ -1,7 +1,10 @@
#include "Lexer.h"
+#include "Parser.h"
#include <iostream>
#define LOG(msg) std::cout << msg << std::endl
#define EXECUTE_TEST(test) std::cout << #test << " "; test();
+
+// Lexer Tests
void TestLess()
{
auto tokens = Tokenize("<");
@@ -70,6 +73,13 @@ void TestVariableDeclaration()
LOG("FAIL");
}
}
+// Parser Tests
+void TestParseUnaryExpr()
+{
+ // TODO make actual test :D
+ auto expr = Parse(Tokenize("-10"));
+ expr->Print(std::cout);
+}
int main()
{
@@ -78,6 +88,7 @@ int main()
EXECUTE_TEST(TestString);
EXECUTE_TEST(TestKeyWord);
EXECUTE_TEST(TestVariableDeclaration);
+ EXECUTE_TEST(TestParseUnaryExpr);
std::system("pause");
return 0;
} \ No newline at end of file