Implements parsing for loop, cleanup of memory handling in parser.
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
0c8b9f3943
commit
a3a996d68a
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace MalachScript::Parser {
|
|||
Decrement,
|
||||
Continue,
|
||||
Break,
|
||||
For,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue