feat(frontends/lean/parse_table): start support for multiple "actions" in parsing tables

This commit is contained in:
Leonardo de Moura 2015-08-16 13:51:41 -07:00
parent df1a847255
commit 1d6bebf3a3
4 changed files with 51 additions and 38 deletions

View file

@ -132,14 +132,16 @@ static auto parse_mixfix_notation(parser & p, mixfix_kind k, bool overload, nota
optional<action> reserved_action; optional<action> reserved_action;
if (grp == notation_entry_group::Main) { if (grp == notation_entry_group::Main) {
if (k == mixfix_kind::prefix) { if (k == mixfix_kind::prefix) {
if (auto at = get_reserved_nud_table(p.env()).find(tks)) { if (auto ls = get_reserved_nud_table(p.env()).find(tks)) {
reserved_pt = at->second; // Remark: we are ignoring multiple actions in the reserved notation table
reserved_action = at->first; reserved_pt = head(ls).second;
reserved_action = head(ls).first;
} }
} else { } else {
if (auto at = get_reserved_led_table(p.env()).find(tks)) { if (auto ls = get_reserved_led_table(p.env()).find(tks)) {
reserved_pt = at->second; // Remark: we are ignoring multiple actions in the reserved notation table
reserved_action = at->first; reserved_pt = head(ls).second;
reserved_action = head(ls).first;
} }
} }
} }
@ -408,9 +410,11 @@ static action parse_action(parser & p, name const & prev_token, unsigned default
static unsigned get_default_prec(optional<parse_table> const & pt, name const & tk) { static unsigned get_default_prec(optional<parse_table> const & pt, name const & tk) {
if (!pt) if (!pt)
return LEAN_DEFAULT_PRECEDENCE; return LEAN_DEFAULT_PRECEDENCE;
if (auto at = pt->find(tk)) { if (auto ls = pt->find(tk)) {
if (at->first.kind() == notation::action_kind::Expr) for (auto at : ls) {
return at->first.rbp(); if (at.first.kind() == notation::action_kind::Expr)
return at.first.rbp();
}
} }
return LEAN_DEFAULT_PRECEDENCE; return LEAN_DEFAULT_PRECEDENCE;
} }
@ -419,20 +423,22 @@ static unsigned get_default_prec(optional<parse_table> const & pt, name const &
transition in \c pt, then return the successor table */ transition in \c pt, then return the successor table */
static optional<parse_table> find_match(optional<parse_table> const & pt, transition const & new_trans) { static optional<parse_table> find_match(optional<parse_table> const & pt, transition const & new_trans) {
if (pt) { if (pt) {
if (auto at = pt->find(new_trans.get_token())) { if (auto ls = pt->find(new_trans.get_token())) {
if (new_trans.get_action().is_equal(at->first)) for (auto at : ls) {
return optional<parse_table>(at->second); if (new_trans.get_action().is_equal(at.first))
return optional<parse_table>(at.second);
}
} }
} }
return optional<parse_table>(); return optional<parse_table>();
} }
/** \brief Lift parse_table::find method to optional<parse_table> */ /** \brief Lift parse_table::find method to optional<parse_table> */
static optional<pair<action, parse_table>> find_next(optional<parse_table> const & pt, name const & tk) { static list<pair<action, parse_table>> find_next(optional<parse_table> const & pt, name const & tk) {
if (pt) if (pt)
return pt->find(tk); return pt->find(tk);
else else
return optional<pair<action, parse_table>>(); return list<pair<action, parse_table>>();
} }
static unsigned parse_binders_rbp(parser & p) { static unsigned parse_binders_rbp(parser & p) {
@ -506,8 +512,9 @@ static notation_entry parse_notation_core(parser & p, bool overload, notation_en
(grp == notation_entry_group::Reserve && !p.curr_is_command() && !p.curr_is_eof())) { (grp == notation_entry_group::Reserve && !p.curr_is_command() && !p.curr_is_eof())) {
name tk = parse_quoted_symbol_or_token(p, new_tokens, used_default, grp); name tk = parse_quoted_symbol_or_token(p, new_tokens, used_default, grp);
if (auto at = find_next(reserved_pt, tk)) { if (auto at = find_next(reserved_pt, tk)) {
action const & a = at->first; // Remark: we are ignoring multiple actions in the reserved notation table
reserved_pt = at->second; action const & a = head(at).first;
reserved_pt = head(at).second;
switch (a.kind()) { switch (a.kind()) {
case notation::action_kind::Skip: case notation::action_kind::Skip:
if (!p.curr_is_quoted_symbol() && !p.curr_is_keyword() && !p.curr_is_token(get_assign_tk())) { if (!p.curr_is_quoted_symbol() && !p.curr_is_keyword() && !p.curr_is_token(get_assign_tk())) {

View file

@ -303,7 +303,7 @@ transition replace(transition const & t, std::function<expr(expr const &)> const
struct parse_table::cell { struct parse_table::cell {
bool m_nud; bool m_nud;
list<pair<unsigned, expr>> m_accept; list<pair<unsigned, expr>> m_accept;
name_map<pair<action, parse_table>> m_children; name_map<list<pair<action, parse_table>>> m_children;
MK_LEAN_RC(); // Declare m_rc counter MK_LEAN_RC(); // Declare m_rc counter
void dealloc() { delete this; } void dealloc() { delete this; }
cell(bool nud = true):m_nud(nud), m_rc(1) {} cell(bool nud = true):m_nud(nud), m_rc(1) {}
@ -317,12 +317,12 @@ parse_table::parse_table(parse_table && s):m_ptr(s.m_ptr) { s.m_ptr = nullptr; }
parse_table::~parse_table() { if (m_ptr) m_ptr->dec_ref(); } parse_table::~parse_table() { if (m_ptr) m_ptr->dec_ref(); }
parse_table & parse_table::operator=(parse_table const & s) { LEAN_COPY_REF(s); } parse_table & parse_table::operator=(parse_table const & s) { LEAN_COPY_REF(s); }
parse_table & parse_table::operator=(parse_table && s) { LEAN_MOVE_REF(s); } parse_table & parse_table::operator=(parse_table && s) { LEAN_MOVE_REF(s); }
optional<pair<action, parse_table>> parse_table::find(name const & tk) const { list<pair<action, parse_table>> parse_table::find(name const & tk) const {
auto * it = m_ptr->m_children.find(tk); list<pair<action, parse_table>> const * it = m_ptr->m_children.find(tk);
if (it) if (it)
return optional<pair<action, parse_table>>(*it); return *it;
else else
return optional<pair<action, parse_table>>(); return list<pair<action, parse_table>>();
} }
list<pair<unsigned, expr>> const & parse_table::is_accepting() const { list<pair<unsigned, expr>> const & parse_table::is_accepting() const {
@ -378,11 +378,12 @@ parse_table parse_table::add_core(unsigned num, transition const * ts, expr cons
r.m_ptr->m_accept = insert(new_accept, priority, a); r.m_ptr->m_accept = insert(new_accept, priority, a);
} }
} else { } else {
auto * it = r.m_ptr->m_children.find(ts->get_token()); list<pair<action, parse_table>> const * it = r.m_ptr->m_children.find(ts->get_token());
parse_table new_child; parse_table new_child;
if (it) { if (it) {
action const & act = it->first; // TODO(Leo): support multiple actions
parse_table const & child = it->second; action const & act = head(*it).first;
parse_table const & child = head(*it).second;
if (act.is_equal(ts->get_action())) { if (act.is_equal(ts->get_action())) {
new_child = child.add_core(num-1, ts+1, a, priority, overload); new_child = child.add_core(num-1, ts+1, a, priority, overload);
} else { } else {
@ -391,7 +392,7 @@ parse_table parse_table::add_core(unsigned num, transition const * ts, expr cons
} else { } else {
new_child = parse_table().add_core(num-1, ts+1, a, priority, overload); new_child = parse_table().add_core(num-1, ts+1, a, priority, overload);
} }
r.m_ptr->m_children.insert(ts->get_token(), mk_pair(ts->get_action(), new_child)); r.m_ptr->m_children.insert(ts->get_token(), to_list(mk_pair(ts->get_action(), new_child)));
} }
return r; return r;
} }
@ -469,10 +470,12 @@ void parse_table::for_each(buffer<transition> & ts,
list<pair<unsigned, expr>> const &)> const & fn) const { list<pair<unsigned, expr>> const &)> const & fn) const {
if (!is_nil(m_ptr->m_accept)) if (!is_nil(m_ptr->m_accept))
fn(ts.size(), ts.data(), m_ptr->m_accept); fn(ts.size(), ts.data(), m_ptr->m_accept);
m_ptr->m_children.for_each([&](name const & k, pair<action, parse_table> const & p) { m_ptr->m_children.for_each([&](name const & k, list<pair<action, parse_table>> const & lst) {
for (auto const & p : lst) {
ts.push_back(transition(k, p.first)); ts.push_back(transition(k, p.first));
p.second.for_each(ts, fn); p.second.for_each(ts, fn);
ts.pop_back(); ts.pop_back();
}
}); });
} }
@ -713,10 +716,12 @@ static int merge(lua_State * L) {
} }
static int find(lua_State * L) { static int find(lua_State * L) {
auto p = to_parse_table(L, 1).find(to_name_ext(L, 2)); list<pair<action, parse_table>> it = to_parse_table(L, 1).find(to_name_ext(L, 2));
if (p) { if (it) {
push_notation_action(L, p->first); // TODO(Leo): support multiple actions
push_parse_table(L, p->second); auto p = head(it);
push_notation_action(L, p.first);
push_parse_table(L, p.second);
return 2; return 2;
} else { } else {
return push_nil(L); return push_nil(L);

View file

@ -157,7 +157,7 @@ public:
return add(ts.size(), ts.begin(), a, LEAN_DEFAULT_NOTATION_PRIORITY, true); return add(ts.size(), ts.begin(), a, LEAN_DEFAULT_NOTATION_PRIORITY, true);
} }
parse_table merge(parse_table const & s, bool overload) const; parse_table merge(parse_table const & s, bool overload) const;
optional<pair<action, parse_table>> find(name const & tk) const; list<pair<action, parse_table>> find(name const & tk) const;
list<pair<unsigned, expr>> const & is_accepting() const; list<pair<unsigned, expr>> const & is_accepting() const;
void for_each(std::function<void(unsigned, transition const *, list<pair<unsigned, expr>> const &)> const & fn) const; void for_each(std::function<void(unsigned, transition const *, list<pair<unsigned, expr>> const &)> const & fn) const;

View file

@ -1086,7 +1086,8 @@ expr parser::parse_notation_core(parse_table t, expr * left, bool as_tactic) {
auto r = t.find(get_token_info().value()); auto r = t.find(get_token_info().value());
if (!r) if (!r)
break; break;
notation::action const & a = r->first; // TODO(Leo): handle multiple actions
notation::action const & a = head(r).first;
switch (a.kind()) { switch (a.kind()) {
case notation::action_kind::Skip: case notation::action_kind::Skip:
next(); next();
@ -1214,7 +1215,7 @@ expr parser::parse_notation_core(parse_table t, expr * left, bool as_tactic) {
break; break;
} }
t = r->second; t = head(r).second; // TODO(Leo):
} }
list<pair<unsigned, expr>> const & as = t.is_accepting(); list<pair<unsigned, expr>> const & as = t.is_accepting();
save_overload_notation(as, p); save_overload_notation(as, p);