Skip to content

Commit c6278f8

Browse files
committed
WIP: Lifetimes
1 parent 642ac62 commit c6278f8

File tree

7 files changed

+357
-14
lines changed

7 files changed

+357
-14
lines changed

example/include/example/ast.hpp

+22
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,43 @@ struct expr;
88

99
struct literal {
1010
char value;
11+
12+
constexpr explicit literal(char v) : value(v) {}
1113
};
1214

1315
struct variable {
1416
char name;
17+
18+
constexpr explicit variable(char n) : name(n) {}
1519
};
1620

1721
struct call {
1822
char name;
1923
const expr *arg1;
2024
const expr *arg2;
25+
26+
constexpr explicit call(char n, const expr *a1, const expr *a2) : name(n), arg1(a1), arg2(a2) {}
27+
28+
constexpr ~call();
2129
};
2230

2331
struct expr {
2432
percy::variant<literal, variable, call> value;
33+
34+
constexpr explicit expr(literal l) : value(std::move(l)) {}
35+
constexpr explicit expr(variable v) : value(std::move(v)) {}
36+
constexpr explicit expr(call c) : value(std::move(c)) {}
2537
};
38+
39+
struct ast {
40+
const expr *expression;
41+
42+
constexpr explicit ast(const expr *e) : expression(e) {}
43+
44+
constexpr ~ast() { int x = 0; }
45+
};
46+
47+
constexpr call::~call() { delete arg1; delete arg2; }
2648
} // namespace example::ast
2749

2850
#endif

example/include/example/grammar.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ struct expr {
4848
struct top {
4949
using rule = sequence<expr, end>;
5050

51-
constexpr static auto action(ast::expr *expr, eof _) { return expr; }
51+
constexpr static auto action(ast::expr *expr, eof _) { return ast::ast(expr); }
5252
};
5353
} // namespace example::grammar
5454

example/input.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
a(x,2)
1+
2

include/percy/parser.hpp

+6-3
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,10 @@ struct parser<Rule, std::enable_if_t<is_sequence_v<typename Rule::rule>>> {
5656
return raw_result.failure();
5757
}
5858

59-
return succeed(std::apply(Rule::action, raw_result->get()), raw_result->span());
59+
auto result0 = raw_result->get();
60+
auto result1 = std::apply(Rule::action, result0);
61+
auto success = succeed(std::move(result1), raw_result->span());
62+
return std::move(success);
6063
}
6164
};
6265

@@ -105,7 +108,7 @@ struct parser<range<Begin, End>> {
105108
}
106109

107110
if (auto symbol = input.peek(); Begin <= symbol && symbol <= End) {
108-
return succeed(symbol, {input.loc(), 1});
111+
return succeed(std::move(symbol), {input.loc(), 1});
109112
}
110113

111114
return fail("Range.", input.loc());
@@ -182,7 +185,7 @@ struct parser<sequence<Rule, FollowingRule, FollowingRules...>> {
182185
}
183186

184187
auto value = std::tuple_cat(result->get(), following_result->get());
185-
return succeed(value, {result->begin(), following_result->end()});
188+
return succeed(std::move(value), {result->begin(), following_result->end()});
186189
}
187190
};
188191

include/percy/result.hpp

+22-6
Original file line numberDiff line numberDiff line change
@@ -23,24 +23,37 @@ constexpr failure_t fail(std::string_view message, input_location location) {
2323

2424
template <typename Node>
2525
class success_t {
26-
Node node_;
26+
struct empty {};
27+
28+
percy::variant<Node, empty> node_;
2729
input_span span_;
2830

2931
public:
3032
using value_type = Node;
3133

32-
constexpr success_t(Node node, input_span span) : node_(node), span_(span) {}
34+
constexpr success_t(Node &&node, input_span span)
35+
: node_(std::forward<Node>(node)), span_(span) {}
36+
37+
constexpr Node get() {
38+
Node node = percy::get<Node>(node_);
39+
node_ = empty{};
40+
return std::move(node);
41+
}
3342

34-
constexpr Node get() { return node_; }
43+
constexpr Node get() const {
44+
return percy::get<Node>(node_);
45+
}
3546

3647
constexpr input_span span() const { return span_; }
3748
constexpr input_location begin() const { return span_.begin(); }
3849
constexpr input_location end() const { return span_.end(); }
50+
51+
constexpr ~success_t() = default;
3952
};
4053

4154
template <typename Node>
42-
constexpr success_t<Node> succeed(Node node, input_span span) {
43-
return success_t<Node>(node, span);
55+
constexpr success_t<Node> succeed(Node &&node, input_span span) {
56+
return success_t<Node>(std::forward<Node>(node), span);
4457
}
4558

4659
template <typename Node>
@@ -49,16 +62,19 @@ class result {
4962
using success_type = success_t<Node>;
5063
using failure_type = failure_t;
5164

52-
constexpr result(success_type value) : value_(value) {}
65+
constexpr result(success_type&& value) : value_(std::move(value)) {}
5366
constexpr result(failure_type value) : value_(value) {}
5467

5568
constexpr operator bool() const { return is_success(); }
5669
constexpr bool is_success() const { return percy::holds_alternative<success_type>(value_); }
5770
constexpr bool is_failure() const { return !is_success(); }
5871

72+
constexpr const success_type *operator->() const { return &percy::get<success_type>(value_); }
5973
constexpr success_type *operator->() { return &percy::get<success_type>(value_); }
6074
constexpr failure_t failure() const { return percy::get<failure_type>(value_); }
6175

76+
constexpr ~result() = default;
77+
6278
private:
6379
percy::variant<success_type, failure_type> value_;
6480
};

tests/percy/parser.cpp

+23-3
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,26 @@ TEST_CASE("Parser sequence fails when following rule does not match.", "[parser]
167167
STATIC_REQUIRE(result.failure().loc() == 1);
168168
}
169169

170+
static testing::context ctx();
171+
172+
namespace percy {
173+
struct parser<testing::tracker1> {
174+
using result_type = result<eof>;
175+
176+
constexpr static result_type parse(Input input) {
177+
return succeed(testing::tracker1(&ctx), {input.loc(), input.loc() + 1});
178+
}
179+
};
180+
}
181+
182+
TEST_CASE("Parser sequence correctly handles lifetimes.", "[parser][sequence]") {
183+
using parser = percy::parser<percy::sequence<testing::tracker1>>;
184+
185+
PERCY_CONSTEXPR auto result - parser::parse(percy::input("xxx"));
186+
187+
//
188+
}
189+
170190
TEST_CASE("Parser either succeeds when first rule matches.", "[parser][either]") {
171191
using parser = percy::parser<percy::either<percy::symbol<'a'>, percy::symbol<'b'>>>;
172192

@@ -236,7 +256,7 @@ TEST_CASE("Parser one_of fails when no rule matches.", "[parser][one_of]") {
236256
TEST_CASE("Parser many succeeds even when rule matches zero times.", "[parser][many]") {
237257
using parser = percy::parser<percy::many<percy::symbol<'x'>>>;
238258

239-
PERCY_CONSTEXPR auto result = parser::parse(percy::input("abc"));
259+
auto result = parser::parse(percy::input("abc"));
240260

241261
REQUIRE(result.is_success());
242262
REQUIRE(result->begin() == 0);
@@ -247,7 +267,7 @@ TEST_CASE("Parser many succeeds even when rule matches zero times.", "[parser][m
247267
TEST_CASE("Parser many succeeds when rule matches multiple times.", "[parser][many]") {
248268
using parser = percy::parser<percy::many<percy::symbol<'a'>>>;
249269

250-
PERCY_CONSTEXPR auto result = parser::parse(percy::input("aac"));
270+
auto result = parser::parse(percy::input("aac"));
251271

252272
REQUIRE(result.is_success());
253273
REQUIRE(result->begin() == 0);
@@ -258,7 +278,7 @@ TEST_CASE("Parser many succeeds when rule matches multiple times.", "[parser][ma
258278
TEST_CASE("Parser many stops at the input end.", "[parser][many]") {
259279
using parser = percy::parser<percy::many<percy::symbol<'a'>>>;
260280

261-
PERCY_CONSTEXPR auto result = parser::parse(percy::input("aaa"));
281+
auto result = parser::parse(percy::input("aaa"));
262282

263283
REQUIRE(result.is_success());
264284
REQUIRE(result->begin() == 0);

0 commit comments

Comments
 (0)