feat(frontends/lean): import error message for "unknown" tactics when parsing
This commit is contained in:
parent
118189eaac
commit
441f1f9fe2
7 changed files with 36 additions and 20 deletions
|
@ -124,7 +124,6 @@ static expr parse_placeholder(parser & p, unsigned, expr const *, pos_info const
|
|||
}
|
||||
|
||||
static expr parse_by(parser & p, unsigned, expr const *, pos_info const & pos) {
|
||||
parser::undef_id_to_local_scope scope(p);
|
||||
p.next();
|
||||
expr t = p.parse_tactic();
|
||||
return p.mk_by(t, pos);
|
||||
|
@ -133,7 +132,6 @@ static expr parse_by(parser & p, unsigned, expr const *, pos_info const & pos) {
|
|||
static expr parse_begin_end_core(parser & p, pos_info const & pos, name const & end_token, bool nested = false) {
|
||||
if (!p.has_tactic_decls())
|
||||
throw parser_error("invalid 'begin-end' expression, tactic module has not been imported", pos);
|
||||
parser::undef_id_to_local_scope scope1(p);
|
||||
p.next();
|
||||
optional<expr> pre_tac = get_begin_end_pre_tactic(p.env());
|
||||
buffer<expr> tacs;
|
||||
|
@ -171,7 +169,7 @@ static expr parse_begin_end_core(parser & p, pos_info const & pos, name const &
|
|||
p.next();
|
||||
name id = p.check_id_next("invalid 'assert' tactic, identifier expected");
|
||||
p.check_token_next(get_colon_tk(), "invalid 'assert' tactic, ':' expected");
|
||||
expr A = p.parse_expr();
|
||||
expr A = p.parse_tactic_expr_arg();
|
||||
expr assert_tac = p.save_pos(mk_assert_tactic_expr(id, A), pos);
|
||||
tacs.push_back(mk_begin_end_element_annotation(assert_tac));
|
||||
} else if (p.curr_is_token(get_have_tk())) {
|
||||
|
@ -180,7 +178,7 @@ static expr parse_begin_end_core(parser & p, pos_info const & pos, name const &
|
|||
auto id_pos = p.pos();
|
||||
name id = p.check_id_next("invalid 'have' tactic, identifier expected");
|
||||
p.check_token_next(get_colon_tk(), "invalid 'have' tactic, ':' expected");
|
||||
expr A = p.parse_expr();
|
||||
expr A = p.parse_tactic_expr_arg();
|
||||
expr assert_tac = p.save_pos(mk_assert_tactic_expr(id, A), pos);
|
||||
tacs.push_back(mk_begin_end_element_annotation(assert_tac));
|
||||
if (p.curr_is_token(get_bar_tk())) {
|
||||
|
@ -196,7 +194,7 @@ static expr parse_begin_end_core(parser & p, pos_info const & pos, name const &
|
|||
// parse: 'from' expr
|
||||
p.next();
|
||||
auto pos = p.pos();
|
||||
expr t = p.parse_expr();
|
||||
expr t = p.parse_tactic_expr_arg();
|
||||
t = p.mk_app(get_rexact_tac_fn(), t, pos);
|
||||
t = p.save_pos(mk_begin_end_element_annotation(t), pos);
|
||||
t = p.save_pos(mk_begin_end_annotation(t), pos);
|
||||
|
@ -204,7 +202,7 @@ static expr parse_begin_end_core(parser & p, pos_info const & pos, name const &
|
|||
} else if (p.curr_is_token(get_proof_tk())) {
|
||||
auto pos = p.pos();
|
||||
p.next();
|
||||
expr t = p.parse_expr();
|
||||
expr t = p.parse_tactic_expr_arg();
|
||||
p.check_token_next(get_qed_tk(), "invalid proof-qed, 'qed' expected");
|
||||
t = p.mk_app(get_rexact_tac_fn(), t, pos);
|
||||
t = p.save_pos(mk_begin_end_element_annotation(t), pos);
|
||||
|
@ -225,13 +223,13 @@ static expr parse_begin_end_core(parser & p, pos_info const & pos, name const &
|
|||
}
|
||||
} else if (p.curr_is_token(get_show_tk())) {
|
||||
auto pos = p.pos();
|
||||
expr t = p.parse_expr();
|
||||
expr t = p.parse_tactic_expr_arg();
|
||||
t = p.mk_app(get_rexact_tac_fn(), t, pos);
|
||||
add_tac(t, pos);
|
||||
} else if (p.curr_is_token(get_match_tk()) || p.curr_is_token(get_assume_tk()) ||
|
||||
p.curr_is_token(get_take_tk()) || p.curr_is_token(get_fun_tk())) {
|
||||
auto pos = p.pos();
|
||||
expr t = p.parse_expr();
|
||||
expr t = p.parse_tactic_expr_arg();
|
||||
t = p.mk_app(get_exact_tac_fn(), t, pos);
|
||||
add_tac(t, pos);
|
||||
} else {
|
||||
|
|
|
@ -35,12 +35,12 @@ static expr parse_rparen(parser &, unsigned, expr const * args, pos_info const &
|
|||
static expr parse_let_tactic(parser & p, unsigned, expr const *, pos_info const & pos) {
|
||||
name id = p.check_atomic_id_next("invalid 'let' tactic, identifier expected");
|
||||
p.check_token_next(get_assign_tk(), "invalid 'let' tactic, ':=' expected");
|
||||
expr value = p.parse_expr();
|
||||
expr value = p.parse_tactic_expr_arg();
|
||||
return p.save_pos(mk_let_tactic_expr(id, value), pos);
|
||||
}
|
||||
|
||||
static expr parse_generalize_tactic(parser & p, unsigned, expr const *, pos_info const & pos) {
|
||||
expr e = p.parse_expr();
|
||||
expr e = p.parse_tactic_expr_arg();
|
||||
name id;
|
||||
if (p.curr_is_token(get_as_tk())) {
|
||||
p.next();
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace lean {
|
|||
static optional<expr> parse_pattern(parser & p) {
|
||||
if (p.curr_is_token(get_lcurly_tk())) {
|
||||
p.next();
|
||||
expr r = p.parse_expr();
|
||||
expr r = p.parse_tactic_expr_arg();
|
||||
p.check_token_next(get_rcurly_tk(), "invalid rewrite pattern, '}' expected");
|
||||
return some_expr(r);
|
||||
} else {
|
||||
|
@ -25,14 +25,14 @@ static expr parse_rule(parser & p, bool use_paren) {
|
|||
if (use_paren) {
|
||||
if (p.curr_is_token(get_lparen_tk())) {
|
||||
p.next();
|
||||
expr r = p.parse_expr();
|
||||
expr r = p.parse_tactic_expr_arg();
|
||||
p.check_token_next(get_rparen_tk(), "invalid rewrite pattern, ')' expected");
|
||||
return r;
|
||||
} else {
|
||||
return p.parse_id();
|
||||
return p.parse_tactic_id_arg();
|
||||
}
|
||||
} else {
|
||||
return p.parse_expr();
|
||||
return p.parse_tactic_expr_arg();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ static expr parse_rewrite_element(parser & p, bool use_paren) {
|
|||
return parse_rewrite_unfold(p);
|
||||
if (p.curr_is_token(get_down_tk())) {
|
||||
p.next();
|
||||
expr e = p.parse_expr();
|
||||
expr e = p.parse_tactic_expr_arg();
|
||||
location loc = parse_tactic_location(p);
|
||||
return mk_rewrite_fold(e, loc);
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ static expr parse_rewrite_element(parser & p, bool use_paren) {
|
|||
location loc = parse_tactic_location(p);
|
||||
return mk_rewrite_reduce(loc);
|
||||
} else {
|
||||
expr e = p.parse_expr();
|
||||
expr e = p.parse_tactic_expr_arg();
|
||||
location loc = parse_tactic_location(p);
|
||||
return mk_rewrite_reduce_to(e, loc);
|
||||
}
|
||||
|
@ -175,7 +175,7 @@ expr parse_fold_tactic(parser & p) {
|
|||
p.next();
|
||||
while (true) {
|
||||
auto pos = p.pos();
|
||||
expr e = p.parse_expr();
|
||||
expr e = p.parse_tactic_expr_arg();
|
||||
location loc = parse_tactic_location(p);
|
||||
elems.push_back(p.save_pos(mk_rewrite_fold(e, loc), pos));
|
||||
if (!p.curr_is_token(get_comma_tk()))
|
||||
|
@ -184,7 +184,7 @@ expr parse_fold_tactic(parser & p) {
|
|||
}
|
||||
p.check_token_next(get_rbracket_tk(), "invalid 'fold' tactic, ',' or ']' expected");
|
||||
} else {
|
||||
expr e = p.parse_expr();
|
||||
expr e = p.parse_tactic_expr_arg();
|
||||
location loc = parse_tactic_location(p);
|
||||
elems.push_back(p.save_pos(mk_rewrite_fold(e, loc), pos));;
|
||||
}
|
||||
|
|
|
@ -1383,6 +1383,16 @@ static bool is_tactic_command_type(expr e) {
|
|||
return is_tactic_type(e);
|
||||
}
|
||||
|
||||
expr parser::parse_tactic_expr_arg(unsigned rbp) {
|
||||
parser::undef_id_to_local_scope scope1(*this);
|
||||
return parse_expr(rbp);
|
||||
}
|
||||
|
||||
expr parser::parse_tactic_id_arg() {
|
||||
parser::undef_id_to_local_scope scope1(*this);
|
||||
return parse_id();
|
||||
}
|
||||
|
||||
optional<expr> parser::is_tactic_command(name & id) {
|
||||
if (id.is_atomic())
|
||||
id = get_tactic_name() + id;
|
||||
|
@ -1410,7 +1420,7 @@ expr parser::parse_tactic_expr_list() {
|
|||
check_token_next(get_lbracket_tk(), "invalid tactic, '[' expected");
|
||||
buffer<expr> args;
|
||||
while (true) {
|
||||
args.push_back(parse_expr());
|
||||
args.push_back(parse_tactic_expr_arg());
|
||||
if (!curr_is_token(get_comma_tk()))
|
||||
break;
|
||||
next();
|
||||
|
@ -1510,7 +1520,7 @@ expr parser::parse_tactic_nud() {
|
|||
rbp = 0;
|
||||
else
|
||||
rbp = get_max_prec();
|
||||
r = mk_app(r, parse_expr(rbp), id_pos);
|
||||
r = mk_app(r, parse_tactic_expr_arg(rbp), id_pos);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
|
|
|
@ -404,6 +404,8 @@ public:
|
|||
expr parse_scoped_expr(buffer<expr> const & ps, unsigned rbp = 0) { return parse_scoped_expr(ps.size(), ps.data(), rbp); }
|
||||
|
||||
expr parse_tactic(unsigned rbp = 0);
|
||||
expr parse_tactic_expr_arg(unsigned rbp = 0);
|
||||
expr parse_tactic_id_arg();
|
||||
|
||||
struct local_scope { parser & m_p; environment m_env;
|
||||
local_scope(parser & p, bool save_options = false);
|
||||
|
|
5
tests/lean/tactic_error_msg.lean
Normal file
5
tests/lean/tactic_error_msg.lean
Normal file
|
@ -0,0 +1,5 @@
|
|||
example (a b : Prop) : a → b → a ∧ b :=
|
||||
begin
|
||||
intros,
|
||||
splits
|
||||
end
|
1
tests/lean/tactic_error_msg.lean.expected.out
Normal file
1
tests/lean/tactic_error_msg.lean.expected.out
Normal file
|
@ -0,0 +1 @@
|
|||
tactic_error_msg.lean:4:2: error: unknown identifier 'splits'
|
Loading…
Reference in a new issue