Skip to content

Commit 36e841d

Browse files
committed
libnixf: parse pipe operator
Implements: NixOS/rfcs#148 Closes: #554
1 parent f9d141f commit 36e841d

File tree

4 files changed

+97
-10
lines changed

4 files changed

+97
-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
@@ -17,6 +17,7 @@ namespace {
1717

1818
/// Binary operators:
1919
///
20+
/// %left |> | %right <|
2021
/// %right ->
2122
/// %left ||
2223
/// %left &&
@@ -31,31 +32,35 @@ namespace {
3132
/// %nonassoc NEGATE
3233
std::pair<unsigned, unsigned> getBP(TokenKind Kind) {
3334
switch (Kind) {
34-
case tok_op_impl: // %right ->
35+
case tok_op_pipe_from:
36+
return {1, 2};
37+
case tok_op_pipe_into:
3538
return {2, 1};
39+
case tok_op_impl: // %right ->
40+
return {4, 3};
3641
case tok_op_or: // %left ||
37-
return {3, 4};
38-
case tok_op_and: // %left &&
3942
return {5, 6};
43+
case tok_op_and: // %left &&
44+
return {7, 8};
4045
case tok_op_eq: // %nonassoc == !=
4146
case tok_op_neq:
42-
return {7, 7};
47+
return {9, 9};
4348
case tok_op_lt: // %nonassoc < > <= >=
4449
case tok_op_le:
4550
case tok_op_ge:
4651
case tok_op_gt:
47-
return {8, 8};
52+
return {10, 10};
4853
case tok_op_update: // %right //
49-
return {10, 9};
50-
// %left NOT - 11
54+
return {12, 11};
55+
// %left NOT - 13
5156
case tok_op_add: // %left + -
5257
case tok_op_negate:
53-
return {12, 13};
54-
case tok_op_mul: // %left * /
5558
return {14, 15};
59+
case tok_op_mul: // %left * /
60+
return {16, 17};
5661
case tok_op_div:
5762
case tok_op_concat: // %right ++
58-
return {17, 16};
63+
return {19, 18};
5964
// % op_negate
6065
default:
6166
__builtin_unreachable();

libnixf/test/Parse/ParseOp.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,78 @@ TEST(Parser, Op_NonAssociative) {
8484
ASSERT_EQ(Diags[0].kind(), Diagnostic::DK_OperatorNotAssociative);
8585
}
8686

87+
TEST(Parser, Op_PipeOperator_Forward) {
88+
auto Src = R"(a |> b)"sv;
89+
90+
std::vector<Diagnostic> Diags;
91+
Parser P(Src, Diags);
92+
auto AST = P.parseExpr();
93+
94+
95+
ASSERT_EQ(AST->kind(), Node::NK_ExprBinOp);
96+
ASSERT_EQ(Diags.size(), 0);
97+
}
98+
99+
100+
TEST(Parser, Op_PipeOperator_Forward_LeftAssosiative) {
101+
auto Src = R"(a |> b |> c)"sv;
102+
103+
std::vector<Diagnostic> Diags;
104+
Parser P(Src, Diags);
105+
auto AST = P.parseExpr();
106+
107+
ASSERT_TRUE(AST);
108+
109+
ASSERT_EQ(AST->kind(), Node::NK_ExprBinOp);
110+
111+
const auto &BinOp = static_cast<const ExprBinOp &>(*AST);
112+
ASSERT_EQ(BinOp.lhs()->kind(), Node::NK_ExprVar);
113+
ASSERT_EQ(Diags.size(), 0);
114+
}
115+
116+
TEST(Parser, Op_PipeOperator_Backward) {
117+
auto Src = R"(a <| b)"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+
ASSERT_EQ(Diags.size(), 0);
127+
}
128+
129+
TEST(Parser, Op_PipeOperator_Forward_RightAssosiative) {
130+
auto Src = R"(a <| b <| c)"sv;
131+
132+
std::vector<Diagnostic> Diags;
133+
Parser P(Src, Diags);
134+
auto AST = P.parseExpr();
135+
136+
ASSERT_TRUE(AST);
137+
138+
ASSERT_EQ(AST->kind(), Node::NK_ExprBinOp);
139+
140+
const auto &BinOp = static_cast<const ExprBinOp &>(*AST);
141+
ASSERT_EQ(BinOp.lhs()->kind(), Node::NK_ExprBinOp);
142+
ASSERT_EQ(BinOp.rhs()->kind(), Node::NK_ExprVar);
143+
ASSERT_EQ(Diags.size(), 0);
144+
}
145+
146+
TEST(Parser, Op_PipeOperator_NonAssociative) {
147+
auto Src = R"(a <| b |> c)"sv;
148+
149+
std::vector<Diagnostic> Diags;
150+
Parser P(Src, Diags);
151+
auto AST = P.parseExpr();
152+
153+
ASSERT_TRUE(AST);
154+
155+
ASSERT_EQ(AST->kind(), Node::NK_ExprBinOp);
156+
157+
ASSERT_EQ(Diags.size(), 1);
158+
ASSERT_EQ(Diags[0].kind(), nixf::Diagnostic::DK_OperatorNotAssociative);
159+
}
160+
87161
} // namespace

0 commit comments

Comments
 (0)