Skip to content

Commit

Permalink
Add parser support for question mark operator
Browse files Browse the repository at this point in the history
The benchmark results below indicate that this addition does not regress
performance, likely thanks in part to commit c913d3f:

```
parse_example/parse example.nix
                        time:   [304.64 us 306.29 us 308.22 us]
                        thrpt:  [1.5502 MiB/s 1.5599 MiB/s 1.5684 MiB/s]
                 change:
                        time:   [-4.5555% -0.1801% +4.1732%] (p = 0.94 > 0.05)
                        thrpt:  [-4.0060% +0.1804% +4.7729%]
                        No change in performance detected.
Found 10 outliers among 100 measurements (10.00%)
  3 (3.00%) high mild
  7 (7.00%) high severe
```
  • Loading branch information
ebkalderon committed Oct 20, 2019
1 parent 116009e commit e1711bd
Showing 1 changed file with 15 additions and 1 deletion.
16 changes: 15 additions & 1 deletion nix-parser/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ fn product(input: Tokens) -> IResult<Partial<Expr>> {
}

fn concat(input: Tokens) -> IResult<Partial<Expr>> {
let expr = pair(unary, many0(preceded(tokens::op_concat, unary)));
let expr = pair(has_attr, many0(preceded(tokens::op_concat, has_attr)));
map(expr, |(first, rest)| {
let exprs = Partial::from_iter(iter::once(first).chain(rest));
exprs.map(|mut exprs| {
Expand All @@ -196,6 +196,20 @@ fn concat(input: Tokens) -> IResult<Partial<Expr>> {
})(input)
}

fn has_attr(input: Tokens) -> IResult<Partial<Expr>> {
let rhs = alt((unary, util::error_expr_if(tokens::eof)));
let expr = pair(unary, opt(preceded(tokens::op_question, rhs)));
map(expr, |(lhs, rhs)| match rhs {
None => lhs,
Some(rhs) => lhs.flat_map(|lhs| {
rhs.map(|rhs| {
let span = Span::merge(lhs.span(), rhs.span());
Expr::from(ExprBinary::new(BinaryOp::HasAttr, lhs, rhs, span))
})
}),
})(input)
}

fn unary(input: Tokens) -> IResult<Partial<Expr>> {
let neg = map(tokens::op_sub, |_| UnaryOp::Neg);
let not = map(tokens::op_not, |_| UnaryOp::Not);
Expand Down

0 comments on commit e1711bd

Please sign in to comment.