From 9e3f17711f3a590b9d112bf0efe5c4d4528b5dc7 Mon Sep 17 00:00:00 2001 From: PuqiAR Date: Mon, 19 Jan 2026 04:13:55 +0800 Subject: [PATCH] =?UTF-8?q?[VER]=200.4.0-alpha=20[Fix]=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E6=81=B6=E6=80=A7Bug:=20Parser:=20parseExpression?= =?UTF-8?q?=E6=B2=A1=E6=9C=89=E6=AD=A3=E7=A1=AE=E8=A7=A3=E6=9E=90=E4=BA=8C?= =?UTF-8?q?=E5=85=83=E8=A1=A8=E8=BE=BE=E5=BC=8F,=E6=B2=A1=E6=9C=89?= =?UTF-8?q?=E7=94=A8=E5=88=B0=20right=20binding=20power=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98=EF=BC=8C=E8=A1=A8=E7=8E=B0=E5=9C=A8=E7=94=9F=E6=88=90?= =?UTF-8?q?=E7=B1=BB=E4=BC=BC=20a=20*=20b=20*=20c=E6=97=B6=EF=BC=8C?= =?UTF-8?q?=E7=BB=93=E6=9E=9C=E4=B8=BA=20a=20*=20(b=20*=20c)=20=E7=9A=84Bu?= =?UTF-8?q?g=20[Impl][Fix]=20=E4=BF=AE=E5=A4=8D=E8=B7=A8=E6=96=87=E4=BB=B6?= =?UTF-8?q?(=E5=A6=82import)=E6=8A=A5=E9=94=99=E4=BF=A1=E6=81=AF=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=8C=E7=8E=B0=E5=9C=A8?= =?UTF-8?q?Ast=E8=B7=9F=E8=B8=AA=E4=BF=9D=E5=AD=98=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=EF=BC=8C=E6=8A=A5=E9=94=99=E7=BB=9F=E4=B8=80?= =?UTF-8?q?=E4=BB=8EError=E7=88=B6=E7=B1=BB=E8=8E=B7=E5=8F=96=20[...]=20?= =?UTF-8?q?=E5=BF=98=E4=BA=86=EF=BC=8C=E5=A5=BD=E5=9B=B0=E4=B8=8D=E7=AE=A1?= =?UTF-8?q?=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ast/astBase.hpp | 2 + src/Core/core.hpp | 2 +- src/Error/error.hpp | 22 ++++---- src/Error/errorLog.hpp | 5 +- src/Evaluator/evaluator.cpp | 71 ++++++++++++----------- src/Evaluator/evaluator.hpp | 12 +++- src/Evaluator/evaluator_error.hpp | 24 +++++--- src/Evaluator/main.cpp | 13 +++-- src/Lexer/lexer.cpp | 84 +++++++++++++++++----------- src/Lexer/lexer.hpp | 7 ++- src/Module/Library/std/time/time.fig | 2 +- src/Parser/parser.cpp | 29 ++++------ src/Parser/parser.hpp | 30 +++++++--- 13 files changed, 176 insertions(+), 127 deletions(-) diff --git a/src/Ast/astBase.hpp b/src/Ast/astBase.hpp index a5b1016..0e0ec29 100644 --- a/src/Ast/astBase.hpp +++ b/src/Ast/astBase.hpp @@ -100,6 +100,8 @@ namespace Fig::Ast struct AstAddressInfo { size_t line, column; + std::shared_ptr sourcePath; + std::shared_ptr> sourceLines; }; class _AstBase diff --git a/src/Core/core.hpp b/src/Core/core.hpp index 79d6f5d..d7878b2 100644 --- a/src/Core/core.hpp +++ b/src/Core/core.hpp @@ -4,7 +4,7 @@ #include #include -#define __FCORE_VERSION "0.3.9-alpha" +#define __FCORE_VERSION "0.4.0-alpha" #if defined(_WIN32) #define __FCORE_PLATFORM "Windows" diff --git a/src/Error/error.hpp b/src/Error/error.hpp index ffe2317..5a9755d 100644 --- a/src/Error/error.hpp +++ b/src/Error/error.hpp @@ -6,6 +6,7 @@ #include #include #include +#include namespace Fig { @@ -16,8 +17,10 @@ namespace Fig explicit AddressableError(FString _msg, size_t _line, size_t _column, + FString _sourcePath, + std::vector _sourceLines, 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; } @@ -33,9 +36,11 @@ namespace Fig } std::source_location src_loc; - size_t getLine() const { return line; } - size_t getColumn() const { return column; } + virtual size_t getLine() const { return line; } + virtual size_t getColumn() const { return column; } FString getMessage() const { return message; } + FString getSourcePath() const { return sourcePath; } + std::vector getSourceLines() const { return sourceLines; } virtual FString getErrorType() const { @@ -45,6 +50,9 @@ namespace Fig protected: size_t line, column; FString message; + + FString sourcePath; + std::vector sourceLines; }; class UnaddressableError : public std::exception @@ -84,14 +92,6 @@ namespace Fig public: 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 { std::string msg = std::format("[SyntaxError] {} in [{}] {}", this->message.toBasicString(), this->src_loc.file_name(), this->src_loc.function_name()); diff --git a/src/Error/errorLog.hpp b/src/Error/errorLog.hpp index 84f8e61..d615e2d 100644 --- a/src/Error/errorLog.hpp +++ b/src/Error/errorLog.hpp @@ -98,8 +98,11 @@ namespace Fig } - inline void logAddressableError(const AddressableError &err, FString fileName, std::vector sourceLines) + inline void logAddressableError(const AddressableError &err) { + const FString &fileName = err.getSourcePath(); + const std::vector &sourceLines = err.getSourceLines(); + std::print("\n"); namespace TC = TerminalColors; coloredPrint(TC::LightWhite, "An error occurred! "); diff --git a/src/Evaluator/evaluator.cpp b/src/Evaluator/evaluator.cpp index 51d5c21..a97a464 100644 --- a/src/Evaluator/evaluator.cpp +++ b/src/Evaluator/evaluator.cpp @@ -24,6 +24,10 @@ #include #include +#ifndef SourceInfo + #define SourceInfo(ptr) (ptr->sourcePath), (ptr->sourceLines) +#endif + namespace Fig { @@ -210,11 +214,10 @@ namespace Fig return evalIndexExpr(ie, ctx); } default: { - // throw EvaluatorError( - // u8"TypeError", - // std::format("Expression '{}' doesn't refer to a lvalue", exp->typeName().toBasicString()), - // exp); - + throw EvaluatorError( + u8"TypeError", + std::format("Expression '{}' doesn't refer to a lvalue", exp->typeName().toBasicString()), + exp); } } } @@ -316,7 +319,7 @@ namespace Fig return std::make_shared(implements(si.parentType, it.type, ctx)); } - if (ValueType::isTypeBuiltin(lhsType) && rhsType == ValueType::StructType) + if (ValueType::isTypeBuiltin(lhsType) && rhsType == ValueType::StructType) { const StructType &st = rhs->as(); const TypeInfo &type = st.type; @@ -329,24 +332,20 @@ namespace Fig e.g: "123" is String L OP R - + 其中 L 类型为 String 而 R 类型为 StructType (builtins.hpp) 中注册 拿到 R 的 StructType, 其中的 type 为 String */ - if (lhs->getTypeInfo() == type) - { - return Object::getTrueInstance(); - } + if (lhs->getTypeInfo() == type) { return Object::getTrueInstance(); } return Object::getFalseInstance(); } - throw EvaluatorError( - u8"TypeError", - std::format("Unsupported operator `is` for '{}' && '{}'", - lhsType.toString().toBasicString(), - rhsType.toString().toBasicString()), - bin->lexp); + throw EvaluatorError(u8"TypeError", + std::format("Unsupported operator `is` for '{}' && '{}'", + lhsType.toString().toBasicString(), + rhsType.toString().toBasicString()), + bin->lexp); } case Operator::BitAnd: { @@ -1017,11 +1016,8 @@ namespace Fig return std::make_shared(std::move(map)); } - default: - { - throw RuntimeError(FString( - std::format("err type of expr: {}", magic_enum::enum_name(type)) - )); + default: { + throw RuntimeError(FString(std::format("err type of expr: {}", magic_enum::enum_name(type)))); } } return Object::getNullInstance(); // ignore warning @@ -1478,11 +1474,13 @@ namespace Fig case BreakSt: { 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()) { - throw EvaluatorError(u8"BreakOutsideLoopError", u8"`break` statement outside loop", stmt); + throw EvaluatorError( + u8"BreakOutsideLoopError", u8"`break` statement outside loop", stmt); } return StatementResult::breakFlow(); } @@ -1490,11 +1488,13 @@ namespace Fig case ContinueSt: { 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()) { - throw EvaluatorError(u8"ContinueOutsideLoopError", u8"`continue` statement outside loop", stmt); + throw EvaluatorError( + u8"ContinueOutsideLoopError", u8"`continue` statement outside loop", stmt); } return StatementResult::continueFlow(); } @@ -1620,28 +1620,30 @@ namespace Fig ContextPtr Evaluator::loadModule(const std::filesystem::path &path) { + FString modSourcePath(path.string()); std::ifstream file(path); assert(file.is_open()); std::string source((std::istreambuf_iterator(file)), std::istreambuf_iterator()); file.close(); - Lexer lexer((FString(source))); - Parser parser(lexer); - std::vector asts; + std::vector modSourceLines = Utils::splitSource(FString(source)); - std::vector sourceLines = Utils::splitSource(FString(source)); + Lexer lexer((FString(source)), modSourcePath, modSourceLines); + Parser parser(lexer, modSourcePath, modSourceLines); + std::vector asts; asts = parser.parseAll(); Evaluator evaluator; - evaluator.SetSourcePath(FString(path.string())); + evaluator.SetSourcePath(modSourcePath); + evaluator.SetSourceLines(modSourceLines); ContextPtr modctx = std::make_shared(FString(std::format("", path.string())), nullptr); evaluator.SetGlobalContext(modctx); 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; } @@ -1663,8 +1665,9 @@ namespace Fig if (ctx->containsInThisScope(modName)) { - throw EvaluatorError( - u8"RedeclarationError", std::format("{} has already been declared.", modName.toBasicString()), i); + throw EvaluatorError(u8"RedeclarationError", + std::format("{} has already been declared.", modName.toBasicString()), + i); } ctx->def( modName, ValueType::Module, AccessModifier::PublicConst, std::make_shared(Module(modName, modCtx))); diff --git a/src/Evaluator/evaluator.hpp b/src/Evaluator/evaluator.hpp index 1ab53ab..f42c420 100644 --- a/src/Evaluator/evaluator.hpp +++ b/src/Evaluator/evaluator.hpp @@ -1,6 +1,6 @@ -#include "Ast/Statements/ImplementSt.hpp" -#include "Ast/Statements/InterfaceDefSt.hpp" -#include "Value/Type.hpp" +#include +#include +#include #include #include @@ -63,12 +63,18 @@ namespace Fig public: FString sourcePath; + std::vector sourceLines; void SetSourcePath(const FString &sp) { sourcePath = sp; } + void SetSourceLines(const std::vector &sl) + { + sourceLines = sl; + } + void SetGlobalContext(ContextPtr ctx) { assert(ctx != nullptr); diff --git a/src/Evaluator/evaluator_error.hpp b/src/Evaluator/evaluator_error.hpp index 2998c25..a9b7f5f 100644 --- a/src/Evaluator/evaluator_error.hpp +++ b/src/Evaluator/evaluator_error.hpp @@ -10,7 +10,10 @@ namespace Fig public: FString typeName; 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; line = ast->getAAI().line; @@ -20,8 +23,13 @@ namespace Fig 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())); line = ast->getAAI().line; @@ -30,13 +38,11 @@ namespace Fig src_loc = std::move(loc); typeName = std::move(_typeName); + + sourcePath = *ast->getAAI().sourcePath; + sourceLines = *ast->getAAI().sourceLines; } - virtual FString getErrorType() const override - { - return typeName; - } - - + virtual FString getErrorType() const override { return typeName; } }; -}; \ No newline at end of file +}; // namespace Fig \ No newline at end of file diff --git a/src/Evaluator/main.cpp b/src/Evaluator/main.cpp index 8836b86..0ab453a 100644 --- a/src/Evaluator/main.cpp +++ b/src/Evaluator/main.cpp @@ -89,7 +89,9 @@ int main(int argc, char **argv) std::string source((std::istreambuf_iterator(file)), std::istreambuf_iterator()); file.close(); - Fig::Lexer lexer((Fig::FString(source))); + std::vector sourceLines = Fig::Utils::splitSource(Fig::FString(source)); + + Fig::Lexer lexer((Fig::FString(source)), sourcePath, sourceLines); // Token tok; // while ((tok = lexer.nextToken()).getType() != TokenType::EndOfFile) @@ -97,11 +99,9 @@ int main(int argc, char **argv) // std::println("{}", tok.toString().toBasicString()); // } - Fig::Parser parser(lexer); + Fig::Parser parser(lexer, sourcePath, sourceLines); std::vector asts; - std::vector sourceLines = Fig::Utils::splitSource(Fig::FString(source)); - try { asts = parser.parseAll(); @@ -109,7 +109,7 @@ int main(int argc, char **argv) catch (const Fig::AddressableError &e) { addressableErrorCount++; - ErrorLog::logAddressableError(e, sourcePath, sourceLines); + ErrorLog::logAddressableError(e); return 1; } catch (const Fig::UnaddressableError &e) @@ -134,6 +134,7 @@ int main(int argc, char **argv) Fig::Evaluator evaluator; evaluator.SetSourcePath(sourcePath); + evaluator.SetSourceLines(sourceLines); evaluator.CreateGlobalContext(); evaluator.RegisterBuiltinsValue(); @@ -144,7 +145,7 @@ int main(int argc, char **argv) catch (const Fig::AddressableError &e) { addressableErrorCount++; - ErrorLog::logAddressableError(e, sourcePath, sourceLines); + ErrorLog::logAddressableError(e); evaluator.printStackTrace(); return 1; } diff --git a/src/Lexer/lexer.cpp b/src/Lexer/lexer.cpp index f577239..45399ed 100644 --- a/src/Lexer/lexer.cpp +++ b/src/Lexer/lexer.cpp @@ -10,6 +10,10 @@ #include // debug #endif +#ifndef SourceInfo + #define SourceInfo(ptr) (ptr->sourcePath), (ptr->sourceLines) +#endif + namespace Fig { @@ -163,7 +167,7 @@ namespace Fig { 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; } next(); @@ -200,12 +204,11 @@ namespace Fig } else { - error = SyntaxError(FString( - std::format( - "Unsupported escape character: {}", - FString(ec.getString()).toBasicString())), + error = SyntaxError(FString(std::format("Unsupported escape character: {}", + FString(ec.getString()).toBasicString())), this->line, - it.column()); + it.column(), + SourceInfo(this)); return IllegalTok; } } @@ -217,7 +220,7 @@ namespace Fig } 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 Token(str, TokenType::LiteralString); @@ -244,7 +247,7 @@ namespace Fig } 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 Token(str, TokenType::LiteralString); @@ -275,7 +278,7 @@ namespace Fig { 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; } next(); @@ -317,12 +320,11 @@ namespace Fig } else { - error = SyntaxError(FString( - std::format( - "Unsupported escape character: {}", - FString(ec.getString()).toBasicString())), + error = SyntaxError(FString(std::format("Unsupported escape character: {}", + FString(ec.getString()).toBasicString())), this->line, - it.column()); + it.column(), + SourceInfo(this)); return IllegalTok; } } @@ -334,7 +336,7 @@ namespace Fig } 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 Token(str, TokenType::LiteralString); @@ -378,8 +380,10 @@ namespace Fig if (numStr.ends_with(U'e')) { - error = SyntaxError( - FString(std::format("Illegal number literal: {}", numStr.toBasicString())), this->line, it.column()); + error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())), + this->line, + it.column(), + SourceInfo(this)); return IllegalTok; } @@ -395,8 +399,10 @@ namespace Fig if (!hasDigit) { - error = SyntaxError( - FString(std::format("Illegal number literal: {}", numStr.toBasicString())), this->line, it.column()); + error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())), + this->line, + it.column(), + SourceInfo(this)); return IllegalTok; } @@ -407,14 +413,16 @@ namespace Fig { error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())), this->line, - it.column()); + it.column(), + SourceInfo(this)); return IllegalTok; } if (ePos + 1 >= numStr.length()) { error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())), this->line, - it.column()); + it.column(), + SourceInfo(this)); return IllegalTok; } bool hasDigitAfterE = false; @@ -427,7 +435,8 @@ namespace Fig { error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())), this->line, - it.column()); + it.column(), + SourceInfo(this)); return IllegalTok; } continue; @@ -438,7 +447,8 @@ namespace Fig { error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())), this->line, - it.column()); + it.column(), + SourceInfo(this)); return IllegalTok; } } @@ -447,7 +457,8 @@ namespace Fig { error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())), this->line, - it.column()); + it.column(), + SourceInfo(this)); return IllegalTok; } } @@ -472,9 +483,10 @@ namespace Fig if (!startsWith(sym)) { - error = SyntaxError( - FString(std::format("No such operator: {}", sym.toBasicString())), - this->line, it.column()); + error = SyntaxError(FString(std::format("No such operator: {}", sym.toBasicString())), + this->line, + it.column(), + SourceInfo(this)); next(); return IllegalTok; } @@ -500,9 +512,10 @@ namespace Fig if (!symbol_map.contains(sym)) { - error = SyntaxError( - FString(std::format("No such operator: {}", sym.toBasicString())), - this->line, it.column()); + error = SyntaxError(FString(std::format("No such operator: {}", sym.toBasicString())), + this->line, + it.column(), + SourceInfo(this)); next(); return IllegalTok; } @@ -562,7 +575,8 @@ namespace Fig 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(); return IllegalTok; } @@ -633,9 +647,11 @@ namespace Fig } else { - error = SyntaxError(FString( - std::format("Cannot tokenize char: '{}'", FString(ch.getString()).toBasicString())), - this->line, it.column()); + error = + SyntaxError(FString(std::format("Cannot tokenize char: '{}'", FString(ch.getString()).toBasicString())), + this->line, + it.column(), + SourceInfo(this)); if (hasNext()) { next(); diff --git a/src/Lexer/lexer.hpp b/src/Lexer/lexer.hpp index 75a2297..196749e 100644 --- a/src/Lexer/lexer.hpp +++ b/src/Lexer/lexer.hpp @@ -23,6 +23,9 @@ namespace Fig SyntaxError error; UTF8Iterator it; + FString sourcePath; + std::vector sourceLines; + std::vector warnings; size_t last_line, last_column, column = 1; @@ -60,8 +63,8 @@ namespace Fig static const std::unordered_map symbol_map; static const std::unordered_map keyword_map; - inline Lexer(const FString &_source) : - source(_source), it(source) + inline Lexer(const FString &_source, const FString &_sourcePath, const std::vector &_sourceLines) : + source(_source), it(source), sourcePath(_sourcePath), sourceLines(_sourceLines) { line = 1; } diff --git a/src/Module/Library/std/time/time.fig b/src/Module/Library/std/time/time.fig index c0704c1..1f62cfd 100644 --- a/src/Module/Library/std/time/time.fig +++ b/src/Module/Library/std/time/time.fig @@ -38,7 +38,7 @@ public struct Time const result := ns - time_ns; if result < 0 { - throw "time has reversed! 😢"; + throw "time has been reversed! 😢"; } return result; } diff --git a/src/Parser/parser.cpp b/src/Parser/parser.cpp index 6d27777..6f0841e 100644 --- a/src/Parser/parser.cpp +++ b/src/Parser/parser.cpp @@ -22,7 +22,7 @@ namespace Fig // 逻辑 {Ast::Operator::And, {5, 6}}, {Ast::Operator::Or, {4, 5}}, - {Ast::Operator::Not, {30, 31}}, // 一元 + // {Ast::Operator::Not, {30, 31}}, // 一元 // 比较 {Ast::Operator::Equal, {7, 8}}, @@ -37,7 +37,7 @@ namespace Fig {Ast::Operator::BitAnd, {6, 7}}, {Ast::Operator::BitOr, {4, 5}}, {Ast::Operator::BitXor, {5, 6}}, - {Ast::Operator::BitNot, {30, 31}}, // 一元 + // {Ast::Operator::BitNot, {30, 31}}, // 一元 {Ast::Operator::ShiftLeft, {15, 16}}, {Ast::Operator::ShiftRight, {15, 16}}, @@ -214,7 +214,7 @@ namespace Fig variaPara = pname; next(); // skip `...` if (!isThis(TokenType::RightParen)) - throw SyntaxError( + throwAddressableError( u8"Expects right paren, variable parameter function can only have one parameter", currentAAI.line, currentAAI.column); @@ -433,7 +433,7 @@ namespace Fig } else { - throw SyntaxError(FString(u8"Invalid syntax"), currentAAI.line, currentAAI.column); + throwAddressableError(FString(u8"Invalid syntax"), currentAAI.line, currentAAI.column); } } return makeAst(interfaceName, methods, isPublic); @@ -480,7 +480,7 @@ namespace Fig } else { - throw SyntaxError(FString(u8"Invalid syntax"), currentAAI.line, currentAAI.column); + throwAddressableError(FString(u8"Invalid syntax"), currentAAI.line, currentAAI.column); } } @@ -556,7 +556,8 @@ namespace Fig { if (finallyBlock != nullptr) { - throw SyntaxError(u8"Duplicate try finally-block", currentAAI.line, currentAAI.column); + throwAddressableError( + u8"Duplicate try finally-block", currentAAI.line, currentAAI.column); } next(); // consume `finally` expect(TokenType::LeftBrace); @@ -678,11 +679,7 @@ namespace Fig } else { - throw SyntaxError( - u8"invalid syntax", - currentAAI.line, - currentAAI.column - ); + throwAddressableError(u8"invalid syntax", currentAAI.line, currentAAI.column); } return stmt; } @@ -1208,11 +1205,11 @@ namespace Fig if (!isTokenOp(tok)) break; op = Ast::TokenToOp.at(tok.getType()); - Precedence lbp = getLeftBindingPower(op); + auto [lbp, rbp] = getBindingPower(op); if (bp >= lbp) break; next(); // consume op - lhs = makeAst(lhs, op, parseExpression(bp, stop, stop2)); + lhs = makeAst(lhs, op, parseExpression(rbp, stop, stop2)); } return lhs; @@ -1232,10 +1229,8 @@ namespace Fig auto stmt = __parseStatement(); if (!output.empty() && stmt->getType() == Ast::AstType::PackageSt) { - throw SyntaxError( - u8"Package must be at the beginning of the file", - currentAAI.line, - currentAAI.column); + throwAddressableError( + u8"Package must be at the beginning of the file", currentAAI.line, currentAAI.column); } pushNode(stmt); } diff --git a/src/Parser/parser.hpp b/src/Parser/parser.hpp index dcb2800..7cad4d5 100644 --- a/src/Parser/parser.hpp +++ b/src/Parser/parser.hpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -22,6 +23,9 @@ namespace Fig std::vector output; std::vector previousTokens; + std::shared_ptr sourcePathPtr; + std::shared_ptr> sourceLinesPtr; + size_t tokenPruduced = 0; size_t currentTokenIndex = 0; @@ -72,7 +76,11 @@ namespace Fig static const std::unordered_map> opPrecedence; static const std::unordered_map unaryOpPrecedence; - Parser(const Lexer &_lexer) : lexer(_lexer) {} + Parser(const Lexer &_lexer, FString _sourcePath, std::vector _sourceLines) : lexer(_lexer) + { + sourcePathPtr = std::make_shared(_sourcePath); + sourceLinesPtr = std::make_shared>(_sourceLines); + } AddressableError *getError() const { return error.get(); } @@ -83,7 +91,7 @@ namespace Fig std::source_location loc = std::source_location::current()) { static_assert(std::is_base_of_v, "_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); throw spError; } @@ -92,7 +100,7 @@ namespace Fig { static_assert(std::is_base_of_v, "_ErrT must derive from AddressableError"); // 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); throw spError; } @@ -135,7 +143,10 @@ namespace Fig CTI也需要显示转换,否则转换完的pruduced又会被转回去,变为 int64_t max */ currentTokenIndex++; - setCurrentAAI(Ast::AstAddressInfo{.line = currentToken().line, .column = currentToken().column}); + setCurrentAAI(Ast::AstAddressInfo{.line = currentToken().line, + .column = currentToken().column, + .sourcePath = sourcePathPtr, + .sourceLines = sourceLinesPtr}); return; } if (isEOF()) return; @@ -143,7 +154,11 @@ namespace Fig tokenPruduced++; if (tok == IllegalTok) throw lexer.getError(); 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); } inline const Token ¤tToken() @@ -298,9 +313,8 @@ namespace Fig Ast::ListExpr __parseListExpr(); // entry: current is `[` Ast::MapExpr __parseMapExpr(); // entry: current is `{` - Ast::InitExpr __parseInitExpr( - Ast::Expression); // entry: current is `{`, ahead is struct type exp. - Ast::Expression __parseTupleOrParenExpr(); // entry: current is `(` + Ast::InitExpr __parseInitExpr(Ast::Expression); // entry: current is `{`, ahead is struct type exp. + Ast::Expression __parseTupleOrParenExpr(); // entry: current is `(` Ast::FunctionLiteralExpr __parseFunctionLiteralExpr(); // entry: current is Token::LParen after Token::Function