Skip to content

Commit 3371e96

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 d8c1a50 commit 3371e96

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
@@ -984,6 +984,14 @@ struct selection_statement_node
984984
std::unique_ptr<compound_statement_node> false_branch;
985985
bool has_source_false_branch = false;
986986

987+
struct else_if {
988+
bool is_constexpr = false;
989+
std::unique_ptr<expression_node> expression;
990+
std::unique_ptr<compound_statement_node> branch;
991+
source_position pos;
992+
};
993+
std::vector<else_if> else_ifs;
994+
987995
auto position() const
988996
-> source_position
989997
{
@@ -1001,6 +1009,14 @@ struct selection_statement_node
10011009
expression->visit(v, depth+1);
10021010
assert (true_branch);
10031011
true_branch->visit(v, depth+1);
1012+
1013+
for(const auto& elif : else_ifs) {
1014+
assert (elif.expression);
1015+
elif.expression->visit(v, depth+1);
1016+
assert (elif.branch);
1017+
elif.branch->visit(v, depth+1);
1018+
}
1019+
10041020
if (false_branch) {
10051021
false_branch->visit(v, depth+1);
10061022
}
@@ -4262,6 +4278,48 @@ class parser
42624278
return {};
42634279
}
42644280

4281+
while (
4282+
curr().type() == lexeme::Keyword
4283+
&& curr() == "else"
4284+
&& peek(1) && peek(1)->type() == lexeme::Keyword && peek(1)->to_string(true) == "if"
4285+
) {
4286+
selection_statement_node::else_if elif;
4287+
elif.pos = curr().position();
4288+
next(2); // skip "else if"
4289+
4290+
if (
4291+
curr().type() == lexeme::Keyword
4292+
&& curr() == "constexpr"
4293+
)
4294+
{
4295+
elif.is_constexpr = true;
4296+
next();
4297+
}
4298+
4299+
if (auto e = expression()) {
4300+
elif.expression = std::move(e);
4301+
}
4302+
else {
4303+
error("invalid else if condition", true, {}, true);
4304+
return {};
4305+
}
4306+
4307+
if (curr().type() != lexeme::LeftBrace) {
4308+
error("an if branch body must be enclosed with { }");
4309+
return {};
4310+
}
4311+
4312+
if (auto s = compound_statement()) {
4313+
elif.branch = std::move(s);
4314+
}
4315+
else {
4316+
error("invalid if branch body", true, {}, true);
4317+
return {};
4318+
}
4319+
4320+
n->else_ifs.emplace_back(std::move(elif));
4321+
}
4322+
42654323
if (
42664324
curr().type() != lexeme::Keyword
42674325
|| 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)