#ifndef MALACHSCRIPT_PARSER_HPP #define MALACHSCRIPT_PARSER_HPP #include #include "../CoreData/Operators.hpp" #include "../Diagnostics/Logger.hpp" #include "../Utils/ScopedPtr.hpp" #include "Lexer/LexToken.hpp" #include "Statements/ParsedStatement.hpp" namespace MalachScript::Parser { class Parser { public: static const ParsedScriptStatement* Parse(const LexToken* firstToken, Diagnostics::Logger* diagnostics); private: using log_func = const std::function&)>; ///////////////////////////////////////////////////////////////////////////////////////// // Underlying functions are laid out in the order they are defined in the grammar.ebnf // ///////////////////////////////////////////////////////////////////////////////////////// static inline bool ParseIdentifier(Identifier& out, const LexToken* token) { if (token->GetKind() != LexTokenKind::Identifier) { return false; } out = reinterpret_cast(token)->GetValue(); return true; } static inline bool ParseAssignOp(AssignmentOperator& op, const LexToken*& token) { switch (token->GetKind()) { case LexTokenKind::EqualsSymbol: op = AssignmentOperator::Assignment; return true; case LexTokenKind::PlusEqualsSymbol: op = AssignmentOperator::AdditionAssignment; return true; case LexTokenKind::MinusEqualsSymbol: op = AssignmentOperator::SubtractionAssignment; return true; case LexTokenKind::StarEqualsSymbol: op = AssignmentOperator::MultiplicationAssignment; return true; case LexTokenKind::SlashEqualsSymbol: op = AssignmentOperator::DivisionAssignment; return true; case LexTokenKind::VerticalLineEqualsSymbol: op = AssignmentOperator::BitwiseOrAssignment; return true; case LexTokenKind::AmpersandEqualsSymbol: op = AssignmentOperator::BitwiseAndAssignment; return true; case LexTokenKind::CaretEqualsSymbol: op = AssignmentOperator::BitwiseXorAssignment; return true; case LexTokenKind::PercentEqualsSymbol: op = AssignmentOperator::ModuloAssignment; return true; case LexTokenKind::StarStarEqualsSymbol: op = AssignmentOperator::ExponentiationAssignment; return true; case LexTokenKind::LessThanLessThanEqualsSymbol: op = AssignmentOperator::BitwiseLeftShiftAssignment; return true; case LexTokenKind::GreaterThanGreaterThanEqualsSymbol: op = AssignmentOperator::BitwiseRightShiftAssignment; return true; case LexTokenKind::GreaterThanGreaterThanGreaterThanEqualsSymbol: op = AssignmentOperator::ArithmeticRightShiftAssignment; return true; default: return false; } } static inline bool ParseLogicOp(LogicOperator& op, const LexToken*& token) { switch (token->GetKind()) { case LexTokenKind::AmpersandAmpersandSymbol: case LexTokenKind::AndKeyword: op = LogicOperator::LogicalAnd; return true; case LexTokenKind::VerticalLineVerticalLineSymbol: case LexTokenKind::OrKeyword: op = LogicOperator::LogicalOr; return true; case LexTokenKind::CaretCaretSymbol: case LexTokenKind::XorKeyword: op = LogicOperator::LogicalXor; return true; default: return false; } } static inline bool ParseCompOp(ComparisonOperator& op, const LexToken*& token) { switch (token->GetKind()) { case LexTokenKind::EqualsEqualsSymbol: op = ComparisonOperator::Equality; return true; case LexTokenKind::ExclamationMarkEqualsSymbol: op = ComparisonOperator::Inequality; return true; case LexTokenKind::LessThanSymbol: op = ComparisonOperator::LessThan; return true; case LexTokenKind::LessThanEqualsSymbol: op = ComparisonOperator::LessThanEquals; return true; case LexTokenKind::GreaterThanSymbol: op = ComparisonOperator::GreaterThan; return true; case LexTokenKind::GreaterThanEqualsSymbol: op = ComparisonOperator::GreaterThanEquals; return true; case LexTokenKind::IsKeyword: op = ComparisonOperator::Identity; return true; case LexTokenKind::ExclamationMarkIsSymbol: op = ComparisonOperator::InverseIdentity; return true; default: return false; } } static inline bool ParseMathOp(MathOperator& op, const LexToken*& token) { switch (token->GetKind()) { case LexTokenKind::PlusSymbol: op = MathOperator::Addition; return true; case LexTokenKind::MinusSymbol: op = MathOperator::Subtraction; return true; case LexTokenKind::StarSymbol: op = MathOperator::Multiplication; return true; case LexTokenKind::SlashSymbol: op = MathOperator::Division; return true; case LexTokenKind::PercentSymbol: op = MathOperator::Modulo; return true; case LexTokenKind::StarStarSymbol: op = MathOperator::Exponentiation; return true; default: return false; } } static inline bool ParseBitOp(BitOperator& op, const LexToken*& token) { switch (token->GetKind()) { case LexTokenKind::AmpersandSymbol: op = BitOperator::BitwiseAnd; return true; case LexTokenKind::VerticalLineSymbol: op = BitOperator::BitwiseOr; return true; case LexTokenKind::CaretSymbol: op = BitOperator::BitwiseXor; return true; case LexTokenKind::LessThanLessThanSymbol: op = BitOperator::BitwiseLeftShift; return true; case LexTokenKind::GreaterThanGreaterThanSymbol: op = BitOperator::BitwiseRightShift; return true; case LexTokenKind::GreaterThanGreaterThanGreaterThanSymbol: op = BitOperator::ArithmeticRightShift; return true; default: return false; } } static bool ParsePrimType(Identifier& out, const LexToken*& currentToken, const log_func&); static bool ParseDataType(Identifier& out, const LexToken*& currentToken, const log_func&); static bool ParseScope(std::vector& out, const LexToken*& currentToken, const log_func&); static bool ParseType(ScopedPtr& out, const LexToken*& currentToken, const log_func&); static bool ParseAssign(ScopedPtr& out, const LexToken*& currentToken, const log_func&); // InitList inline static bool ParsePreOp(PreOperator& op, const LexToken*& token, const log_func&) { switch (token->GetKind()) { case LexTokenKind::MinusSymbol: op = PreOperator::Negation; return true; case LexTokenKind::PlusSymbol: op = PreOperator::Identity; return true; case LexTokenKind::ExclamationMarkSymbol: op = PreOperator::Inversion; return true; case LexTokenKind::PlusPlusSymbol: op = PreOperator::Increment; return true; case LexTokenKind::MinusMinusSymbol: op = PreOperator::Decrement; return true; case LexTokenKind::TildeSymbol: op = PreOperator::BitwiseComplement; return true; case LexTokenKind::AtSymbol: op = PreOperator::Handle; return true; default: return false; } } // ArgList // FuncCall // ConstructCall static bool ParseVarAccess(ScopedPtr& out, const LexToken*& currentToken, const log_func&); // Cast static bool ParseLiteral(ScopedPtr& out, const LexToken*& currentToken, const log_func&); static bool ParseTypeMod(TypeMod& typeMod, const LexToken*& currentToken, const log_func&); // Lambda static bool ParseExprValue(ScopedPtr& out, const LexToken*& currentToken, const log_func&); // ExprPostOp static bool ParseExprTerm(ScopedPtr& out, const LexToken*& currentToken, const log_func&); static bool ParseExpr(ScopedPtr& out, const LexToken*& currentToken, const log_func&); static bool ParseTernary(ScopedPtr& out, const LexToken*& currentToken, const log_func&); static bool ParseReturn(ScopedPtr& out, const LexToken*& currentToken, const log_func&); static bool ParseExprStat(ScopedPtr& out, const LexToken*& currentToken, const log_func&); static bool ParseContinue(ScopedPtr& out, const LexToken*& currentToken, const log_func&); static bool ParseBreak(ScopedPtr& out, const LexToken*& currentToken, const log_func&); static bool ParseIfStatement(ScopedPtr& out, const LexToken*& currentToken, const log_func&); static bool ParseForStatement(ScopedPtr& out, const LexToken*& currentToken, const log_func&); static bool ParseWhileStatement(ScopedPtr& out, const LexToken*& currentToken, const log_func&); static bool ParseDoWhileStatement(ScopedPtr& out, const LexToken*& currentToken, const log_func&); static bool ParseTryStatement(ScopedPtr& out, const LexToken*& currentToken, const log_func&); static bool ParseCaseStatement(ScopedPtr& out, const LexToken*& currentToken, const log_func&); static bool ParseSwitchStatement(ScopedPtr& out, const LexToken*& currentToken, const log_func&); static bool ParseStatement(ScopedPtr& out, const LexToken*& currentToken, const log_func&); static bool ParseVar(ScopedPtr& out, const LexToken*& currentToken, const log_func&); static bool ParseStatBlock(ScopedPtr& out, const LexToken*& currentToken, const log_func&); static bool ParseFuncAttr(FuncAttr& out, const LexToken*& currentToken, const log_func&); static bool ParseParamList(ScopedPtr& out, const LexToken*& currentToken, const log_func&); static bool ParseVirtProp(ScopedPtr& out, const LexToken*& currentToken, const log_func&); static bool ParseFunc(ScopedPtr& out, const LexToken*& currentToken, const log_func&); static bool ParseFuncDef(ScopedPtr& out, const LexToken*& currentToken, const log_func&); static bool ParseClass(ScopedPtr& out, const LexToken*& currentToken, const log_func&); // Mixin // Enum // Import static bool ParseTypeDef(ScopedPtr& out, const LexToken*& currentToken, const log_func&); // InterfaceMethod // Interface static bool ParseNamespace(ScopedPtr& out, const LexToken*& currentToken, const log_func&); static bool ParseScript(ScopedPtr& out, const LexToken*& currentToken, const log_func&); }; } #endif // MALACHSCRIPT_PARSER_HPP