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