Skip to content

Commit

Permalink
Deduce found token name in error_expr_if()
Browse files Browse the repository at this point in the history
This changes `nix_parser::parser::util::error_expr_if()` to use
`nom::combinator::recognize()` to figure out the token name instead of
passing in an explicit message.
  • Loading branch information
ebkalderon committed Oct 13, 2019
1 parent cb32a4a commit c807b89
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 34 deletions.
35 changes: 21 additions & 14 deletions nix-parser/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,14 @@ fn function(input: Tokens) -> IResult<Partial<Expr>> {
}

fn if_else(input: Tokens) -> IResult<Partial<Expr>> {
let found = "keyword `then`";
let cond = alt((util::error_expr_if(tokens::keyword_then, found), expr));
let cond = alt((util::error_expr_if(tokens::keyword_then), expr));
let cond_then = expect_terminated(cond, tokens::keyword_then);
let if_cond_then = preceded(tokens::keyword_if, cond_then);

let found = "keyword `else`";
let body = alt((util::error_expr_if(tokens::keyword_else, found), expr));
let body = alt((util::error_expr_if(tokens::keyword_else), expr));
let body_else = expect_terminated(body, tokens::keyword_else);

let expr = alt((util::error_expr_if(tokens::eof, "<eof>"), expr));
let expr = alt((util::error_expr_if(tokens::eof), expr));
let block = pair_partial(if_cond_then, pair_partial(body_else, expr));
let if_else = map_partial_spanned(block, |span, (cond, (body, fallback))| {
Expr::If(Box::new(ExprIf::new(cond, body, fallback, span)))
Expand All @@ -56,7 +54,8 @@ fn if_else(input: Tokens) -> IResult<Partial<Expr>> {
}

fn imply(input: Tokens) -> IResult<Partial<Expr>> {
let expr = pair(and, many0(preceded(tokens::op_imply, and)));
let rhs = alt((and, util::error_expr_if(tokens::eof)));
let expr = pair(and, many0(preceded(tokens::op_imply, rhs)));
map(expr, |(first, rest)| {
rest.into_iter().fold(first, |lhs, rhs| {
lhs.flat_map(|lhs| {
Expand All @@ -70,7 +69,8 @@ fn imply(input: Tokens) -> IResult<Partial<Expr>> {
}

fn and(input: Tokens) -> IResult<Partial<Expr>> {
let expr = pair(or, many0(preceded(tokens::op_and, or)));
let rhs = alt((or, util::error_expr_if(tokens::eof)));
let expr = pair(or, many0(preceded(tokens::op_and, rhs)));
map(expr, |(first, rest)| {
rest.into_iter().fold(first, |lhs, rhs| {
lhs.flat_map(|lhs| {
Expand All @@ -84,7 +84,8 @@ fn and(input: Tokens) -> IResult<Partial<Expr>> {
}

fn or(input: Tokens) -> IResult<Partial<Expr>> {
let expr = pair(equality, many0(preceded(tokens::op_or, equality)));
let rhs = alt((equality, util::error_expr_if(tokens::eof)));
let expr = pair(equality, many0(preceded(tokens::op_or, rhs)));
map(expr, |(first, rest)| {
rest.into_iter().fold(first, |lhs, rhs| {
lhs.flat_map(|lhs| {
Expand All @@ -100,7 +101,8 @@ fn or(input: Tokens) -> IResult<Partial<Expr>> {
fn equality(input: Tokens) -> IResult<Partial<Expr>> {
let eq = map(tokens::op_eq, |_| BinaryOp::Eq);
let neq = map(tokens::op_neq, |_| BinaryOp::NotEq);
let expr = pair(compare, opt(pair(alt((eq, neq)), compare)));
let rhs = alt((compare, util::error_expr_if(tokens::eof)));
let expr = pair(compare, opt(pair(alt((eq, neq)), rhs)));
map(expr, |(lhs, op)| match op {
None => lhs,
Some((op, rhs)) => lhs.flat_map(|lhs| {
Expand All @@ -117,7 +119,9 @@ fn compare(input: Tokens) -> IResult<Partial<Expr>> {
let lt = map(tokens::op_lt, |_| BinaryOp::LessThan);
let gte = map(tokens::op_gte, |_| BinaryOp::GreaterThanEq);
let gt = map(tokens::op_gt, |_| BinaryOp::GreaterThan);
let expr = pair(update, opt(pair(alt((lte, lt, gte, gt)), update)));

let rhs = alt((update, util::error_expr_if(tokens::eof)));
let expr = pair(update, opt(pair(alt((lte, lt, gte, gt)), rhs)));
map(expr, |(lhs, op)| match op {
None => lhs,
Some((op, rhs)) => lhs.flat_map(|lhs| {
Expand All @@ -130,7 +134,8 @@ fn compare(input: Tokens) -> IResult<Partial<Expr>> {
}

fn update(input: Tokens) -> IResult<Partial<Expr>> {
let expr = pair(sum, many0(preceded(tokens::op_update, sum)));
let rhs = alt((sum, util::error_expr_if(tokens::eof)));
let expr = pair(sum, many0(preceded(tokens::op_update, rhs)));
map(expr, |(first, rest)| {
let exprs = Partial::from_iter(iter::once(first).chain(rest));
exprs.map(|mut exprs| {
Expand All @@ -146,7 +151,8 @@ fn update(input: Tokens) -> IResult<Partial<Expr>> {
fn sum(input: Tokens) -> IResult<Partial<Expr>> {
let add = map(tokens::op_add, |_| BinaryOp::Add);
let sub = map(tokens::op_sub, |_| BinaryOp::Sub);
let expr = pair(product, many0(pair(alt((add, sub)), product)));
let rhs = alt((product, util::error_expr_if(tokens::eof)));
let expr = pair(product, many0(pair(alt((add, sub)), rhs)));
map(expr, |(first, rest)| {
rest.into_iter().fold(first, |lhs, (op, rhs)| {
lhs.flat_map(|lhs| {
Expand All @@ -162,7 +168,8 @@ fn sum(input: Tokens) -> IResult<Partial<Expr>> {
fn product(input: Tokens) -> IResult<Partial<Expr>> {
let mul = map(tokens::op_mul, |_| BinaryOp::Mul);
let div = map(tokens::op_div, |_| BinaryOp::Div);
let expr = pair(concat, many0(pair(alt((mul, div)), concat)));
let rhs = alt((concat, util::error_expr_if(tokens::eof)));
let expr = pair(concat, many0(pair(alt((mul, div)), rhs)));
map(expr, |(first, rest)| {
rest.into_iter().fold(first, |lhs, (op, rhs)| {
lhs.flat_map(|lhs| {
Expand Down Expand Up @@ -217,7 +224,7 @@ fn project(input: Tokens) -> IResult<Partial<Expr>> {
let (input, atomic) = atomic(input)?;

if let Ok((remaining, _)) = tokens::dot(input) {
let default = alt((project, error, util::error_expr_if(tokens::eof, "<eof>")));
let default = alt((project, error, util::error_expr_if(tokens::eof)));
let or_default = opt_partial(preceded(tokens::keyword_or, default));

let (remaining, path) = pair_partial(attr::attr_path, or_default)(remaining)?;
Expand Down
6 changes: 2 additions & 4 deletions nix-parser/src/parser/expr/bind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,9 @@ pub fn bind(input: Tokens) -> IResult<Partial<Bind>> {
}

fn simple(input: Tokens) -> IResult<Partial<BindSimple>> {
let found = "one of `;` or `}`";
let error = util::error_expr_if(alt((tokens::semi, tokens::brace_right)), found);
let error = util::error_expr_if(alt((tokens::semi, tokens::brace_right)));
let lhs = expect_terminated(attr::attr_path, tokens::eq);
let bind = pair_partial(final_comment, pair_partial(lhs, alt((expr, error))));

map_partial(bind, move |(comment, (attr, expr))| {
let span = Span::merge(attr.span(), expr.span());
BindSimple::new(comment, attr, expr, span)
Expand All @@ -51,7 +49,7 @@ fn inherit(input: Tokens) -> IResult<Partial<BindInherit>> {

fn inherit_expr(input: Tokens) -> IResult<Partial<BindInheritExpr>> {
let keyword_inherit = pair(many0(tokens::comment), tokens::keyword_inherit);
let inner = alt((expr, util::error_expr_if(tokens::paren_right, "`}`")));
let inner = alt((expr, util::error_expr_if(tokens::paren_right)));
let expr = expect_terminated(preceded(tokens::paren_left, inner), tokens::paren_right);
let bind = preceded(keyword_inherit, pair_partial(expr, ident_sequence));
map_partial_spanned(bind, |span, (expr, idents)| {
Expand Down
6 changes: 3 additions & 3 deletions nix-parser/src/parser/expr/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ pub fn fn_decl(input: Tokens) -> IResult<Partial<ExprFnDecl>> {
}

fn simple(input: Tokens) -> IResult<Partial<FnDeclSimple>> {
let expr = alt((expr, util::error_expr_if(tokens::eof, "<eof>")));
let expr = alt((expr, util::error_expr_if(tokens::eof)));
map_partial(pair_partial(identifier_arg, expr), |(ident, body)| {
let span = Span::merge(ident.span(), body.span());
FnDeclSimple::new(ident, body, span)
})(input)
}

fn formals(input: Tokens) -> IResult<Partial<FnDeclFormals>> {
let value = alt((expr, util::error_expr_if(tokens::comma, "comma")));
let value = alt((expr, util::error_expr_if(tokens::comma)));
let default = opt(preceded(tokens::op_question, verify_full(value)));
let formal = map(pair(tokens::identifier, default), |(name, def)| {
let name_span = name.span();
Expand All @@ -43,7 +43,7 @@ fn formals(input: Tokens) -> IResult<Partial<FnDeclFormals>> {
let term = pair(tokens::brace_right, tokens::colon);
let formals = delimited(tokens::brace_left, args, term);

let expr = alt((expr, util::error_expr_if(tokens::eof, "<eof>")));
let expr = alt((expr, util::error_expr_if(tokens::eof)));
map_partial_spanned(pair_partial(formals, expr), |span, (formals, expr)| {
FnDeclFormals::new(formals, None, None, expr, span)
})(input)
Expand Down
4 changes: 2 additions & 2 deletions nix-parser/src/parser/expr/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ use crate::parser::{tokens, IResult};

pub fn with(input: Tokens) -> IResult<Partial<ExprWith>> {
let delims = alt((tokens::semi, tokens::eof));
let scope = alt((expr, util::error_expr_if(delims, "semicolon")));
let scope = alt((expr, util::error_expr_if(delims)));
let with = expect_terminated(preceded(tokens::keyword_with, expr), tokens::semi);
let stmt = pair_partial(with, scope);
map_partial_spanned(stmt, |span, (with, body)| ExprWith::new(with, body, span))(input)
}

pub fn assert(input: Tokens) -> IResult<Partial<ExprAssert>> {
let delims = alt((tokens::semi, tokens::eof));
let cond = alt((expr, util::error_expr_if(delims, "semicolon")));
let cond = alt((expr, util::error_expr_if(delims)));
let assert = expect_terminated(preceded(tokens::keyword_assert, cond), tokens::semi);
let stmt = pair_partial(assert, expr);
map_partial_spanned(stmt, |span, (cond, body)| ExprAssert::new(cond, body, span))(input)
Expand Down
20 changes: 9 additions & 11 deletions nix-parser/src/parser/expr/util.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use nom::combinator::peek;
use codespan::Span;
use nom::combinator::{peek, recognize};

use crate::ast::Expr;
use crate::error::{Errors, ExpectedFoundError};
Expand All @@ -7,20 +8,17 @@ use crate::parser::partial::Partial;
use crate::parser::IResult;
use crate::ToSpan;

pub fn error_expr_if<'a, O, F>(
parser: F,
found: &'a str,
) -> impl Fn(Tokens<'a>) -> IResult<Partial<Expr>>
pub fn error_expr_if<'a, F>(token: F) -> impl Fn(Tokens<'a>) -> IResult<Partial<Expr>>
where
F: Fn(Tokens<'a>) -> IResult<O>,
O: ToSpan,
F: Fn(Tokens<'a>) -> IResult<Span>,
{
move |input| match peek(&parser)(input) {
move |input| match peek(recognize(&token))(input) {
Err(error) => Err(error),
Ok((remaining, token)) => {
let span = token.to_span();
Ok((remaining, tokens)) => {
let desc = tokens.current().description();
let span = tokens.current().to_span();
let mut errors = Errors::new();
errors.push(ExpectedFoundError::new("expression", found, span));
errors.push(ExpectedFoundError::new("expression", desc, span));
let expr = Partial::with_errors(Some(Expr::Error(span)), errors);
Ok((remaining, expr))
}
Expand Down

0 comments on commit c807b89

Please sign in to comment.