From 47e8b1bf518d89a1b6c742e2e90f57a2a2dbb1d5 Mon Sep 17 00:00:00 2001 From: CHatingPython Date: Sun, 9 Aug 2026 17:17:47 +0200 Subject: [PATCH] feat(furc/parser): add pre- and post- conditions --- furc/include/furc/front/ast.hpp | 14 ++++++++++---- furc/include/furc/front/token.hpp | 4 ++++ furc/src/front/lexer.cpp | 2 ++ furc/src/front/parser.cpp | 22 +++++++++++++++++++++- furc/src/main.cpp | 2 +- 5 files changed, 38 insertions(+), 6 deletions(-) diff --git a/furc/include/furc/front/ast.hpp b/furc/include/furc/front/ast.hpp index 429f629..96b522b 100644 --- a/furc/include/furc/front/ast.hpp +++ b/furc/include/furc/front/ast.hpp @@ -116,10 +116,16 @@ struct var_decl_node final : public decl_node { struct func_decl_node final : public decl_node { decl_type_e decl_type() const override { return Function; } - std::string name; - ast_type type; - std::vector params; - std::optional body; + struct def_s { + comp_stmt_node body; + std::vector preConds; + std::vector postConds; + }; + + std::string name; + ast_type type; + std::vector params; + std::optional def; }; class expr_node : public stmt_node { diff --git a/furc/include/furc/front/token.hpp b/furc/include/furc/front/token.hpp index 39382db..7b7921b 100644 --- a/furc/include/furc/front/token.hpp +++ b/furc/include/furc/front/token.hpp @@ -76,6 +76,8 @@ struct token { While, /**< `while` */ Public, /**< `public` */ Private, /**< `private` */ + Pre, /**< `pre` */ + Post, /**< `post` */ Pointerof, /**< `pointerof` */ Sizeof, /**< `sizeof` */ @@ -186,6 +188,8 @@ struct token { case token::While: return os << "while"; case token::Public: return os << "public"; case token::Private: return os << "private"; + case token::Pre: return os << "pre"; + case token::Post: return os << "post"; case token::Pointerof: return os << "pointerof"; case token::Sizeof: return os << "sizeof"; case token::Lengthof: return os << "lengthof"; diff --git a/furc/src/front/lexer.cpp b/furc/src/front/lexer.cpp index 0b11fbb..92c4b0c 100644 --- a/furc/src/front/lexer.cpp +++ b/furc/src/front/lexer.cpp @@ -52,6 +52,8 @@ token lexer::next_token() { { "while", token::While }, { "public", token::Public }, { "private", token::Private }, + { "pre", token::Pre }, + { "post", token::Post }, { "pointerof", token::Pointerof }, { "sizeof", token::Sizeof }, { "lengthof", token::Lengthof }, diff --git a/furc/src/front/parser.cpp b/furc/src/front/parser.cpp index 3bb27c6..6422a3d 100644 --- a/furc/src/front/parser.cpp +++ b/furc/src/front/parser.cpp @@ -99,7 +99,27 @@ decl_node* parser::parse_decl() { return m_arena->allocate(std::move(func)); } - func.body = parse_comp(); + func_decl_node::def_s def; + + while (m_lexer.peek_token().type == token::Pre || m_lexer.peek_token().type == token::Post) { + auto token = m_lexer.next_token(); + eat_token(token::LParen); + auto* expr = parse_expr(); + eat_token(token::RParen); + + switch (token.type) { + case token::Pre: { + def.preConds.push_back(expr); + } break; + case token::Post: { + def.postConds.push_back(expr); + } break; + default: throw std::runtime_error("unreachable"); + } + } + + def.body = parse_comp(); + func.def = std::move(def); return m_arena->allocate(std::move(func)); } diff --git a/furc/src/main.cpp b/furc/src/main.cpp index de7bc4e..8f12bf6 100644 --- a/furc/src/main.cpp +++ b/furc/src/main.cpp @@ -6,7 +6,7 @@ int main(void) { furlang::arena arena; std::string_view content = R"( - func main(argc: u64) -> s32 { + func main(argc: u64) -> s32 pre(arc > 1) { x: s32 = 1 + 2 * 3; if (x == 9) return 1; else return 0;