Skip to content

Commit 020fe8d

Browse files
committed
Added support for the experimental pipe operators
1 parent 01e6582 commit 020fe8d

File tree

8 files changed

+106
-4
lines changed

8 files changed

+106
-4
lines changed

Diff for: Cargo.lock

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ license = "MIT"
66
name = "rnix"
77
readme = "README.md"
88
repository = "https://github.com/nix-community/rnix-parser"
9-
version = "0.11.0"
9+
version = "0.11.1"
1010

1111
[[bench]]
1212
harness = false

Diff for: src/ast/operators.rs

+5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ pub enum BinOpKind {
1919
MoreOrEq,
2020
NotEqual,
2121
Or,
22+
PipeRight,
23+
PipeLeft,
2224
}
2325

2426
impl BinOpKind {
@@ -43,6 +45,9 @@ impl BinOpKind {
4345
TOKEN_NOT_EQUAL => Some(BinOpKind::NotEqual),
4446
TOKEN_OR_OR => Some(BinOpKind::Or),
4547

48+
TOKEN_PIPE_RIGHT => Some(BinOpKind::PipeRight),
49+
TOKEN_PIPE_LEFT => Some(BinOpKind::PipeLeft),
50+
4651
_ => None,
4752
}
4853
}

Diff for: src/ast/tokens.rs

+82
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,88 @@ mod tests {
6666
use super::*;
6767
use rowan::ast::AstNode;
6868

69+
#[test]
70+
fn pipe_right() {
71+
let s = "1 |> toString";
72+
73+
let parsed = Root::parse(s).ok();
74+
assert!(parsed.is_ok(), "Failed to parse syntax `{s}`: {:?}", parsed);
75+
let parsed = parsed.unwrap();
76+
77+
let nodes: Vec<_> = parsed.syntax().children().collect();
78+
assert_eq!(nodes.len(), 1);
79+
assert_eq!(nodes[0].kind(), NODE_BIN_OP);
80+
81+
let op_children: Vec<_> = nodes[0].children().collect();
82+
assert_eq!(op_children.len(), 2);
83+
assert_eq!(op_children[0].kind(), NODE_LITERAL);
84+
assert_eq!(op_children[1].kind(), NODE_IDENT);
85+
}
86+
87+
#[test]
88+
fn pipe_right_precedence() {
89+
let s = "toString <| 1 + 1";
90+
91+
let parsed = Root::parse(s).ok();
92+
assert!(parsed.is_ok(), "Failed to parse syntax `{s}`: {:?}", parsed);
93+
let parsed = parsed.unwrap();
94+
95+
let nodes: Vec<_> = parsed.syntax().children().collect();
96+
assert_eq!(nodes.len(), 1);
97+
assert_eq!(nodes[0].kind(), NODE_BIN_OP);
98+
99+
let op_children: Vec<_> = nodes[0].children().collect();
100+
assert_eq!(op_children.len(), 2);
101+
assert_eq!(op_children[0].kind(), NODE_BIN_OP);
102+
assert_eq!(op_children[1].kind(), NODE_LITERAL);
103+
104+
let op_children: Vec<_> = op_children[0].children().collect();
105+
assert_eq!(op_children.len(), 2);
106+
assert_eq!(op_children[0].kind(), NODE_IDENT);
107+
assert_eq!(op_children[1].kind(), NODE_LITERAL);
108+
}
109+
110+
#[test]
111+
fn pipe_left() {
112+
let s = "toString <| 1";
113+
114+
let parsed = Root::parse(s).ok();
115+
assert!(parsed.is_ok(), "Failed to parse syntax `{s}`: {:?}", parsed);
116+
let parsed = parsed.unwrap();
117+
118+
let nodes: Vec<_> = parsed.syntax().children().collect();
119+
assert_eq!(nodes.len(), 1);
120+
assert_eq!(nodes[0].kind(), NODE_BIN_OP);
121+
122+
let op_children: Vec<_> = nodes[0].children().collect();
123+
assert_eq!(op_children.len(), 2);
124+
assert_eq!(op_children[0].kind(), NODE_IDENT);
125+
assert_eq!(op_children[1].kind(), NODE_LITERAL);
126+
}
127+
128+
#[test]
129+
fn pipe_left_precedence() {
130+
let s = "1 + 1 |> toString";
131+
132+
let parsed = Root::parse(s).ok();
133+
assert!(parsed.is_ok(), "Failed to parse syntax `{s}`: {:?}", parsed);
134+
let parsed = parsed.unwrap();
135+
136+
let nodes: Vec<_> = parsed.syntax().children().collect();
137+
assert_eq!(nodes.len(), 1);
138+
assert_eq!(nodes[0].kind(), NODE_BIN_OP);
139+
140+
let op_children: Vec<_> = nodes[0].children().collect();
141+
assert_eq!(op_children.len(), 2);
142+
assert_eq!(op_children[0].kind(), NODE_LITERAL);
143+
assert_eq!(op_children[1].kind(), NODE_BIN_OP);
144+
145+
let op_children: Vec<_> = op_children[1].children().collect();
146+
assert_eq!(op_children.len(), 2);
147+
assert_eq!(op_children[0].kind(), NODE_LITERAL);
148+
assert_eq!(op_children[1].kind(), NODE_IDENT);
149+
}
150+
69151
#[test]
70152
fn comment() {
71153
let s = "# comment bruh

Diff for: src/kinds.rs

+2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ pub enum SyntaxKind {
5454
TOKEN_MORE_OR_EQ,
5555
TOKEN_NOT_EQUAL,
5656
TOKEN_OR_OR,
57+
TOKEN_PIPE_RIGHT,
58+
TOKEN_PIPE_LEFT,
5759

5860
// Identifiers and values
5961
TOKEN_FLOAT,

Diff for: src/macros.rs

+2
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,7 @@ macro_rules! T {
4545
(>=) => ($crate::SyntaxKind::TOKEN_MORE_OR_EQ);
4646
(!=) => ($crate::SyntaxKind::TOKEN_NOT_EQUAL);
4747
(||) => ($crate::SyntaxKind::TOKEN_OR_OR);
48+
("|>") => ($crate::SyntaxKind::TOKEN_PIPE_RIGHT);
49+
("<|") => ($crate::SyntaxKind::TOKEN_PIPE_LEFT);
4850
($kind:ident) => ($crate::SyntaxKind::$kind);
4951
}

Diff for: src/parser.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -583,8 +583,11 @@ where
583583

584584
checkpoint
585585
}
586+
fn parse_pipe(&mut self) -> Checkpoint {
587+
self.parse_left_assoc(Self::parse_simple, T!["|>"] | T!["<|"])
588+
}
586589
fn parse_fn(&mut self) -> Checkpoint {
587-
let checkpoint = self.parse_simple();
590+
let checkpoint = self.parse_pipe();
588591

589592
while self.peek().map(|t| t.is_fn_arg()).unwrap_or(false) {
590593
self.start_node_at(checkpoint, NODE_APPLY);

Diff for: src/tokenizer.rs

+8
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,10 @@ impl Tokenizer<'_> {
364364
'-' => TOKEN_SUB,
365365
'*' => TOKEN_MUL,
366366
'/' => TOKEN_DIV,
367+
'<' if self.peek() == Some('|') => {
368+
self.next().unwrap();
369+
TOKEN_PIPE_LEFT
370+
}
367371
'<' if kind == Some(IdentType::Store) => {
368372
self.consume(is_valid_path_char);
369373
if self.next() != Some('>') {
@@ -376,6 +380,10 @@ impl Tokenizer<'_> {
376380
self.next().unwrap();
377381
TOKEN_AND_AND
378382
}
383+
'|' if self.peek() == Some('>') => {
384+
self.next().unwrap();
385+
TOKEN_PIPE_RIGHT
386+
}
379387
'|' if self.peek() == Some('|') => {
380388
self.next().unwrap();
381389
TOKEN_OR_OR

0 commit comments

Comments
 (0)