1 Commits

Author SHA1 Message Date
9e3f17711f [VER] 0.4.0-alpha
All checks were successful
Release Build / build-windows-x64 (push) Successful in 54s
Release Build / build-linux-x64 (push) Successful in 1m21s
[Fix] 修复恶性Bug: Parser: parseExpression没有正确解析二元表达式,没有用到 right binding power的问题,表现在生成类似 a * b * c时,结果为 a * (b * c) 的Bug
[Impl][Fix] 修复跨文件(如import)报错信息错误的问题,现在Ast跟踪保存文件信息,报错统一从Error父类获取
[...] 忘了,好困不管了
2026-01-19 04:13:55 +08:00
13 changed files with 176 additions and 127 deletions

View File

@@ -100,6 +100,8 @@ namespace Fig::Ast
struct AstAddressInfo struct AstAddressInfo
{ {
size_t line, column; size_t line, column;
std::shared_ptr<FString> sourcePath;
std::shared_ptr<std::vector<FString>> sourceLines;
}; };
class _AstBase class _AstBase

View File

@@ -4,7 +4,7 @@
#include <cstdint> #include <cstdint>
#include <string_view> #include <string_view>
#define __FCORE_VERSION "0.3.9-alpha" #define __FCORE_VERSION "0.4.0-alpha"
#if defined(_WIN32) #if defined(_WIN32)
#define __FCORE_PLATFORM "Windows" #define __FCORE_PLATFORM "Windows"

View File

@@ -6,6 +6,7 @@
#include <format> #include <format>
#include <source_location> #include <source_location>
#include <string> #include <string>
#include <vector>
namespace Fig namespace Fig
{ {
@@ -16,8 +17,10 @@ namespace Fig
explicit AddressableError(FString _msg, explicit AddressableError(FString _msg,
size_t _line, size_t _line,
size_t _column, size_t _column,
FString _sourcePath,
std::vector<FString> _sourceLines,
std::source_location loc = std::source_location::current()) : std::source_location loc = std::source_location::current()) :
src_loc(loc), line(_line), column(_column) src_loc(loc), line(_line), column(_column), sourcePath(std::move(_sourcePath)), sourceLines(std::move(_sourceLines))
{ {
message = _msg; message = _msg;
} }
@@ -33,9 +36,11 @@ namespace Fig
} }
std::source_location src_loc; std::source_location src_loc;
size_t getLine() const { return line; } virtual size_t getLine() const { return line; }
size_t getColumn() const { return column; } virtual size_t getColumn() const { return column; }
FString getMessage() const { return message; } FString getMessage() const { return message; }
FString getSourcePath() const { return sourcePath; }
std::vector<FString> getSourceLines() const { return sourceLines; }
virtual FString getErrorType() const virtual FString getErrorType() const
{ {
@@ -45,6 +50,9 @@ namespace Fig
protected: protected:
size_t line, column; size_t line, column;
FString message; FString message;
FString sourcePath;
std::vector<FString> sourceLines;
}; };
class UnaddressableError : public std::exception class UnaddressableError : public std::exception
@@ -84,14 +92,6 @@ namespace Fig
public: public:
using AddressableError::AddressableError; using AddressableError::AddressableError;
explicit SyntaxError(FString _msg,
size_t _line,
size_t _column,
std::source_location loc = std::source_location::current()) :
AddressableError(_msg, _line, _column, loc)
{
}
virtual FString toString() const override virtual FString toString() const override
{ {
std::string msg = std::format("[SyntaxError] {} in [{}] {}", this->message.toBasicString(), this->src_loc.file_name(), this->src_loc.function_name()); std::string msg = std::format("[SyntaxError] {} in [{}] {}", this->message.toBasicString(), this->src_loc.file_name(), this->src_loc.function_name());

View File

@@ -98,8 +98,11 @@ namespace Fig
} }
inline void logAddressableError(const AddressableError &err, FString fileName, std::vector<FString> sourceLines) inline void logAddressableError(const AddressableError &err)
{ {
const FString &fileName = err.getSourcePath();
const std::vector<FString> &sourceLines = err.getSourceLines();
std::print("\n"); std::print("\n");
namespace TC = TerminalColors; namespace TC = TerminalColors;
coloredPrint(TC::LightWhite, "An error occurred! "); coloredPrint(TC::LightWhite, "An error occurred! ");

View File

@@ -24,6 +24,10 @@
#include <memory> #include <memory>
#include <unordered_map> #include <unordered_map>
#ifndef SourceInfo
#define SourceInfo(ptr) (ptr->sourcePath), (ptr->sourceLines)
#endif
namespace Fig namespace Fig
{ {
@@ -210,11 +214,10 @@ namespace Fig
return evalIndexExpr(ie, ctx); return evalIndexExpr(ie, ctx);
} }
default: { default: {
// throw EvaluatorError( throw EvaluatorError(
// u8"TypeError", u8"TypeError",
// std::format("Expression '{}' doesn't refer to a lvalue", exp->typeName().toBasicString()), std::format("Expression '{}' doesn't refer to a lvalue", exp->typeName().toBasicString()),
// exp); exp);
} }
} }
} }
@@ -334,15 +337,11 @@ namespace Fig
而 R 类型为 StructType (builtins.hpp) 中注册 而 R 类型为 StructType (builtins.hpp) 中注册
拿到 R 的 StructType, 其中的 type 为 String 拿到 R 的 StructType, 其中的 type 为 String
*/ */
if (lhs->getTypeInfo() == type) if (lhs->getTypeInfo() == type) { return Object::getTrueInstance(); }
{
return Object::getTrueInstance();
}
return Object::getFalseInstance(); return Object::getFalseInstance();
} }
throw EvaluatorError( throw EvaluatorError(u8"TypeError",
u8"TypeError",
std::format("Unsupported operator `is` for '{}' && '{}'", std::format("Unsupported operator `is` for '{}' && '{}'",
lhsType.toString().toBasicString(), lhsType.toString().toBasicString(),
rhsType.toString().toBasicString()), rhsType.toString().toBasicString()),
@@ -1017,11 +1016,8 @@ namespace Fig
return std::make_shared<Object>(std::move(map)); return std::make_shared<Object>(std::move(map));
} }
default: default: {
{ throw RuntimeError(FString(std::format("err type of expr: {}", magic_enum::enum_name(type))));
throw RuntimeError(FString(
std::format("err type of expr: {}", magic_enum::enum_name(type))
));
} }
} }
return Object::getNullInstance(); // ignore warning return Object::getNullInstance(); // ignore warning
@@ -1478,11 +1474,13 @@ namespace Fig
case BreakSt: { case BreakSt: {
if (!ctx->parent) if (!ctx->parent)
{ {
throw EvaluatorError(u8"BreakOutsideLoopError", u8"`break` statement outside loop", stmt); throw EvaluatorError(
u8"BreakOutsideLoopError", u8"`break` statement outside loop", stmt);
} }
if (!ctx->isInLoopContext()) if (!ctx->isInLoopContext())
{ {
throw EvaluatorError(u8"BreakOutsideLoopError", u8"`break` statement outside loop", stmt); throw EvaluatorError(
u8"BreakOutsideLoopError", u8"`break` statement outside loop", stmt);
} }
return StatementResult::breakFlow(); return StatementResult::breakFlow();
} }
@@ -1490,11 +1488,13 @@ namespace Fig
case ContinueSt: { case ContinueSt: {
if (!ctx->parent) if (!ctx->parent)
{ {
throw EvaluatorError(u8"ContinueOutsideLoopError", u8"`continue` statement outside loop", stmt); throw EvaluatorError(
u8"ContinueOutsideLoopError", u8"`continue` statement outside loop", stmt);
} }
if (!ctx->isInLoopContext()) if (!ctx->isInLoopContext())
{ {
throw EvaluatorError(u8"ContinueOutsideLoopError", u8"`continue` statement outside loop", stmt); throw EvaluatorError(
u8"ContinueOutsideLoopError", u8"`continue` statement outside loop", stmt);
} }
return StatementResult::continueFlow(); return StatementResult::continueFlow();
} }
@@ -1620,28 +1620,30 @@ namespace Fig
ContextPtr Evaluator::loadModule(const std::filesystem::path &path) ContextPtr Evaluator::loadModule(const std::filesystem::path &path)
{ {
FString modSourcePath(path.string());
std::ifstream file(path); std::ifstream file(path);
assert(file.is_open()); assert(file.is_open());
std::string source((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>()); std::string source((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
file.close(); file.close();
Lexer lexer((FString(source))); std::vector<FString> modSourceLines = Utils::splitSource(FString(source));
Parser parser(lexer);
std::vector<Ast::AstBase> asts;
std::vector<FString> sourceLines = Utils::splitSource(FString(source)); Lexer lexer((FString(source)), modSourcePath, modSourceLines);
Parser parser(lexer, modSourcePath, modSourceLines);
std::vector<Ast::AstBase> asts;
asts = parser.parseAll(); asts = parser.parseAll();
Evaluator evaluator; Evaluator evaluator;
evaluator.SetSourcePath(FString(path.string())); evaluator.SetSourcePath(modSourcePath);
evaluator.SetSourceLines(modSourceLines);
ContextPtr modctx = std::make_shared<Context>(FString(std::format("<Module at {}>", path.string())), nullptr); ContextPtr modctx = std::make_shared<Context>(FString(std::format("<Module at {}>", path.string())), nullptr);
evaluator.SetGlobalContext(modctx); evaluator.SetGlobalContext(modctx);
evaluator.RegisterBuiltinsValue(); evaluator.RegisterBuiltinsValue();
evaluator.Run(asts); evaluator.Run(asts); // error upward pass-by, log outside, we have already keep info in evaluator error
return evaluator.global; return evaluator.global;
} }
@@ -1663,8 +1665,9 @@ namespace Fig
if (ctx->containsInThisScope(modName)) if (ctx->containsInThisScope(modName))
{ {
throw EvaluatorError( throw EvaluatorError(u8"RedeclarationError",
u8"RedeclarationError", std::format("{} has already been declared.", modName.toBasicString()), i); std::format("{} has already been declared.", modName.toBasicString()),
i);
} }
ctx->def( ctx->def(
modName, ValueType::Module, AccessModifier::PublicConst, std::make_shared<Object>(Module(modName, modCtx))); modName, ValueType::Module, AccessModifier::PublicConst, std::make_shared<Object>(Module(modName, modCtx)));

View File

@@ -1,6 +1,6 @@
#include "Ast/Statements/ImplementSt.hpp" #include <Ast/Statements/ImplementSt.hpp>
#include "Ast/Statements/InterfaceDefSt.hpp" #include <Ast/Statements/InterfaceDefSt.hpp>
#include "Value/Type.hpp" #include <Value/Type.hpp>
#include <Ast/ast.hpp> #include <Ast/ast.hpp>
#include <Context/context.hpp> #include <Context/context.hpp>
@@ -63,12 +63,18 @@ namespace Fig
public: public:
FString sourcePath; FString sourcePath;
std::vector<FString> sourceLines;
void SetSourcePath(const FString &sp) void SetSourcePath(const FString &sp)
{ {
sourcePath = sp; sourcePath = sp;
} }
void SetSourceLines(const std::vector<FString> &sl)
{
sourceLines = sl;
}
void SetGlobalContext(ContextPtr ctx) void SetGlobalContext(ContextPtr ctx)
{ {
assert(ctx != nullptr); assert(ctx != nullptr);

View File

@@ -10,7 +10,10 @@ namespace Fig
public: public:
FString typeName; FString typeName;
using AddressableError::AddressableError; using AddressableError::AddressableError;
EvaluatorError(FString _typeName, FString msg, Ast::AstBase ast, std::source_location loc = std::source_location::current()) EvaluatorError(FString _typeName,
FString msg,
Ast::AstBase ast,
std::source_location loc = std::source_location::current())
{ {
message = msg; message = msg;
line = ast->getAAI().line; line = ast->getAAI().line;
@@ -20,8 +23,13 @@ namespace Fig
typeName = std::move(_typeName); typeName = std::move(_typeName);
sourcePath = *ast->getAAI().sourcePath;
sourceLines = *ast->getAAI().sourceLines;
} }
EvaluatorError(FString _typeName, std::string_view msg, Ast::AstBase ast, std::source_location loc = std::source_location::current()) EvaluatorError(FString _typeName,
std::string_view msg,
Ast::AstBase ast,
std::source_location loc = std::source_location::current())
{ {
message = FString::fromBasicString(std::string(msg.data())); message = FString::fromBasicString(std::string(msg.data()));
line = ast->getAAI().line; line = ast->getAAI().line;
@@ -30,13 +38,11 @@ namespace Fig
src_loc = std::move(loc); src_loc = std::move(loc);
typeName = std::move(_typeName); typeName = std::move(_typeName);
sourcePath = *ast->getAAI().sourcePath;
sourceLines = *ast->getAAI().sourceLines;
} }
virtual FString getErrorType() const override virtual FString getErrorType() const override { return typeName; }
{
return typeName;
}
};
}; };
}; // namespace Fig

View File

@@ -89,7 +89,9 @@ int main(int argc, char **argv)
std::string source((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>()); std::string source((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
file.close(); file.close();
Fig::Lexer lexer((Fig::FString(source))); std::vector<FString> sourceLines = Fig::Utils::splitSource(Fig::FString(source));
Fig::Lexer lexer((Fig::FString(source)), sourcePath, sourceLines);
// Token tok; // Token tok;
// while ((tok = lexer.nextToken()).getType() != TokenType::EndOfFile) // while ((tok = lexer.nextToken()).getType() != TokenType::EndOfFile)
@@ -97,11 +99,9 @@ int main(int argc, char **argv)
// std::println("{}", tok.toString().toBasicString()); // std::println("{}", tok.toString().toBasicString());
// } // }
Fig::Parser parser(lexer); Fig::Parser parser(lexer, sourcePath, sourceLines);
std::vector<Fig::Ast::AstBase> asts; std::vector<Fig::Ast::AstBase> asts;
std::vector<FString> sourceLines = Fig::Utils::splitSource(Fig::FString(source));
try try
{ {
asts = parser.parseAll(); asts = parser.parseAll();
@@ -109,7 +109,7 @@ int main(int argc, char **argv)
catch (const Fig::AddressableError &e) catch (const Fig::AddressableError &e)
{ {
addressableErrorCount++; addressableErrorCount++;
ErrorLog::logAddressableError(e, sourcePath, sourceLines); ErrorLog::logAddressableError(e);
return 1; return 1;
} }
catch (const Fig::UnaddressableError &e) catch (const Fig::UnaddressableError &e)
@@ -134,6 +134,7 @@ int main(int argc, char **argv)
Fig::Evaluator evaluator; Fig::Evaluator evaluator;
evaluator.SetSourcePath(sourcePath); evaluator.SetSourcePath(sourcePath);
evaluator.SetSourceLines(sourceLines);
evaluator.CreateGlobalContext(); evaluator.CreateGlobalContext();
evaluator.RegisterBuiltinsValue(); evaluator.RegisterBuiltinsValue();
@@ -144,7 +145,7 @@ int main(int argc, char **argv)
catch (const Fig::AddressableError &e) catch (const Fig::AddressableError &e)
{ {
addressableErrorCount++; addressableErrorCount++;
ErrorLog::logAddressableError(e, sourcePath, sourceLines); ErrorLog::logAddressableError(e);
evaluator.printStackTrace(); evaluator.printStackTrace();
return 1; return 1;
} }

View File

@@ -10,6 +10,10 @@
#include <iostream> // debug #include <iostream> // debug
#endif #endif
#ifndef SourceInfo
#define SourceInfo(ptr) (ptr->sourcePath), (ptr->sourceLines)
#endif
namespace Fig namespace Fig
{ {
@@ -163,7 +167,7 @@ namespace Fig
{ {
if (it.isEnd()) if (it.isEnd())
{ {
error = SyntaxError(u8"Unterminated FString", this->line, it.column()); error = SyntaxError(u8"Unterminated FString", this->line, it.column(), SourceInfo(this));
return IllegalTok; return IllegalTok;
} }
next(); next();
@@ -200,12 +204,11 @@ namespace Fig
} }
else else
{ {
error = SyntaxError(FString( error = SyntaxError(FString(std::format("Unsupported escape character: {}",
std::format(
"Unsupported escape character: {}",
FString(ec.getString()).toBasicString())), FString(ec.getString()).toBasicString())),
this->line, this->line,
it.column()); it.column(),
SourceInfo(this));
return IllegalTok; return IllegalTok;
} }
} }
@@ -217,7 +220,7 @@ namespace Fig
} }
if (unterminated) if (unterminated)
{ {
error = SyntaxError(u8"Unterminated FString", this->line, str_start_col); error = SyntaxError(u8"Unterminated FString", this->line, str_start_col, SourceInfo(this));
return IllegalTok; return IllegalTok;
} }
return Token(str, TokenType::LiteralString); return Token(str, TokenType::LiteralString);
@@ -244,7 +247,7 @@ namespace Fig
} }
if (unterminated) if (unterminated)
{ {
error = SyntaxError(u8"Unterminated FString", this->line, str_start_col); error = SyntaxError(u8"Unterminated FString", this->line, str_start_col, SourceInfo(this));
return IllegalTok; return IllegalTok;
} }
return Token(str, TokenType::LiteralString); return Token(str, TokenType::LiteralString);
@@ -275,7 +278,7 @@ namespace Fig
{ {
if (it.isEnd()) if (it.isEnd())
{ {
error = SyntaxError(u8"Unterminated FString", this->line, it.column()); error = SyntaxError(u8"Unterminated FString", this->line, it.column(), SourceInfo(this));
return IllegalTok; return IllegalTok;
} }
next(); next();
@@ -317,12 +320,11 @@ namespace Fig
} }
else else
{ {
error = SyntaxError(FString( error = SyntaxError(FString(std::format("Unsupported escape character: {}",
std::format(
"Unsupported escape character: {}",
FString(ec.getString()).toBasicString())), FString(ec.getString()).toBasicString())),
this->line, this->line,
it.column()); it.column(),
SourceInfo(this));
return IllegalTok; return IllegalTok;
} }
} }
@@ -334,7 +336,7 @@ namespace Fig
} }
if (unterminated) if (unterminated)
{ {
error = SyntaxError(u8"Unterminated FString", this->line, str_start_col); error = SyntaxError(u8"Unterminated FString", this->line, str_start_col, SourceInfo(this));
return IllegalTok; return IllegalTok;
} }
return Token(str, TokenType::LiteralString); return Token(str, TokenType::LiteralString);
@@ -378,8 +380,10 @@ namespace Fig
if (numStr.ends_with(U'e')) if (numStr.ends_with(U'e'))
{ {
error = SyntaxError( error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())),
FString(std::format("Illegal number literal: {}", numStr.toBasicString())), this->line, it.column()); this->line,
it.column(),
SourceInfo(this));
return IllegalTok; return IllegalTok;
} }
@@ -395,8 +399,10 @@ namespace Fig
if (!hasDigit) if (!hasDigit)
{ {
error = SyntaxError( error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())),
FString(std::format("Illegal number literal: {}", numStr.toBasicString())), this->line, it.column()); this->line,
it.column(),
SourceInfo(this));
return IllegalTok; return IllegalTok;
} }
@@ -407,14 +413,16 @@ namespace Fig
{ {
error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())), error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())),
this->line, this->line,
it.column()); it.column(),
SourceInfo(this));
return IllegalTok; return IllegalTok;
} }
if (ePos + 1 >= numStr.length()) if (ePos + 1 >= numStr.length())
{ {
error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())), error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())),
this->line, this->line,
it.column()); it.column(),
SourceInfo(this));
return IllegalTok; return IllegalTok;
} }
bool hasDigitAfterE = false; bool hasDigitAfterE = false;
@@ -427,7 +435,8 @@ namespace Fig
{ {
error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())), error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())),
this->line, this->line,
it.column()); it.column(),
SourceInfo(this));
return IllegalTok; return IllegalTok;
} }
continue; continue;
@@ -438,7 +447,8 @@ namespace Fig
{ {
error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())), error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())),
this->line, this->line,
it.column()); it.column(),
SourceInfo(this));
return IllegalTok; return IllegalTok;
} }
} }
@@ -447,7 +457,8 @@ namespace Fig
{ {
error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())), error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())),
this->line, this->line,
it.column()); it.column(),
SourceInfo(this));
return IllegalTok; return IllegalTok;
} }
} }
@@ -472,9 +483,10 @@ namespace Fig
if (!startsWith(sym)) if (!startsWith(sym))
{ {
error = SyntaxError( error = SyntaxError(FString(std::format("No such operator: {}", sym.toBasicString())),
FString(std::format("No such operator: {}", sym.toBasicString())), this->line,
this->line, it.column()); it.column(),
SourceInfo(this));
next(); next();
return IllegalTok; return IllegalTok;
} }
@@ -500,9 +512,10 @@ namespace Fig
if (!symbol_map.contains(sym)) if (!symbol_map.contains(sym))
{ {
error = SyntaxError( error = SyntaxError(FString(std::format("No such operator: {}", sym.toBasicString())),
FString(std::format("No such operator: {}", sym.toBasicString())), this->line,
this->line, it.column()); it.column(),
SourceInfo(this));
next(); next();
return IllegalTok; return IllegalTok;
} }
@@ -562,7 +575,8 @@ namespace Fig
if (!terminated) if (!terminated)
{ {
error = SyntaxError(FString(u8"Unterminated multiline comment"), this->line, it.column()); error =
SyntaxError(FString(u8"Unterminated multiline comment"), this->line, it.column(), SourceInfo(this));
next(); next();
return IllegalTok; return IllegalTok;
} }
@@ -633,9 +647,11 @@ namespace Fig
} }
else else
{ {
error = SyntaxError(FString( error =
std::format("Cannot tokenize char: '{}'", FString(ch.getString()).toBasicString())), SyntaxError(FString(std::format("Cannot tokenize char: '{}'", FString(ch.getString()).toBasicString())),
this->line, it.column()); this->line,
it.column(),
SourceInfo(this));
if (hasNext()) if (hasNext())
{ {
next(); next();

View File

@@ -23,6 +23,9 @@ namespace Fig
SyntaxError error; SyntaxError error;
UTF8Iterator it; UTF8Iterator it;
FString sourcePath;
std::vector<FString> sourceLines;
std::vector<Warning> warnings; std::vector<Warning> warnings;
size_t last_line, last_column, column = 1; size_t last_line, last_column, column = 1;
@@ -60,8 +63,8 @@ namespace Fig
static const std::unordered_map<FString, TokenType> symbol_map; static const std::unordered_map<FString, TokenType> symbol_map;
static const std::unordered_map<FString, TokenType> keyword_map; static const std::unordered_map<FString, TokenType> keyword_map;
inline Lexer(const FString &_source) : inline Lexer(const FString &_source, const FString &_sourcePath, const std::vector<FString> &_sourceLines) :
source(_source), it(source) source(_source), it(source), sourcePath(_sourcePath), sourceLines(_sourceLines)
{ {
line = 1; line = 1;
} }

View File

@@ -38,7 +38,7 @@ public struct Time
const result := ns - time_ns; const result := ns - time_ns;
if result < 0 if result < 0
{ {
throw "time has reversed! 😢"; throw "time has been reversed! 😢";
} }
return result; return result;
} }

View File

@@ -22,7 +22,7 @@ namespace Fig
// 逻辑 // 逻辑
{Ast::Operator::And, {5, 6}}, {Ast::Operator::And, {5, 6}},
{Ast::Operator::Or, {4, 5}}, {Ast::Operator::Or, {4, 5}},
{Ast::Operator::Not, {30, 31}}, // 一元 // {Ast::Operator::Not, {30, 31}}, // 一元
// 比较 // 比较
{Ast::Operator::Equal, {7, 8}}, {Ast::Operator::Equal, {7, 8}},
@@ -37,7 +37,7 @@ namespace Fig
{Ast::Operator::BitAnd, {6, 7}}, {Ast::Operator::BitAnd, {6, 7}},
{Ast::Operator::BitOr, {4, 5}}, {Ast::Operator::BitOr, {4, 5}},
{Ast::Operator::BitXor, {5, 6}}, {Ast::Operator::BitXor, {5, 6}},
{Ast::Operator::BitNot, {30, 31}}, // 一元 // {Ast::Operator::BitNot, {30, 31}}, // 一元
{Ast::Operator::ShiftLeft, {15, 16}}, {Ast::Operator::ShiftLeft, {15, 16}},
{Ast::Operator::ShiftRight, {15, 16}}, {Ast::Operator::ShiftRight, {15, 16}},
@@ -214,7 +214,7 @@ namespace Fig
variaPara = pname; variaPara = pname;
next(); // skip `...` next(); // skip `...`
if (!isThis(TokenType::RightParen)) if (!isThis(TokenType::RightParen))
throw SyntaxError( throwAddressableError<SyntaxError>(
u8"Expects right paren, variable parameter function can only have one parameter", u8"Expects right paren, variable parameter function can only have one parameter",
currentAAI.line, currentAAI.line,
currentAAI.column); currentAAI.column);
@@ -433,7 +433,7 @@ namespace Fig
} }
else else
{ {
throw SyntaxError(FString(u8"Invalid syntax"), currentAAI.line, currentAAI.column); throwAddressableError<SyntaxError>(FString(u8"Invalid syntax"), currentAAI.line, currentAAI.column);
} }
} }
return makeAst<Ast::InterfaceDefAst>(interfaceName, methods, isPublic); return makeAst<Ast::InterfaceDefAst>(interfaceName, methods, isPublic);
@@ -480,7 +480,7 @@ namespace Fig
} }
else else
{ {
throw SyntaxError(FString(u8"Invalid syntax"), currentAAI.line, currentAAI.column); throwAddressableError<SyntaxError>(FString(u8"Invalid syntax"), currentAAI.line, currentAAI.column);
} }
} }
@@ -556,7 +556,8 @@ namespace Fig
{ {
if (finallyBlock != nullptr) if (finallyBlock != nullptr)
{ {
throw SyntaxError(u8"Duplicate try finally-block", currentAAI.line, currentAAI.column); throwAddressableError<SyntaxError>(
u8"Duplicate try finally-block", currentAAI.line, currentAAI.column);
} }
next(); // consume `finally` next(); // consume `finally`
expect(TokenType::LeftBrace); expect(TokenType::LeftBrace);
@@ -678,11 +679,7 @@ namespace Fig
} }
else else
{ {
throw SyntaxError( throwAddressableError<SyntaxError>(u8"invalid syntax", currentAAI.line, currentAAI.column);
u8"invalid syntax",
currentAAI.line,
currentAAI.column
);
} }
return stmt; return stmt;
} }
@@ -1208,11 +1205,11 @@ namespace Fig
if (!isTokenOp(tok)) break; if (!isTokenOp(tok)) break;
op = Ast::TokenToOp.at(tok.getType()); op = Ast::TokenToOp.at(tok.getType());
Precedence lbp = getLeftBindingPower(op); auto [lbp, rbp] = getBindingPower(op);
if (bp >= lbp) break; if (bp >= lbp) break;
next(); // consume op next(); // consume op
lhs = makeAst<Ast::BinaryExprAst>(lhs, op, parseExpression(bp, stop, stop2)); lhs = makeAst<Ast::BinaryExprAst>(lhs, op, parseExpression(rbp, stop, stop2));
} }
return lhs; return lhs;
@@ -1232,10 +1229,8 @@ namespace Fig
auto stmt = __parseStatement(); auto stmt = __parseStatement();
if (!output.empty() && stmt->getType() == Ast::AstType::PackageSt) if (!output.empty() && stmt->getType() == Ast::AstType::PackageSt)
{ {
throw SyntaxError( throwAddressableError<SyntaxError>(
u8"Package must be at the beginning of the file", u8"Package must be at the beginning of the file", currentAAI.line, currentAAI.column);
currentAAI.line,
currentAAI.column);
} }
pushNode(stmt); pushNode(stmt);
} }

View File

@@ -6,6 +6,7 @@
#include <Core/fig_string.hpp> #include <Core/fig_string.hpp>
#include <Error/error.hpp> #include <Error/error.hpp>
#include <memory>
#include <print> #include <print>
#include <source_location> #include <source_location>
#include <unordered_map> #include <unordered_map>
@@ -22,6 +23,9 @@ namespace Fig
std::vector<Ast::AstBase> output; std::vector<Ast::AstBase> output;
std::vector<Token> previousTokens; std::vector<Token> previousTokens;
std::shared_ptr<FString> sourcePathPtr;
std::shared_ptr<std::vector<FString>> sourceLinesPtr;
size_t tokenPruduced = 0; size_t tokenPruduced = 0;
size_t currentTokenIndex = 0; size_t currentTokenIndex = 0;
@@ -72,7 +76,11 @@ namespace Fig
static const std::unordered_map<Ast::Operator, std::pair<Precedence, Precedence>> opPrecedence; static const std::unordered_map<Ast::Operator, std::pair<Precedence, Precedence>> opPrecedence;
static const std::unordered_map<Ast::Operator, Precedence> unaryOpPrecedence; static const std::unordered_map<Ast::Operator, Precedence> unaryOpPrecedence;
Parser(const Lexer &_lexer) : lexer(_lexer) {} Parser(const Lexer &_lexer, FString _sourcePath, std::vector<FString> _sourceLines) : lexer(_lexer)
{
sourcePathPtr = std::make_shared<FString>(_sourcePath);
sourceLinesPtr = std::make_shared<std::vector<FString>>(_sourceLines);
}
AddressableError *getError() const { return error.get(); } AddressableError *getError() const { return error.get(); }
@@ -83,7 +91,7 @@ namespace Fig
std::source_location loc = std::source_location::current()) std::source_location loc = std::source_location::current())
{ {
static_assert(std::is_base_of_v<AddressableError, _ErrT>, "_ErrT must derive from AddressableError"); static_assert(std::is_base_of_v<AddressableError, _ErrT>, "_ErrT must derive from AddressableError");
_ErrT spError(msg, line, column, loc); _ErrT spError(msg, line, column, *sourcePathPtr, *sourceLinesPtr, loc);
error = std::make_unique<_ErrT>(spError); error = std::make_unique<_ErrT>(spError);
throw spError; throw spError;
} }
@@ -92,7 +100,7 @@ namespace Fig
{ {
static_assert(std::is_base_of_v<AddressableError, _ErrT>, "_ErrT must derive from AddressableError"); static_assert(std::is_base_of_v<AddressableError, _ErrT>, "_ErrT must derive from AddressableError");
// line, column provide by `currentAAI` // line, column provide by `currentAAI`
_ErrT spError(msg, currentAAI.line, currentAAI.column, loc); _ErrT spError(msg, currentAAI.line, currentAAI.column, *sourcePathPtr, *sourceLinesPtr, loc);
error = std::make_unique<_ErrT>(spError); error = std::make_unique<_ErrT>(spError);
throw spError; throw spError;
} }
@@ -135,7 +143,10 @@ namespace Fig
CTI也需要显示转换否则转换完的pruduced又会被转回去变为 int64_t max CTI也需要显示转换否则转换完的pruduced又会被转回去变为 int64_t max
*/ */
currentTokenIndex++; currentTokenIndex++;
setCurrentAAI(Ast::AstAddressInfo{.line = currentToken().line, .column = currentToken().column}); setCurrentAAI(Ast::AstAddressInfo{.line = currentToken().line,
.column = currentToken().column,
.sourcePath = sourcePathPtr,
.sourceLines = sourceLinesPtr});
return; return;
} }
if (isEOF()) return; if (isEOF()) return;
@@ -143,7 +154,11 @@ namespace Fig
tokenPruduced++; tokenPruduced++;
if (tok == IllegalTok) throw lexer.getError(); if (tok == IllegalTok) throw lexer.getError();
currentTokenIndex = tokenPruduced - 1; currentTokenIndex = tokenPruduced - 1;
setCurrentAAI(Ast::AstAddressInfo{.line = tok.line, .column = tok.column}); setCurrentAAI(Ast::AstAddressInfo{.line = tok.line,
.column = tok.column,
.sourcePath = sourcePathPtr,
.sourceLines = sourceLinesPtr});
previousTokens.push_back(tok); previousTokens.push_back(tok);
} }
inline const Token &currentToken() inline const Token &currentToken()
@@ -298,8 +313,7 @@ namespace Fig
Ast::ListExpr __parseListExpr(); // entry: current is `[` Ast::ListExpr __parseListExpr(); // entry: current is `[`
Ast::MapExpr __parseMapExpr(); // entry: current is `{` Ast::MapExpr __parseMapExpr(); // entry: current is `{`
Ast::InitExpr __parseInitExpr( Ast::InitExpr __parseInitExpr(Ast::Expression); // entry: current is `{`, ahead is struct type exp.
Ast::Expression); // entry: current is `{`, ahead is struct type exp.
Ast::Expression __parseTupleOrParenExpr(); // entry: current is `(` Ast::Expression __parseTupleOrParenExpr(); // entry: current is `(`
Ast::FunctionLiteralExpr __parseFunctionLiteralExpr(); // entry: current is Token::LParen after Token::Function Ast::FunctionLiteralExpr __parseFunctionLiteralExpr(); // entry: current is Token::LParen after Token::Function