diff options
| Commit | 560a585091f1948efb47d58c82dede281ebef54d (patch) | |
|---|---|---|
| Author | 2018-09-07 19:00:01 +0300 | |
| Committer | 2018-09-07 19:00:01 +0300 | |
| Files | e62ac68d4fe03881be70b7ce6f400fb0a63060a9 /JSImpl/src | |
| IPL-560a585091f1948efb47d58c82dede281ebef54d.tar IPL-560a585091f1948efb47d58c82dede281ebef54d.tar.gz IPL-560a585091f1948efb47d58c82dede281ebef54d.zip | ||
| Parent | 23067c0e3a92d452c1f8f3519c64d970a27732e3 (diff) | |
Introduce Parser and Expression hierarchy.
5 files changed, 371 insertions, 0 deletions
| -rw-r--r-- | JSImpl/src/Expression.cpp | 100 | ||||
| -rw-r--r-- | JSImpl/src/Expression.h | 71 | ||||
| -rw-r--r-- | JSImpl/src/Parser.cpp | 182 | ||||
| -rw-r--r-- | JSImpl/src/Parser.h | 7 | ||||
| -rw-r--r-- | JSImpl/src/main.cpp | 11 |
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 |
