Implements assignment parsing
This commit is contained in:
parent
0205b92ae6
commit
dbd7dfdd73
|
@ -1,30 +1,32 @@
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef PORYGONLANG_PARSEDSTATEMENT_HPP
|
#ifndef PORYGONLANG_PARSEDSTATEMENT_HPP
|
||||||
#define PORYGONLANG_PARSEDSTATEMENT_HPP
|
#define PORYGONLANG_PARSEDSTATEMENT_HPP
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "../ParsedExpressions/ParsedExpression.hpp"
|
#include "../ParsedExpressions/ParsedExpression.hpp"
|
||||||
|
|
||||||
enum class ParsedStatementKind{
|
enum class ParsedStatementKind{
|
||||||
|
Bad,
|
||||||
Script,
|
Script,
|
||||||
Block,
|
Block,
|
||||||
Expression,
|
Expression,
|
||||||
|
Assignment
|
||||||
};
|
};
|
||||||
|
|
||||||
class ParsedStatement {
|
class ParsedStatement {
|
||||||
unsigned int _start;
|
unsigned int _start;
|
||||||
unsigned int _length;
|
unsigned int _length;
|
||||||
public:
|
public:
|
||||||
virtual ParsedStatementKind GetKind() = 0;
|
|
||||||
ParsedStatement(unsigned int start, unsigned int length){
|
ParsedStatement(unsigned int start, unsigned int length){
|
||||||
_start = start;
|
_start = start;
|
||||||
_length = length;
|
_length = length;
|
||||||
}
|
}
|
||||||
virtual ~ParsedStatement() = default;
|
virtual ~ParsedStatement() = default;
|
||||||
|
virtual ParsedStatementKind GetKind() = 0;
|
||||||
|
|
||||||
unsigned int GetStartPosition(){
|
unsigned int GetStartPosition(){
|
||||||
return _start;
|
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{
|
class ParsedBlockStatement : public ParsedStatement{
|
||||||
std::vector<ParsedStatement*> _statements;
|
std::vector<ParsedStatement*> _statements;
|
||||||
public:
|
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
|
#endif //PORYGONLANG_PARSEDSTATEMENT_HPP
|
||||||
|
|
|
@ -19,15 +19,53 @@ ParsedScriptStatement* Parser::Parse() {
|
||||||
return new ParsedScriptStatement(statements);
|
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){
|
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));
|
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){
|
ParsedExpression* Parser::ParseExpression(IToken* current){
|
||||||
return this -> ParseBinaryExpression(current, OperatorPrecedence::No);
|
return this -> ParseBinaryExpression(current, OperatorPrecedence::No);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
OperatorPrecedence GetUnaryPrecedence(TokenKind kind){
|
OperatorPrecedence GetUnaryPrecedence(TokenKind kind){
|
||||||
switch (kind){
|
switch (kind){
|
||||||
case TokenKind::PlusToken:
|
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* Peek();
|
||||||
IToken* Next();
|
IToken* Next();
|
||||||
|
|
||||||
ParsedStatement* ParseStatement(IToken* current);
|
ParsedStatement* ParseStatement(IToken* current);
|
||||||
|
ParsedStatement* ParseAssignment(IToken *current);
|
||||||
|
|
||||||
ParsedExpression* ParseExpression(IToken* current);
|
ParsedExpression* ParseExpression(IToken* current);
|
||||||
ParsedExpression* ParseBinaryExpression(IToken* current, OperatorPrecedence parentPrecedence);
|
ParsedExpression* ParseBinaryExpression(IToken* current, OperatorPrecedence parentPrecedence);
|
||||||
ParsedExpression* ParsePrimaryExpression(IToken* current);
|
ParsedExpression* ParsePrimaryExpression(IToken* current);
|
||||||
|
|
|
@ -154,5 +154,42 @@ TEST_CASE( "Parse String Tokens", "[parser]" ) {
|
||||||
REQUIRE(boolean->GetValue() == "foo bar");
|
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
|
#endif
|
Loading…
Reference in New Issue