Implements numeric for loops
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
#include <utility>
|
||||
|
||||
#ifndef PORYGONLANG_PARSEDEXPRESSION_HPP
|
||||
#define PORYGONLANG_PARSEDEXPRESSION_HPP
|
||||
@@ -12,7 +11,7 @@
|
||||
#include "../../Utilities/HashedString.hpp"
|
||||
|
||||
namespace Porygon::Parser {
|
||||
enum class ParsedExpressionKind {
|
||||
enum class ParsedExpressionKind : uint8_t {
|
||||
Bad,
|
||||
|
||||
LiteralInteger,
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
#include <utility>
|
||||
|
||||
#include <utility>
|
||||
|
||||
#ifndef PORYGONLANG_PARSEDSTATEMENT_HPP
|
||||
#define PORYGONLANG_PARSEDSTATEMENT_HPP
|
||||
@@ -14,7 +11,7 @@
|
||||
#include "../TypedVariableIdentifier.hpp"
|
||||
|
||||
namespace Porygon::Parser {
|
||||
enum class ParsedStatementKind {
|
||||
enum class ParsedStatementKind : uint8_t {
|
||||
Bad,
|
||||
Script,
|
||||
Block,
|
||||
@@ -23,7 +20,8 @@ namespace Porygon::Parser {
|
||||
IndexAssignment,
|
||||
FunctionDeclaration,
|
||||
Return,
|
||||
Conditional
|
||||
Conditional,
|
||||
NumericalFor
|
||||
};
|
||||
|
||||
class ParsedStatement {
|
||||
@@ -278,5 +276,51 @@ namespace Porygon::Parser {
|
||||
return _elseStatement;
|
||||
}
|
||||
};
|
||||
|
||||
class ParsedNumericalForStatement : public ParsedStatement {
|
||||
const HashedString _identifier;
|
||||
const ParsedExpression *_start;
|
||||
const ParsedExpression *_end;
|
||||
const ParsedExpression *_step;
|
||||
const ParsedStatement *_block;
|
||||
public:
|
||||
ParsedNumericalForStatement(const HashedString identifier, const ParsedExpression *start,
|
||||
const ParsedExpression *end, const ParsedExpression *step, const ParsedStatement *block,
|
||||
unsigned int startPos, unsigned int length)
|
||||
: ParsedStatement(startPos, length), _identifier(identifier), _start(start), _end(end), _step(step), _block(block) {
|
||||
}
|
||||
|
||||
~ParsedNumericalForStatement() final {
|
||||
delete _start;
|
||||
delete _end;
|
||||
delete _step;
|
||||
delete _block;
|
||||
}
|
||||
|
||||
const ParsedStatementKind GetKind() const final {
|
||||
return ParsedStatementKind::NumericalFor;
|
||||
}
|
||||
|
||||
const HashedString GetIdentifier() const{
|
||||
return _identifier;
|
||||
}
|
||||
|
||||
const ParsedExpression *GetStart() const{
|
||||
return _start;
|
||||
}
|
||||
|
||||
const ParsedExpression *GetEnd() const{
|
||||
return _end;
|
||||
}
|
||||
|
||||
const ParsedExpression *GetStep() const{
|
||||
return _step;
|
||||
}
|
||||
|
||||
const ParsedStatement *GetBlock() const{
|
||||
return _block;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
#endif //PORYGONLANG_PARSEDSTATEMENT_HPP
|
||||
|
||||
@@ -44,6 +44,8 @@ namespace Porygon::Parser {
|
||||
return this->ParseReturnStatement(current);
|
||||
case TokenKind::IfKeyword:
|
||||
return this->ParseIfStatement(current);
|
||||
case TokenKind ::ForKeyword:
|
||||
return this->ParseForStatement(current);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -191,7 +193,6 @@ namespace Porygon::Parser {
|
||||
}
|
||||
|
||||
ParsedStatement *Parser::ParseReturnStatement(const IToken *current) {
|
||||
//TODO: if next token is on a different line, don't parse it as return expression.
|
||||
auto start = current->GetStartPosition();
|
||||
auto startLine = this -> ScriptData -> Diagnostics ->GetLineFromPosition(start);
|
||||
if (startLine != this -> ScriptData -> Diagnostics -> GetLineFromPosition(this -> Peek() -> GetStartPosition())){
|
||||
@@ -224,6 +225,55 @@ namespace Porygon::Parser {
|
||||
return new ParsedConditionalStatement(condition, block, start, block->GetEndPosition() - start);
|
||||
}
|
||||
|
||||
ParsedStatement *Parser::ParseForStatement(const IToken *current) {
|
||||
auto identifier = this -> Next();
|
||||
if (this -> Peek()->GetKind() == TokenKind::AssignmentToken){
|
||||
return ParseNumericForStatement(identifier);
|
||||
} else {
|
||||
return ParseGenericForStatement(identifier);
|
||||
}
|
||||
}
|
||||
|
||||
ParsedStatement *Parser::ParseNumericForStatement(const IToken *current) {
|
||||
auto identifier = (IdentifierToken*)current;
|
||||
this->Next(); // consume assignment token
|
||||
bool hasErrors = false;
|
||||
auto start = this ->ParseExpression(this ->Next());
|
||||
auto comma = this -> Next(); // consume comma token
|
||||
if (comma->GetKind() != TokenKind::CommaToken){
|
||||
hasErrors = true;
|
||||
this->ScriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::UnexpectedToken, comma->GetStartPosition(),
|
||||
comma->GetLength());
|
||||
}
|
||||
auto end = this -> ParseExpression(this -> Next());
|
||||
ParsedExpression *step = nullptr;
|
||||
if (this -> Peek()->GetKind() == TokenKind::CommaToken){
|
||||
this -> Next();
|
||||
step = this -> ParseExpression(this -> Next());
|
||||
}
|
||||
auto doToken = this ->Next();
|
||||
if (doToken->GetKind() != TokenKind::DoKeyword && !hasErrors){
|
||||
hasErrors = true;
|
||||
this->ScriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::UnexpectedToken, doToken->GetStartPosition(),
|
||||
doToken->GetLength());
|
||||
}
|
||||
auto block = this -> ParseBlock({TokenKind ::EndKeyword});
|
||||
auto startPos = current->GetStartPosition();
|
||||
if (hasErrors){
|
||||
return new ParsedBadStatement(startPos, block -> GetEndPosition() - startPos);
|
||||
}
|
||||
return new ParsedNumericalForStatement(identifier->GetValue(), start, end, step, block, startPos, block->GetEndPosition() - startPos);
|
||||
|
||||
}
|
||||
|
||||
ParsedStatement *Parser::ParseGenericForStatement(const IToken *current) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/////////////////
|
||||
// Expressions //
|
||||
/////////////////
|
||||
|
||||
ParsedExpression *Parser::ParseExpression(const IToken *current) {
|
||||
auto expression = this->ParseBinaryExpression(current, OperatorPrecedence::No);
|
||||
auto peekKind = this->Peek()->GetKind();
|
||||
|
||||
@@ -29,14 +29,15 @@ namespace Porygon::Parser {
|
||||
|
||||
const IToken *Next();
|
||||
|
||||
// Statements
|
||||
|
||||
ParsedStatement *ParseStatement(const IToken *current);
|
||||
|
||||
ParsedStatement *ParseVariableAssignment(const IToken *current);
|
||||
|
||||
ParsedStatement *ParseIndexAssignment(ParsedExpression *indexer);
|
||||
|
||||
ParsedStatement *
|
||||
ParseBlock(const vector<TokenKind> &endTokens, const vector<const ParsedStatement *> &openStatements = {});
|
||||
ParsedStatement *ParseBlock(const vector<TokenKind> &endTokens, const vector<const ParsedStatement *> &openStatements = {});
|
||||
|
||||
ParsedStatement *ParseFunctionDeclaration(const IToken *current);
|
||||
|
||||
@@ -44,6 +45,12 @@ namespace Porygon::Parser {
|
||||
|
||||
ParsedStatement *ParseIfStatement(const IToken *current);
|
||||
|
||||
ParsedStatement *ParseForStatement(const IToken *current);
|
||||
ParsedStatement *ParseNumericForStatement(const IToken *current);
|
||||
ParsedStatement *ParseGenericForStatement(const IToken *current);
|
||||
|
||||
// Expressions
|
||||
|
||||
ParsedExpression *ParseExpression(const IToken *current);
|
||||
|
||||
ParsedExpression *ParseBinaryExpression(const IToken *current, OperatorPrecedence parentPrecedence);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define PORYGONLANG_TOKENKIND_HPP
|
||||
|
||||
namespace Porygon::Parser {
|
||||
enum class TokenKind {
|
||||
enum class TokenKind : uint8_t {
|
||||
EndOfFile,
|
||||
BadToken,
|
||||
WhiteSpace,
|
||||
|
||||
Reference in New Issue
Block a user