Implements parsing function declarations

This commit is contained in:
Deukhoofd 2019-05-31 15:00:14 +02:00
parent 6fad5a0a7d
commit c407ba2f50
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
8 changed files with 191 additions and 15 deletions

View File

@ -56,6 +56,8 @@ IToken* Lexer::LexNext(char c){
return new SimpleToken(TokenKind::OpenParenthesis, this -> Position - 1, 1);
case ')':
return new SimpleToken(TokenKind::CloseParenthesis, this -> Position - 1, 1);
case ',':
return new SimpleToken(TokenKind::CommaToken, this -> Position - 1, 1);
case '=':
if (Lexer::Peek() == '='){
Lexer::Next();

View File

@ -1,9 +1,3 @@
#include <utility>
#include <utility>
#ifndef PORYGONLANG_PARSEDSTATEMENT_HPP
#define PORYGONLANG_PARSEDSTATEMENT_HPP
@ -13,13 +7,15 @@
#include "../ParsedExpressions/ParsedExpression.hpp"
#include "../../Utilities/HashedString.hpp"
#include "../TypedVariableIdentifier.hpp"
enum class ParsedStatementKind{
Bad,
Script,
Block,
Expression,
Assignment
Assignment,
FunctionDeclaration
};
class ParsedStatement {
@ -105,6 +101,39 @@ public:
}
};
class ParsedFunctionDeclarationStatement : public ParsedStatement{
HashedString _identifier;
vector<TypedVariableIdentifier*> _parameters;
ParsedBlockStatement* _block;
public:
ParsedFunctionDeclarationStatement(HashedString identifier, vector<TypedVariableIdentifier*> parameters, ParsedBlockStatement* block,
unsigned int start, unsigned int length)
: ParsedStatement(start, length), _identifier(identifier), _parameters(std::move(parameters)), _block(block){};
~ParsedFunctionDeclarationStatement() override {
for (auto v : _parameters){
delete v;
}
delete _block;
}
ParsedStatementKind GetKind() final{
return ParsedStatementKind ::FunctionDeclaration;
}
HashedString GetIdentifier(){
return _identifier;
}
vector<TypedVariableIdentifier*> GetParameters(){
return _parameters;
}
ParsedBlockStatement* GetBlock(){
return _block;
}
};
class ParsedAssignmentStatement : public ParsedStatement{
bool _local;
HashedString _identifier;

View File

@ -2,6 +2,7 @@
#include "Parser.hpp"
#include "UnaryOperatorKind.hpp"
#include "BinaryOperatorKind.hpp"
#include "TypedVariableIdentifier.hpp"
ParsedScriptStatement* Parser::Parse() {
@ -11,9 +12,6 @@ ParsedScriptStatement* Parser::Parse() {
if (next->GetKind() == TokenKind::EndOfFile){
break;
}
if (next->GetKind() == TokenKind::WhiteSpace){
continue;
}
statements.push_back(this -> ParseStatement(next));
}
return new ParsedScriptStatement(statements);
@ -29,9 +27,13 @@ IToken *Parser::Next() {
}
ParsedStatement* Parser::ParseStatement(IToken* current){
if (current->GetKind() == TokenKind::LocalKeyword){
return ParseAssignment(current);
} else if (this->Peek()->GetKind() == TokenKind::AssignmentToken){
auto currentKind = current->GetKind();
switch (currentKind){
case TokenKind ::LocalKeyword: return this -> ParseAssignment(current);
case TokenKind ::FunctionKeyword: return this -> ParseFunctionDeclaration(current);
default: break;
}
if (this->Peek()->GetKind() == TokenKind::AssignmentToken){
return ParseAssignment(current);
}
return new ParsedExpressionStatement(this -> ParseExpression(current));
@ -62,8 +64,83 @@ ParsedStatement *Parser::ParseAssignment(IToken *current) {
return new ParsedAssignmentStatement(isLocal, ((IdentifierToken*)identifier) -> Value, expression, start, expression->GetEndPosition() - start);
}
ParsedStatement *Parser::ParseBlock(vector<TokenKind> endTokens) {
vector<ParsedStatement*> statements;
while (true){
auto next = this -> Next();
auto nextKind = next->GetKind();
if (std::find(endTokens.begin(), endTokens.end(), nextKind) != endTokens.end()){
break;
}
if (nextKind == TokenKind::EndOfFile){
this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, next->GetStartPosition(), next->GetLength());
break;
}
statements.push_back(this -> ParseStatement(next));
}
return new ParsedBlockStatement(statements);
}
ParsedStatement *Parser::ParseFunctionDeclaration(IToken *current) {
auto functionIdentifierToken = this->Next();
auto openParenthesis = this->Next();
vector<TypedVariableIdentifier*> parameters;
bool hasErrors = false;
if (functionIdentifierToken->GetKind() != TokenKind::Identifier){
this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, functionIdentifierToken->GetStartPosition(), functionIdentifierToken->GetLength());
hasErrors = true;
}
if (openParenthesis->GetKind() != TokenKind::OpenParenthesis && !hasErrors){
this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, openParenthesis->GetStartPosition(), openParenthesis->GetLength());
hasErrors = true;
}
while (true){
auto type = this->Next();
auto identifier = this->Next();
auto next = this->Next();
if (type->GetKind() != TokenKind::Identifier &&!hasErrors){
this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, type->GetStartPosition(), type->GetLength());
hasErrors = true;
continue;
}
if (identifier->GetKind() != TokenKind::Identifier &&!hasErrors){
this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, identifier->GetStartPosition(), identifier->GetLength());
hasErrors = true;
continue;
}
auto typeToken = (IdentifierToken*)type;
auto identifierToken = (IdentifierToken*)identifier;
parameters.push_back(new TypedVariableIdentifier(HashedString(typeToken->Value), HashedString(identifierToken->Value)));
auto nextKind = next->GetKind();
if (nextKind == TokenKind::CloseParenthesis || nextKind == TokenKind::EndOfFile){
break;
} else if (nextKind != TokenKind::CommaToken && !hasErrors){
this->ScriptData->Diagnostics->LogError(DiagnosticCode::UnexpectedToken, next->GetStartPosition(), next->GetLength());
hasErrors = true;
}
}
auto block = this -> ParseBlock({TokenKind ::EndKeyword});
auto start = current->GetStartPosition();
if (hasErrors){
return new ParsedBadStatement(start, block->GetEndPosition() - start);
}
if (block->GetKind() == ParsedStatementKind::Bad){
return new ParsedBadStatement(start, block->GetEndPosition() - start);
}
auto functionIdentifier = ((IdentifierToken*) functionIdentifierToken)->Value;
return new ParsedFunctionDeclarationStatement(HashedString(functionIdentifier), parameters, (ParsedBlockStatement*)block, start, block->GetEndPosition() - start);
}
ParsedExpression* Parser::ParseExpression(IToken* current){
return this -> ParseBinaryExpression(current, OperatorPrecedence::No);
auto expression = this -> ParseBinaryExpression(current, OperatorPrecedence::No);
if (this -> Peek() -> GetKind() == TokenKind::OpenParenthesis){
//TODO: Function Evaluation
}
return expression;
}
OperatorPrecedence GetUnaryPrecedence(TokenKind kind){
@ -175,3 +252,5 @@ ParsedExpression *Parser::ParseParenthesizedExpression(IToken *current) {

View File

@ -26,7 +26,9 @@ class Parser {
IToken* Next();
ParsedStatement* ParseStatement(IToken* current);
ParsedStatement* ParseAssignment(IToken *current);
ParsedStatement* ParseAssignment(IToken* current);
ParsedStatement *ParseBlock(vector<TokenKind> endTokens);
ParsedStatement* ParseFunctionDeclaration(IToken* current);
ParsedExpression* ParseExpression(IToken* current);
ParsedExpression* ParseBinaryExpression(IToken* current, OperatorPrecedence parentPrecedence);

View File

@ -15,6 +15,7 @@ enum class TokenKind{
InequalityToken,
OpenParenthesis,
CloseParenthesis,
CommaToken,
Identifier,

View File

@ -0,0 +1,25 @@
#ifndef PORYGONLANG_TYPEDVARIABLEIDENTIFIER_HPP
#define PORYGONLANG_TYPEDVARIABLEIDENTIFIER_HPP
#include "../Utilities/HashedString.hpp"
class TypedVariableIdentifier{
HashedString _type;
HashedString _identifier;
public:
TypedVariableIdentifier(HashedString type, HashedString identifier)
: _type(type), _identifier(identifier)
{
}
HashedString GetType(){
return _type;
}
HashedString GetIdentifier(){
return _identifier;
}
};
#endif //PORYGONLANG_TYPEDVARIABLEIDENTIFIER_HPP

View File

@ -19,6 +19,13 @@ public:
const int GetHash(){
return _hash;
}
bool operator==(const HashedString& b) const{
return _hash == b._hash;
}
bool operator!=(const HashedString& b) const{
return _hash != b._hash;
}
};
#endif //PORYGONLANG_HASHEDSTRING_HPP

View File

@ -191,5 +191,36 @@ TEST_CASE( "Parse local Assignment", "[parser]" ) {
REQUIRE(((LiteralBoolExpression*)assignment->GetExpression()) -> GetValue());
}
TEST_CASE( "Parse function declaration", "[parser]" ){
vector<IToken*> v {
new SimpleToken(TokenKind::FunctionKeyword,0,0),
new IdentifierToken("foo",0,0),
new SimpleToken(TokenKind::OpenParenthesis,0,0),
new IdentifierToken("number",0,0),
new IdentifierToken("bar",0,0),
new SimpleToken(TokenKind::CommaToken,0,0),
new IdentifierToken("number",0,0),
new IdentifierToken("par",0,0),
new SimpleToken(TokenKind::CloseParenthesis,0,0),
new IdentifierToken("bar",0,0),
new SimpleToken(TokenKind::PlusToken,0,0),
new IdentifierToken("par",0,0),
new SimpleToken(TokenKind::EndKeyword,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::FunctionDeclaration);
auto functionDeclaration = (ParsedFunctionDeclarationStatement*)firstStatement;
REQUIRE(functionDeclaration->GetIdentifier() == HashedString("foo"));
auto parameters = functionDeclaration->GetParameters();
CHECK(parameters[0]->GetType() == HashedString("number"));
CHECK(parameters[0]->GetIdentifier() == HashedString("bar"));
CHECK(parameters[1]->GetType() == HashedString("number"));
CHECK(parameters[1]->GetIdentifier() == HashedString("par"));
}
#endif