feat(frontends/lean): improve error handling inside match-with expressions

This commit is contained in:
Leonardo de Moura 2015-03-13 23:25:46 -07:00
parent bed0d6df6b
commit fc3a7bac59
6 changed files with 71 additions and 49 deletions

View file

@ -242,17 +242,8 @@ static expr parse_begin_end_core(parser & p, pos_info const & pos, name const &
} }
} }
} catch (exception & ex) { } catch (exception & ex) {
if (end_token == get_end_tk()) { if (end_token == get_end_tk())
// When the end_token is 'end', the default parser consume_until_end(p);
// sync_command does not work well because it will
// interpret 'end' as a synchronization point because 'end' is also a command.
while (!p.curr_is_token(get_end_tk())) {
if (p.curr() == scanner::token_kind::Eof)
ex.rethrow();
p.next();
}
p.next(); // consume 'end'
}
ex.rethrow(); ex.rethrow();
} }
auto end_pos = p.pos(); auto end_pos = p.pos();

View file

@ -698,8 +698,10 @@ expr parse_local_equations(parser & p, expr const & fn) {
/** \brief Use equations compiler infrastructure to implement match-with */ /** \brief Use equations compiler infrastructure to implement match-with */
expr parse_match(parser & p, unsigned, expr const *, pos_info const & pos) { expr parse_match(parser & p, unsigned, expr const *, pos_info const & pos) {
expr t = p.parse_expr();
buffer<expr> eqns; buffer<expr> eqns;
expr t;
try {
t = p.parse_expr();
p.check_token_next(get_with_tk(), "invalid 'match' expression, 'with' expected"); p.check_token_next(get_with_tk(), "invalid 'match' expression, 'with' expected");
expr fn = mk_local(p.mk_fresh_name(), "match", mk_expr_placeholder(), binder_info()); expr fn = mk_local(p.mk_fresh_name(), "match", mk_expr_placeholder(), binder_info());
if (p.curr_is_token(get_end_tk())) { if (p.curr_is_token(get_end_tk())) {
@ -740,6 +742,10 @@ expr parse_match(parser & p, unsigned, expr const *, pos_info const & pos) {
break; break;
p.next(); p.next();
} }
} catch (exception & ex) {
consume_until_end(p);
ex.rethrow();
}
p.check_token_next(get_end_tk(), "invalid 'match' expression, 'end' expected"); p.check_token_next(get_end_tk(), "invalid 'match' expression, 'end' expected");
expr f = p.save_pos(mk_equations(1, eqns.size(), eqns.data()), pos); expr f = p.save_pos(mk_equations(1, eqns.size(), eqns.data()), pos);
return p.mk_app(f, t, pos); return p.mk_app(f, t, pos);

View file

@ -22,6 +22,15 @@ Author: Leonardo de Moura
#include "frontends/lean/tokens.h" #include "frontends/lean/tokens.h"
namespace lean { namespace lean {
void consume_until_end(parser & p) {
while (!p.curr_is_token(get_end_tk())) {
if (p.curr() == scanner::token_kind::Eof)
return;
p.next();
}
p.next();
}
bool parse_persistent(parser & p, bool & persistent) { bool parse_persistent(parser & p, bool & persistent) {
if (p.curr_is_token_or_id(get_persistent_tk())) { if (p.curr_is_token_or_id(get_persistent_tk())) {
p.next(); p.next();

View file

@ -14,6 +14,9 @@ Author: Leonardo de Moura
namespace lean { namespace lean {
class parser; class parser;
/** \brief Consume tokes until 'end' token is consumed */
void consume_until_end(parser & p);
/** \brief Parse optional '[persistent]' modifier. /** \brief Parse optional '[persistent]' modifier.
return true if it is was found, and paremeter \c persistent to true. return true if it is was found, and paremeter \c persistent to true.
*/ */

12
tests/lean/errors2.lean Normal file
View file

@ -0,0 +1,12 @@
open nat
namespace foo
definition tst1 (a b : nat) : nat :=
match a with
| 0 := 1
| (n+1) := foo
end
end foo

View file

@ -0,0 +1 @@
errors2.lean:8:11: error: unknown identifier 'foo'