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-*, Checks: 'readability-*,clang-diagnostic-*,clang-analyzer-*,-clang-analyzer-alpha*,performance-*,
bugprone-*,modernize-*,-modernize-use-trailing-return-type' bugprone-*,modernize-*,-modernize-use-trailing-return-type,-readability-function-cognitive-complexity'
HeaderFilterRegex: '' HeaderFilterRegex: ''
AnalyzeTemporaryDtors: false AnalyzeTemporaryDtors: false
CheckOptions: CheckOptions:

View File

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

View File

@ -370,6 +370,30 @@ namespace MalachScript::Parser {
ParsedBreakStatement(const TextSpan& span) : ParsedStatementImpl(span) {} 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 #endif // MALACHSCRIPT_PARSEDSTATEMENT_HPP

View File

@ -24,6 +24,7 @@ namespace MalachScript::Parser {
Decrement, Decrement,
Continue, Continue,
Break, 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