MalachScript/src/Parser/Parser.hpp

186 lines
10 KiB
C++

#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<const IdentifierToken*>(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<Identifier>& out, const LexToken*& currentToken);
bool ParseType(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
bool ParseAssign(ScopedPtr<const ParsedStatement>& 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<const ParsedStatement>& out, const LexToken*& currentToken);
// Cast
bool ParseLiteral(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
bool ParseTypeMod(TypeMod& typeMod, const LexToken*& currentToken);
// Lambda
bool ParseExprValue(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
// ExprPostOp
bool ParseExprTerm(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
bool ParseExpr(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
bool ParseTernary(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
bool ParseReturn(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
bool ParseExprStat(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
bool ParseContinue(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
bool ParseBreak(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
bool ParseIfStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
bool ParseForStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
// While
// DoWhile
// Try
// Case
// Switch
bool ParseStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
bool ParseVar(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
bool ParseStatBlock(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
bool ParseFuncAttr(FuncAttr& out, const LexToken*& currentToken);
bool ParseParamList(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
bool ParseVirtProp(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
bool ParseFunc(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
bool ParseFuncDef(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
bool ParseClass(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
// Mixin
// Enum
// Import
bool ParseTypeDef(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
// InterfaceMethod
// Interface
bool ParseNamespace(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
const ParsedScriptStatement* ParseScript();
};
}
#endif // MALACHSCRIPT_PARSER_HPP