#ifndef MALACHSCRIPT_PARSER_HPP #define MALACHSCRIPT_PARSER_HPP #include "../CoreData/Operators.hpp" #include "../Diagnostics/Diagnostics.hpp" #include "../Utils/ScopedPtr.hpp" #include "Lexer/LexToken.hpp" #include "Statements/ParsedStatement.hpp" namespace MalachScript::Parser { class Parser { public: Parser(std::u8string_view scriptName, const LexToken* firstToken, Diagnostics::Diagnostics* diagnostics) : _scriptName(scriptName), _diagnostics(diagnostics), _firstToken(firstToken) {} const ParsedScriptStatement* Parse(); private: std::u8string_view _scriptName; Diagnostics::Diagnostics* _diagnostics; const LexToken* _firstToken; inline void LogError(Diagnostics::DiagnosticType type, const TextSpan& span) { _diagnostics->LogError(type, _scriptName, span); } ///////////////////////////////////////////////////////////////////////////////////////// // 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; } } bool ParsePrimType(Identifier& out, const LexToken*& currentToken); bool ParseDataType(Identifier& out, const LexToken*& currentToken); bool ParseScope(std::vector& out, const LexToken*& currentToken); bool ParseType(ScopedPtr& out, const LexToken*& currentToken); bool ParseAssign(ScopedPtr& out, const LexToken*& currentToken); // InitList inline static bool ParsePreOp(PreOperator& op, const LexToken*& token) { 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 bool ParseVarAccess(ScopedPtr& out, const LexToken*& currentToken); // Cast bool ParseLiteral(ScopedPtr& out, const LexToken*& currentToken); bool ParseTypeMod(TypeMod& typeMod, const LexToken*& currentToken); // Lambda bool ParseExprValue(ScopedPtr& out, const LexToken*& currentToken); // ExprPostOp bool ParseExprTerm(ScopedPtr& out, const LexToken*& currentToken); bool ParseExpr(ScopedPtr& out, const LexToken*& currentToken); bool ParseTernary(ScopedPtr& out, const LexToken*& currentToken); bool ParseReturn(ScopedPtr& out, const LexToken*& currentToken); bool ParseExprStat(ScopedPtr& out, const LexToken*& currentToken); bool ParseContinue(ScopedPtr& out, const LexToken*& currentToken); bool ParseBreak(ScopedPtr& out, const LexToken*& currentToken); bool ParseIfStatement(ScopedPtr& out, const LexToken*& currentToken); bool ParseForStatement(ScopedPtr& out, const LexToken*& currentToken); // While // DoWhile // Try // Case // Switch bool ParseStatement(ScopedPtr& out, const LexToken*& currentToken); bool ParseVar(ScopedPtr& out, const LexToken*& currentToken); bool ParseStatBlock(ScopedPtr& out, const LexToken*& currentToken); bool ParseFuncAttr(FuncAttr& out, const LexToken*& currentToken); bool ParseParamList(ScopedPtr& out, const LexToken*& currentToken); bool ParseVirtProp(ScopedPtr& out, const LexToken*& currentToken); bool ParseFunc(ScopedPtr& out, const LexToken*& currentToken); bool ParseFuncDef(ScopedPtr& out, const LexToken*& currentToken); bool ParseClass(ScopedPtr& out, const LexToken*& currentToken); // Mixin // Enum // Import bool ParseTypeDef(ScopedPtr& out, const LexToken*& currentToken); // InterfaceMethod // Interface bool ParseNamespace(ScopedPtr& out, const LexToken*& currentToken); const ParsedScriptStatement* ParseScript(); }; } #endif // MALACHSCRIPT_PARSER_HPP