FEATURE: Better parsing errors.

More specific reports about what is wrong when we know the correct
next tokens to expect.
This commit is contained in:
Jeremy Wall 2019-01-22 20:51:25 -06:00
parent 5bfe38140a
commit b6c2a08c8f
2 changed files with 26 additions and 24 deletions

View File

@ -237,7 +237,7 @@ make_fn!(
_ => punct!("{"), _ => punct!("{"),
v => optional!(field_list), v => optional!(field_list),
_ => optional!(punct!(",")), _ => optional!(punct!(",")),
_ => punct!("}"), _ => must!(punct!("}")),
(vec_to_tuple(pos, v)) (vec_to_tuple(pos, v))
) )
); );
@ -255,7 +255,7 @@ make_fn!(
start => punct!("["), start => punct!("["),
elements => optional!(separated!(punct!(","), expression)), elements => optional!(separated!(punct!(","), expression)),
_ => optional!(punct!(",")), _ => optional!(punct!(",")),
_ => punct!("]"), _ => must!(punct!("]")),
(tuple_to_list(start.pos, elements)) (tuple_to_list(start.pos, elements))
) )
); );
@ -309,7 +309,7 @@ make_fn!(
_ => punct!("("), _ => punct!("("),
expr => do_each!( expr => do_each!(
expr => trace_parse!(expression), expr => trace_parse!(expression),
_ => punct!(")"), _ => must!(punct!(")")),
(expr) (expr)
), ),
(expression_to_grouped_expression(expr)) (expression_to_grouped_expression(expr))
@ -332,12 +332,11 @@ fn tuple_to_copy(sym: Value, fields: Option<FieldList>) -> Expression {
make_fn!( make_fn!(
copy_expression<SliceIter<Token>, Expression>, copy_expression<SliceIter<Token>, Expression>,
do_each!( do_each!(
// TODO This should become just a bareword symbol now
sym => trace_parse!(symbol), sym => trace_parse!(symbol),
_ => punct!("{"), _ => punct!("{"),
fields => optional!(trace_parse!(field_list)), fields => optional!(trace_parse!(field_list)),
_ => optional!(punct!(",")), // noms opt! macro does not preserve error types properly but this one does. _ => optional!(punct!(",")),
_ => punct!("}"), _ => must!(punct!("}")),
(tuple_to_copy(sym, fields)) (tuple_to_copy(sym, fields))
) )
); );
@ -452,16 +451,16 @@ fn select_expression(input: SliceIter<Token>) -> Result<SliceIter<Token>, Expres
let parsed = do_each!(input, let parsed = do_each!(input,
_ => word!("select"), _ => word!("select"),
val => do_each!( val => do_each!(
expr => trace_parse!(expression), expr => trace_parse!(must!(expression)),
_ => must!(punct!(",")), _ => must!(punct!(",")),
(expr) (expr)
), ),
default => do_each!( default => do_each!(
expr => trace_parse!(expression), expr => trace_parse!(must!(expression)),
_ => must!(punct!(",")), _ => must!(punct!(",")),
(expr) (expr)
), ),
map => trace_parse!(tuple), map => trace_parse!(must!(tuple)),
(val, default, map) (val, default, map)
); );
match parsed { match parsed {
@ -537,11 +536,10 @@ fn tuple_to_call<'a>(
fn call_expression(input: SliceIter<Token>) -> Result<SliceIter<Token>, Expression> { fn call_expression(input: SliceIter<Token>) -> Result<SliceIter<Token>, Expression> {
let parsed = do_each!(input.clone(), let parsed = do_each!(input.clone(),
// TODO This should become just a bareword symbol now
callee_name => trace_parse!(symbol), callee_name => trace_parse!(symbol),
_ => punct!("("), _ => punct!("("),
args => optional!(separated!(punct!(","), trace_parse!(expression))), args => optional!(separated!(punct!(","), trace_parse!(expression))),
_ => punct!(")"), _ => must!(punct!(")")),
(callee_name, args) (callee_name, args)
); );
match parsed { match parsed {
@ -564,10 +562,10 @@ make_fn!(
do_each!( do_each!(
pos => pos, pos => pos,
_ => word!("reduce"), _ => word!("reduce"),
macroname => match_type!(BAREWORD), macroname => must!(match_type!(BAREWORD)),
acc => trace_parse!(non_op_expression), acc => must!(trace_parse!(non_op_expression)),
_ => punct!(","), _ => must!(punct!(",")),
tgt => trace_parse!(non_op_expression), tgt => must!(trace_parse!(non_op_expression)),
(Expression::FuncOp(FuncOpDef::Reduce(ReduceOpDef{ (Expression::FuncOp(FuncOpDef::Reduce(ReduceOpDef{
mac: (&macroname).into(), mac: (&macroname).into(),
acc: Box::new(acc), acc: Box::new(acc),
@ -582,9 +580,8 @@ make_fn!(
do_each!( do_each!(
pos => pos, pos => pos,
_ => word!("map"), _ => word!("map"),
// TODO This should become just a bareword symbol now macroname => must!(match_type!(BAREWORD)),
macroname => match_type!(BAREWORD), list => must!(trace_parse!(non_op_expression)),
list => trace_parse!(non_op_expression),
(Expression::FuncOp(FuncOpDef::Map(MapFilterOpDef{ (Expression::FuncOp(FuncOpDef::Map(MapFilterOpDef{
mac: (&macroname).into(), mac: (&macroname).into(),
target: Box::new(list), target: Box::new(list),
@ -598,9 +595,8 @@ make_fn!(
do_each!( do_each!(
pos => pos, pos => pos,
_ => word!("filter"), _ => word!("filter"),
// TODO This should become just a bareword symbol now macroname => must!(match_type!(BAREWORD)),
macroname => match_type!(BAREWORD), list => must!(trace_parse!(non_op_expression)),
list => trace_parse!(non_op_expression),
(Expression::FuncOp(FuncOpDef::Filter(MapFilterOpDef{ (Expression::FuncOp(FuncOpDef::Filter(MapFilterOpDef{
mac: (&macroname).into(), mac: (&macroname).into(),
target: Box::new(list), target: Box::new(list),
@ -627,7 +623,7 @@ make_fn!(
(Box::new(step)) (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{ (Expression::Range(RangeDef{
pos: pos, pos: pos,
start: Box::new(start), start: Box::new(start),
@ -713,7 +709,7 @@ make_fn!(
do_each!( do_each!(
e => do_each!( e => do_each!(
expr => trace_parse!(expression), expr => trace_parse!(expression),
_ => punct!(";"), _ => must!(punct!(";")),
(expr) (expr)
), ),
(Statement::Expression(e)) (Statement::Expression(e))

View File

@ -250,6 +250,12 @@ fn parse_operand_list<'a>(i: SliceIter<'a, Token>) -> ParseResult<'a, Vec<Elemen
Result::Fail(e) => { Result::Fail(e) => {
// A failure to parse an expression // A failure to parse an expression
// is always an error. // 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); return Result::Fail(e);
} }
Result::Abort(e) => { Result::Abort(e) => {
@ -284,7 +290,7 @@ fn parse_operand_list<'a>(i: SliceIter<'a, Token>) -> ParseResult<'a, Vec<Elemen
break; break;
} }
Result::Abort(e) => { Result::Abort(e) => {
// A failure to parse an expression // A failure to parse an operator
// is always an error. // is always an error.
return Result::Abort(e); return Result::Abort(e);
} }