#pragma once #include #include #include #include #include #include #include namespace Fig { class Parser { private: Lexer lexer; std::vector output; std::vector previousTokens; size_t tokenPruduced = 0; size_t currentTokenIndex = 0; std::unique_ptr error; Ast::AstAddressInfo currentAAI; std::stack exprStack; bool needSemicolon = true; class SemicolonDisabler { Parser *p; bool original; public: SemicolonDisabler(Parser *parser) : p(parser), original(p->needSemicolon) { p->needSemicolon = false; } ~SemicolonDisabler() { p->needSemicolon = original; } // disable copy and assign SemicolonDisabler(const SemicolonDisabler &) = delete; SemicolonDisabler &operator=(const SemicolonDisabler &) = delete; }; void pushNode(const Ast::AstBase &_node) { Ast::AstBase node = _node; node->setAAI(currentAAI); output.push_back(std::move(node)); } void pushNode(const Ast::AstBase &_node, Ast::AstAddressInfo _aai) { Ast::AstBase node = _node; node->setAAI(_aai); output.push_back(node); } bool isTokenSymbol(Token tok) { return Lexer::symbol_map.contains(tok.getValue()); } bool isTokenOp(Token tok) { return Ast::TokenToOp.contains(tok.getType()); } bool isEOF() { if (tokenPruduced == 0) return false; return currentToken() == EOFTok; } public: using Precedence = uint32_t; static const std::unordered_map> opPrecedence; Parser(const Lexer &_lexer) : lexer(_lexer) { } AddressableError* getError() const { return error.get(); } template void throwAddressableError(FStringView msg, size_t line, size_t column, 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); error = std::make_unique<_ErrT>(spError); throw spError; } template void throwAddressableError(FStringView msg, std::source_location loc = std::source_location::current()) { 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); error = std::make_unique<_ErrT>(spError); throw spError; } template void throwUnaddressableError(FStringView msg, std::source_location loc = std::source_location::current()) { static_assert(std::is_base_of_v, "_ErrT must derive from AddressableError"); _ErrT spError(msg, loc); error = std::make_unique<_ErrT>(spError); throw spError; } void setCurrentAAI(Ast::AstAddressInfo _aai) { currentAAI = std::move(_aai); } Ast::AstAddressInfo getCurrentAAI() const { return currentAAI; } inline const Token &nextToken() { // 没有Rollback时, 存在 currentTokenIndex = tokenPruduced - 1 next(); return currentToken(); } inline void rollback() { if (int64_t(currentTokenIndex - 1) < int64_t(0)) // 同下 next注释 { throw std::runtime_error("Internal Error in Parser::rollbackToken, trying to rollback but it's already on the begin"); } currentTokenIndex--; } inline void next() { if (int64_t(currentTokenIndex) < (int64_t(tokenPruduced) - 1)) { /* 必须两个都显示转换为int64_t.否则,负数时会超出范围,变成int64_t max, 并且 CTI也需要显示转换,否则转换完的pruduced又会被转回去,变为 int64_t max */ currentTokenIndex++; setCurrentAAI(Ast::AstAddressInfo{.line = currentToken().line, .column = currentToken().column}); return; } if (isEOF()) return; const Token &tok = lexer.nextToken(); tokenPruduced++; if (tok == IllegalTok) throw lexer.getError(); currentTokenIndex = tokenPruduced - 1; setCurrentAAI(Ast::AstAddressInfo{.line = tok.line, .column = tok.column}); previousTokens.push_back(tok); } inline const Token ¤tToken() { if (tokenPruduced == 0) return nextToken(); return previousTokens.at(currentTokenIndex); } inline Token rollbackToken() { rollback(); return previousTokens.at(currentTokenIndex); } inline Token peekToken() { Token tok = nextToken(); rollback(); return tok; } std::pair getBindingPower(Ast::Operator op) { return opPrecedence.at(op); } Precedence getLeftBindingPower(Ast::Operator op) { return getBindingPower(op).first; } Precedence getRightBindingPower(Ast::Operator op) { return getBindingPower(op).second; } // template // std::shared_ptr<_Tp> makeAst(Args &&...args) // { // _Tp node(std::forward(args)...); // node.setAAI(currentAAI); // return std::shared_ptr<_Tp>(new _Tp(node)); // } template std::shared_ptr<_Tp> makeAst(Args &&...args) { std::shared_ptr<_Tp> ptr = std::make_shared<_Tp>(std::forward(args)...); ptr->setAAI(currentAAI); return ptr; } void expectPeek(TokenType type) { if (peekToken().getType() != type) { throwAddressableError(FStringView(std::format("Expected `{}`, but got `{}`", magic_enum::enum_name(type), magic_enum::enum_name(peekToken().getType())))); } } void expect(TokenType type) { if (currentToken().getType() != type) { throwAddressableError(FStringView(std::format("Expected `{}`, but got `{}`", magic_enum::enum_name(type), magic_enum::enum_name(currentToken().getType())))); } } void expectPeek(TokenType type, FString expected) { if (peekToken().getType() != type) { throwAddressableError(FStringView(std::format("Expected `{}`, but got `{}`", expected.toBasicString(), magic_enum::enum_name(peekToken().getType())))); } } void expect(TokenType type, FString expected) { if (currentToken().getType() != type) { throwAddressableError(FStringView(std::format("Expected `{}`, but got `{}`", expected.toBasicString(), magic_enum::enum_name(currentToken().getType())))); } } [[nodiscard]] SemicolonDisabler disableSemicolon() { return SemicolonDisabler(this); } void expectSemicolon() { // if need semicolon and stream has `;`, consume it. if not need semicolon, do nothing if (!needSemicolon) { // disabled semicolon check if (currentToken().getType() == TokenType::Semicolon) { next(); // consume `;` } return; } // normal semicolon check expectConsume(TokenType::Semicolon); } void expectConsume(TokenType type, FString expected) { expect(type, expected); next(); } void expectConsume(TokenType type) { expect(type); next(); } bool isNext(TokenType type) { return peekToken().getType() == type; } bool isThis(TokenType type) { return currentToken().getType() == type; } static constexpr FString varDefTypeFollowed = u8"(Followed)"; Ast::VarDef __parseVarDef(bool); // entry: current is keyword `var` or `const` (isConst: Bool) Value __parseValue(); Ast::ValueExpr __parseValueExpr(); Ast::FunctionParameters __parseFunctionParameters(); // entry: current is Token::LeftParen Ast::BlockStatement __parseBlockStatement(); // entry: current is Token::LeftBrace Ast::If __parseIf(); // entry: current is Token::If Ast::While __parseWhile(); // entry: current is Token::While Ast::Statement __parseIncrementStatement(); // only allowed in __parseFor function Ast::For __parseFor(); // entry: current is Token::For Ast::Return __parseReturn(); // entry: current is Token::Return Ast::Break __parseBreak(); // entry: current is Token::Break Ast::Continue __parseContinue(); // entry: current is Token::Continue Ast::VarExpr __parseVarExpr(FString); Ast::FunctionDef __parseFunctionDef(bool); // entry: current is Token::Identifier (isPublic: Bool) Ast::StructDef __parseStructDef(bool); // entry: current is Token::Identifier (struct name) arg(isPublic: bool) Ast::BinaryExpr __parseInfix(Ast::Expression, Ast::Operator, Precedence); Ast::UnaryExpr __parsePrefix(Ast::Operator, Precedence); Ast::Expression __parseCall(Ast::Expression); Ast::ListExpr __parseListExpr(); // entry: current is `[` Ast::MapExpr __parseMapExpr(); // entry: current is `{` Ast::InitExpr __parseInitExpr(FString); // entry: current is `{`, ahead is struct name. arg (struct name : FString) Ast::Expression __parseTupleOrParenExpr(); // entry: current is `(` Ast::FunctionLiteralExpr __parseFunctionLiteralExpr(); // entry: current is Token::LParen after Token::Function Ast::Statement __parseStatement(); // entry: (idk) Ast::Expression parseExpression(Precedence, TokenType = TokenType::Semicolon, TokenType = TokenType::Semicolon); std::vector parseAll(); }; }; // namespace Fig