Skip to content

Commit

Permalink
libnixf/Parse: parse expr_with
Browse files Browse the repository at this point in the history
  • Loading branch information
inclyc committed Feb 12, 2024
1 parent 8b596ef commit 3ead1fb
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 0 deletions.
1 change: 1 addition & 0 deletions libnixf/include/nixf/Basic/NodeKinds.inc
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,6 @@ EXPR(ExprOpHasAttr)
EXPR(ExprIf)
EXPR(ExprAssert)
EXPR(ExprLet)
EXPR(ExprWith)

#endif // EXPR
17 changes: 17 additions & 0 deletions libnixf/include/nixf/Basic/Nodes/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,4 +153,21 @@ class ExprLet : public Expr {
}
};

class ExprWith : public Expr {
std::unique_ptr<Expr> With;
std::unique_ptr<Expr> E;

public:
ExprWith(LexerCursorRange Range, std::unique_ptr<Expr> With,
std::unique_ptr<Expr> E)
: Expr(NK_ExprWith, Range), With(std::move(With)), E(std::move(E)) {}

[[nodiscard]] Expr *with() const { return With.get(); }
[[nodiscard]] Expr *expr() const { return E.get(); }

[[nodiscard]] ChildVector children() const override {
return {With.get(), E.get()};
}
};

} // namespace nixf
37 changes: 37 additions & 0 deletions libnixf/src/Parse/ParseExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ std::unique_ptr<Expr> Parser::parseExpr() {
case tok_comma: // { a ,
case tok_id: // { a b
case tok_ellipsis: // { a ...
case tok_r_curly:
return parseExprLambda();
default:
break;
Expand All @@ -116,6 +117,8 @@ std::unique_ptr<Expr> Parser::parseExpr() {
if (peek(1).kind() != tok_l_curly)
return parseExprLet();
break;
case tok_kw_with:
return parseExprWith();
default:
break;
}
Expand Down Expand Up @@ -271,4 +274,38 @@ std::unique_ptr<ExprLet> Parser::parseExprLet() {
std::move(In), std::move(E));
}

std::unique_ptr<ExprWith> Parser::parseExprWith() {
LexerCursor LCur = lCur();
Token TokWith = peek();
assert(TokWith.kind() == tok_kw_with && "token should be tok_kw_with");

consume(); // with
assert(LastToken && "LastToken should be set after consume()");

auto SyncSemi = withSync(tok_semi_colon);

auto With = parseExpr();

if (!With)
diagNullExpr(Diags, LastToken->rCur(), "with expression");

ExpectResult ExpSemi = expect(tok_semi_colon);
if (!ExpSemi.ok()) {
ExpSemi.diag().note(Note::NK_ToMachThis, TokWith.range())
<< std::string(tok::spelling(tok_kw_with));
return std::make_unique<ExprWith>(LexerCursorRange{LCur, LastToken->rCur()},
std::move(With), /*E=*/nullptr);
}

consume(); // ;

auto E = parseExpr();

if (!E)
diagNullExpr(Diags, LastToken->rCur(), "with body");

return std::make_unique<ExprWith>(LexerCursorRange{LCur, LastToken->rCur()},
std::move(With), std::move(E));
}

} // namespace nixf
6 changes: 6 additions & 0 deletions libnixf/src/Parse/ParserImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class ExprLambda;
class ExprIf;
class ExprAssert;
class ExprLet;
class ExprWith;

namespace detail {

Expand Down Expand Up @@ -342,6 +343,11 @@ class Parser {
/// \endcode
std::unique_ptr<ExprLet> parseExprLet();

/// \code
/// expr_with : 'with' expr ';' expr
/// \endcode
std::unique_ptr<ExprWith> parseExprWith();

std::unique_ptr<Expr> parse() { return parseExpr(); }
};

Expand Down
27 changes: 27 additions & 0 deletions libnixf/test/Parse/ParseExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,4 +302,31 @@ TEST(Parser, ExprLet_Binds) {
ASSERT_FALSE(static_cast<ExprLet *>(AST.get())->binds());
}

TEST(Parser, ExprWith_Ok) {
auto Src = R"(with 1; 1)"sv;

std::vector<Diagnostic> Diags;
Parser P(Src, Diags);
auto AST = P.parseExpr();

ASSERT_TRUE(AST);
ASSERT_EQ(AST->kind(), Node::NK_ExprWith);

ASSERT_EQ(Diags.size(), 0);
}

TEST(Parser, ExprWith_NoExpr) {
auto Src = R"(with 1;)"sv;

std::vector<Diagnostic> Diags;
Parser P(Src, Diags);
auto AST = P.parseExpr();

ASSERT_TRUE(AST);
ASSERT_EQ(AST->kind(), Node::NK_ExprWith);

ASSERT_EQ(Diags.size(), 1);
ASSERT_EQ(Diags[0].kind(), Diagnostic::DK_Expected);
}

} // namespace

0 comments on commit 3ead1fb

Please sign in to comment.