Add support for diagnostics to parser
This commit is contained in:
parent
2b35da3a7b
commit
99f50b6471
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
enum class DiagnosticCode{
|
enum class DiagnosticCode{
|
||||||
UnexpectedCharacter,
|
UnexpectedCharacter,
|
||||||
|
UnexpectedToken,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //PORYGONLANG_DIAGNOSTICCODE_HPP
|
#endif //PORYGONLANG_DIAGNOSTICCODE_HPP
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include "../BinaryOperatorKind.hpp"
|
#include "../BinaryOperatorKind.hpp"
|
||||||
|
|
||||||
enum class ParsedExpressionKind{
|
enum class ParsedExpressionKind{
|
||||||
|
Bad,
|
||||||
|
|
||||||
LiteralInteger,
|
LiteralInteger,
|
||||||
LiteralFloat,
|
LiteralFloat,
|
||||||
LiteralString,
|
LiteralString,
|
||||||
|
@ -40,6 +42,15 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class BadExpression : public ParsedExpression{
|
||||||
|
public:
|
||||||
|
BadExpression(unsigned int position, unsigned int length) : ParsedExpression(position, length){}
|
||||||
|
|
||||||
|
ParsedExpressionKind GetKind() final{
|
||||||
|
return ParsedExpressionKind::Bad;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class LiteralIntegerExpression : public ParsedExpression{
|
class LiteralIntegerExpression : public ParsedExpression{
|
||||||
long _value;
|
long _value;
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -7,24 +7,24 @@
|
||||||
ParsedScriptStatement* Parser::Parse() {
|
ParsedScriptStatement* Parser::Parse() {
|
||||||
vector<ParsedStatement*> statements;
|
vector<ParsedStatement*> statements;
|
||||||
while (true){
|
while (true){
|
||||||
auto next = Parser::Next();
|
auto next = this -> Next();
|
||||||
if (next->GetKind() == TokenKind::EndOfFile){
|
if (next->GetKind() == TokenKind::EndOfFile){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (next->GetKind() == TokenKind::WhiteSpace){
|
if (next->GetKind() == TokenKind::WhiteSpace){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
statements.push_back(Parser::ParseStatement(next));
|
statements.push_back(this -> ParseStatement(next));
|
||||||
}
|
}
|
||||||
return new ParsedScriptStatement(statements);
|
return new ParsedScriptStatement(statements);
|
||||||
}
|
}
|
||||||
|
|
||||||
ParsedStatement* Parser::ParseStatement(IToken* current){
|
ParsedStatement* Parser::ParseStatement(IToken* current){
|
||||||
return new ParsedExpressionStatement(Parser::ParseExpression(current));
|
return new ParsedExpressionStatement(this -> ParseExpression(current));
|
||||||
}
|
}
|
||||||
|
|
||||||
ParsedExpression* Parser::ParseExpression(IToken* current){
|
ParsedExpression* Parser::ParseExpression(IToken* current){
|
||||||
return Parser::ParseBinaryExpression(current, OperatorPrecedence::No);
|
return this -> ParseBinaryExpression(current, OperatorPrecedence::No);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ UnaryOperatorKind GetUnaryOperatorKind(TokenKind kind){
|
||||||
case TokenKind::PlusToken: return UnaryOperatorKind::Identity;
|
case TokenKind::PlusToken: return UnaryOperatorKind::Identity;
|
||||||
case TokenKind::MinusToken: return UnaryOperatorKind::Negation;
|
case TokenKind::MinusToken: return UnaryOperatorKind::Negation;
|
||||||
case TokenKind::NotKeyword: return UnaryOperatorKind::LogicalNegation;
|
case TokenKind::NotKeyword: return UnaryOperatorKind::LogicalNegation;
|
||||||
default:
|
default: // This should never trigger, so throw.
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ BinaryOperatorKind GetBinaryOperatorKind(TokenKind kind){
|
||||||
case TokenKind::EqualityToken: return BinaryOperatorKind ::Equality;
|
case TokenKind::EqualityToken: return BinaryOperatorKind ::Equality;
|
||||||
case TokenKind::AndKeyword: return BinaryOperatorKind ::LogicalAnd;
|
case TokenKind::AndKeyword: return BinaryOperatorKind ::LogicalAnd;
|
||||||
case TokenKind::OrKeyword: return BinaryOperatorKind ::LogicalOr;
|
case TokenKind::OrKeyword: return BinaryOperatorKind ::LogicalOr;
|
||||||
default:
|
default: // This should never trigger, so throw.
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,22 +82,22 @@ ParsedExpression* Parser::ParseBinaryExpression(IToken* current, OperatorPrecede
|
||||||
ParsedExpression* left;
|
ParsedExpression* left;
|
||||||
if (unaryPrecedence != OperatorPrecedence::No && unaryPrecedence >= parentPrecedence){
|
if (unaryPrecedence != OperatorPrecedence::No && unaryPrecedence >= parentPrecedence){
|
||||||
UnaryOperatorKind operatorKind = GetUnaryOperatorKind(current -> GetKind());
|
UnaryOperatorKind operatorKind = GetUnaryOperatorKind(current -> GetKind());
|
||||||
auto next = Parser::Next();
|
auto next = this -> Next();
|
||||||
auto operand = Parser::ParseBinaryExpression(next, unaryPrecedence);
|
auto operand = this -> ParseBinaryExpression(next, unaryPrecedence);
|
||||||
auto startPos = current -> GetStartPosition();
|
auto startPos = current -> GetStartPosition();
|
||||||
left = new UnaryExpression(operatorKind, operand, startPos, operand -> GetEndPosition() - startPos);
|
left = new UnaryExpression(operatorKind, operand, startPos, operand -> GetEndPosition() - startPos);
|
||||||
} else{
|
} else{
|
||||||
left = Parser::ParsePrimaryExpression(current);
|
left = this -> ParsePrimaryExpression(current);
|
||||||
}
|
}
|
||||||
while (true){
|
while (true){
|
||||||
auto next = Parser::Peek();
|
auto next = this -> Peek();
|
||||||
OperatorPrecedence binaryPrecedence = GetBinaryPrecedence(next -> GetKind());
|
OperatorPrecedence binaryPrecedence = GetBinaryPrecedence(next -> GetKind());
|
||||||
if (binaryPrecedence == OperatorPrecedence::No || binaryPrecedence <= parentPrecedence){
|
if (binaryPrecedence == OperatorPrecedence::No || binaryPrecedence <= parentPrecedence){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
auto operatorKind = GetBinaryOperatorKind(next -> GetKind());
|
auto operatorKind = GetBinaryOperatorKind(next -> GetKind());
|
||||||
Parser::Next();
|
this -> Next();
|
||||||
auto right = ParseBinaryExpression(Parser::Next(), binaryPrecedence);
|
auto right = ParseBinaryExpression(this -> Next(), binaryPrecedence);
|
||||||
auto startPos = left -> GetStartPosition();
|
auto startPos = left -> GetStartPosition();
|
||||||
left = new BinaryExpression(operatorKind, left, right, startPos, right -> GetEndPosition() - startPos);
|
left = new BinaryExpression(operatorKind, left, right, startPos, right -> GetEndPosition() - startPos);
|
||||||
}
|
}
|
||||||
|
@ -111,18 +111,19 @@ ParsedExpression *Parser::ParsePrimaryExpression(IToken *current) {
|
||||||
case TokenKind ::TrueKeyword: return new LiteralBoolExpression(current);
|
case TokenKind ::TrueKeyword: return new LiteralBoolExpression(current);
|
||||||
case TokenKind ::FalseKeyword: return new LiteralBoolExpression(current);
|
case TokenKind ::FalseKeyword: return new LiteralBoolExpression(current);
|
||||||
default:
|
default:
|
||||||
throw;
|
this -> ScriptData -> Diagnostics.LogError(DiagnosticCode::UnexpectedToken, current->GetStartPosition(), current->GetLength());
|
||||||
|
return new BadExpression(current->GetStartPosition(), current->GetLength());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
IToken *Parser::Peek() {
|
IToken *Parser::Peek() {
|
||||||
return Parser::_tokens[_position];
|
return this -> _tokens[_position];
|
||||||
}
|
}
|
||||||
|
|
||||||
IToken *Parser::Next() {
|
IToken *Parser::Next() {
|
||||||
Parser::_position++;
|
this -> _position++;
|
||||||
return Parser::_tokens[_position - 1];
|
return this -> _tokens[_position - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TESTS_BUILD
|
#ifdef TESTS_BUILD
|
||||||
|
@ -130,7 +131,7 @@ IToken *Parser::Next() {
|
||||||
|
|
||||||
TEST_CASE( "Parse single true keyword", "[parser]" ) {
|
TEST_CASE( "Parse single true keyword", "[parser]" ) {
|
||||||
vector<IToken*> v {new SimpleToken(TokenKind::TrueKeyword,0,0), new SimpleToken(TokenKind::EndOfFile,0,0)};
|
vector<IToken*> v {new SimpleToken(TokenKind::TrueKeyword,0,0), new SimpleToken(TokenKind::EndOfFile,0,0)};
|
||||||
Parser parser = Parser(v);
|
Parser parser = Parser(v, nullptr);
|
||||||
auto parsedStatements = parser.Parse() -> GetStatements();
|
auto parsedStatements = parser.Parse() -> GetStatements();
|
||||||
REQUIRE(parsedStatements.size() == 1);
|
REQUIRE(parsedStatements.size() == 1);
|
||||||
auto firstStatement = parsedStatements[0];
|
auto firstStatement = parsedStatements[0];
|
||||||
|
@ -143,7 +144,7 @@ TEST_CASE( "Parse single true keyword", "[parser]" ) {
|
||||||
|
|
||||||
TEST_CASE( "Parse single false keyword", "[parser]" ) {
|
TEST_CASE( "Parse single false keyword", "[parser]" ) {
|
||||||
vector<IToken*> v {new SimpleToken(TokenKind::FalseKeyword,0,0), new SimpleToken(TokenKind::EndOfFile,0,0)};
|
vector<IToken*> v {new SimpleToken(TokenKind::FalseKeyword,0,0), new SimpleToken(TokenKind::EndOfFile,0,0)};
|
||||||
Parser parser = Parser(v);
|
Parser parser = Parser(v, nullptr);
|
||||||
auto parsedStatements = parser.Parse() -> GetStatements();
|
auto parsedStatements = parser.Parse() -> GetStatements();
|
||||||
REQUIRE(parsedStatements.size() == 1);
|
REQUIRE(parsedStatements.size() == 1);
|
||||||
auto firstStatement = parsedStatements[0];
|
auto firstStatement = parsedStatements[0];
|
||||||
|
@ -161,7 +162,7 @@ TEST_CASE( "Parse simple addition", "[parser]" ) {
|
||||||
new IntegerToken(10, 0, 0),
|
new IntegerToken(10, 0, 0),
|
||||||
new SimpleToken(TokenKind::EndOfFile,0,0)
|
new SimpleToken(TokenKind::EndOfFile,0,0)
|
||||||
};
|
};
|
||||||
Parser parser = Parser(v);
|
Parser parser = Parser(v, nullptr);
|
||||||
auto parsedStatements = parser.Parse() -> GetStatements();
|
auto parsedStatements = parser.Parse() -> GetStatements();
|
||||||
REQUIRE(parsedStatements.size() == 1);
|
REQUIRE(parsedStatements.size() == 1);
|
||||||
auto firstStatement = parsedStatements[0];
|
auto firstStatement = parsedStatements[0];
|
||||||
|
@ -184,7 +185,7 @@ TEST_CASE( "Parse simple negation", "[parser]" ) {
|
||||||
new IntegerToken(10, 0, 0),
|
new IntegerToken(10, 0, 0),
|
||||||
new SimpleToken(TokenKind::EndOfFile,0,0)
|
new SimpleToken(TokenKind::EndOfFile,0,0)
|
||||||
};
|
};
|
||||||
Parser parser = Parser(v);
|
Parser parser = Parser(v, nullptr);
|
||||||
auto parsedStatements = parser.Parse() -> GetStatements();
|
auto parsedStatements = parser.Parse() -> GetStatements();
|
||||||
REQUIRE(parsedStatements.size() == 1);
|
REQUIRE(parsedStatements.size() == 1);
|
||||||
auto firstStatement = parsedStatements[0];
|
auto firstStatement = parsedStatements[0];
|
||||||
|
@ -204,7 +205,7 @@ TEST_CASE( "Parse logical negation", "[parser]" ) {
|
||||||
new SimpleToken(TokenKind::FalseKeyword,0,0),
|
new SimpleToken(TokenKind::FalseKeyword,0,0),
|
||||||
new SimpleToken(TokenKind::EndOfFile,0,0)
|
new SimpleToken(TokenKind::EndOfFile,0,0)
|
||||||
};
|
};
|
||||||
Parser parser = Parser(v);
|
Parser parser = Parser(v, nullptr);
|
||||||
auto parsedStatements = parser.Parse() -> GetStatements();
|
auto parsedStatements = parser.Parse() -> GetStatements();
|
||||||
REQUIRE(parsedStatements.size() == 1);
|
REQUIRE(parsedStatements.size() == 1);
|
||||||
auto firstStatement = parsedStatements[0];
|
auto firstStatement = parsedStatements[0];
|
||||||
|
@ -227,7 +228,7 @@ TEST_CASE( "Assert binary precedence", "[parser]" ) {
|
||||||
new IntegerToken(6, 0, 0),
|
new IntegerToken(6, 0, 0),
|
||||||
new SimpleToken(TokenKind::EndOfFile,0,0)
|
new SimpleToken(TokenKind::EndOfFile,0,0)
|
||||||
};
|
};
|
||||||
Parser parser = Parser(v);
|
Parser parser = Parser(v, nullptr);
|
||||||
auto parsedStatements = parser.Parse() -> GetStatements();
|
auto parsedStatements = parser.Parse() -> GetStatements();
|
||||||
REQUIRE(parsedStatements.size() == 1);
|
REQUIRE(parsedStatements.size() == 1);
|
||||||
auto firstStatement = parsedStatements[0];
|
auto firstStatement = parsedStatements[0];
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include "ParsedStatements/ParsedStatement.hpp"
|
#include "ParsedStatements/ParsedStatement.hpp"
|
||||||
|
#include "../Script.hpp"
|
||||||
|
|
||||||
enum class OperatorPrecedence {
|
enum class OperatorPrecedence {
|
||||||
No,
|
No,
|
||||||
|
@ -19,6 +20,7 @@ enum class OperatorPrecedence {
|
||||||
class Parser {
|
class Parser {
|
||||||
vector<IToken*> _tokens;
|
vector<IToken*> _tokens;
|
||||||
unsigned int _position;
|
unsigned int _position;
|
||||||
|
Script* ScriptData;
|
||||||
|
|
||||||
IToken* Peek();
|
IToken* Peek();
|
||||||
IToken* Next();
|
IToken* Next();
|
||||||
|
@ -28,9 +30,10 @@ class Parser {
|
||||||
ParsedExpression* ParsePrimaryExpression(IToken* current);
|
ParsedExpression* ParsePrimaryExpression(IToken* current);
|
||||||
public:
|
public:
|
||||||
ParsedScriptStatement* Parse();
|
ParsedScriptStatement* Parse();
|
||||||
explicit Parser(vector<IToken*> tokens){
|
explicit Parser(vector<IToken*> tokens, Script* scriptData){
|
||||||
_tokens = std::move(tokens);
|
_tokens = std::move(tokens);
|
||||||
_position = 0;
|
_position = 0;
|
||||||
|
ScriptData = scriptData;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ Script Script::Create(string script) {
|
||||||
void Script::Parse(string script) {
|
void Script::Parse(string script) {
|
||||||
auto lexer = Lexer(std::move(script), this);
|
auto lexer = Lexer(std::move(script), this);
|
||||||
auto lexResult = lexer.Lex();
|
auto lexResult = lexer.Lex();
|
||||||
auto parser = Parser(lexResult);
|
auto parser = Parser(lexResult, this);
|
||||||
auto parseResult = parser.Parse();
|
auto parseResult = parser.Parse();
|
||||||
for (auto token : lexResult){
|
for (auto token : lexResult){
|
||||||
delete token;
|
delete token;
|
||||||
|
|
Loading…
Reference in New Issue