From b6c2a08c8f3491bdb3dbde0a86fbd268c6ca2a75 Mon Sep 17 00:00:00 2001 From: Jeremy Wall Date: Tue, 22 Jan 2019 20:51:25 -0600 Subject: [PATCH] FEATURE: Better parsing errors. More specific reports about what is wrong when we know the correct next tokens to expect. --- src/parse/mod.rs | 42 +++++++++++++++++++---------------------- src/parse/precedence.rs | 8 +++++++- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/parse/mod.rs b/src/parse/mod.rs index 2add3aa..08bc57d 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -237,7 +237,7 @@ make_fn!( _ => punct!("{"), v => optional!(field_list), _ => optional!(punct!(",")), - _ => punct!("}"), + _ => must!(punct!("}")), (vec_to_tuple(pos, v)) ) ); @@ -255,7 +255,7 @@ make_fn!( start => punct!("["), elements => optional!(separated!(punct!(","), expression)), _ => optional!(punct!(",")), - _ => punct!("]"), + _ => must!(punct!("]")), (tuple_to_list(start.pos, elements)) ) ); @@ -309,7 +309,7 @@ make_fn!( _ => punct!("("), expr => do_each!( expr => trace_parse!(expression), - _ => punct!(")"), + _ => must!(punct!(")")), (expr) ), (expression_to_grouped_expression(expr)) @@ -332,12 +332,11 @@ fn tuple_to_copy(sym: Value, fields: Option) -> Expression { make_fn!( copy_expression, Expression>, do_each!( - // TODO This should become just a bareword symbol now sym => trace_parse!(symbol), _ => punct!("{"), fields => optional!(trace_parse!(field_list)), - _ => optional!(punct!(",")), // noms opt! macro does not preserve error types properly but this one does. - _ => punct!("}"), + _ => optional!(punct!(",")), + _ => must!(punct!("}")), (tuple_to_copy(sym, fields)) ) ); @@ -452,16 +451,16 @@ fn select_expression(input: SliceIter) -> Result, Expres let parsed = do_each!(input, _ => word!("select"), val => do_each!( - expr => trace_parse!(expression), + expr => trace_parse!(must!(expression)), _ => must!(punct!(",")), (expr) ), default => do_each!( - expr => trace_parse!(expression), + expr => trace_parse!(must!(expression)), _ => must!(punct!(",")), (expr) ), - map => trace_parse!(tuple), + map => trace_parse!(must!(tuple)), (val, default, map) ); match parsed { @@ -537,11 +536,10 @@ fn tuple_to_call<'a>( fn call_expression(input: SliceIter) -> Result, Expression> { let parsed = do_each!(input.clone(), - // TODO This should become just a bareword symbol now callee_name => trace_parse!(symbol), _ => punct!("("), args => optional!(separated!(punct!(","), trace_parse!(expression))), - _ => punct!(")"), + _ => must!(punct!(")")), (callee_name, args) ); match parsed { @@ -564,10 +562,10 @@ make_fn!( do_each!( pos => pos, _ => word!("reduce"), - macroname => match_type!(BAREWORD), - acc => trace_parse!(non_op_expression), - _ => punct!(","), - tgt => trace_parse!(non_op_expression), + macroname => must!(match_type!(BAREWORD)), + acc => must!(trace_parse!(non_op_expression)), + _ => must!(punct!(",")), + tgt => must!(trace_parse!(non_op_expression)), (Expression::FuncOp(FuncOpDef::Reduce(ReduceOpDef{ mac: (¯oname).into(), acc: Box::new(acc), @@ -582,9 +580,8 @@ make_fn!( do_each!( pos => pos, _ => word!("map"), - // TODO This should become just a bareword symbol now - macroname => match_type!(BAREWORD), - list => trace_parse!(non_op_expression), + macroname => must!(match_type!(BAREWORD)), + list => must!(trace_parse!(non_op_expression)), (Expression::FuncOp(FuncOpDef::Map(MapFilterOpDef{ mac: (¯oname).into(), target: Box::new(list), @@ -598,9 +595,8 @@ make_fn!( do_each!( pos => pos, _ => word!("filter"), - // TODO This should become just a bareword symbol now - macroname => match_type!(BAREWORD), - list => trace_parse!(non_op_expression), + macroname => must!(match_type!(BAREWORD)), + list => must!(trace_parse!(non_op_expression)), (Expression::FuncOp(FuncOpDef::Filter(MapFilterOpDef{ mac: (¯oname).into(), target: Box::new(list), @@ -627,7 +623,7 @@ make_fn!( (Box::new(step)) ) ), - end => either!(simple_expression, grouped_expression), + end => must!(wrap_err!(either!(simple_expression, grouped_expression), "Expected simple or grouped expression")), (Expression::Range(RangeDef{ pos: pos, start: Box::new(start), @@ -713,7 +709,7 @@ make_fn!( do_each!( e => do_each!( expr => trace_parse!(expression), - _ => punct!(";"), + _ => must!(punct!(";")), (expr) ), (Statement::Expression(e)) diff --git a/src/parse/precedence.rs b/src/parse/precedence.rs index c9611ce..0efa847 100644 --- a/src/parse/precedence.rs +++ b/src/parse/precedence.rs @@ -250,6 +250,12 @@ fn parse_operand_list<'a>(i: SliceIter<'a, Token>) -> ParseResult<'a, Vec { // A failure to parse an expression // is always an error. + if !firstrun { + // if we have successfully parsed an element and an operator then + // failing to parse a second expression is an abort since we know + // for sure now that the next expression is supposed to be there. + return Result::Abort(e); + } return Result::Fail(e); } Result::Abort(e) => { @@ -284,7 +290,7 @@ fn parse_operand_list<'a>(i: SliceIter<'a, Token>) -> ParseResult<'a, Vec { - // A failure to parse an expression + // A failure to parse an operator // is always an error. return Result::Abort(e); }