Implements parsing for loop, cleanup of memory handling in parser.
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Deukhoofd 2020-12-06 12:35:08 +01:00
parent 0c8b9f3943
commit a3a996d68a
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
6 changed files with 216 additions and 158 deletions

View File

@ -1,5 +1,5 @@
Checks: 'readability-*,clang-diagnostic-*,clang-analyzer-*,-clang-analyzer-alpha*,performance-*,cppcoreguidelines-*,
bugprone-*,modernize-*,-modernize-use-trailing-return-type'
Checks: 'readability-*,clang-diagnostic-*,clang-analyzer-*,-clang-analyzer-alpha*,performance-*,
bugprone-*,modernize-*,-modernize-use-trailing-return-type,-readability-function-cognitive-complexity'
HeaderFilterRegex: ''
AnalyzeTemporaryDtors: false
CheckOptions:

View File

@ -30,7 +30,7 @@ namespace MalachScript::Parser {
if (currentToken->GetKind() == LexTokenKind::EndOfFile) {
break;
}
const ParsedStatement* statement;
ScopedPtr<const ParsedStatement> statement;
auto result = ParseClass(statement, currentToken) || ParseFunc(statement, currentToken) ||
ParseNamespace(statement, currentToken);
if (!result) {
@ -38,7 +38,7 @@ namespace MalachScript::Parser {
PROGRESS_TOKEN(currentToken);
continue;
}
statements.push_back(statement);
statements.push_back(statement.TakeOwnership());
current++;
}
statements.resize(current);
@ -48,7 +48,7 @@ namespace MalachScript::Parser {
}
return new ParsedScriptStatement(TextSpan(0, end), statements);
}
bool Parser::ParseClass(const ParsedStatement*& out, const LexToken*& currentToken) {
bool Parser::ParseClass(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken) {
const auto* current = currentToken;
auto start = current->GetSpan().GetStart();
bool lookingForClass = true;
@ -107,14 +107,14 @@ namespace MalachScript::Parser {
PROGRESS_TOKEN(current);
break;
}
const ParsedStatement* statement = nullptr;
ScopedPtr<const ParsedStatement> statement = nullptr;
// TODO: Sort by complexity
if (!ParseVirtProp(statement, current) && !ParseFunc(statement, current) &&
!ParseVar(statement, current) && !ParseFuncDef(statement, current)) {
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
break;
}
body.push_back(statement);
body.push_back(statement.TakeOwnership());
}
break;
}
@ -124,7 +124,7 @@ namespace MalachScript::Parser {
currentToken = current;
return true;
}
bool Parser::ParseTypeDef(const ParsedStatement*& out, const LexToken*& currentToken) {
bool Parser::ParseTypeDef(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken) {
const auto* current = currentToken;
if (current->GetKind() != LexTokenKind::TypedefKeyword) {
return false;
@ -143,10 +143,10 @@ namespace MalachScript::Parser {
}
PROGRESS_TOKEN(current);
EXPECT_TOKEN(current, SemicolonSymbol);
out = new ParsedTypeDefStatement(TextSpan(start, current->GetSpan().GetEnd()), defineTo, defineFrom);
out = new ParsedTypeDefStatement(TextSpan(start, current->GetSpan().GetEnd()), defineFrom, defineTo);
return true;
}
bool Parser::ParseNamespace(const ParsedStatement*& out, const LexToken*& currentToken) {
bool Parser::ParseNamespace(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken) {
const auto* current = currentToken;
if (current->GetKind() != LexTokenKind::NamespaceKeyword) {
return false;
@ -164,7 +164,7 @@ namespace MalachScript::Parser {
currentToken = current;
return true;
}
bool Parser::ParseFunc(const ParsedStatement*& out, const LexToken*& currentToken) {
bool Parser::ParseFunc(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken) {
const auto* current = currentToken;
auto start = current->GetSpan().GetStart();
bool isShared = false;
@ -191,7 +191,7 @@ namespace MalachScript::Parser {
accessModifier = AccessModifier::Protected;
PROGRESS_TOKEN(current);
}
const ParsedStatement* typeStatement = nullptr;
ScopedPtr<const ParsedStatement> typeStatement = nullptr;
bool returnsReference = false;
if (current->GetKind() == LexTokenKind::TildeSymbol) {
// TODO: Handle destructor
@ -204,13 +204,11 @@ namespace MalachScript::Parser {
}
Identifier identifier;
if (!ParseIdentifier(identifier, current)) {
delete typeStatement;
return false;
}
PROGRESS_TOKEN(current);
const ParsedStatement* paramList = nullptr;
ScopedPtr<const ParsedStatement> paramList = nullptr;
if (!ParseParamList(paramList, current)) {
delete typeStatement;
return false;
}
bool isConst = false;
@ -220,7 +218,7 @@ namespace MalachScript::Parser {
}
FuncAttr funcAttr = FuncAttr::None;
ParseFuncAttr(funcAttr, current);
const ParsedStatement* statblock = nullptr;
ScopedPtr<const ParsedStatement> statblock = nullptr;
if (current->GetKind() != LexTokenKind::SemicolonSymbol) {
if (!ParseStatBlock(statblock, current)) {
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
@ -229,13 +227,13 @@ namespace MalachScript::Parser {
PROGRESS_TOKEN(current);
}
out = new ParsedFuncStatement(TextSpan(start, current->GetSpan().GetEnd()), isShared, isExternal,
accessModifier, typeStatement, returnsReference, identifier, paramList, isConst,
funcAttr, statblock);
accessModifier, typeStatement.TakeOwnership(), returnsReference, identifier,
paramList.TakeOwnership(), isConst, funcAttr, statblock.TakeOwnership());
currentToken = current;
return true;
}
bool Parser::ParseType(const ParsedStatement*& out, const LexToken*& currentToken) {
bool Parser::ParseType(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken) {
const auto* token = currentToken;
auto start = token->GetSpan().GetStart();
bool isConst = false;
@ -339,7 +337,7 @@ namespace MalachScript::Parser {
return true;
}
bool Parser::ParseParamList(const ParsedStatement*& out, const LexToken*& currentToken) {
bool Parser::ParseParamList(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken) {
if (currentToken->GetKind() != LexTokenKind::OpenParenthesisSymbol) {
return false;
}
@ -362,7 +360,7 @@ namespace MalachScript::Parser {
return true;
}
while (true) {
const ParsedStatement* typeStatement = nullptr;
ScopedPtr<const ParsedStatement> typeStatement = nullptr;
TypeMod typeMod = TypeMod::None;
Identifier identifier;
const ParsedStatement* defaultExpression = nullptr;
@ -376,7 +374,8 @@ namespace MalachScript::Parser {
// TODO: Default expression
parameters.push_back(new ParsedParamListStatement::ParsedParameter(
dynamic_cast<const ParsedTypeStatement*>(typeStatement), typeMod, identifier, defaultExpression));
dynamic_cast<const ParsedTypeStatement*>(typeStatement.TakeOwnership()), typeMod, identifier,
defaultExpression));
if (currentToken->GetKind() != LexTokenKind::CommaSymbol) {
break;
@ -419,7 +418,7 @@ namespace MalachScript::Parser {
}
}
bool Parser::ParseVirtProp([[maybe_unused]] const ParsedStatement*& out, const LexToken*& currentToken) {
bool Parser::ParseVirtProp([[maybe_unused]] ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken) {
const auto* current = currentToken;
AccessModifier access = AccessModifier::Public;
if (current->GetKind() == LexTokenKind::PrivateKeyword) {
@ -429,7 +428,7 @@ namespace MalachScript::Parser {
access = AccessModifier::Protected;
PROGRESS_TOKEN(current);
}
const ParsedStatement* typeStatement = nullptr;
ScopedPtr<const ParsedStatement> typeStatement = nullptr;
if (!ParseType(typeStatement, current)) {
return false;
}
@ -440,22 +439,20 @@ namespace MalachScript::Parser {
}
Identifier identifier;
if (!ParseIdentifier(identifier, current)) {
delete typeStatement;
return false;
}
PROGRESS_TOKEN(current);
if (current->GetKind() != LexTokenKind::OpenCurlyParenthesisSymbol) {
delete typeStatement;
return false;
}
bool hasGet = false;
bool getConst = false;
FuncAttr getAttr = FuncAttr::None;
const ParsedStatement* getStatement = nullptr;
ScopedPtr<const ParsedStatement> getStatement = nullptr;
bool hasSet = false;
bool setConst = false;
FuncAttr setAttr = FuncAttr::None;
const ParsedStatement* setStatement = nullptr;
ScopedPtr<const ParsedStatement> setStatement = nullptr;
PROGRESS_TOKEN(current);
while (true) {
auto start = current->GetSpan().GetStart();
@ -510,31 +507,33 @@ namespace MalachScript::Parser {
}
out = new ParsedVirtPropStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()),
access, typeStatement, ref, identifier, hasGet, getConst, getAttr,
getStatement, hasSet, setConst, setAttr, setStatement);
access, typeStatement.TakeOwnership(), ref, identifier, hasGet, getConst,
getAttr, getStatement.TakeOwnership(), hasSet, setConst, setAttr,
setStatement.TakeOwnership());
currentToken = current;
return true;
}
bool Parser::ParseIfStatement([[maybe_unused]] const ParsedStatement*& out, const LexToken*& currentToken) {
bool Parser::ParseIfStatement([[maybe_unused]] ScopedPtr<const ParsedStatement>& out,
const LexToken*& currentToken) {
const auto* current = currentToken;
if (current->GetKind() != LexTokenKind::IfKeyword) {
return false;
}
PROGRESS_TOKEN(current);
EXPECT_TOKEN(current, OpenParenthesisSymbol);
const ParsedStatement* condition = nullptr;
ScopedPtr<const ParsedStatement> condition = nullptr;
if (!ParseAssign(condition, current)) {
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
return false;
}
EXPECT_TOKEN(current, CloseParenthesisSymbol);
const ParsedStatement* body = nullptr;
ScopedPtr<const ParsedStatement> body = nullptr;
if (!ParseStatement(body, current)) {
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
return false;
}
const ParsedStatement* elseStatement = nullptr;
ScopedPtr<const ParsedStatement> elseStatement = nullptr;
if (current->GetKind() == LexTokenKind::ElseKeyword) {
PROGRESS_TOKEN(current);
if (!ParseStatement(elseStatement, current)) {
@ -542,19 +541,20 @@ namespace MalachScript::Parser {
}
}
out = new ParsedIfStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()),
condition, body, elseStatement);
condition.TakeOwnership(), body.TakeOwnership(), elseStatement.TakeOwnership());
currentToken = current;
return true;
}
bool Parser::ParseStatement(const ParsedStatement*& out, const LexToken*& currentToken) {
bool Parser::ParseStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken) {
// TODO: All the other statements.
return ParseIfStatement(out, currentToken) || ParseReturn(out, currentToken) ||
ParseStatBlock(out, currentToken) || ParseExprStat(out, currentToken);
return ParseIfStatement(out, currentToken) || ParseForStatement(out, currentToken) ||
ParseReturn(out, currentToken) || ParseStatBlock(out, currentToken) || ParseBreak(out, currentToken) ||
ParseContinue(out, currentToken) || ParseExprStat(out, currentToken);
}
bool Parser::ParseVar([[maybe_unused]] const ParsedStatement*& out, const LexToken*& currentToken) {
bool Parser::ParseVar([[maybe_unused]] ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken) {
const auto* current = currentToken;
AccessModifier access = AccessModifier::Public;
if (current->GetKind() == LexTokenKind::PrivateKeyword) {
@ -564,13 +564,12 @@ namespace MalachScript::Parser {
access = AccessModifier::Protected;
PROGRESS_TOKEN(current);
}
const ParsedStatement* typeStatement = nullptr;
ScopedPtr<const ParsedStatement> typeStatement = nullptr;
if (!ParseType(typeStatement, current)) {
return false;
}
Identifier identifier;
if (!ParseIdentifier(identifier, current)) {
delete typeStatement;
return false;
}
PROGRESS_TOKEN(current);
@ -578,12 +577,12 @@ namespace MalachScript::Parser {
// TODO: Creating multiple vars in a single line (int a, b, c)
EXPECT_TOKEN(current, SemicolonSymbol);
out = new ParsedVarStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), access,
typeStatement, identifier);
typeStatement.TakeOwnership(), identifier);
currentToken = current;
return true;
}
bool Parser::ParseStatBlock(const ParsedStatement*& out, const LexToken*& currentToken) {
bool Parser::ParseStatBlock(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken) {
const auto* current = currentToken;
if (current->GetKind() != LexTokenKind::OpenCurlyParenthesisSymbol) {
return false;
@ -594,9 +593,9 @@ namespace MalachScript::Parser {
if (current->GetKind() == LexTokenKind::CloseCurlyParenthesisSymbol) {
break;
}
const ParsedStatement* stat = nullptr;
ScopedPtr<const ParsedStatement> stat = nullptr;
if (ParseVar(stat, current) || ParseStatement(stat, current)) {
statements.push_back(stat);
statements.push_back(stat.TakeOwnership());
} else {
break;
}
@ -613,7 +612,7 @@ namespace MalachScript::Parser {
return true;
}
bool Parser::ParseFuncDef([[maybe_unused]] const ParsedStatement*& out,
bool Parser::ParseFuncDef([[maybe_unused]] ScopedPtr<const ParsedStatement>& out,
[[maybe_unused]] const LexToken*& currentToken) {
return false;
}
@ -657,111 +656,73 @@ namespace MalachScript::Parser {
default: typeMod = TypeMod::RefInOut; return true;
}
}
bool Parser::ParseAssign(const ParsedStatement*& out, const LexToken*& currentToken) {
bool Parser::ParseAssign(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken) {
const auto* current = currentToken;
const ParsedStatement* leftHand = nullptr;
ScopedPtr<const ParsedStatement> leftHand = nullptr;
if (!ParseTernary(leftHand, current)) {
return false;
}
AssignmentOperator op;
if (!ParseAssignOp(op, current)) {
out = leftHand;
out = leftHand.TakeOwnership();
currentToken = current;
return true;
}
PROGRESS_TOKEN(current);
const ParsedStatement* rightHand = nullptr;
ScopedPtr<const ParsedStatement> rightHand = nullptr;
if (!ParseAssign(rightHand, current)) {
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
out = leftHand;
out = leftHand.TakeOwnership();
currentToken = current;
return true;
}
out = new ParsedBinaryStatement<AssignmentOperator>(
TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), leftHand, op, rightHand);
TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), leftHand.TakeOwnership(), op,
rightHand.TakeOwnership());
currentToken = current;
return true;
}
bool Parser::ParseTernary(const ParsedStatement*& out, const LexToken*& currentToken) {
bool Parser::ParseTernary(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken) {
// TODO: implement ternary.
return ParseExpr(out, currentToken);
}
bool Parser::ParseExpr(const ParsedStatement*& out, const LexToken*& currentToken) {
#define EXPR_PARSER(operator, name, func) \
operator name; \
if (func(name, current)) { \
PROGRESS_TOKEN(current); \
ScopedPtr<const ParsedStatement> rightHand = nullptr; \
if (!ParseExprTerm(rightHand, current)) { \
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan()); \
out = leftHand.TakeOwnership(); \
currentToken = current; \
return true; \
} \
out = new ParsedBinaryStatement < operator>(TextSpan(currentToken->GetSpan().GetStart(), \
current->GetSpan().GetEnd()), \
leftHand.TakeOwnership(), name, rightHand.TakeOwnership()); \
currentToken = current; \
return true; \
}
bool Parser::ParseExpr(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken) {
const auto* current = currentToken;
const ParsedStatement* leftHand = nullptr;
ScopedPtr<const ParsedStatement> leftHand = nullptr;
if (!ParseExprTerm(leftHand, current)) {
return false;
}
MathOperator mathOp;
if (ParseMathOp(mathOp, current)) {
PROGRESS_TOKEN(current);
const ParsedStatement* rightHand = nullptr;
if (!ParseExprTerm(rightHand, current)) {
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
out = leftHand;
currentToken = current;
return true;
}
out = new ParsedBinaryStatement<MathOperator>(
TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), leftHand, mathOp, rightHand);
currentToken = current;
return true;
}
ComparisonOperator compOp;
if (ParseCompOp(compOp, current)) {
PROGRESS_TOKEN(current);
const ParsedStatement* rightHand = nullptr;
if (!ParseExprTerm(rightHand, current)) {
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
out = leftHand;
currentToken = current;
return true;
}
out = new ParsedBinaryStatement<ComparisonOperator>(
TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), leftHand, compOp, rightHand);
currentToken = current;
return true;
}
LogicOperator logicOp;
if (ParseLogicOp(logicOp, current)) {
PROGRESS_TOKEN(current);
const ParsedStatement* rightHand = nullptr;
if (!ParseExprTerm(rightHand, current)) {
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
out = leftHand;
currentToken = current;
return true;
}
out = new ParsedBinaryStatement<LogicOperator>(
TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), leftHand, logicOp,
rightHand);
currentToken = current;
return true;
}
BitOperator bitOp;
if (ParseBitOp(bitOp, current)) {
PROGRESS_TOKEN(current);
const ParsedStatement* rightHand = nullptr;
if (!ParseExprTerm(rightHand, current)) {
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
out = leftHand;
currentToken = current;
return true;
}
out = new ParsedBinaryStatement<BitOperator>(
TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), leftHand, bitOp, rightHand);
currentToken = current;
return true;
}
out = leftHand;
EXPR_PARSER(MathOperator, mathOp, ParseMathOp);
EXPR_PARSER(ComparisonOperator, compOp, ParseCompOp);
EXPR_PARSER(LogicOperator, logicOp, ParseLogicOp);
EXPR_PARSER(BitOperator, bitOp, ParseBitOp);
out = leftHand.TakeOwnership();
currentToken = current;
return true;
}
bool Parser::ParseExprTerm([[maybe_unused]] const ParsedStatement*& out,
[[maybe_unused]] const LexToken*& currentToken) {
bool Parser::ParseExprTerm(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken) {
const auto* current = currentToken;
// TODO ([type '='] initlist)
@ -770,7 +731,7 @@ namespace MalachScript::Parser {
if (hasPreOp) {
PROGRESS_TOKEN(current);
}
const ParsedStatement* operand = nullptr;
ScopedPtr<const ParsedStatement> operand = nullptr;
if (!ParseExprValue(operand, current)) {
return false;
}
@ -778,22 +739,22 @@ namespace MalachScript::Parser {
// TODO: remainder of
if (current->GetKind() == LexTokenKind::PlusPlusSymbol) {
operand = new ParsedIncrementStatement(TextSpan(operand->GetSpan().GetStart(), current->GetSpan().GetEnd()),
operand);
operand.TakeOwnership());
PROGRESS_TOKEN(current);
} else if (current->GetKind() == LexTokenKind::MinusMinusSymbol) {
operand = new ParsedDecrementStatement(TextSpan(operand->GetSpan().GetStart(), current->GetSpan().GetEnd()),
operand);
operand.TakeOwnership());
PROGRESS_TOKEN(current);
}
if (hasPreOp) {
// TODO: integrate pre operator
}
out = operand;
out = operand.TakeOwnership();
currentToken = current;
return true;
}
bool Parser::ParseExprValue(const ParsedStatement*& out, const LexToken*& currentToken) {
bool Parser::ParseExprValue(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken) {
const auto* current = currentToken;
if (current->GetKind() == LexTokenKind::VoidKeyword) {
PROGRESS_TOKEN(current);
@ -825,7 +786,7 @@ namespace MalachScript::Parser {
return false;
}
bool Parser::ParseLiteral(const ParsedStatement*& out, const LexToken*& currentToken) {
bool Parser::ParseLiteral(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken) {
switch (currentToken->GetKind()) {
case LexTokenKind::IntegerLiteral:
out = new ParsedLiteralStatement<ParseInt>(
@ -857,26 +818,26 @@ namespace MalachScript::Parser {
default: return false;
}
}
bool Parser::ParseReturn(const ParsedStatement*& out, const LexToken*& currentToken) {
bool Parser::ParseReturn(ScopedPtr<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;
ScopedPtr<const ParsedStatement> returnBody;
ParseAssign(returnBody, currentToken);
EXPECT_TOKEN(currentToken, SemicolonSymbol);
out = new ParsedReturnStatement(TextSpan(start, currentToken->GetSpan().GetEnd()), returnBody);
out = new ParsedReturnStatement(TextSpan(start, currentToken->GetSpan().GetEnd()), returnBody.TakeOwnership());
return true;
}
bool Parser::ParseExprStat(const ParsedStatement*& out, const LexToken*& currentToken) {
bool Parser::ParseExprStat(ScopedPtr<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) {
bool Parser::ParseVarAccess(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken) {
std::vector<Identifier> scope;
auto start = currentToken->GetSpan().GetStart();
if (ParseScope(scope, currentToken)) {
@ -893,8 +854,8 @@ namespace MalachScript::Parser {
}
return false;
}
bool Parser::ParseContinue(const ParsedStatement*& out, const LexToken*& currentToken) {
if (currentToken->GetKind() == LexTokenKind::ContinueKeyword) {
bool Parser::ParseContinue(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken) {
if (currentToken->GetKind() != LexTokenKind::ContinueKeyword) {
return false;
}
auto start = currentToken->GetSpan().GetStart();
@ -903,8 +864,8 @@ namespace MalachScript::Parser {
out = new ParsedContinueStatement(TextSpan(start, currentToken->GetSpan().GetEnd()));
return true;
}
bool Parser::ParseBreak(const ParsedStatement*& out, const LexToken*& currentToken) {
if (currentToken->GetKind() == LexTokenKind::BreakKeyword) {
bool Parser::ParseBreak(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken) {
if (currentToken->GetKind() != LexTokenKind::BreakKeyword) {
return false;
}
auto start = currentToken->GetSpan().GetStart();
@ -913,4 +874,44 @@ namespace MalachScript::Parser {
out = new ParsedBreakStatement(TextSpan(start, currentToken->GetSpan().GetEnd()));
return true;
}
bool Parser::ParseForStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken) {
if (currentToken->GetKind() != LexTokenKind::ForKeyword) {
return false;
}
const auto* current = currentToken;
PROGRESS_TOKEN(current);
EXPECT_TOKEN(current, OpenParenthesisSymbol);
ScopedPtr<const ParsedStatement> init;
if (!ParseVar(init, current) && !ParseExprStat(init, current)) {
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
return false;
}
ScopedPtr<const ParsedStatement> condition;
if (!ParseExprStat(condition, current)) {
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
return false;
}
std::vector<const ParsedStatement*> increment;
while (true) {
ScopedPtr<const ParsedStatement> element;
if (ParseAssign(element, current)) {
increment.push_back(element.TakeOwnership());
}
if (current->GetKind() != LexTokenKind::CommaSymbol) {
break;
}
}
EXPECT_TOKEN(current, CloseParenthesisSymbol);
ScopedPtr<const ParsedStatement> statementBlock;
if (!ParseStatement(statementBlock, current)) {
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
return false;
}
out = new ParsedForStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()),
init.TakeOwnership(), condition.TakeOwnership(), increment,
statementBlock.TakeOwnership());
currentToken = current;
return true;
}
}

View File

@ -3,6 +3,7 @@
#include "../CoreData/Operators.hpp"
#include "../Diagnostics/Diagnostics.hpp"
#include "../Utils/ScopedPtr.hpp"
#include "Lexer/LexToken.hpp"
#include "Statements/ParsedStatement.hpp"
@ -114,8 +115,8 @@ namespace MalachScript::Parser {
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(const ParsedStatement*& out, const LexToken*& currentToken);
bool ParseAssign(const ParsedStatement*& 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()) {
@ -132,51 +133,51 @@ namespace MalachScript::Parser {
// ArgList
// FuncCall
// ConstructCall
bool ParseVarAccess(const ParsedStatement*& out, const LexToken*& currentToken);
bool ParseVarAccess(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
// Cast
bool ParseLiteral(const ParsedStatement*& out, const LexToken*& currentToken);
bool ParseLiteral(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
bool ParseTypeMod(TypeMod& typeMod, const LexToken*& currentToken);
// Lambda
bool ParseExprValue(const ParsedStatement*& out, const LexToken*& currentToken);
bool ParseExprValue(ScopedPtr<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);
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(const ParsedStatement*& out, const LexToken*& currentToken);
bool ParseExprStat(const ParsedStatement*& out, const LexToken*& currentToken);
bool ParseContinue(const ParsedStatement*& out, const LexToken*& currentToken);
bool ParseBreak(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(const ParsedStatement*& out, const LexToken*& currentToken);
// For
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(const ParsedStatement*& out, const LexToken*& currentToken);
bool ParseVar(const ParsedStatement*& out, const LexToken*& currentToken);
bool ParseStatBlock(const ParsedStatement*& out, const LexToken*& currentToken);
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(const ParsedStatement*& out, const LexToken*& currentToken);
bool ParseParamList(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
bool ParseVirtProp(const ParsedStatement*& out, const LexToken*& currentToken);
bool ParseFunc(const ParsedStatement*& out, const LexToken*& currentToken);
bool ParseFuncDef(const ParsedStatement*& out, const LexToken*& currentToken);
bool ParseClass(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(const ParsedStatement*& out, const LexToken*& currentToken);
bool ParseTypeDef(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
// InterfaceMethod
// Interface
bool ParseNamespace(const ParsedStatement*& out, const LexToken*& currentToken);
bool ParseNamespace(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
const ParsedScriptStatement* ParseScript();
};
}

View File

@ -370,6 +370,30 @@ namespace MalachScript::Parser {
ParsedBreakStatement(const TextSpan& span) : ParsedStatementImpl(span) {}
};
class ParsedForStatement : public ParsedStatementImpl<ParsedStatementKind::For> {
public:
ParsedForStatement(const TextSpan& span, const ParsedStatement* init, const ParsedStatement* condition,
std::vector<const ParsedStatement*> increment, const ParsedStatement* body)
: ParsedStatementImpl(span), _init(init), _condition(condition), _increment(increment.size()), _body(body) {
for (size_t i = 0; i < increment.size(); i++) {
_increment[i] = std::unique_ptr<const ParsedStatement>(increment[i]);
}
}
inline const std::unique_ptr<const ParsedStatement>& GetInit() const noexcept { return _init; }
inline const std::unique_ptr<const ParsedStatement>& GetCondition() const noexcept { return _condition; }
inline const std::vector<std::unique_ptr<const ParsedStatement>>& GetIncrement() const noexcept {
return _increment;
}
inline const std::unique_ptr<const ParsedStatement>& GetBody() const noexcept { return _body; }
private:
std::unique_ptr<const ParsedStatement> _init;
std::unique_ptr<const ParsedStatement> _condition;
std::vector<std::unique_ptr<const ParsedStatement>> _increment;
std::unique_ptr<const ParsedStatement> _body;
};
}
#endif // MALACHSCRIPT_PARSEDSTATEMENT_HPP

View File

@ -24,6 +24,7 @@ namespace MalachScript::Parser {
Decrement,
Continue,
Break,
For,
};
}

31
src/Utils/ScopedPtr.hpp Normal file
View File

@ -0,0 +1,31 @@
#ifndef MALACHSCRIPT_SCOPEDPTR_HPP
#define MALACHSCRIPT_SCOPEDPTR_HPP
template <class T> class ScopedPtr {
T* _raw;
public:
inline ScopedPtr() { _raw = nullptr; }
inline ScopedPtr(T* ptr) { _raw = ptr; }
inline ScopedPtr& operator=(T* b) {
_raw = b;
return *this;
}
ScopedPtr(const ScopedPtr& b) = delete;
ScopedPtr& operator=(ScopedPtr const&) = delete;
inline ~ScopedPtr() { delete _raw; }
inline T* TakeOwnership() noexcept {
auto b = _raw;
_raw = nullptr;
return b;
}
inline T* operator->() { return _raw; }
};
#endif // MALACHSCRIPT_SCOPEDPTR_HPP