From c807b89d3bd9c6007e6fa7283e9d6a43f20ecdc8 Mon Sep 17 00:00:00 2001 From: Eyal Kalderon Date: Mon, 14 Oct 2019 03:43:45 +0800 Subject: [PATCH] Deduce found token name in error_expr_if() 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. --- nix-parser/src/parser/expr.rs | 35 ++++++++++++++++++------------ nix-parser/src/parser/expr/bind.rs | 6 ++--- nix-parser/src/parser/expr/func.rs | 6 ++--- nix-parser/src/parser/expr/stmt.rs | 4 ++-- nix-parser/src/parser/expr/util.rs | 20 ++++++++--------- 5 files changed, 37 insertions(+), 34 deletions(-) diff --git a/nix-parser/src/parser/expr.rs b/nix-parser/src/parser/expr.rs index b935711..559872d 100644 --- a/nix-parser/src/parser/expr.rs +++ b/nix-parser/src/parser/expr.rs @@ -37,16 +37,14 @@ fn function(input: Tokens) -> IResult> { } fn if_else(input: Tokens) -> IResult> { - 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, ""), 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))) @@ -56,7 +54,8 @@ fn if_else(input: Tokens) -> IResult> { } fn imply(input: Tokens) -> IResult> { - 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| { @@ -70,7 +69,8 @@ fn imply(input: Tokens) -> IResult> { } fn and(input: Tokens) -> IResult> { - 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| { @@ -84,7 +84,8 @@ fn and(input: Tokens) -> IResult> { } fn or(input: Tokens) -> IResult> { - 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| { @@ -100,7 +101,8 @@ fn or(input: Tokens) -> IResult> { fn equality(input: Tokens) -> IResult> { 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| { @@ -117,7 +119,9 @@ fn compare(input: Tokens) -> IResult> { 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| { @@ -130,7 +134,8 @@ fn compare(input: Tokens) -> IResult> { } fn update(input: Tokens) -> IResult> { - 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| { @@ -146,7 +151,8 @@ fn update(input: Tokens) -> IResult> { fn sum(input: Tokens) -> IResult> { 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| { @@ -162,7 +168,8 @@ fn sum(input: Tokens) -> IResult> { fn product(input: Tokens) -> IResult> { 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| { @@ -217,7 +224,7 @@ fn project(input: Tokens) -> IResult> { let (input, atomic) = atomic(input)?; if let Ok((remaining, _)) = tokens::dot(input) { - let default = alt((project, error, util::error_expr_if(tokens::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)?; diff --git a/nix-parser/src/parser/expr/bind.rs b/nix-parser/src/parser/expr/bind.rs index 5d67642..1b90481 100644 --- a/nix-parser/src/parser/expr/bind.rs +++ b/nix-parser/src/parser/expr/bind.rs @@ -32,11 +32,9 @@ pub fn bind(input: Tokens) -> IResult> { } fn simple(input: Tokens) -> IResult> { - 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) @@ -51,7 +49,7 @@ fn inherit(input: Tokens) -> IResult> { fn inherit_expr(input: Tokens) -> IResult> { 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)| { diff --git a/nix-parser/src/parser/expr/func.rs b/nix-parser/src/parser/expr/func.rs index 5bfe68d..d5c424d 100644 --- a/nix-parser/src/parser/expr/func.rs +++ b/nix-parser/src/parser/expr/func.rs @@ -23,7 +23,7 @@ pub fn fn_decl(input: Tokens) -> IResult> { } fn simple(input: Tokens) -> IResult> { - let expr = alt((expr, util::error_expr_if(tokens::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) @@ -31,7 +31,7 @@ fn simple(input: Tokens) -> IResult> { } fn formals(input: Tokens) -> IResult> { - 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(); @@ -43,7 +43,7 @@ fn formals(input: Tokens) -> IResult> { 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, ""))); + 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) diff --git a/nix-parser/src/parser/expr/stmt.rs b/nix-parser/src/parser/expr/stmt.rs index 892b983..9556111 100644 --- a/nix-parser/src/parser/expr/stmt.rs +++ b/nix-parser/src/parser/expr/stmt.rs @@ -11,7 +11,7 @@ use crate::parser::{tokens, IResult}; pub fn with(input: Tokens) -> IResult> { 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) @@ -19,7 +19,7 @@ pub fn with(input: Tokens) -> IResult> { pub fn assert(input: Tokens) -> IResult> { 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) diff --git a/nix-parser/src/parser/expr/util.rs b/nix-parser/src/parser/expr/util.rs index 4cc991b..87bb1cf 100644 --- a/nix-parser/src/parser/expr/util.rs +++ b/nix-parser/src/parser/expr/util.rs @@ -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}; @@ -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> +pub fn error_expr_if<'a, F>(token: F) -> impl Fn(Tokens<'a>) -> IResult> where - F: Fn(Tokens<'a>) -> IResult, - O: ToSpan, + F: Fn(Tokens<'a>) -> IResult, { - 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)) }