Skip to content

Commit c41e5d1

Browse files
committed
Add support for else if branches and constexpr ifs
Added support for else if branches. Added support for constexpr ifs Added support for definite initialization checks Added support for debug symbols (if branch, if else branch, else branch)
1 parent 8c0915c commit c41e5d1

File tree

3 files changed

+105
-8
lines changed

3 files changed

+105
-8
lines changed

source/cppfront.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1976,6 +1976,10 @@ class cppfront
19761976
assert(n.identifier);
19771977
emit(*n.identifier);
19781978

1979+
if (n.is_constexpr) {
1980+
printer.print_cpp2(" constexpr", n.position());
1981+
}
1982+
19791983
printer.print_cpp2(" (", n.position());
19801984
printer.add_pad_in_this_line(1);
19811985

@@ -1988,6 +1992,26 @@ class cppfront
19881992
assert(n.true_branch);
19891993
emit(*n.true_branch);
19901994

1995+
for(const auto& elif : n.else_ifs) {
1996+
printer.print_cpp2(" else if ", elif.pos);
1997+
1998+
if (elif.is_constexpr) {
1999+
printer.print_cpp2("constexpr ", elif.pos);
2000+
}
2001+
2002+
printer.print_cpp2("(", elif.pos);
2003+
printer.add_pad_in_this_line(1);
2004+
2005+
assert(elif.expression);
2006+
emit(*elif.expression);
2007+
2008+
printer.print_cpp2(") ", elif.pos);
2009+
printer.add_pad_in_this_line(1);
2010+
2011+
assert(elif.branch);
2012+
emit(*elif.branch);
2013+
}
2014+
19912015
if (n.has_source_false_branch) {
19922016
printer.print_cpp2("else ", n.else_pos);
19932017
emit(*n.false_branch);

source/parse.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1168,6 +1168,14 @@ struct selection_statement_node
11681168
std::unique_ptr<compound_statement_node> false_branch;
11691169
bool has_source_false_branch = false;
11701170

1171+
struct else_if {
1172+
bool is_constexpr = false;
1173+
std::unique_ptr<expression_node> expression;
1174+
std::unique_ptr<compound_statement_node> branch;
1175+
source_position pos;
1176+
};
1177+
std::vector<else_if> else_ifs;
1178+
11711179
auto position() const
11721180
-> source_position
11731181
{
@@ -1185,6 +1193,14 @@ struct selection_statement_node
11851193
expression->visit(v, depth+1);
11861194
assert (true_branch);
11871195
true_branch->visit(v, depth+1);
1196+
1197+
for(const auto& elif : else_ifs) {
1198+
assert (elif.expression);
1199+
elif.expression->visit(v, depth+1);
1200+
assert (elif.branch);
1201+
elif.branch->visit(v, depth+1);
1202+
}
1203+
11881204
if (false_branch) {
11891205
false_branch->visit(v, depth+1);
11901206
}
@@ -4643,6 +4659,48 @@ class parser
46434659
return {};
46444660
}
46454661

4662+
while (
4663+
curr().type() == lexeme::Keyword
4664+
&& curr() == "else"
4665+
&& peek(1) && peek(1)->type() == lexeme::Keyword && peek(1)->to_string(true) == "if"
4666+
) {
4667+
selection_statement_node::else_if elif;
4668+
elif.pos = curr().position();
4669+
next(2); // skip "else if"
4670+
4671+
if (
4672+
curr().type() == lexeme::Keyword
4673+
&& curr() == "constexpr"
4674+
)
4675+
{
4676+
elif.is_constexpr = true;
4677+
next();
4678+
}
4679+
4680+
if (auto e = expression()) {
4681+
elif.expression = std::move(e);
4682+
}
4683+
else {
4684+
error("invalid else if condition", true, {}, true);
4685+
return {};
4686+
}
4687+
4688+
if (curr().type() != lexeme::LeftBrace) {
4689+
error("an if branch body must be enclosed with { }");
4690+
return {};
4691+
}
4692+
4693+
if (auto s = compound_statement()) {
4694+
elif.branch = std::move(s);
4695+
}
4696+
else {
4697+
error("invalid if branch body", true, {}, true);
4698+
return {};
4699+
}
4700+
4701+
n->else_ifs.emplace_back(std::move(elif));
4702+
}
4703+
46464704
if (
46474705
curr().type() != lexeme::Keyword
46484706
|| curr() != "else"

source/sema.h

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ struct selection_sym {
104104
struct compound_sym {
105105
bool start = false;
106106
compound_statement_node const* compound = {};
107-
enum kind { is_scope, is_true, is_false } kind_ = is_scope;
107+
enum kind { is_scope, is_if, is_else_if, is_else } kind_ = is_scope;
108108

109109
compound_sym(
110110
bool s,
@@ -434,11 +434,14 @@ class sema
434434
o << "/";
435435
--scope_depth;
436436
}
437-
if (sym.kind_ == sym.is_true) {
438-
o << "true branch";
437+
if (sym.kind_ == sym.is_if) {
438+
o << "if branch";
439439
}
440-
else if (sym.kind_ == sym.is_false) {
441-
o << "false branch";
440+
else if (sym.kind_ == sym.is_else_if) {
441+
o << "if else branch";
442+
}
443+
else if (sym.kind_ == sym.is_else) {
444+
o << "else branch";
442445
}
443446
else {
444447
o << "scope";
@@ -1479,14 +1482,26 @@ class sema
14791482
assert(active_selections.back()->true_branch);
14801483
if (active_selections.back()->true_branch.get() == &n)
14811484
{
1482-
kind = compound_sym::is_true;
1485+
kind = compound_sym::is_if;
14831486
}
1484-
if (
1487+
else if (
1488+
std::any_of(
1489+
std::cbegin(active_selections.back()->else_ifs),
1490+
std::cend(active_selections.back()->else_ifs),
1491+
[&](const auto& elif) -> bool {
1492+
return elif.branch && elif.branch.get() == &n;
1493+
}
1494+
)
1495+
)
1496+
{
1497+
kind = compound_sym::is_else_if;
1498+
}
1499+
else if (
14851500
active_selections.back()->false_branch
14861501
&& active_selections.back()->false_branch.get() == &n
14871502
)
14881503
{
1489-
kind = compound_sym::is_false;
1504+
kind = compound_sym::is_else;
14901505
}
14911506
}
14921507
return kind;

0 commit comments

Comments
 (0)