Improve diagnostic output
This commit is contained in:
parent
fb69ab745c
commit
fcea25c9bb
14 changed files with 122 additions and 63 deletions
|
@ -8,8 +8,10 @@ set(CMAKE_CXX_STANDARD 17)
|
||||||
add_subdirectory(deps/zen EXCLUDE_FROM_ALL)
|
add_subdirectory(deps/zen EXCLUDE_FROM_ALL)
|
||||||
|
|
||||||
set(ICU_DIR "${CMAKE_CURRENT_SOURCE_DIR}/build/icu/install")
|
set(ICU_DIR "${CMAKE_CURRENT_SOURCE_DIR}/build/icu/install")
|
||||||
|
set(ICU_CFLAGS "-DUNISTR_FROM_CHAR_EXPLICIT=explicit -DUNISTR_FROM_STRING_EXPLICIT=explicit -DU_NO_DEFAULT_INCLUDE_UTF_HEADERS=1 -DU_HIDE_OBSOLETE_UTF_OLD_H=1")
|
||||||
set(ICU_INCLUDE_DIRS "${ICU_DIR}/include")
|
set(ICU_INCLUDE_DIRS "${ICU_DIR}/include")
|
||||||
set(ICU_LIBRARY_DIRS "${ICU_DIR}/lib")
|
set(ICU_LIBRARY_DIRS "${ICU_DIR}/lib")
|
||||||
|
set(ICU_LIBRARIES icuuc)
|
||||||
|
|
||||||
add_library(
|
add_library(
|
||||||
BoltCore
|
BoltCore
|
||||||
|
@ -29,6 +31,7 @@ target_compile_options(
|
||||||
BoltCore
|
BoltCore
|
||||||
PUBLIC
|
PUBLIC
|
||||||
-fstandalone-debug
|
-fstandalone-debug
|
||||||
|
${ICU_CFLAGS}
|
||||||
)
|
)
|
||||||
target_include_directories(
|
target_include_directories(
|
||||||
BoltCore
|
BoltCore
|
||||||
|
|
|
@ -122,11 +122,7 @@ namespace bolt {
|
||||||
return StartLoc;
|
return StartLoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline TextLoc getEndLoc() {
|
TextLoc getEndLoc();
|
||||||
TextLoc EndLoc;
|
|
||||||
EndLoc.advance(getText());
|
|
||||||
return EndLoc;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t getStartLine() {
|
inline size_t getStartLine() {
|
||||||
return StartLoc.Line;
|
return StartLoc.Line;
|
||||||
|
|
|
@ -228,9 +228,10 @@ namespace bolt {
|
||||||
|
|
||||||
Type* Left;
|
Type* Left;
|
||||||
Type* Right;
|
Type* Right;
|
||||||
|
Node* Source;
|
||||||
|
|
||||||
inline CEqual(Type* Left, Type* Right):
|
inline CEqual(Type* Left, Type* Right, Node* Source = nullptr):
|
||||||
Constraint(ConstraintKind::Equal), Left(Left), Right(Right) {}
|
Constraint(ConstraintKind::Equal), Left(Left), Right(Right), Source(Source) {}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -40,22 +40,24 @@ namespace bolt {
|
||||||
class UnexpectedTokenDiagnostic : public Diagnostic {
|
class UnexpectedTokenDiagnostic : public Diagnostic {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
TextFile& File;
|
||||||
Token* Actual;
|
Token* Actual;
|
||||||
std::vector<NodeType> Expected;
|
std::vector<NodeType> Expected;
|
||||||
|
|
||||||
inline UnexpectedTokenDiagnostic(Token* Actual, std::vector<NodeType> Expected):
|
inline UnexpectedTokenDiagnostic(TextFile& File, Token* Actual, std::vector<NodeType> Expected):
|
||||||
Diagnostic(DiagnosticKind::UnexpectedToken), Actual(Actual), Expected(Expected) {}
|
Diagnostic(DiagnosticKind::UnexpectedToken), File(File), Actual(Actual), Expected(Expected) {}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class UnexpectedStringDiagnostic : public Diagnostic {
|
class UnexpectedStringDiagnostic : public Diagnostic {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
TextFile& File;
|
||||||
TextLoc Location;
|
TextLoc Location;
|
||||||
String Actual;
|
String Actual;
|
||||||
|
|
||||||
inline UnexpectedStringDiagnostic(TextLoc Location, String Actual):
|
inline UnexpectedStringDiagnostic(TextFile& File, TextLoc Location, String Actual):
|
||||||
Diagnostic(DiagnosticKind::UnexpectedString), Location(Location), Actual(Actual) {}
|
Diagnostic(DiagnosticKind::UnexpectedString), File(File), Location(Location), Actual(Actual) {}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -75,9 +77,10 @@ namespace bolt {
|
||||||
|
|
||||||
Type* Left;
|
Type* Left;
|
||||||
Type* Right;
|
Type* Right;
|
||||||
|
Node* Source;
|
||||||
|
|
||||||
inline UnificationErrorDiagnostic(Type* Left, Type* Right):
|
inline UnificationErrorDiagnostic(Type* Left, Type* Right, Node* Source):
|
||||||
Diagnostic(DiagnosticKind::UnificationError), Left(Left), Right(Right) {}
|
Diagnostic(DiagnosticKind::UnificationError), Left(Left), Right(Right), Source(Source) {}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -116,6 +119,9 @@ namespace bolt {
|
||||||
|
|
||||||
void setForegroundColor(Color C);
|
void setForegroundColor(Color C);
|
||||||
void setBackgroundColor(Color C);
|
void setBackgroundColor(Color C);
|
||||||
|
void setBold(bool Enable);
|
||||||
|
void setItalic(bool Enable);
|
||||||
|
void setUnderline(bool Enable);
|
||||||
void resetStyles();
|
void resetStyles();
|
||||||
|
|
||||||
void writeGutter(
|
void writeGutter(
|
||||||
|
|
|
@ -24,11 +24,11 @@ namespace bolt {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ContainerT>
|
template<typename ContainerT, typename T = typename ContainerT::value_type>
|
||||||
class VectorStream : public Stream<typename ContainerT::value_type> {
|
class VectorStream : public Stream<T> {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using value_type = typename ContainerT::value_type;
|
using value_type = T;
|
||||||
|
|
||||||
ContainerT& Data;
|
ContainerT& Data;
|
||||||
value_type Sentry;
|
value_type Sentry;
|
||||||
|
@ -82,6 +82,8 @@ namespace bolt {
|
||||||
|
|
||||||
class Scanner : public BufferedStream<Token*> {
|
class Scanner : public BufferedStream<Token*> {
|
||||||
|
|
||||||
|
TextFile& File;
|
||||||
|
|
||||||
Stream<Char>& Chars;
|
Stream<Char>& Chars;
|
||||||
|
|
||||||
TextLoc CurrLoc;
|
TextLoc CurrLoc;
|
||||||
|
@ -111,7 +113,7 @@ namespace bolt {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Scanner(Stream<Char>& Chars);
|
Scanner(TextFile& File, Stream<Char>& Chars);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
|
|
||||||
namespace bolt {
|
namespace bolt {
|
||||||
|
|
||||||
using Char = char32_t;
|
using Char = int;
|
||||||
|
|
||||||
using String = std::basic_string<Char>;
|
using String = std::string;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace bolt {
|
||||||
size_t Line = 1;
|
size_t Line = 1;
|
||||||
size_t Column = 1;
|
size_t Column = 1;
|
||||||
|
|
||||||
inline void advance(const std::string& Text) {
|
inline void advance(const String& Text) {
|
||||||
for (auto Chr: Text) {
|
for (auto Chr: Text) {
|
||||||
if (Chr == '\n') {
|
if (Chr == '\n') {
|
||||||
Line++;
|
Line++;
|
||||||
|
@ -28,6 +28,12 @@ namespace bolt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline TextLoc operator+(const String& Text) const {
|
||||||
|
TextLoc Out { Line, Column };
|
||||||
|
Out.advance(Text);
|
||||||
|
return Out;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TextRange {
|
class TextRange {
|
||||||
|
@ -39,13 +45,13 @@ namespace bolt {
|
||||||
class TextFile {
|
class TextFile {
|
||||||
|
|
||||||
ByteString Path;
|
ByteString Path;
|
||||||
String Text;
|
ByteString Text;
|
||||||
|
|
||||||
std::vector<size_t> LineOffsets;
|
std::vector<size_t> LineOffsets;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
TextFile(ByteString Path, String Text);
|
TextFile(ByteString Path, ByteString Text);
|
||||||
|
|
||||||
size_t getLine(size_t Offset);
|
size_t getLine(size_t Offset);
|
||||||
size_t getColumn(size_t Offset);
|
size_t getColumn(size_t Offset);
|
||||||
|
@ -55,7 +61,7 @@ namespace bolt {
|
||||||
|
|
||||||
ByteString getPath() const;
|
ByteString getPath() const;
|
||||||
|
|
||||||
String getText() const;
|
ByteString getText() const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ namespace bolt {
|
||||||
auto CurrNode = this;
|
auto CurrNode = this;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (CurrNode->Type == NodeType::SourceFile) {
|
if (CurrNode->Type == NodeType::SourceFile) {
|
||||||
return static_cast<SourceFile*>(this);
|
return static_cast<SourceFile*>(CurrNode);
|
||||||
}
|
}
|
||||||
CurrNode = CurrNode->Parent;
|
CurrNode = CurrNode->Parent;
|
||||||
ZEN_ASSERT(CurrNode != nullptr);
|
ZEN_ASSERT(CurrNode != nullptr);
|
||||||
|
@ -23,6 +23,12 @@ namespace bolt {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextLoc Token::getEndLoc() {
|
||||||
|
auto EndLoc = StartLoc;
|
||||||
|
EndLoc.advance(getText());
|
||||||
|
return EndLoc;
|
||||||
|
}
|
||||||
|
|
||||||
void Token::setParents() {
|
void Token::setParents() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -203,7 +203,7 @@ namespace bolt {
|
||||||
std::vector<Type*> ArgTys;
|
std::vector<Type*> ArgTys;
|
||||||
ArgTys.push_back(inferExpression(Y->LHS, Ctx));
|
ArgTys.push_back(inferExpression(Y->LHS, Ctx));
|
||||||
ArgTys.push_back(inferExpression(Y->RHS, Ctx));
|
ArgTys.push_back(inferExpression(Y->RHS, Ctx));
|
||||||
Ctx.addConstraint(new CEqual { new TArrow(ArgTys, RetTy), OpTy });
|
Ctx.addConstraint(new CEqual { new TArrow(ArgTys, RetTy), OpTy, X });
|
||||||
return RetTy;
|
return RetTy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,7 +257,7 @@ namespace bolt {
|
||||||
{
|
{
|
||||||
auto Y = static_cast<CEqual*>(Constraint);
|
auto Y = static_cast<CEqual*>(Constraint);
|
||||||
if (!unify(Y->Left, Y->Right, Sub)) {
|
if (!unify(Y->Left, Y->Right, Sub)) {
|
||||||
DE.add<UnificationErrorDiagnostic>(Y->Left, Y->Right);
|
DE.add<UnificationErrorDiagnostic>(Y->Left, Y->Right, Y->Source);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
#include "bolt/CST.hpp"
|
||||||
#include "zen/config.hpp"
|
#include "zen/config.hpp"
|
||||||
|
|
||||||
#include "bolt/Diagnostics.hpp"
|
#include "bolt/Diagnostics.hpp"
|
||||||
|
@ -201,6 +202,24 @@ namespace bolt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConsoleDiagnostics::setBold(bool Enable) {
|
||||||
|
if (Enable) {
|
||||||
|
Out << ANSI_BOLD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleDiagnostics::setItalic(bool Enable) {
|
||||||
|
if (Enable) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConsoleDiagnostics::setUnderline(bool Enable) {
|
||||||
|
if (Enable) {
|
||||||
|
Out << ANSI_UNDERLINE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ConsoleDiagnostics::resetStyles() {
|
void ConsoleDiagnostics::resetStyles() {
|
||||||
if (EnableColors) {
|
if (EnableColors) {
|
||||||
Out << ANSI_RESET;
|
Out << ANSI_RESET;
|
||||||
|
@ -311,7 +330,14 @@ namespace bolt {
|
||||||
case DiagnosticKind::UnexpectedToken:
|
case DiagnosticKind::UnexpectedToken:
|
||||||
{
|
{
|
||||||
auto E = static_cast<const UnexpectedTokenDiagnostic&>(D);
|
auto E = static_cast<const UnexpectedTokenDiagnostic&>(D);
|
||||||
Out << "<unknown.bolt>:" << E.Actual->getStartLine() << ":" << E.Actual->getStartColumn() << ": expected ";
|
setForegroundColor(Color::Red);
|
||||||
|
setBold(true);
|
||||||
|
Out << "error: ";
|
||||||
|
resetStyles();
|
||||||
|
setForegroundColor(Color::Yellow);
|
||||||
|
Out << E.File.getPath() << ":" << E.Actual->getStartLine() << ":" << E.Actual->getStartColumn() << ":";
|
||||||
|
resetStyles();
|
||||||
|
Out << " expected ";
|
||||||
switch (E.Expected.size()) {
|
switch (E.Expected.size()) {
|
||||||
case 0:
|
case 0:
|
||||||
Out << "nothing";
|
Out << "nothing";
|
||||||
|
@ -322,7 +348,7 @@ namespace bolt {
|
||||||
default:
|
default:
|
||||||
auto Iter = E.Expected.begin();
|
auto Iter = E.Expected.begin();
|
||||||
Out << describe(*Iter++);
|
Out << describe(*Iter++);
|
||||||
NodeType Prev;
|
NodeType Prev = *Iter++;
|
||||||
while (Iter != E.Expected.end()) {
|
while (Iter != E.Expected.end()) {
|
||||||
Out << ", " << describe(Prev);
|
Out << ", " << describe(Prev);
|
||||||
Prev = *Iter++;
|
Prev = *Iter++;
|
||||||
|
@ -330,15 +356,20 @@ namespace bolt {
|
||||||
Out << " or " << describe(Prev);
|
Out << " or " << describe(Prev);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Out << " but instead got '" << E.Actual->getText() << "'\n";
|
Out << " but instead got '" << E.Actual->getText() << "'\n\n";
|
||||||
writeExcerpt(E.Actual->getSourceFile()->getTextFile(), E.Actual->getRange(), E.Actual->getRange(), Color::Red);
|
writeExcerpt(E.File, E.Actual->getRange(), E.Actual->getRange(), Color::Red);
|
||||||
|
Out << "\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case DiagnosticKind::UnexpectedString:
|
case DiagnosticKind::UnexpectedString:
|
||||||
{
|
{
|
||||||
auto E = static_cast<const UnexpectedStringDiagnostic&>(D);
|
auto E = static_cast<const UnexpectedStringDiagnostic&>(D);
|
||||||
Out << "<unknown.bolt>:" << E.Location.Line << ":" << E.Location.Column << ": unexpected '";
|
setForegroundColor(Color::Red);
|
||||||
|
setBold(true);
|
||||||
|
Out << "error: ";
|
||||||
|
resetStyles();
|
||||||
|
Out << E.File.getPath() << ":" << E.Location.Line << ":" << E.Location.Column << ": unexpected '";
|
||||||
for (auto Chr: E.Actual) {
|
for (auto Chr: E.Actual) {
|
||||||
switch (Chr) {
|
switch (Chr) {
|
||||||
case '\\':
|
case '\\':
|
||||||
|
@ -352,14 +383,28 @@ namespace bolt {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Out << "'\n\n";
|
||||||
|
TextRange Range { E.Location, E.Location + E.Actual };
|
||||||
|
writeExcerpt(E.File, Range, Range, Color::Red);
|
||||||
|
Out << "\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case DiagnosticKind::UnificationError:
|
case DiagnosticKind::UnificationError:
|
||||||
{
|
{
|
||||||
auto E = static_cast<const UnificationErrorDiagnostic&>(D);
|
auto E = static_cast<const UnificationErrorDiagnostic&>(D);
|
||||||
Out << ANSI_FG_RED << ANSI_BOLD << "error: " << ANSI_RESET << "the types " << ANSI_FG_GREEN << describe(E.Left) << ANSI_RESET
|
setForegroundColor(Color::Red);
|
||||||
<< " and " << ANSI_FG_GREEN << describe(E.Right) << ANSI_RESET << " failed to match\n";
|
setBold(true);
|
||||||
|
Out << "error: ";
|
||||||
|
resetStyles();
|
||||||
|
Out << "the types " << ANSI_FG_GREEN << describe(E.Left) << ANSI_RESET
|
||||||
|
<< " and " << ANSI_FG_GREEN << describe(E.Right) << ANSI_RESET << " failed to match\n\n";
|
||||||
|
if (E.Source) {
|
||||||
|
auto Range = E.Source->getRange();
|
||||||
|
//std::cerr << Range.Start.Line << ":" << Range.Start.Column << "-" << Range.End.Line << ":" << Range.End.Column << "\n";
|
||||||
|
writeExcerpt(E.Source->getSourceFile()->getTextFile(), Range, Range, Color::Red);
|
||||||
|
Out << "\n";
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ namespace bolt {
|
||||||
{ \
|
{ \
|
||||||
auto __Token = Tokens.get(); \
|
auto __Token = Tokens.get(); \
|
||||||
if (__Token->Type != NodeType::name) { \
|
if (__Token->Type != NodeType::name) { \
|
||||||
throw UnexpectedTokenDiagnostic(__Token, std::vector<NodeType> { NodeType::name }); \
|
throw UnexpectedTokenDiagnostic(File, __Token, std::vector<NodeType> { NodeType::name }); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ namespace bolt {
|
||||||
Tokens.get();
|
Tokens.get();
|
||||||
return new BindPattern(static_cast<Identifier*>(T0));
|
return new BindPattern(static_cast<Identifier*>(T0));
|
||||||
default:
|
default:
|
||||||
throw UnexpectedTokenDiagnostic(T0, std::vector { NodeType::Identifier });
|
throw UnexpectedTokenDiagnostic(File, T0, std::vector { NodeType::Identifier });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,18 +89,18 @@ namespace bolt {
|
||||||
std::vector<Identifier*> ModulePath;
|
std::vector<Identifier*> ModulePath;
|
||||||
auto Name = Tokens.get();
|
auto Name = Tokens.get();
|
||||||
if (Name->Type != NodeType::Identifier) {
|
if (Name->Type != NodeType::Identifier) {
|
||||||
throw UnexpectedTokenDiagnostic(Name, std::vector { NodeType::Identifier });
|
throw UnexpectedTokenDiagnostic(File, Name, std::vector { NodeType::Identifier });
|
||||||
}
|
}
|
||||||
for (;;) {
|
for (;;) {
|
||||||
auto T1 = Tokens.peek();
|
auto T1 = Tokens.peek();
|
||||||
if (T1->Type == NodeType::Dot) {
|
if (T1->Type != NodeType::Dot) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Tokens.get();
|
Tokens.get();
|
||||||
ModulePath.push_back(static_cast<Identifier*>(Name));
|
ModulePath.push_back(static_cast<Identifier*>(Name));
|
||||||
Name = Tokens.get();
|
Name = Tokens.get();
|
||||||
if (Name->Type != NodeType::Identifier) {
|
if (Name->Type != NodeType::Identifier) {
|
||||||
throw UnexpectedTokenDiagnostic(Name, std::vector { NodeType::Identifier });
|
throw UnexpectedTokenDiagnostic(File, Name, std::vector { NodeType::Identifier });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new QualifiedName(ModulePath, static_cast<Identifier*>(Name));
|
return new QualifiedName(ModulePath, static_cast<Identifier*>(Name));
|
||||||
|
@ -112,7 +112,7 @@ namespace bolt {
|
||||||
case NodeType::Identifier:
|
case NodeType::Identifier:
|
||||||
return new ReferenceTypeExpression(parseQualifiedName());
|
return new ReferenceTypeExpression(parseQualifiedName());
|
||||||
default:
|
default:
|
||||||
throw UnexpectedTokenDiagnostic(T0, std::vector { NodeType::Identifier });
|
throw UnexpectedTokenDiagnostic(File, T0, std::vector { NodeType::Identifier });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ namespace bolt {
|
||||||
Tokens.get();
|
Tokens.get();
|
||||||
return new ConstantExpression(T0);
|
return new ConstantExpression(T0);
|
||||||
default:
|
default:
|
||||||
throw UnexpectedTokenDiagnostic(T0, std::vector { NodeType::Identifier, NodeType::IntegerLiteral });
|
throw UnexpectedTokenDiagnostic(File, T0, std::vector { NodeType::Identifier, NodeType::IntegerLiteral, NodeType::StringLiteral });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,16 +200,16 @@ namespace bolt {
|
||||||
|
|
||||||
LetDeclaration* Parser::parseLetDeclaration() {
|
LetDeclaration* Parser::parseLetDeclaration() {
|
||||||
|
|
||||||
PubKeyword* Pub;
|
PubKeyword* Pub = nullptr;
|
||||||
LetKeyword* Let;
|
LetKeyword* Let;
|
||||||
MutKeyword* Mut;
|
MutKeyword* Mut = nullptr;
|
||||||
auto T0 = Tokens.get();
|
auto T0 = Tokens.get();
|
||||||
if (T0->Type == NodeType::PubKeyword) {
|
if (T0->Type == NodeType::PubKeyword) {
|
||||||
Pub = static_cast<PubKeyword*>(T0);
|
Pub = static_cast<PubKeyword*>(T0);
|
||||||
T0 = Tokens.get();
|
T0 = Tokens.get();
|
||||||
}
|
}
|
||||||
if (T0->Type != NodeType::LetKeyword) {
|
if (T0->Type != NodeType::LetKeyword) {
|
||||||
throw UnexpectedTokenDiagnostic(T0, std::vector { NodeType::LetKeyword });
|
throw UnexpectedTokenDiagnostic(File, T0, std::vector { NodeType::LetKeyword });
|
||||||
}
|
}
|
||||||
Let = static_cast<LetKeyword*>(T0);
|
Let = static_cast<LetKeyword*>(T0);
|
||||||
auto T1 = Tokens.peek();
|
auto T1 = Tokens.peek();
|
||||||
|
@ -277,7 +277,7 @@ after_params:
|
||||||
// First tokens of Pattern
|
// First tokens of Pattern
|
||||||
Expected.push_back(NodeType::Identifier);
|
Expected.push_back(NodeType::Identifier);
|
||||||
}
|
}
|
||||||
throw UnexpectedTokenDiagnostic(T2, Expected);
|
throw UnexpectedTokenDiagnostic(File, T2, Expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOLT_EXPECT_TOKEN(LineFoldEnd);
|
BOLT_EXPECT_TOKEN(LineFoldEnd);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "zen/config.hpp"
|
#include "zen/config.hpp"
|
||||||
|
|
||||||
|
#include "bolt/Text.hpp"
|
||||||
#include "bolt/Integer.hpp"
|
#include "bolt/Integer.hpp"
|
||||||
#include "bolt/CST.hpp"
|
#include "bolt/CST.hpp"
|
||||||
#include "bolt/Diagnostics.hpp"
|
#include "bolt/Diagnostics.hpp"
|
||||||
|
@ -65,8 +66,8 @@ namespace bolt {
|
||||||
{ "mod", NodeType::ModKeyword },
|
{ "mod", NodeType::ModKeyword },
|
||||||
};
|
};
|
||||||
|
|
||||||
Scanner::Scanner(Stream<Char>& Chars):
|
Scanner::Scanner(TextFile& File, Stream<Char>& Chars):
|
||||||
Chars(Chars) {}
|
File(File), Chars(Chars) {}
|
||||||
|
|
||||||
Token* Scanner::read() {
|
Token* Scanner::read() {
|
||||||
|
|
||||||
|
@ -225,7 +226,7 @@ digit_finish:
|
||||||
case '\'': Text.push_back('\''); break;
|
case '\'': Text.push_back('\''); break;
|
||||||
case '"': Text.push_back('"'); break;
|
case '"': Text.push_back('"'); break;
|
||||||
default:
|
default:
|
||||||
throw UnexpectedStringDiagnostic(Loc, String { C1 });
|
throw UnexpectedStringDiagnostic(File, Loc, String { static_cast<char>(C1) });
|
||||||
}
|
}
|
||||||
Escaping = false;
|
Escaping = false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -252,7 +253,7 @@ after_string_contents:
|
||||||
getChar();
|
getChar();
|
||||||
auto C2 = peekChar();
|
auto C2 = peekChar();
|
||||||
if (C2 == '.') {
|
if (C2 == '.') {
|
||||||
throw UnexpectedStringDiagnostic(getCurrentLoc(), String { C2 });
|
throw UnexpectedStringDiagnostic(File, getCurrentLoc(), String { static_cast<char>(C2) });
|
||||||
}
|
}
|
||||||
return new DotDot(StartLoc);
|
return new DotDot(StartLoc);
|
||||||
}
|
}
|
||||||
|
@ -304,11 +305,7 @@ after_string_contents:
|
||||||
BOLT_SIMPLE_TOKEN('}', RBrace)
|
BOLT_SIMPLE_TOKEN('}', RBrace)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
throw UnexpectedStringDiagnostic(File, StartLoc, String { static_cast<char>(C0) });
|
||||||
throw UnexpectedStringDiagnostic(StartLoc, String { C0 });
|
|
||||||
|
|
||||||
// TODO Add a diagnostic message indicating that scanning failed.
|
|
||||||
//return new Invalid(StartLoc);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
namespace bolt {
|
namespace bolt {
|
||||||
|
|
||||||
TextFile::TextFile(ByteString Path, String Text):
|
TextFile::TextFile(ByteString Path, ByteString Text):
|
||||||
Path(Path), Text(Text) {
|
Path(Path), Text(Text) {
|
||||||
LineOffsets.push_back(0);
|
LineOffsets.push_back(0);
|
||||||
for (size_t I = 0; I < Text.size(); I++) {
|
for (size_t I = 0; I < Text.size(); I++) {
|
||||||
|
@ -46,7 +46,7 @@ namespace bolt {
|
||||||
return Path;
|
return Path;
|
||||||
}
|
}
|
||||||
|
|
||||||
String TextFile::getText() const {
|
ByteString TextFile::getText() const {
|
||||||
return Text;
|
return Text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
13
src/main.cc
13
src/main.cc
|
@ -14,10 +14,10 @@
|
||||||
|
|
||||||
using namespace bolt;
|
using namespace bolt;
|
||||||
|
|
||||||
String readFile(std::string Path) {
|
ByteString readFile(std::string Path) {
|
||||||
|
|
||||||
std::ifstream File(Path);
|
std::ifstream File(Path);
|
||||||
String Out;
|
ByteString Out;
|
||||||
|
|
||||||
File.seekg(0, std::ios::end);
|
File.seekg(0, std::ios::end);
|
||||||
Out.reserve(File.tellg());
|
Out.reserve(File.tellg());
|
||||||
|
@ -40,22 +40,19 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
auto Text = readFile(argv[1]);
|
auto Text = readFile(argv[1]);
|
||||||
TextFile File { argv[1], Text };
|
TextFile File { argv[1], Text };
|
||||||
VectorStream<String> Chars(Text, EOF);
|
VectorStream<ByteString, Char> Chars(Text, EOF);
|
||||||
Scanner S(Chars);
|
Scanner S(File, Chars);
|
||||||
Punctuator PT(S);
|
Punctuator PT(S);
|
||||||
Parser P(File, PT);
|
Parser P(File, PT);
|
||||||
|
|
||||||
SourceFile* SF;
|
SourceFile* SF;
|
||||||
|
|
||||||
#ifdef NDEBUG
|
|
||||||
try {
|
try {
|
||||||
SF = P.parseSourceFile();
|
SF = P.parseSourceFile();
|
||||||
} catch (Diagnostic& D) {
|
} catch (Diagnostic& D) {
|
||||||
DE.addDiagnostic(D);
|
DE.addDiagnostic(D);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
SF = P.parseSourceFile();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SF->setParents();
|
SF->setParents();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue