Skip to content

Commit

Permalink
add syntax errors
Browse files Browse the repository at this point in the history
  • Loading branch information
jackparsonss committed Jun 28, 2024
1 parent f436493 commit 01e0bb9
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 3 deletions.
3 changes: 3 additions & 0 deletions include/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "ast/builder.h"
#include "ast/symbol/symbol_table.h"
#include "backend/backend.h"
#include "errors/syntax.h"

using std::shared_ptr, std::unique_ptr;

Expand All @@ -22,6 +23,8 @@ class Compiler {
antlr4::tree::ParseTree* tree;
antlr4::CommonTokenStream* tokens;
fusion::FusionParser* parser;
LexerErrorListener* lexer_error;
SyntaxErrorListener* syntax_error;

public:
Compiler(std::string filename,
Expand Down
File renamed without changes.
36 changes: 36 additions & 0 deletions include/errors/syntax.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#pragma once

#include "BaseErrorListener.h"
#include "antlr4-runtime.h"

#define _NC "\033[0m"
#define _RED "\033[0;31m"
#define _BLUE "\033[0;34m"

class LexerErrorListener : public antlr4::BaseErrorListener {
public:
void syntaxError(antlr4::Recognizer* recognizer,
antlr4::Token* offending_symbol,
size_t line,
size_t char_position_in_line,
const std::string& msg,
std::exception_ptr e) override;
};

class SyntaxErrorListener : public antlr4::BaseErrorListener {
public:
void syntaxError(antlr4::Recognizer* recognizer,
antlr4::Token* offending_symbol,
size_t line,
size_t char_position_in_line,
const std::string& msg,
std::exception_ptr e) override;
};

void underline_error(antlr4::Recognizer* recognizer,
antlr4::Token* offending_symbol,
size_t line,
size_t char_position_in_line,
std::ostream& out);

void show_rule_stack(antlr4::Recognizer* recognizer, std::ostream& out);
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ set(
"${CMAKE_CURRENT_SOURCE_DIR}/ast/passes/builtin.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/shared/type.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/shared/context.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/errors/syntax.cpp"
)

# Build our executable from the source files.
Expand Down
2 changes: 1 addition & 1 deletion src/ast/passes/def_ref.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "ast/passes/def_ref.h"
#include "ast/ast.h"
#include "ast/symbol/function_symbol.h"
#include "errors.h"
#include "errors/errors.h"

DefRef::DefRef(shared_ptr<SymbolTable> symbol_table) : Pass("DefRef") {
this->symbol_table = symbol_table;
Expand Down
2 changes: 1 addition & 1 deletion src/ast/passes/type_check.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "ast/passes/type_check.h"
#include "ast/ast.h"
#include "errors.h"
#include "errors/errors.h"
#include "shared/context.h"

TypeCheck::TypeCheck() : Pass("Typecheck") {}
Expand Down
13 changes: 12 additions & 1 deletion src/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
#include "FusionParser.h"
#include "ast/passes/pass.h"
#include "compiler.h"
#include "errors.h"
#include "errors/errors.h"
#include "errors/syntax.h"

Compiler::Compiler(std::string filename,
shared_ptr<SymbolTable> symbol_table,
Expand All @@ -19,9 +20,17 @@ Compiler::Compiler(std::string filename,
file = new antlr4::ANTLRFileStream();
file->loadFromFile(filename);

lexer_error = new LexerErrorListener();
lexer = new fusion::FusionLexer(file);
lexer->removeErrorListeners();
lexer->addErrorListener(lexer_error);

tokens = new antlr4::CommonTokenStream(lexer);

syntax_error = new SyntaxErrorListener();
parser = new fusion::FusionParser(tokens);
parser->removeErrorListeners();
parser->addErrorListener(syntax_error);

tree = parser->file();
}
Expand All @@ -31,6 +40,8 @@ Compiler::~Compiler() {
delete lexer;
delete tokens;
delete parser;
delete lexer_error;
delete syntax_error;
}

void Compiler::build_ast() {
Expand Down
61 changes: 61 additions & 0 deletions src/errors/syntax.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include "errors/syntax.h"
#include "errors/errors.h"

void SyntaxErrorListener::syntaxError(antlr4::Recognizer* recognizer,
antlr4::Token* offending_symbol,
size_t line,
size_t char_position_in_line,
const std::string& msg,
std::exception_ptr e) {
std::ostringstream out;
underline_error(recognizer, offending_symbol, line, char_position_in_line,
out);
show_rule_stack(recognizer, out);
throw SyntaxError(line, msg + out.rdbuf()->str());
}

void LexerErrorListener::syntaxError(antlr4::Recognizer* recognizer,
antlr4::Token* offending_symbol,
size_t line,
size_t char_position_in_line,
const std::string& msg,
std::exception_ptr e) {
throw SyntaxError(line, msg);
}

void underline_error(antlr4::Recognizer* recognizer,
antlr4::Token* offending_symbol,
size_t line,
size_t char_position_in_line,
std::ostream& out) {
auto tokens =
dynamic_cast<antlr4::CommonTokenStream*>(recognizer->getInputStream());
auto input = tokens->getTokenSource()->getInputStream()->toString();
std::string error_line = "\n";
for (size_t i = 0, line_counter = 0;
i < input.size() && line_counter <= line; i++) {
if (input[i] == '\n') {
line_counter++;
} else if (line_counter == line - 1) {
error_line += input[i];
}
}
auto length = offending_symbol->getStopIndex() -
offending_symbol->getStartIndex() + 1;
out << error_line << std::endl
<< _RED << std::string(char_position_in_line, ' ')
<< std::string(length, '^') << _NC << std::endl;
}

void show_rule_stack(antlr4::Recognizer* recognizer, std::ostream& out) {
auto parser = dynamic_cast<antlr4::Parser*>(recognizer);
auto rule_stack = parser->getRuleInvocationStack();
out << "Rule stack:" << std::endl;
size_t i = rule_stack.size();
out << _BLUE << rule_stack[--i] << std::endl;
for (size_t indent_level = 0; i-- > 0; indent_level++) {
out << std::string(indent_level * 2, ' ') << "└─" << rule_stack[i]
<< std::endl;
}
out << _NC;
}

0 comments on commit 01e0bb9

Please sign in to comment.