Large chunk of work in parser for getting expressions to work.
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
c20a1089a9
commit
5fb64e12e1
@ -62,7 +62,7 @@ expr ::= exprterm {(mathop | compop | logicop | bitop) exprterm};
|
|||||||
ternary ::= expr ['?' assign : assign];
|
ternary ::= expr ['?' assign : assign];
|
||||||
|
|
||||||
return ::= 'return' [assign] ';';
|
return ::= 'return' [assign] ';';
|
||||||
exprstat ::= [assign] ';';
|
exprstat ::= assign ';';
|
||||||
continue ::= 'continue' ';';
|
continue ::= 'continue' ';';
|
||||||
break ::= 'break' ';';
|
break ::= 'break' ';';
|
||||||
|
|
||||||
|
@ -54,6 +54,16 @@ namespace MalachScript {
|
|||||||
BitwiseRightShift,
|
BitwiseRightShift,
|
||||||
ArithmeticRightShift,
|
ArithmeticRightShift,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class PreOperator : uint8_t {
|
||||||
|
Negation,
|
||||||
|
Identity,
|
||||||
|
Inversion,
|
||||||
|
Increment,
|
||||||
|
Decrement,
|
||||||
|
BitwiseComplement,
|
||||||
|
Handle
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // MALACHSCRIPT_OPERATORS_HPP
|
#endif // MALACHSCRIPT_OPERATORS_HPP
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include "../../CoreData/Identifier.hpp"
|
#include "../../CoreData/Identifier.hpp"
|
||||||
#include "../../TextSpan.hpp"
|
#include "../../TextSpan.hpp"
|
||||||
|
#include "../ParserDefines.hpp"
|
||||||
#include "LexTokenKind.hpp"
|
#include "LexTokenKind.hpp"
|
||||||
|
|
||||||
namespace MalachScript::Parser {
|
namespace MalachScript::Parser {
|
||||||
@ -28,30 +29,30 @@ namespace MalachScript::Parser {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class IntegerLiteral : public LexTokenImpl<LexTokenKind::IntegerLiteral> {
|
class IntegerLiteral : public LexTokenImpl<LexTokenKind::IntegerLiteral> {
|
||||||
uint64_t _value;
|
ParseInt _value;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IntegerLiteral(const TextSpan& span, uint64_t value)
|
IntegerLiteral(const TextSpan& span, ParseInt value)
|
||||||
: LexTokenImpl<LexTokenKind::IntegerLiteral>(span), _value(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> {
|
class FloatLiteral : public LexTokenImpl<LexTokenKind::FloatLiteral> {
|
||||||
double _value;
|
ParseFloat _value;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FloatLiteral(const TextSpan& span, double value)
|
FloatLiteral(const TextSpan& span, ParseFloat value)
|
||||||
: LexTokenImpl<LexTokenKind::FloatLiteral>(span), _value(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> {
|
class StringLiteral : public LexTokenImpl<LexTokenKind::StringLiteral> {
|
||||||
std::u8string _value;
|
ParseString _value;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
StringLiteral(const TextSpan& span, std::u8string value)
|
StringLiteral(const TextSpan& span, ParseString value)
|
||||||
: LexTokenImpl<LexTokenKind::StringLiteral>(span), _value(std::move(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> {
|
class IdentifierToken : public LexTokenImpl<LexTokenKind::Identifier> {
|
||||||
|
@ -338,16 +338,16 @@ namespace MalachScript::Parser {
|
|||||||
return pow10[n];
|
return pow10[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
LexToken* Lexer::LexDecimal(uint64_t initial) {
|
LexToken* Lexer::LexDecimal(ParseInt initial) {
|
||||||
auto start = _position;
|
auto start = _position;
|
||||||
uint64_t value = initial;
|
ParseInt value = initial;
|
||||||
uint64_t decimalValue = 0;
|
ParseInt decimalValue = 0;
|
||||||
uint64_t exponentValue = 0;
|
ParseInt exponentValue = 0;
|
||||||
uint8_t decimalLength = 0;
|
uint8_t decimalLength = 0;
|
||||||
bool isDecimal = false;
|
bool isDecimal = false;
|
||||||
bool isExponent = false;
|
bool isExponent = false;
|
||||||
while (true) {
|
while (true) {
|
||||||
auto v = (uint64_t)LexDecimalValue(Peek());
|
auto v = (ParseInt)LexDecimalValue(Peek());
|
||||||
if (v == 255) {
|
if (v == 255) {
|
||||||
if (!isDecimal && Peek() == u8'.') {
|
if (!isDecimal && Peek() == u8'.') {
|
||||||
isDecimal = true;
|
isDecimal = true;
|
||||||
@ -376,7 +376,7 @@ namespace MalachScript::Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isDecimal || isExponent) {
|
if (isDecimal || isExponent) {
|
||||||
auto val = value + ((double)decimalValue / quick_pow10(decimalLength));
|
auto val = value + ((ParseFloat)decimalValue / quick_pow10(decimalLength));
|
||||||
if (isExponent) {
|
if (isExponent) {
|
||||||
val *= pow(10, exponentValue);
|
val *= pow(10, exponentValue);
|
||||||
}
|
}
|
||||||
@ -387,7 +387,7 @@ namespace MalachScript::Parser {
|
|||||||
|
|
||||||
IntegerLiteral* Lexer::LexHexadecimal() {
|
IntegerLiteral* Lexer::LexHexadecimal() {
|
||||||
auto start = _position;
|
auto start = _position;
|
||||||
uint64_t value = 0;
|
ParseInt value = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
auto v = LexHexadecimalValue(Peek());
|
auto v = LexHexadecimalValue(Peek());
|
||||||
if (v == 255) {
|
if (v == 255) {
|
||||||
@ -401,7 +401,7 @@ namespace MalachScript::Parser {
|
|||||||
}
|
}
|
||||||
IntegerLiteral* Lexer::LexOctal() {
|
IntegerLiteral* Lexer::LexOctal() {
|
||||||
auto start = _position;
|
auto start = _position;
|
||||||
uint64_t value = 0;
|
ParseInt value = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
auto v = LexOctalValue(Peek());
|
auto v = LexOctalValue(Peek());
|
||||||
if (v == 255) {
|
if (v == 255) {
|
||||||
@ -415,7 +415,7 @@ namespace MalachScript::Parser {
|
|||||||
}
|
}
|
||||||
IntegerLiteral* Lexer::LexBinary() {
|
IntegerLiteral* Lexer::LexBinary() {
|
||||||
auto start = _position;
|
auto start = _position;
|
||||||
uint64_t value = 0;
|
ParseInt value = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
auto v = LexBinaryValue(Peek());
|
auto v = LexBinaryValue(Peek());
|
||||||
if (v == 255) {
|
if (v == 255) {
|
||||||
@ -457,7 +457,7 @@ namespace MalachScript::Parser {
|
|||||||
if (heredoc) {
|
if (heredoc) {
|
||||||
Progress(2);
|
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() {
|
LexToken* Lexer::LexKeywordOrIdentifier() {
|
||||||
|
@ -204,11 +204,13 @@ namespace MalachScript::Parser {
|
|||||||
}
|
}
|
||||||
Identifier identifier;
|
Identifier identifier;
|
||||||
if (!ParseIdentifier(identifier, current)) {
|
if (!ParseIdentifier(identifier, current)) {
|
||||||
|
delete typeStatement;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
const ParsedStatement* paramList = nullptr;
|
const ParsedStatement* paramList = nullptr;
|
||||||
if (!ParseParamList(paramList, current)) {
|
if (!ParseParamList(paramList, current)) {
|
||||||
|
delete typeStatement;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool isConst = false;
|
bool isConst = false;
|
||||||
@ -285,7 +287,7 @@ namespace MalachScript::Parser {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (current != nullptr && current->GetKind() == LexTokenKind::ColonColonSymbol) {
|
while (current->GetKind() == LexTokenKind::ColonColonSymbol) {
|
||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
const auto* n = current;
|
const auto* n = current;
|
||||||
if (ParseIdentifier(identifier, n)) {
|
if (ParseIdentifier(identifier, n)) {
|
||||||
@ -440,6 +442,7 @@ namespace MalachScript::Parser {
|
|||||||
}
|
}
|
||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
if (current->GetKind() != LexTokenKind::OpenCurlyParenthesisSymbol) {
|
if (current->GetKind() != LexTokenKind::OpenCurlyParenthesisSymbol) {
|
||||||
|
delete typeStatement;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool hasGet = false;
|
bool hasGet = false;
|
||||||
@ -464,8 +467,9 @@ namespace MalachScript::Parser {
|
|||||||
if (!ParseStatBlock(getStatement, current)) {
|
if (!ParseStatBlock(getStatement, current)) {
|
||||||
this->LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
this->LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
PROGRESS_TOKEN(current);
|
||||||
}
|
}
|
||||||
PROGRESS_TOKEN(current);
|
|
||||||
|
|
||||||
if (hasGet) {
|
if (hasGet) {
|
||||||
this->LogError(Diagnostics::DiagnosticType::DoubleProperty,
|
this->LogError(Diagnostics::DiagnosticType::DoubleProperty,
|
||||||
@ -483,8 +487,9 @@ namespace MalachScript::Parser {
|
|||||||
if (!ParseStatBlock(setStatement, current)) {
|
if (!ParseStatBlock(setStatement, current)) {
|
||||||
this->LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
this->LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
PROGRESS_TOKEN(current);
|
||||||
}
|
}
|
||||||
PROGRESS_TOKEN(current);
|
|
||||||
|
|
||||||
if (hasSet) {
|
if (hasSet) {
|
||||||
this->LogError(Diagnostics::DiagnosticType::DoubleProperty,
|
this->LogError(Diagnostics::DiagnosticType::DoubleProperty,
|
||||||
@ -541,7 +546,9 @@ namespace MalachScript::Parser {
|
|||||||
|
|
||||||
bool Parser::ParseStatement(const ParsedStatement*& out, const LexToken*& currentToken) {
|
bool Parser::ParseStatement(const ParsedStatement*& out, const LexToken*& currentToken) {
|
||||||
// TODO: All the other statements.
|
// 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) {
|
bool Parser::ParseVar([[maybe_unused]] const ParsedStatement*& out, const LexToken*& currentToken) {
|
||||||
@ -566,11 +573,7 @@ namespace MalachScript::Parser {
|
|||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
// TODO: Default values
|
// TODO: Default values
|
||||||
// TODO: Creating multiple vars in a single line (int a, b, c)
|
// TODO: Creating multiple vars in a single line (int a, b, c)
|
||||||
if (current->GetKind() == LexTokenKind::SemicolonSymbol) {
|
EXPECT_TOKEN(current, SemicolonSymbol);
|
||||||
PROGRESS_TOKEN(current);
|
|
||||||
} else {
|
|
||||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
|
||||||
}
|
|
||||||
out = new ParsedVarStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), access,
|
out = new ParsedVarStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), access,
|
||||||
typeStatement, identifier);
|
typeStatement, identifier);
|
||||||
currentToken = current;
|
currentToken = current;
|
||||||
@ -582,6 +585,7 @@ namespace MalachScript::Parser {
|
|||||||
if (current->GetKind() != LexTokenKind::OpenCurlyParenthesisSymbol) {
|
if (current->GetKind() != LexTokenKind::OpenCurlyParenthesisSymbol) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
PROGRESS_TOKEN(current);
|
||||||
std::vector<const ParsedStatement*> statements;
|
std::vector<const ParsedStatement*> statements;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (current->GetKind() == LexTokenKind::CloseCurlyParenthesisSymbol) {
|
if (current->GetKind() == LexTokenKind::CloseCurlyParenthesisSymbol) {
|
||||||
@ -699,6 +703,7 @@ namespace MalachScript::Parser {
|
|||||||
}
|
}
|
||||||
out = new ParsedBinaryStatement<MathOperator>(
|
out = new ParsedBinaryStatement<MathOperator>(
|
||||||
TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), leftHand, mathOp, rightHand);
|
TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), leftHand, mathOp, rightHand);
|
||||||
|
currentToken = current;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
ComparisonOperator compOp;
|
ComparisonOperator compOp;
|
||||||
@ -713,6 +718,7 @@ namespace MalachScript::Parser {
|
|||||||
}
|
}
|
||||||
out = new ParsedBinaryStatement<ComparisonOperator>(
|
out = new ParsedBinaryStatement<ComparisonOperator>(
|
||||||
TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), leftHand, compOp, rightHand);
|
TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), leftHand, compOp, rightHand);
|
||||||
|
currentToken = current;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
LogicOperator logicOp;
|
LogicOperator logicOp;
|
||||||
@ -728,6 +734,7 @@ namespace MalachScript::Parser {
|
|||||||
out = new ParsedBinaryStatement<LogicOperator>(
|
out = new ParsedBinaryStatement<LogicOperator>(
|
||||||
TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), leftHand, logicOp,
|
TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), leftHand, logicOp,
|
||||||
rightHand);
|
rightHand);
|
||||||
|
currentToken = current;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
BitOperator bitOp;
|
BitOperator bitOp;
|
||||||
@ -742,6 +749,7 @@ namespace MalachScript::Parser {
|
|||||||
}
|
}
|
||||||
out = new ParsedBinaryStatement<BitOperator>(
|
out = new ParsedBinaryStatement<BitOperator>(
|
||||||
TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), leftHand, bitOp, rightHand);
|
TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), leftHand, bitOp, rightHand);
|
||||||
|
currentToken = current;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
out = leftHand;
|
out = leftHand;
|
||||||
@ -751,6 +759,135 @@ namespace MalachScript::Parser {
|
|||||||
|
|
||||||
bool Parser::ParseExprTerm([[maybe_unused]] const ParsedStatement*& out,
|
bool Parser::ParseExprTerm([[maybe_unused]] const ParsedStatement*& out,
|
||||||
[[maybe_unused]] const LexToken*& currentToken) {
|
[[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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -117,24 +117,35 @@ namespace MalachScript::Parser {
|
|||||||
bool ParseType(const ParsedStatement*& out, const LexToken*& currentToken);
|
bool ParseType(const ParsedStatement*& out, const LexToken*& currentToken);
|
||||||
bool ParseAssign(const ParsedStatement*& out, const LexToken*& currentToken);
|
bool ParseAssign(const ParsedStatement*& out, const LexToken*& currentToken);
|
||||||
// InitList
|
// 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
|
// ArgList
|
||||||
// FuncCall
|
// FuncCall
|
||||||
// ConstructCall
|
// ConstructCall
|
||||||
// VarAccess
|
bool ParseVarAccess(const ParsedStatement*& out, const LexToken*& currentToken);
|
||||||
// Cast
|
// Cast
|
||||||
// Literal
|
bool ParseLiteral(const ParsedStatement*& out, const LexToken*& currentToken);
|
||||||
bool ParseTypeMod(TypeMod& typeMod, const LexToken*& currentToken);
|
bool ParseTypeMod(TypeMod& typeMod, const LexToken*& currentToken);
|
||||||
// Lambda
|
// Lambda
|
||||||
|
|
||||||
// ExprValue
|
bool ParseExprValue(const ParsedStatement*& out, const LexToken*& currentToken);
|
||||||
// ExprPostOp
|
// ExprPostOp
|
||||||
bool ParseExprTerm(const ParsedStatement*& out, const LexToken*& currentToken);
|
bool ParseExprTerm(const ParsedStatement*& out, const LexToken*& currentToken);
|
||||||
bool ParseExpr(const ParsedStatement*& out, const LexToken*& currentToken);
|
bool ParseExpr(const ParsedStatement*& out, const LexToken*& currentToken);
|
||||||
bool ParseTernary(const ParsedStatement*& out, const LexToken*& currentToken);
|
bool ParseTernary(const ParsedStatement*& out, const LexToken*& currentToken);
|
||||||
|
|
||||||
// Return
|
bool ParseReturn(const ParsedStatement*& out, const LexToken*& currentToken);
|
||||||
// ExprStat
|
bool ParseExprStat(const ParsedStatement*& out, const LexToken*& currentToken);
|
||||||
// Continue
|
// Continue
|
||||||
// Break
|
// Break
|
||||||
|
|
||||||
|
10
src/Parser/ParserDefines.hpp
Normal file
10
src/Parser/ParserDefines.hpp
Normal file
@ -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;
|
TOperator _operator;
|
||||||
std::unique_ptr<const ParsedStatement> _rightHand;
|
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
|
#endif // MALACHSCRIPT_PARSEDSTATEMENT_HPP
|
||||||
|
@ -15,7 +15,13 @@ namespace MalachScript::Parser {
|
|||||||
StatBlock,
|
StatBlock,
|
||||||
If,
|
If,
|
||||||
Assign,
|
Assign,
|
||||||
BinaryExpression
|
BinaryExpression,
|
||||||
|
Void,
|
||||||
|
Literal,
|
||||||
|
Return,
|
||||||
|
VarAccess,
|
||||||
|
Increment,
|
||||||
|
Decrement,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,10 +34,10 @@ INTEGER_TEST("0D123456", 123456);
|
|||||||
INTEGER_TEST("50000000000", 50000000000);
|
INTEGER_TEST("50000000000", 50000000000);
|
||||||
|
|
||||||
// Decimal float lexing
|
// Decimal float lexing
|
||||||
FLOAT_TEST("123.456", 123.456);
|
FLOAT_TEST("123.456", 123.456L);
|
||||||
FLOAT_TEST("0.456", 0.456);
|
FLOAT_TEST("0.456", 0.456L);
|
||||||
FLOAT_TEST("0.456e12", 0.456e12);
|
FLOAT_TEST("0.456e12", 0.456e12L);
|
||||||
FLOAT_TEST("0.456E12", 0.456E12);
|
FLOAT_TEST("0.456E12", 0.456E12L);
|
||||||
|
|
||||||
// Hexadecimal lexing
|
// Hexadecimal lexing
|
||||||
INTEGER_TEST("0x0", 0);
|
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->HasSet());
|
||||||
REQUIRE(virtPropStatement->GetGetStatement() == nullptr);
|
REQUIRE(virtPropStatement->GetGetStatement() == nullptr);
|
||||||
REQUIRE(virtPropStatement->GetSetStatement() == nullptr);
|
REQUIRE(virtPropStatement->GetSetStatement() == nullptr);
|
||||||
})
|
})
|
||||||
|
@ -128,4 +128,81 @@ PARSER_TEST(
|
|||||||
REQUIRE(FuncAttrHelpers::Contains(virtPropStatement->GetSetFuncAttr(), FuncAttr::Override));
|
REQUIRE(FuncAttrHelpers::Contains(virtPropStatement->GetSetFuncAttr(), FuncAttr::Override));
|
||||||
REQUIRE(virtPropStatement->GetGetStatement() == nullptr);
|
REQUIRE(virtPropStatement->GetGetStatement() == nullptr);
|
||||||
REQUIRE(virtPropStatement->GetSetStatement() == 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…
x
Reference in New Issue
Block a user