Large chunk of work in parser for getting expressions to work.
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
c20a1089a9
commit
5fb64e12e1
|
@ -62,7 +62,7 @@ expr ::= exprterm {(mathop | compop | logicop | bitop) exprterm};
|
|||
ternary ::= expr ['?' assign : assign];
|
||||
|
||||
return ::= 'return' [assign] ';';
|
||||
exprstat ::= [assign] ';';
|
||||
exprstat ::= assign ';';
|
||||
continue ::= 'continue' ';';
|
||||
break ::= 'break' ';';
|
||||
|
||||
|
|
|
@ -54,6 +54,16 @@ namespace MalachScript {
|
|||
BitwiseRightShift,
|
||||
ArithmeticRightShift,
|
||||
};
|
||||
|
||||
enum class PreOperator : uint8_t {
|
||||
Negation,
|
||||
Identity,
|
||||
Inversion,
|
||||
Increment,
|
||||
Decrement,
|
||||
BitwiseComplement,
|
||||
Handle
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MALACHSCRIPT_OPERATORS_HPP
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <memory>
|
||||
#include "../../CoreData/Identifier.hpp"
|
||||
#include "../../TextSpan.hpp"
|
||||
#include "../ParserDefines.hpp"
|
||||
#include "LexTokenKind.hpp"
|
||||
|
||||
namespace MalachScript::Parser {
|
||||
|
@ -28,30 +29,30 @@ namespace MalachScript::Parser {
|
|||
};
|
||||
|
||||
class IntegerLiteral : public LexTokenImpl<LexTokenKind::IntegerLiteral> {
|
||||
uint64_t _value;
|
||||
ParseInt _value;
|
||||
|
||||
public:
|
||||
IntegerLiteral(const TextSpan& span, uint64_t value)
|
||||
IntegerLiteral(const TextSpan& span, ParseInt value)
|
||||
: LexTokenImpl<LexTokenKind::IntegerLiteral>(span), _value(value) {}
|
||||
[[nodiscard]] inline uint64_t GetValue() const noexcept { return _value; }
|
||||
[[nodiscard]] inline ParseInt GetValue() const noexcept { return _value; }
|
||||
};
|
||||
|
||||
class FloatLiteral : public LexTokenImpl<LexTokenKind::FloatLiteral> {
|
||||
double _value;
|
||||
ParseFloat _value;
|
||||
|
||||
public:
|
||||
FloatLiteral(const TextSpan& span, double value)
|
||||
FloatLiteral(const TextSpan& span, ParseFloat value)
|
||||
: LexTokenImpl<LexTokenKind::FloatLiteral>(span), _value(value) {}
|
||||
[[nodiscard]] inline double GetValue() const noexcept { return _value; }
|
||||
[[nodiscard]] inline long double GetValue() const noexcept { return _value; }
|
||||
};
|
||||
|
||||
class StringLiteral : public LexTokenImpl<LexTokenKind::StringLiteral> {
|
||||
std::u8string _value;
|
||||
ParseString _value;
|
||||
|
||||
public:
|
||||
StringLiteral(const TextSpan& span, std::u8string value)
|
||||
StringLiteral(const TextSpan& span, ParseString value)
|
||||
: LexTokenImpl<LexTokenKind::StringLiteral>(span), _value(std::move(value)) {}
|
||||
[[nodiscard]] inline const std::u8string& GetValue() const noexcept { return _value; }
|
||||
[[nodiscard]] inline const ParseString& GetValue() const noexcept { return _value; }
|
||||
};
|
||||
|
||||
class IdentifierToken : public LexTokenImpl<LexTokenKind::Identifier> {
|
||||
|
|
|
@ -338,16 +338,16 @@ namespace MalachScript::Parser {
|
|||
return pow10[n];
|
||||
}
|
||||
|
||||
LexToken* Lexer::LexDecimal(uint64_t initial) {
|
||||
LexToken* Lexer::LexDecimal(ParseInt initial) {
|
||||
auto start = _position;
|
||||
uint64_t value = initial;
|
||||
uint64_t decimalValue = 0;
|
||||
uint64_t exponentValue = 0;
|
||||
ParseInt value = initial;
|
||||
ParseInt decimalValue = 0;
|
||||
ParseInt exponentValue = 0;
|
||||
uint8_t decimalLength = 0;
|
||||
bool isDecimal = false;
|
||||
bool isExponent = false;
|
||||
while (true) {
|
||||
auto v = (uint64_t)LexDecimalValue(Peek());
|
||||
auto v = (ParseInt)LexDecimalValue(Peek());
|
||||
if (v == 255) {
|
||||
if (!isDecimal && Peek() == u8'.') {
|
||||
isDecimal = true;
|
||||
|
@ -376,7 +376,7 @@ namespace MalachScript::Parser {
|
|||
}
|
||||
}
|
||||
if (isDecimal || isExponent) {
|
||||
auto val = value + ((double)decimalValue / quick_pow10(decimalLength));
|
||||
auto val = value + ((ParseFloat)decimalValue / quick_pow10(decimalLength));
|
||||
if (isExponent) {
|
||||
val *= pow(10, exponentValue);
|
||||
}
|
||||
|
@ -387,7 +387,7 @@ namespace MalachScript::Parser {
|
|||
|
||||
IntegerLiteral* Lexer::LexHexadecimal() {
|
||||
auto start = _position;
|
||||
uint64_t value = 0;
|
||||
ParseInt value = 0;
|
||||
while (true) {
|
||||
auto v = LexHexadecimalValue(Peek());
|
||||
if (v == 255) {
|
||||
|
@ -401,7 +401,7 @@ namespace MalachScript::Parser {
|
|||
}
|
||||
IntegerLiteral* Lexer::LexOctal() {
|
||||
auto start = _position;
|
||||
uint64_t value = 0;
|
||||
ParseInt value = 0;
|
||||
while (true) {
|
||||
auto v = LexOctalValue(Peek());
|
||||
if (v == 255) {
|
||||
|
@ -415,7 +415,7 @@ namespace MalachScript::Parser {
|
|||
}
|
||||
IntegerLiteral* Lexer::LexBinary() {
|
||||
auto start = _position;
|
||||
uint64_t value = 0;
|
||||
ParseInt value = 0;
|
||||
while (true) {
|
||||
auto v = LexBinaryValue(Peek());
|
||||
if (v == 255) {
|
||||
|
@ -457,7 +457,7 @@ namespace MalachScript::Parser {
|
|||
if (heredoc) {
|
||||
Progress(2);
|
||||
}
|
||||
return Create<StringLiteral>(TextSpan(start, start + _position), std::u8string(_script.substr(start, offset)));
|
||||
return Create<StringLiteral>(TextSpan(start, start + _position), ParseString(_script.substr(start, offset)));
|
||||
}
|
||||
|
||||
LexToken* Lexer::LexKeywordOrIdentifier() {
|
||||
|
|
|
@ -204,11 +204,13 @@ namespace MalachScript::Parser {
|
|||
}
|
||||
Identifier identifier;
|
||||
if (!ParseIdentifier(identifier, current)) {
|
||||
delete typeStatement;
|
||||
return false;
|
||||
}
|
||||
PROGRESS_TOKEN(current);
|
||||
const ParsedStatement* paramList = nullptr;
|
||||
if (!ParseParamList(paramList, current)) {
|
||||
delete typeStatement;
|
||||
return false;
|
||||
}
|
||||
bool isConst = false;
|
||||
|
@ -285,7 +287,7 @@ namespace MalachScript::Parser {
|
|||
return false;
|
||||
}
|
||||
|
||||
while (current != nullptr && current->GetKind() == LexTokenKind::ColonColonSymbol) {
|
||||
while (current->GetKind() == LexTokenKind::ColonColonSymbol) {
|
||||
PROGRESS_TOKEN(current);
|
||||
const auto* n = current;
|
||||
if (ParseIdentifier(identifier, n)) {
|
||||
|
@ -440,6 +442,7 @@ namespace MalachScript::Parser {
|
|||
}
|
||||
PROGRESS_TOKEN(current);
|
||||
if (current->GetKind() != LexTokenKind::OpenCurlyParenthesisSymbol) {
|
||||
delete typeStatement;
|
||||
return false;
|
||||
}
|
||||
bool hasGet = false;
|
||||
|
@ -464,8 +467,9 @@ namespace MalachScript::Parser {
|
|||
if (!ParseStatBlock(getStatement, current)) {
|
||||
this->LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
}
|
||||
} else {
|
||||
PROGRESS_TOKEN(current);
|
||||
}
|
||||
PROGRESS_TOKEN(current);
|
||||
|
||||
if (hasGet) {
|
||||
this->LogError(Diagnostics::DiagnosticType::DoubleProperty,
|
||||
|
@ -483,8 +487,9 @@ namespace MalachScript::Parser {
|
|||
if (!ParseStatBlock(setStatement, current)) {
|
||||
this->LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
}
|
||||
} else {
|
||||
PROGRESS_TOKEN(current);
|
||||
}
|
||||
PROGRESS_TOKEN(current);
|
||||
|
||||
if (hasSet) {
|
||||
this->LogError(Diagnostics::DiagnosticType::DoubleProperty,
|
||||
|
@ -541,7 +546,9 @@ namespace MalachScript::Parser {
|
|||
|
||||
bool Parser::ParseStatement(const ParsedStatement*& out, const LexToken*& currentToken) {
|
||||
// TODO: All the other statements.
|
||||
return ParseIfStatement(out, currentToken);
|
||||
|
||||
return ParseIfStatement(out, currentToken) || ParseReturn(out, currentToken) ||
|
||||
ParseStatBlock(out, currentToken) || ParseExprStat(out, currentToken);
|
||||
}
|
||||
|
||||
bool Parser::ParseVar([[maybe_unused]] const ParsedStatement*& out, const LexToken*& currentToken) {
|
||||
|
@ -566,11 +573,7 @@ namespace MalachScript::Parser {
|
|||
PROGRESS_TOKEN(current);
|
||||
// TODO: Default values
|
||||
// TODO: Creating multiple vars in a single line (int a, b, c)
|
||||
if (current->GetKind() == LexTokenKind::SemicolonSymbol) {
|
||||
PROGRESS_TOKEN(current);
|
||||
} else {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
}
|
||||
EXPECT_TOKEN(current, SemicolonSymbol);
|
||||
out = new ParsedVarStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), access,
|
||||
typeStatement, identifier);
|
||||
currentToken = current;
|
||||
|
@ -582,6 +585,7 @@ namespace MalachScript::Parser {
|
|||
if (current->GetKind() != LexTokenKind::OpenCurlyParenthesisSymbol) {
|
||||
return false;
|
||||
}
|
||||
PROGRESS_TOKEN(current);
|
||||
std::vector<const ParsedStatement*> statements;
|
||||
while (true) {
|
||||
if (current->GetKind() == LexTokenKind::CloseCurlyParenthesisSymbol) {
|
||||
|
@ -699,6 +703,7 @@ namespace MalachScript::Parser {
|
|||
}
|
||||
out = new ParsedBinaryStatement<MathOperator>(
|
||||
TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), leftHand, mathOp, rightHand);
|
||||
currentToken = current;
|
||||
return true;
|
||||
}
|
||||
ComparisonOperator compOp;
|
||||
|
@ -713,6 +718,7 @@ namespace MalachScript::Parser {
|
|||
}
|
||||
out = new ParsedBinaryStatement<ComparisonOperator>(
|
||||
TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), leftHand, compOp, rightHand);
|
||||
currentToken = current;
|
||||
return true;
|
||||
}
|
||||
LogicOperator logicOp;
|
||||
|
@ -728,6 +734,7 @@ namespace MalachScript::Parser {
|
|||
out = new ParsedBinaryStatement<LogicOperator>(
|
||||
TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), leftHand, logicOp,
|
||||
rightHand);
|
||||
currentToken = current;
|
||||
return true;
|
||||
}
|
||||
BitOperator bitOp;
|
||||
|
@ -742,6 +749,7 @@ namespace MalachScript::Parser {
|
|||
}
|
||||
out = new ParsedBinaryStatement<BitOperator>(
|
||||
TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), leftHand, bitOp, rightHand);
|
||||
currentToken = current;
|
||||
return true;
|
||||
}
|
||||
out = leftHand;
|
||||
|
@ -751,6 +759,135 @@ namespace MalachScript::Parser {
|
|||
|
||||
bool Parser::ParseExprTerm([[maybe_unused]] const ParsedStatement*& out,
|
||||
[[maybe_unused]] const LexToken*& currentToken) {
|
||||
const auto* current = currentToken;
|
||||
// TODO ([type '='] initlist)
|
||||
|
||||
PreOperator preOperator;
|
||||
bool hasPreOp = ParsePreOp(preOperator, currentToken);
|
||||
if (hasPreOp) {
|
||||
PROGRESS_TOKEN(current);
|
||||
}
|
||||
const ParsedStatement* operand = nullptr;
|
||||
if (!ParseExprValue(operand, current)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: remainder of
|
||||
if (current->GetKind() == LexTokenKind::PlusPlusSymbol) {
|
||||
operand = new ParsedIncrementStatement(TextSpan(operand->GetSpan().GetStart(), current->GetSpan().GetEnd()),
|
||||
operand);
|
||||
PROGRESS_TOKEN(current);
|
||||
} else if (current->GetKind() == LexTokenKind::MinusMinusSymbol) {
|
||||
operand = new ParsedDecrementStatement(TextSpan(operand->GetSpan().GetStart(), current->GetSpan().GetEnd()),
|
||||
operand);
|
||||
PROGRESS_TOKEN(current);
|
||||
}
|
||||
|
||||
if (hasPreOp) {
|
||||
// TODO: integrate pre operator
|
||||
}
|
||||
out = operand;
|
||||
currentToken = current;
|
||||
return true;
|
||||
}
|
||||
bool Parser::ParseExprValue(const ParsedStatement*& out, const LexToken*& currentToken) {
|
||||
const auto* current = currentToken;
|
||||
if (current->GetKind() == LexTokenKind::VoidKeyword) {
|
||||
PROGRESS_TOKEN(current);
|
||||
|
||||
out = new ParsedVoidStatement(currentToken->GetSpan());
|
||||
currentToken = current;
|
||||
return true;
|
||||
}
|
||||
// TODO: constructcall
|
||||
// TODO: funccall
|
||||
if (ParseVarAccess(out, current)) {
|
||||
currentToken = current;
|
||||
return true;
|
||||
}
|
||||
// TODO: cast
|
||||
if (ParseLiteral(out, current)) {
|
||||
currentToken = current;
|
||||
return true;
|
||||
}
|
||||
if (current->GetKind() == LexTokenKind::OpenParenthesisSymbol) {
|
||||
PROGRESS_TOKEN(current);
|
||||
if (!ParseAssign(out, current)) {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
}
|
||||
EXPECT_TOKEN(current, CloseParenthesisSymbol);
|
||||
return true;
|
||||
}
|
||||
// TODO: lambda
|
||||
|
||||
return false;
|
||||
}
|
||||
bool Parser::ParseLiteral(const ParsedStatement*& out, const LexToken*& currentToken) {
|
||||
switch (currentToken->GetKind()) {
|
||||
case LexTokenKind::IntegerLiteral:
|
||||
out = new ParsedLiteralStatement<ParseInt>(
|
||||
currentToken->GetSpan(), static_cast<const IntegerLiteral*>(currentToken)->GetValue());
|
||||
PROGRESS_TOKEN(currentToken);
|
||||
return true;
|
||||
case LexTokenKind::FloatLiteral:
|
||||
out = new ParsedLiteralStatement<ParseFloat>(
|
||||
currentToken->GetSpan(), static_cast<const FloatLiteral*>(currentToken)->GetValue());
|
||||
PROGRESS_TOKEN(currentToken);
|
||||
return true;
|
||||
case LexTokenKind::StringLiteral:
|
||||
out = new ParsedLiteralStatement<ParseString>(
|
||||
currentToken->GetSpan(), static_cast<const StringLiteral*>(currentToken)->GetValue());
|
||||
PROGRESS_TOKEN(currentToken);
|
||||
return true;
|
||||
case LexTokenKind::TrueKeyword:
|
||||
out = new ParsedLiteralStatement<bool>(currentToken->GetSpan(), true);
|
||||
PROGRESS_TOKEN(currentToken);
|
||||
return true;
|
||||
case LexTokenKind::FalseKeyword:
|
||||
out = new ParsedLiteralStatement<bool>(currentToken->GetSpan(), false);
|
||||
PROGRESS_TOKEN(currentToken);
|
||||
return true;
|
||||
case LexTokenKind::NullKeyword:
|
||||
out = new ParsedLiteralStatement<void*>(currentToken->GetSpan(), nullptr);
|
||||
PROGRESS_TOKEN(currentToken);
|
||||
return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
bool Parser::ParseReturn(const ParsedStatement*& out, const LexToken*& currentToken) {
|
||||
auto start = currentToken->GetSpan().GetStart();
|
||||
if (currentToken->GetKind() != LexTokenKind::ReturnKeyword) {
|
||||
return false;
|
||||
}
|
||||
PROGRESS_TOKEN(currentToken);
|
||||
const ParsedStatement* returnBody = nullptr;
|
||||
ParseAssign(returnBody, currentToken);
|
||||
EXPECT_TOKEN(currentToken, SemicolonSymbol);
|
||||
out = new ParsedReturnStatement(TextSpan(start, currentToken->GetSpan().GetEnd()), returnBody);
|
||||
return true;
|
||||
}
|
||||
bool Parser::ParseExprStat(const ParsedStatement*& out, const LexToken*& currentToken) {
|
||||
if (!ParseAssign(out, currentToken)){
|
||||
return false;
|
||||
}
|
||||
EXPECT_TOKEN(currentToken, SemicolonSymbol);
|
||||
return true;
|
||||
}
|
||||
bool Parser::ParseVarAccess(const ParsedStatement*& out, const LexToken*& currentToken) {
|
||||
std::vector<Identifier> scope;
|
||||
auto start = currentToken->GetSpan().GetStart();
|
||||
if (ParseScope(scope, currentToken)) {
|
||||
out = new ParsedVarAccessStatement(TextSpan(start, currentToken->GetSpan().GetEnd()), scope);
|
||||
return true;
|
||||
}
|
||||
Identifier identifier;
|
||||
if (ParseIdentifier(identifier, currentToken)) {
|
||||
scope.clear();
|
||||
scope.push_back(identifier);
|
||||
out = new ParsedVarAccessStatement(currentToken->GetSpan(), scope);
|
||||
PROGRESS_TOKEN(currentToken);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -117,24 +117,35 @@ namespace MalachScript::Parser {
|
|||
bool ParseType(const ParsedStatement*& out, const LexToken*& currentToken);
|
||||
bool ParseAssign(const ParsedStatement*& out, const LexToken*& currentToken);
|
||||
// InitList
|
||||
// ExprPreOp
|
||||
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
|
||||
// VarAccess
|
||||
bool ParseVarAccess(const ParsedStatement*& out, const LexToken*& currentToken);
|
||||
// Cast
|
||||
// Literal
|
||||
bool ParseLiteral(const ParsedStatement*& out, const LexToken*& currentToken);
|
||||
bool ParseTypeMod(TypeMod& typeMod, const LexToken*& currentToken);
|
||||
// Lambda
|
||||
|
||||
// ExprValue
|
||||
bool ParseExprValue(const ParsedStatement*& out, const LexToken*& currentToken);
|
||||
// ExprPostOp
|
||||
bool ParseExprTerm(const ParsedStatement*& out, const LexToken*& currentToken);
|
||||
bool ParseExpr(const ParsedStatement*& out, const LexToken*& currentToken);
|
||||
bool ParseTernary(const ParsedStatement*& out, const LexToken*& currentToken);
|
||||
|
||||
// Return
|
||||
// ExprStat
|
||||
bool ParseReturn(const ParsedStatement*& out, const LexToken*& currentToken);
|
||||
bool ParseExprStat(const ParsedStatement*& out, const LexToken*& currentToken);
|
||||
// Continue
|
||||
// Break
|
||||
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef MALACHSCRIPT_PARSERDEFINES_HPP
|
||||
#define MALACHSCRIPT_PARSERDEFINES_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
using ParseInt = uintmax_t;
|
||||
using ParseFloat = long double;
|
||||
using ParseString = std::u8string;
|
||||
|
||||
#endif // MALACHSCRIPT_PARSERDEFINES_HPP
|
|
@ -307,6 +307,57 @@ namespace MalachScript::Parser {
|
|||
TOperator _operator;
|
||||
std::unique_ptr<const ParsedStatement> _rightHand;
|
||||
};
|
||||
|
||||
class ParsedVoidStatement : public ParsedStatementImpl<ParsedStatementKind::Void> {
|
||||
public:
|
||||
ParsedVoidStatement(const TextSpan& span) : ParsedStatementImpl(span) {}
|
||||
};
|
||||
|
||||
template <class T> class ParsedLiteralStatement : public ParsedStatementImpl<ParsedStatementKind::Literal> {
|
||||
public:
|
||||
ParsedLiteralStatement(const TextSpan& span, T literalValue)
|
||||
: ParsedStatementImpl(span), _literalValue(literalValue) {}
|
||||
|
||||
[[nodiscard]] inline const T& GetLiteralValue() const noexcept { return _literalValue; }
|
||||
private:
|
||||
T _literalValue;
|
||||
};
|
||||
|
||||
class ParsedReturnStatement : public ParsedStatementImpl<ParsedStatementKind::Return>{
|
||||
public:
|
||||
ParsedReturnStatement(const TextSpan& span, const ParsedStatement* statement)
|
||||
: ParsedStatementImpl(span), _statement(statement) {}
|
||||
|
||||
private:
|
||||
std::unique_ptr<const ParsedStatement> _statement;
|
||||
};
|
||||
|
||||
class ParsedVarAccessStatement : public ParsedStatementImpl<ParsedStatementKind::VarAccess>{
|
||||
public:
|
||||
ParsedVarAccessStatement(const TextSpan& span, std::vector<Identifier> scope)
|
||||
: ParsedStatementImpl(span), _scope(std::move(scope)) {}
|
||||
|
||||
private:
|
||||
std::vector<Identifier> _scope;
|
||||
};
|
||||
|
||||
class ParsedIncrementStatement : public ParsedStatementImpl<ParsedStatementKind::Increment>{
|
||||
public:
|
||||
ParsedIncrementStatement(const TextSpan& span, const ParsedStatement* statement)
|
||||
: ParsedStatementImpl(span), _statement(statement) {}
|
||||
|
||||
private:
|
||||
std::unique_ptr<const ParsedStatement> _statement;
|
||||
};
|
||||
|
||||
class ParsedDecrementStatement : public ParsedStatementImpl<ParsedStatementKind::Decrement>{
|
||||
public:
|
||||
ParsedDecrementStatement(const TextSpan& span, const ParsedStatement* statement)
|
||||
: ParsedStatementImpl(span), _statement(statement) {}
|
||||
|
||||
private:
|
||||
std::unique_ptr<const ParsedStatement> _statement;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MALACHSCRIPT_PARSEDSTATEMENT_HPP
|
||||
|
|
|
@ -15,7 +15,13 @@ namespace MalachScript::Parser {
|
|||
StatBlock,
|
||||
If,
|
||||
Assign,
|
||||
BinaryExpression
|
||||
BinaryExpression,
|
||||
Void,
|
||||
Literal,
|
||||
Return,
|
||||
VarAccess,
|
||||
Increment,
|
||||
Decrement,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -34,10 +34,10 @@ INTEGER_TEST("0D123456", 123456);
|
|||
INTEGER_TEST("50000000000", 50000000000);
|
||||
|
||||
// Decimal float lexing
|
||||
FLOAT_TEST("123.456", 123.456);
|
||||
FLOAT_TEST("0.456", 0.456);
|
||||
FLOAT_TEST("0.456e12", 0.456e12);
|
||||
FLOAT_TEST("0.456E12", 0.456E12);
|
||||
FLOAT_TEST("123.456", 123.456L);
|
||||
FLOAT_TEST("0.456", 0.456L);
|
||||
FLOAT_TEST("0.456e12", 0.456e12L);
|
||||
FLOAT_TEST("0.456E12", 0.456E12L);
|
||||
|
||||
// Hexadecimal lexing
|
||||
INTEGER_TEST("0x0", 0);
|
||||
|
|
|
@ -48,4 +48,4 @@ PARSE_TEST("Parse class with virtprop", "class foobar { private bool foo { get;
|
|||
REQUIRE(virtPropStatement->HasSet());
|
||||
REQUIRE(virtPropStatement->GetGetStatement() == nullptr);
|
||||
REQUIRE(virtPropStatement->GetSetStatement() == nullptr);
|
||||
})
|
||||
})
|
||||
|
|
|
@ -128,4 +128,81 @@ PARSER_TEST(
|
|||
REQUIRE(FuncAttrHelpers::Contains(virtPropStatement->GetSetFuncAttr(), FuncAttr::Override));
|
||||
REQUIRE(virtPropStatement->GetGetStatement() == nullptr);
|
||||
REQUIRE(virtPropStatement->GetSetStatement() == nullptr);
|
||||
})
|
||||
|
||||
/// Parse class foobar {
|
||||
// int i;
|
||||
// bool foo {
|
||||
// get {
|
||||
// if (true) return true;
|
||||
// return false;
|
||||
// }
|
||||
// set{
|
||||
// if (1 == 1) i++;
|
||||
// i--;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
PARSER_TEST(
|
||||
"Virtprops with bodies",
|
||||
PARSER_TEST_TOKENS(new Parser::LexTokenImpl<Parser::LexTokenKind::ClassKeyword>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"foobar"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"int"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"i"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0)),
|
||||
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"bool"),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"foo"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::GetKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::IfKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::TrueKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::ReturnKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::TrueKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::ReturnKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::FalseKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::SetKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::IfKeyword>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::IntegerLiteral(TextSpan(0, 0), 1),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::EqualsEqualsSymbol>(TextSpan(0, 0)),
|
||||
new Parser::IntegerLiteral(TextSpan(0, 0), 1),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"i"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::PlusPlusSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0)),
|
||||
new Parser::IdentifierToken(TextSpan(0, 0), u8"i"),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::MinusMinusSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0)),
|
||||
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||||
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseCurlyParenthesisSymbol>(TextSpan(0, 0))),
|
||||
{
|
||||
REQUIRE(script->GetStatements().size() == 1);
|
||||
auto firstStatement = script->GetStatements()[0].get();
|
||||
REQUIRE(firstStatement->GetKind() == Parser::ParsedStatementKind::Class);
|
||||
auto firstClassStatement =
|
||||
dynamic_cast<const MalachScript::Parser::ParsedClassStatement*>(firstStatement)->GetBody()[1].get();
|
||||
REQUIRE(firstClassStatement->GetKind() == Parser::ParsedStatementKind::VirtProp);
|
||||
auto virtPropStatement =
|
||||
dynamic_cast<const MalachScript::Parser::ParsedVirtPropStatement*>(firstClassStatement);
|
||||
REQUIRE(virtPropStatement->GetAccess() == MalachScript::AccessModifier::Public);
|
||||
REQUIRE(virtPropStatement->GetIdentifier().GetString() == u8"foo");
|
||||
REQUIRE(virtPropStatement->HasGet());
|
||||
REQUIRE(virtPropStatement->HasSet());
|
||||
REQUIRE_FALSE(virtPropStatement->IsGetConst());
|
||||
REQUIRE_FALSE(virtPropStatement->IsSetConst());
|
||||
REQUIRE(virtPropStatement->GetGetStatement() != nullptr);
|
||||
REQUIRE(virtPropStatement->GetSetStatement() != nullptr);
|
||||
})
|
Loading…
Reference in New Issue