Skip to content

Commit aa04ee8

Browse files
committed
libnixf: parse pipe operator
Implements: NixOS/rfcs#148 Closes: #554
1 parent 28a4190 commit aa04ee8

File tree

4 files changed

+82
-10
lines changed

4 files changed

+82
-10
lines changed

libnixf/include/nixf/Basic/TokenKinds.inc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,8 @@ TOK_BIN_OP(mul) // *
9393
TOK_BIN_OP(div) // /
9494
TOK_BIN_OP(concat) // ++
9595

96+
// [RFC 0418 Pipe operator](https://github.com/NixOS/rfcs/pull/148)
97+
TOK_BIN_OP(pipe_into) // |>
98+
TOK_BIN_OP(pipe_from) // <|
99+
96100
#endif // TOK_BIN_OP

libnixf/src/Parse/Lexer.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,8 @@ Token Lexer::lex() {
526526
case '|':
527527
if (consumePrefix("||"))
528528
Tok = tok_op_or;
529+
if (consumePrefix("|>"))
530+
Tok = tok_op_pipe_into;
529531
break;
530532
case '!':
531533
if (consumePrefix("!=")) {
@@ -538,6 +540,8 @@ Token Lexer::lex() {
538540
case '<':
539541
if (consumePrefix("<=")) {
540542
Tok = tok_op_le;
543+
} else if (consumePrefix("<|")) {
544+
Tok = tok_op_pipe_from;
541545
} else {
542546
consume();
543547
Tok = tok_op_lt;

libnixf/src/Parse/ParseOp.cpp

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ namespace {
1616

1717
/// Binary operators:
1818
///
19+
/// %left |> | %right <|
1920
/// %right ->
2021
/// %left ||
2122
/// %left &&
@@ -30,31 +31,35 @@ namespace {
3031
/// %nonassoc NEGATE
3132
std::pair<unsigned, unsigned> getBP(TokenKind Kind) {
3233
switch (Kind) {
34+
case tok_op_pipe_from:
35+
return {0, 1};
36+
case tok_op_pipe_into:
37+
return {1, 0};
3338
case tok_op_impl: // %right ->
34-
return {2, 1};
39+
return {3, 2};
3540
case tok_op_or: // %left ||
36-
return {3, 4};
41+
return {4, 5};
3742
case tok_op_and: // %left &&
38-
return {5, 6};
43+
return {6, 7};
3944
case tok_op_eq: // %nonassoc == !=
4045
case tok_op_neq:
41-
return {7, 7};
46+
return {8, 8};
4247
case tok_op_lt: // %nonassoc < > <= >=
4348
case tok_op_le:
4449
case tok_op_ge:
4550
case tok_op_gt:
46-
return {8, 8};
51+
return {9, 9};
4752
case tok_op_update: // %right //
48-
return {10, 9};
49-
// %left NOT - 11
53+
return {11, 10};
54+
// %left NOT - 12
5055
case tok_op_add: // %left + -
5156
case tok_op_negate:
52-
return {12, 13};
57+
return {13, 14};
5358
case tok_op_mul: // %left * /
54-
return {14, 15};
59+
return {15, 16};
5560
case tok_op_div:
5661
case tok_op_concat: // %right ++
57-
return {17, 16};
62+
return {18, 17};
5863
// % op_negate
5964
default:
6065
__builtin_unreachable();

libnixf/test/Parse/ParseOp.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,63 @@ TEST(Parser, OpHasAttr_empty) {
7171
ASSERT_EQ(Diags.size(), 0);
7272
}
7373

74+
TEST(Parser, Op_PipeOperator_Forward) {
75+
auto Src = R"(a |> b)"sv;
76+
77+
std::vector<Diagnostic> Diags;
78+
Parser P(Src, Diags);
79+
auto AST = P.parseExpr();
80+
81+
ASSERT_TRUE(AST);
82+
83+
ASSERT_EQ(AST->kind(), Node::NK_ExprBinOp);
84+
ASSERT_EQ(Diags.size(), 0);
85+
}
86+
87+
TEST(Parser, Op_PipeOperator_Forward_LeftAssosiative) {
88+
auto Src = R"(a |> b |> c)"sv;
89+
90+
std::vector<Diagnostic> Diags;
91+
Parser P(Src, Diags);
92+
auto AST = P.parseExpr();
93+
94+
ASSERT_TRUE(AST);
95+
96+
ASSERT_EQ(AST->kind(), Node::NK_ExprBinOp);
97+
98+
const auto &BinOp = static_cast<const ExprBinOp &>(*AST);
99+
ASSERT_EQ(BinOp.lhs()->kind(), Node::NK_ExprVar);
100+
ASSERT_EQ(Diags.size(), 0);
101+
}
102+
103+
TEST(Parser, Op_PipeOperator_Backward) {
104+
auto Src = R"(a <| b)"sv;
105+
106+
std::vector<Diagnostic> Diags;
107+
Parser P(Src, Diags);
108+
auto AST = P.parseExpr();
109+
110+
ASSERT_TRUE(AST);
111+
112+
ASSERT_EQ(AST->kind(), Node::NK_ExprBinOp);
113+
ASSERT_EQ(Diags.size(), 0);
114+
}
115+
116+
TEST(Parser, Op_PipeOperator_Forward_RightAssosiative) {
117+
auto Src = R"(a <| b <| c)"sv;
118+
119+
std::vector<Diagnostic> Diags;
120+
Parser P(Src, Diags);
121+
auto AST = P.parseExpr();
122+
123+
ASSERT_TRUE(AST);
124+
125+
ASSERT_EQ(AST->kind(), Node::NK_ExprBinOp);
126+
127+
const auto &BinOp = static_cast<const ExprBinOp &>(*AST);
128+
ASSERT_EQ(BinOp.lhs()->kind(), Node::NK_ExprBinOp);
129+
ASSERT_EQ(BinOp.rhs()->kind(), Node::NK_ExprVar);
130+
ASSERT_EQ(Diags.size(), 0);
131+
}
132+
74133
} // namespace

0 commit comments

Comments
 (0)