Skip to content

Commit 82e3b27

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 65fcd0f commit 82e3b27

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
@@ -1993,6 +1993,10 @@ class cppfront
19931993
assert(n.identifier);
19941994
emit(*n.identifier);
19951995

1996+
if (n.is_constexpr) {
1997+
printer.print_cpp2(" constexpr", n.position());
1998+
}
1999+
19962000
printer.print_cpp2(" (", n.position());
19972001
printer.add_pad_in_this_line(1);
19982002

@@ -2005,6 +2009,26 @@ class cppfront
20052009
assert(n.true_branch);
20062010
emit(*n.true_branch);
20072011

2012+
for(const auto& elif : n.else_ifs) {
2013+
printer.print_cpp2(" else if ", elif.pos);
2014+
2015+
if (elif.is_constexpr) {
2016+
printer.print_cpp2("constexpr ", elif.pos);
2017+
}
2018+
2019+
printer.print_cpp2("(", elif.pos);
2020+
printer.add_pad_in_this_line(1);
2021+
2022+
assert(elif.expression);
2023+
emit(*elif.expression);
2024+
2025+
printer.print_cpp2(") ", elif.pos);
2026+
printer.add_pad_in_this_line(1);
2027+
2028+
assert(elif.branch);
2029+
emit(*elif.branch);
2030+
}
2031+
20082032
if (n.has_source_false_branch) {
20092033
printer.print_cpp2("else ", n.else_pos);
20102034
emit(*n.false_branch);

source/parse.h

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

935+
struct else_if {
936+
bool is_constexpr = false;
937+
std::unique_ptr<expression_node> expression;
938+
std::unique_ptr<compound_statement_node> branch;
939+
source_position pos;
940+
};
941+
std::vector<else_if> else_ifs;
942+
935943
auto position() const
936944
-> source_position
937945
{
@@ -949,6 +957,14 @@ struct selection_statement_node
949957
expression->visit(v, depth+1);
950958
assert (true_branch);
951959
true_branch->visit(v, depth+1);
960+
961+
for(const auto& elif : else_ifs) {
962+
assert (elif.expression);
963+
elif.expression->visit(v, depth+1);
964+
assert (elif.branch);
965+
elif.branch->visit(v, depth+1);
966+
}
967+
952968
if (false_branch) {
953969
false_branch->visit(v, depth+1);
954970
}
@@ -4044,6 +4060,48 @@ class parser
40444060
return {};
40454061
}
40464062

4063+
while (
4064+
curr().type() == lexeme::Keyword
4065+
&& curr() == "else"
4066+
&& peek(1) && peek(1)->type() == lexeme::Keyword && peek(1)->to_string(true) == "if"
4067+
) {
4068+
selection_statement_node::else_if elif;
4069+
elif.pos = curr().position();
4070+
next(2); // skip "else if"
4071+
4072+
if (
4073+
curr().type() == lexeme::Keyword
4074+
&& curr() == "constexpr"
4075+
)
4076+
{
4077+
elif.is_constexpr = true;
4078+
next();
4079+
}
4080+
4081+
if (auto e = expression()) {
4082+
elif.expression = std::move(e);
4083+
}
4084+
else {
4085+
error("invalid else if condition", true, {}, true);
4086+
return {};
4087+
}
4088+
4089+
if (curr().type() != lexeme::LeftBrace) {
4090+
error("an if branch body must be enclosed with { }");
4091+
return {};
4092+
}
4093+
4094+
if (auto s = compound_statement()) {
4095+
elif.branch = std::move(s);
4096+
}
4097+
else {
4098+
error("invalid if branch body", true, {}, true);
4099+
return {};
4100+
}
4101+
4102+
n->else_ifs.emplace_back(std::move(elif));
4103+
}
4104+
40474105
if (
40484106
curr().type() != lexeme::Keyword
40494107
|| 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,
@@ -437,11 +437,14 @@ class sema
437437
o << "/";
438438
--scope_depth;
439439
}
440-
if (sym.kind_ == sym.is_true) {
441-
o << "true branch";
440+
if (sym.kind_ == sym.is_if) {
441+
o << "if branch";
442442
}
443-
else if (sym.kind_ == sym.is_false) {
444-
o << "false branch";
443+
else if (sym.kind_ == sym.is_else_if) {
444+
o << "if else branch";
445+
}
446+
else if (sym.kind_ == sym.is_else) {
447+
o << "else branch";
445448
}
446449
else {
447450
o << "scope";
@@ -1110,14 +1113,26 @@ class sema
11101113
assert(active_selections.back()->true_branch);
11111114
if (active_selections.back()->true_branch.get() == &n)
11121115
{
1113-
kind = compound_sym::is_true;
1116+
kind = compound_sym::is_if;
11141117
}
1115-
if (
1118+
else if (
1119+
std::any_of(
1120+
std::cbegin(active_selections.back()->else_ifs),
1121+
std::cend(active_selections.back()->else_ifs),
1122+
[&](const auto& elif) -> bool {
1123+
return elif.branch && elif.branch.get() == &n;
1124+
}
1125+
)
1126+
)
1127+
{
1128+
kind = compound_sym::is_else_if;
1129+
}
1130+
else if (
11161131
active_selections.back()->false_branch
11171132
&& active_selections.back()->false_branch.get() == &n
11181133
)
11191134
{
1120-
kind = compound_sym::is_false;
1135+
kind = compound_sym::is_else;
11211136
}
11221137
}
11231138
return kind;

0 commit comments

Comments
 (0)