Implements assignment parsing
This commit is contained in:
parent
0205b92ae6
commit
dbd7dfdd73
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue