Implements assignment parsing

This commit is contained in:
Deukhoofd 2019-05-26 14:20:40 +02:00
parent 0205b92ae6
commit dbd7dfdd73
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
4 changed files with 125 additions and 13 deletions

View File

@ -1,30 +1,32 @@
#include <utility>
#include <utility>
#ifndef PORYGONLANG_PARSEDSTATEMENT_HPP
#define PORYGONLANG_PARSEDSTATEMENT_HPP
#include <utility>
#include <vector>
#include <string>
#include "../ParsedExpressions/ParsedExpression.hpp"
enum class ParsedStatementKind{
Bad,
Script,
Block,
Expression,
Assignment
};
class ParsedStatement {
unsigned int _start;
unsigned int _length;
public:
virtual ParsedStatementKind GetKind() = 0;
ParsedStatement(unsigned int start, unsigned int length){
_start = start;
_length = length;
}
virtual ~ParsedStatement() = default;
virtual ParsedStatementKind GetKind() = 0;
unsigned int GetStartPosition(){
return _start;
@ -35,6 +37,14 @@ public:
}
};
class ParsedBadStatement : public ParsedStatement{
public:
ParsedBadStatement(unsigned int start, unsigned int length) : ParsedStatement(start, length){};
ParsedStatementKind GetKind() final{
return ParsedStatementKind ::Bad;
}
};
class ParsedBlockStatement : public ParsedStatement{
std::vector<ParsedStatement*> _statements;
public:
@ -86,4 +96,36 @@ public:
}
};
class ParsedAssignmentStatement : public ParsedStatement{
bool _local;
std::string _identifier;
ParsedExpression* _expression;
public:
ParsedAssignmentStatement(bool local, std::string identifier, ParsedExpression* expression, unsigned int start, unsigned int length)
: ParsedStatement(start, length){
_local = local;
_identifier = std::move(identifier);
_expression = expression;
}
~ParsedAssignmentStatement() final{
delete _expression;
}
ParsedStatementKind GetKind() final{
return ParsedStatementKind ::Assignment;
}
bool IsLocal(){
return _local;
}
std::string GetIdentifier(){
return _identifier;
}
ParsedExpression* GetExpression(){
return _expression;
}
};
#endif //PORYGONLANG_PARSEDSTATEMENT_HPP

View File

@ -19,15 +19,53 @@ ParsedScriptStatement* Parser::Parse() {
return new ParsedScriptStatement(statements);
}
IToken *Parser::Peek() {
return this -> _tokens[_position];
}
IToken *Parser::Next() {
this -> _position++;
return this -> _tokens[_position - 1];
}
ParsedStatement* Parser::ParseStatement(IToken* current){
if (current->GetKind() == TokenKind::LocalKeyword){
return ParseAssignment(current);
} else if (this->Peek()->GetKind() == TokenKind::AssignmentToken){
return ParseAssignment(current);
}
return new ParsedExpressionStatement(this -> ParseExpression(current));
}
ParsedStatement *Parser::ParseAssignment(IToken *current) {
bool isLocal = false;
IToken* identifier;
if (current -> GetKind() == TokenKind::LocalKeyword){
isLocal = true;
identifier = this -> Next();
} else{
identifier = current;
}
auto assignmentToken = this->Next();
auto expression = this -> ParseExpression(this -> Next());
if (identifier -> GetKind() != TokenKind::Identifier){
this -> ScriptData -> Diagnostics -> LogError(DiagnosticCode::UnexpectedToken, identifier->GetStartPosition(), identifier->GetLength());
return new ParsedBadStatement(identifier->GetStartPosition(), identifier->GetLength());
}
if (assignmentToken -> GetKind() != TokenKind::AssignmentToken){
this -> ScriptData -> Diagnostics -> LogError(DiagnosticCode::UnexpectedToken, identifier->GetStartPosition(), identifier->GetLength());
return new ParsedBadStatement(identifier->GetStartPosition(), identifier->GetLength());
}
auto start = current -> GetStartPosition();
return new ParsedAssignmentStatement(isLocal, ((IdentifierToken*)identifier) -> Value, expression, start, expression->GetEndPosition() - start);
}
ParsedExpression* Parser::ParseExpression(IToken* current){
return this -> ParseBinaryExpression(current, OperatorPrecedence::No);
}
OperatorPrecedence GetUnaryPrecedence(TokenKind kind){
switch (kind){
case TokenKind::PlusToken:
@ -135,12 +173,4 @@ ParsedExpression *Parser::ParseParenthesizedExpression(IToken *current) {
}
IToken *Parser::Peek() {
return this -> _tokens[_position];
}
IToken *Parser::Next() {
this -> _position++;
return this -> _tokens[_position - 1];
}

View File

@ -24,7 +24,10 @@ class Parser {
IToken* Peek();
IToken* Next();
ParsedStatement* ParseStatement(IToken* current);
ParsedStatement* ParseAssignment(IToken *current);
ParsedExpression* ParseExpression(IToken* current);
ParsedExpression* ParseBinaryExpression(IToken* current, OperatorPrecedence parentPrecedence);
ParsedExpression* ParsePrimaryExpression(IToken* current);

View File

@ -154,5 +154,42 @@ TEST_CASE( "Parse String Tokens", "[parser]" ) {
REQUIRE(boolean->GetValue() == "foo bar");
}
TEST_CASE( "Parse Global Assignment", "[parser]" ) {
vector<IToken*> v {
new IdentifierToken("foo",0,0),
new SimpleToken(TokenKind::AssignmentToken,0,0),
new SimpleToken(TokenKind::TrueKeyword,0,0),
new SimpleToken(TokenKind::EndOfFile,0,0)
};
Parser parser = Parser(v, nullptr);
auto parsedStatements = parser.Parse() -> GetStatements();
REQUIRE(parsedStatements.size() == 1);
auto firstStatement = parsedStatements[0];
REQUIRE(firstStatement -> GetKind() == ParsedStatementKind::Assignment);
auto assignment = (ParsedAssignmentStatement*)firstStatement;
REQUIRE(!assignment -> IsLocal());
REQUIRE(assignment->GetIdentifier() == "foo");
REQUIRE(((LiteralBoolExpression*)assignment->GetExpression()) -> GetValue());
}
TEST_CASE( "Parse local Assignment", "[parser]" ) {
vector<IToken*> v {
new SimpleToken(TokenKind::LocalKeyword,0,0),
new IdentifierToken("foo",0,0),
new SimpleToken(TokenKind::AssignmentToken,0,0),
new SimpleToken(TokenKind::TrueKeyword,0,0),
new SimpleToken(TokenKind::EndOfFile,0,0)
};
Parser parser = Parser(v, nullptr);
auto parsedStatements = parser.Parse() -> GetStatements();
REQUIRE(parsedStatements.size() == 1);
auto firstStatement = parsedStatements[0];
REQUIRE(firstStatement -> GetKind() == ParsedStatementKind::Assignment);
auto assignment = (ParsedAssignmentStatement*)firstStatement;
REQUIRE(assignment -> IsLocal());
REQUIRE(assignment->GetIdentifier() == "foo");
REQUIRE(((LiteralBoolExpression*)assignment->GetExpression()) -> GetValue());
}
#endif