From b462c1b8738e147ac643d4243de157211000aaf8 Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Sat, 14 Sep 2019 10:35:32 +0200 Subject: [PATCH] Fixes empty script returning segmentation fault --- .../ParsedStatements/ParsedStatement.hpp | 95 +++++++++---------- src/Parser/Parser.cpp | 12 ++- tests/parser/ParserTests.cpp | 12 +++ 3 files changed, 69 insertions(+), 50 deletions(-) diff --git a/src/Parser/ParsedStatements/ParsedStatement.hpp b/src/Parser/ParsedStatements/ParsedStatement.hpp index d9729d5..ab5a159 100644 --- a/src/Parser/ParsedStatements/ParsedStatement.hpp +++ b/src/Parser/ParsedStatements/ParsedStatement.hpp @@ -37,17 +37,17 @@ namespace Porygon::Parser { virtual ~ParsedStatement() = default; - virtual const ParsedStatementKind GetKind() const = 0; + [[nodiscard]] virtual ParsedStatementKind GetKind() const = 0; - const unsigned int GetStartPosition() const { + [[nodiscard]] unsigned int GetStartPosition() const { return _start; } - const unsigned int GetLength() const { + [[nodiscard]] unsigned int GetLength() const { return _length; } - const unsigned int GetEndPosition() const { + [[nodiscard]] unsigned int GetEndPosition() const { return _start + _length - 1; } }; @@ -56,7 +56,7 @@ namespace Porygon::Parser { public: ParsedBadStatement(unsigned int start, unsigned int length) : ParsedStatement(start, length) {}; - inline const ParsedStatementKind GetKind() const final { + [[nodiscard]] inline ParsedStatementKind GetKind() const final { return ParsedStatementKind::Bad; } }; @@ -65,7 +65,7 @@ namespace Porygon::Parser { public: ParsedBreakStatement(unsigned int start, unsigned int length) : ParsedStatement(start, length) {}; - inline const ParsedStatementKind GetKind() const final { + [[nodiscard]] inline ParsedStatementKind GetKind() const final { return ParsedStatementKind::Break; } }; @@ -73,10 +73,9 @@ namespace Porygon::Parser { class ParsedBlockStatement : public ParsedStatement { const std::vector _statements; public: - explicit ParsedBlockStatement(const std::vector& statements) - : ParsedStatement(statements.front()->GetStartPosition(), - statements.back()->GetEndPosition() - statements.front()->GetStartPosition()), - _statements(statements) {} + explicit ParsedBlockStatement(std::vector statements, size_t start, size_t length) + : ParsedStatement(start, length), + _statements(std::move(statements)) {} ParsedBlockStatement(std::vector statements, unsigned int start) : ParsedStatement( start, 0), _statements(std::move(statements)) { @@ -89,21 +88,21 @@ namespace Porygon::Parser { } } - inline const ParsedStatementKind GetKind() const override { + [[nodiscard]] inline ParsedStatementKind GetKind() const override { return ParsedStatementKind::Block; } - inline const std::vector *GetStatements() const { + [[nodiscard]] inline const std::vector *GetStatements() const { return &_statements; } }; class ParsedScriptStatement : public ParsedBlockStatement { public: - explicit ParsedScriptStatement(vector statements) : ParsedBlockStatement( - move(statements)) {} + explicit ParsedScriptStatement(const vector& statements, size_t start, size_t length) : ParsedBlockStatement( + statements, start, length) {} - inline const ParsedStatementKind GetKind() const final { + [[nodiscard]] inline ParsedStatementKind GetKind() const final { return ParsedStatementKind::Script; } }; @@ -124,11 +123,11 @@ namespace Porygon::Parser { _expression = nullptr; } - inline const ParsedStatementKind GetKind() const final { + [[nodiscard]] inline ParsedStatementKind GetKind() const final { return ParsedStatementKind::Expression; } - inline const ParsedExpression *GetExpression() const { + [[nodiscard]] inline const ParsedExpression *GetExpression() const { return _expression; } }; @@ -151,19 +150,19 @@ namespace Porygon::Parser { delete _block; } - inline const ParsedStatementKind GetKind() const final { + [[nodiscard]] inline ParsedStatementKind GetKind() const final { return ParsedStatementKind::FunctionDeclaration; } - inline const HashedString GetIdentifier() const { + [[nodiscard]] inline HashedString GetIdentifier() const { return _identifier; } - inline const vector *GetParameters() const { + [[nodiscard]] inline const vector *GetParameters() const { return &_parameters; } - inline const ParsedBlockStatement *GetBlock() const { + [[nodiscard]] inline const ParsedBlockStatement *GetBlock() const { return _block; } }; @@ -182,19 +181,19 @@ namespace Porygon::Parser { delete _expression; } - inline const ParsedStatementKind GetKind() const final { + [[nodiscard]] inline ParsedStatementKind GetKind() const final { return ParsedStatementKind::Assignment; } - inline const bool IsLocal() const { + [[nodiscard]] inline bool IsLocal() const { return _local; } - inline const HashedString GetIdentifier() const { + [[nodiscard]] inline HashedString GetIdentifier() const { return _identifier; } - inline const ParsedExpression *GetExpression() const { + [[nodiscard]] inline const ParsedExpression *GetExpression() const { return _expression; } }; @@ -214,15 +213,15 @@ namespace Porygon::Parser { delete _valueExpression; } - inline const ParsedStatementKind GetKind() const final { + [[nodiscard]] inline ParsedStatementKind GetKind() const final { return ParsedStatementKind::IndexAssignment; } - inline const ParsedExpression *GetIndexExpression() const { + [[nodiscard]] inline const ParsedExpression *GetIndexExpression() const { return _indexExpression; } - inline const ParsedExpression *GetValueExpression() const { + [[nodiscard]] inline const ParsedExpression *GetValueExpression() const { return _valueExpression; } }; @@ -239,11 +238,11 @@ namespace Porygon::Parser { delete _expression; } - inline const ParsedStatementKind GetKind() const final { + [[nodiscard]] inline ParsedStatementKind GetKind() const final { return ParsedStatementKind::Return; } - inline const ParsedExpression *GetExpression() const { + [[nodiscard]] inline const ParsedExpression *GetExpression() const { return _expression; } }; @@ -273,19 +272,19 @@ namespace Porygon::Parser { delete _elseStatement; } - inline const ParsedStatementKind GetKind() const final { + [[nodiscard]] inline ParsedStatementKind GetKind() const final { return ParsedStatementKind::Conditional; } - inline const ParsedExpression *GetCondition() const { + [[nodiscard]] inline const ParsedExpression *GetCondition() const { return _condition; } - inline const ParsedStatement *GetBlock() const { + [[nodiscard]] inline const ParsedStatement *GetBlock() const { return _block; } - inline const ParsedStatement *GetElseStatement() const { + [[nodiscard]] inline const ParsedStatement *GetElseStatement() const { return _elseStatement; } }; @@ -310,27 +309,27 @@ namespace Porygon::Parser { delete _block; } - inline const ParsedStatementKind GetKind() const final { + [[nodiscard]] inline ParsedStatementKind GetKind() const final { return ParsedStatementKind::NumericalFor; } - inline const HashedString GetIdentifier() const{ + [[nodiscard]] inline HashedString GetIdentifier() const{ return _identifier; } - inline const ParsedExpression *GetStart() const{ + [[nodiscard]] inline const ParsedExpression *GetStart() const{ return _start; } - inline const ParsedExpression *GetEnd() const{ + [[nodiscard]] inline const ParsedExpression *GetEnd() const{ return _end; } - inline const ParsedExpression *GetStep() const{ + [[nodiscard]] inline const ParsedExpression *GetStep() const{ return _step; } - inline const ParsedStatement *GetBlock() const{ + [[nodiscard]] inline const ParsedStatement *GetBlock() const{ return _block; } }; @@ -352,23 +351,23 @@ namespace Porygon::Parser { delete _block; } - inline const ParsedStatementKind GetKind() const final { + [[nodiscard]] inline ParsedStatementKind GetKind() const final { return ParsedStatementKind::GenericFor; } - inline const HashedString GetKeyIdentifier() const{ + [[nodiscard]] inline HashedString GetKeyIdentifier() const{ return _keyIdentifier; } - inline const HashedString GetValueIdentifier() const{ + [[nodiscard]] inline HashedString GetValueIdentifier() const{ return _valueIdentifier; } - inline const ParsedExpression* GetIteratorExpression() const{ + [[nodiscard]] inline const ParsedExpression* GetIteratorExpression() const{ return _iteratorExpression; } - inline const ParsedStatement* GetBlock() const{ + [[nodiscard]] inline const ParsedStatement* GetBlock() const{ return _block; } }; @@ -386,15 +385,15 @@ namespace Porygon::Parser { delete _block; } - inline const ParsedStatementKind GetKind() const final { + [[nodiscard]] inline ParsedStatementKind GetKind() const final { return ParsedStatementKind::While; } - inline const ParsedExpression* GetCondition(){ + [[nodiscard]] inline const ParsedExpression* GetCondition(){ return _condition; } - inline const ParsedStatement* GetBlock(){ + [[nodiscard]] inline const ParsedStatement* GetBlock(){ return _block; } }; diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp index b7c3a72..20ab8b8 100644 --- a/src/Parser/Parser.cpp +++ b/src/Parser/Parser.cpp @@ -16,7 +16,11 @@ namespace Porygon::Parser { } statements.push_back(this->ParseStatement(next)); } - return new ParsedScriptStatement(statements); + auto end = 0; + if (statements.size() > 0){ + end = statements.back()->GetEndPosition(); + } + return new ParsedScriptStatement(statements, 0, end); } inline const Token *Parser::Peek() { @@ -123,7 +127,11 @@ namespace Porygon::Parser { if (statements.empty()) { return new ParsedBlockStatement(statements, start); } - return new ParsedBlockStatement(statements); + auto end = 0; + if (statements.size() > 0){ + end = statements.back()->GetEndPosition(); + } + return new ParsedBlockStatement(statements, start, end - start); } ParsedStatement *Parser::ParseFunctionDeclaration(const Token *current) { diff --git a/tests/parser/ParserTests.cpp b/tests/parser/ParserTests.cpp index 30cee3d..7ec290b 100644 --- a/tests/parser/ParserTests.cpp +++ b/tests/parser/ParserTests.cpp @@ -5,6 +5,18 @@ #include "../../src/Parser/Parser.hpp" using namespace Porygon::Parser; +TEST_CASE( "Parse empty script", "[parser]" ) { + vector v { + new SimpleToken(TokenKind::EndOfFile,0,0), + }; + Parser parser = Parser(v, nullptr); + auto parsedScript = parser.Parse(); + for (auto t : v){ + delete t; + } + delete parsedScript; +} + TEST_CASE( "Parse single true keyword", "[parser]" ) { vector v {new SimpleToken(TokenKind::TrueKeyword,0,0), new SimpleToken(TokenKind::EndOfFile,0,0)}; Parser parser = Parser(v, nullptr);