Add missing mixfix notation
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
85daaea8ce
commit
5aae838e1c
6 changed files with 41 additions and 6 deletions
|
@ -192,6 +192,7 @@ struct frontend::imp {
|
|||
void add_mixfixl(unsigned sz, name const * opns, unsigned p, expr const & d) { add_op(mixfixl(sz, opns, p), d, false); }
|
||||
void add_mixfixr(unsigned sz, name const * opns, unsigned p, expr const & d) { add_op(mixfixr(sz, opns, p), d, true); }
|
||||
void add_mixfixc(unsigned sz, name const * opns, unsigned p, expr const & d) { add_op(mixfixc(sz, opns, p), d, false); }
|
||||
void add_mixfixo(unsigned sz, name const * opns, unsigned p, expr const & d) { add_op(mixfixo(sz, opns, p), d, false); }
|
||||
|
||||
void mark_implicit_arguments(name const & n, unsigned sz, bool const * implicit) {
|
||||
if (has_children())
|
||||
|
@ -326,6 +327,7 @@ void frontend::add_postfix(name const & opn, unsigned p, expr const & d) { m_imp
|
|||
void frontend::add_mixfixl(unsigned sz, name const * opns, unsigned p, expr const & d) { m_imp->add_mixfixl(sz, opns, p, d); }
|
||||
void frontend::add_mixfixr(unsigned sz, name const * opns, unsigned p, expr const & d) { m_imp->add_mixfixr(sz, opns, p, d); }
|
||||
void frontend::add_mixfixc(unsigned sz, name const * opns, unsigned p, expr const & d) { m_imp->add_mixfixc(sz, opns, p, d); }
|
||||
void frontend::add_mixfixo(unsigned sz, name const * opns, unsigned p, expr const & d) { m_imp->add_mixfixo(sz, opns, p, d); }
|
||||
operator_info frontend::find_op_for(expr const & n) const { return m_imp->find_op_for(n); }
|
||||
operator_info frontend::find_nud(name const & n) const { return m_imp->find_nud(n); }
|
||||
operator_info frontend::find_led(name const & n) const { return m_imp->find_led(n); }
|
||||
|
|
|
@ -84,6 +84,7 @@ public:
|
|||
void add_mixfixl(unsigned sz, name const * opns, unsigned precedence, expr const & d);
|
||||
void add_mixfixr(unsigned sz, name const * opns, unsigned precedence, expr const & d);
|
||||
void add_mixfixc(unsigned sz, name const * opns, unsigned precedence, expr const & d);
|
||||
void add_mixfixo(unsigned sz, name const * opns, unsigned precedence, expr const & d);
|
||||
/**
|
||||
\brief Return the operator (if one exists) associated with the
|
||||
given expression.
|
||||
|
|
|
@ -100,6 +100,9 @@ operator_info mixfixr(unsigned num_parts, name const * parts, unsigned precedenc
|
|||
operator_info mixfixc(unsigned num_parts, name const * parts, unsigned precedence) {
|
||||
lean_assert(num_parts > 1); return operator_info(new operator_info::imp(num_parts, parts, fixity::Mixfixc, precedence));
|
||||
}
|
||||
operator_info mixfixo(unsigned num_parts, name const * parts, unsigned precedence) {
|
||||
lean_assert(num_parts > 1); return operator_info(new operator_info::imp(num_parts, parts, fixity::Mixfixo, precedence));
|
||||
}
|
||||
|
||||
char const * to_string(fixity f) {
|
||||
switch (f) {
|
||||
|
@ -111,6 +114,7 @@ char const * to_string(fixity f) {
|
|||
case fixity::Mixfixl: return "Mixfixl";
|
||||
case fixity::Mixfixr: return "Mixfixr";
|
||||
case fixity::Mixfixc: return "Mixfixc";
|
||||
case fixity::Mixfixo: return "Mixfixo";
|
||||
}
|
||||
lean_unreachable();
|
||||
return 0;
|
||||
|
|
|
@ -21,8 +21,9 @@ namespace lean {
|
|||
Mixfixl: ID _ ID _ ... ID _ (has at least two parts)
|
||||
Mixfixr: _ ID _ ID ... _ ID (has at least two parts)
|
||||
Mixfixc: ID _ ID _ ... ID _ ID (has at least two parts)
|
||||
Mixfixo: _ ID _ ... ID _ (has at least two parts)
|
||||
*/
|
||||
enum class fixity { Prefix, Infix, Infixl, Infixr, Postfix, Mixfixl, Mixfixr, Mixfixc };
|
||||
enum class fixity { Prefix, Infix, Infixl, Infixr, Postfix, Mixfixl, Mixfixr, Mixfixc, Mixfixo };
|
||||
|
||||
/**
|
||||
\brief Data-structure for storing user defined operator
|
||||
|
@ -54,6 +55,7 @@ public:
|
|||
friend operator_info mixfixl(unsigned num_parts, name const * parts, unsigned precedence);
|
||||
friend operator_info mixfixr(unsigned num_parts, name const * parts, unsigned precedence);
|
||||
friend operator_info mixfixc(unsigned num_parts, name const * parts, unsigned precedence);
|
||||
friend operator_info mixfixo(unsigned num_parts, name const * parts, unsigned precedence);
|
||||
|
||||
/** \brief Associate a denotation (expression) with this operator. */
|
||||
void add_expr(expr const & n);
|
||||
|
@ -95,9 +97,11 @@ operator_info postfix(name const & op, unsigned precedence);
|
|||
operator_info mixfixl(unsigned num_parts, name const * parts, unsigned precedence);
|
||||
operator_info mixfixr(unsigned num_parts, name const * parts, unsigned precedence);
|
||||
operator_info mixfixc(unsigned num_parts, name const * parts, unsigned precedence);
|
||||
operator_info mixfixo(unsigned num_parts, name const * parts, unsigned precedence);
|
||||
inline operator_info mixfixl(std::initializer_list<name> const & l, unsigned precedence) { return mixfixl(l.size(), l.begin(), precedence); }
|
||||
inline operator_info mixfixr(std::initializer_list<name> const & l, unsigned precedence) { return mixfixr(l.size(), l.begin(), precedence); }
|
||||
inline operator_info mixfixc(std::initializer_list<name> const & l, unsigned precedence) { return mixfixc(l.size(), l.begin(), precedence); }
|
||||
inline operator_info mixfixo(std::initializer_list<name> const & l, unsigned precedence) { return mixfixo(l.size(), l.begin(), precedence); }
|
||||
|
||||
format pp(operator_info const & o);
|
||||
std::ostream & operator<<(std::ostream & out, operator_info const & o);
|
||||
|
|
|
@ -477,7 +477,11 @@ class parser::imp {
|
|||
check_name_next(op_part, "invalid mixfix operator application, identifier expected");
|
||||
}
|
||||
|
||||
/** \brief Auxiliary function for #parse_mixfixl and #parse_mixfixr */
|
||||
/**
|
||||
\brief Auxiliary function for #parse_mixfixl and #parse_mixfixr
|
||||
|
||||
It parses (ID _)*
|
||||
*/
|
||||
void parse_mixfix_args(list<name> const & ops, unsigned prec, buffer<expr> & args) {
|
||||
auto it = ops.begin();
|
||||
++it;
|
||||
|
@ -506,6 +510,15 @@ class parser::imp {
|
|||
return mk_application(op, p, args);
|
||||
}
|
||||
|
||||
/** \brief Parse user defined mixfixr operator. It has the form: _ ID ... _ ID _ */
|
||||
expr parse_mixfixo(expr const & left, operator_info const & op) {
|
||||
auto p = pos();
|
||||
buffer<expr> args;
|
||||
args.push_back(left);
|
||||
parse_mixfix_args(op.get_op_name_parts(), op.get_precedence(), args);
|
||||
return mk_application(op, p, args);
|
||||
}
|
||||
|
||||
/** \brief Parse user defined mixfixc operator. It has the form: ID _ ID ... _ ID */
|
||||
expr parse_mixfixc(operator_info const & op) {
|
||||
auto p = pos();
|
||||
|
@ -619,6 +632,7 @@ class parser::imp {
|
|||
case fixity::Infixl: return parse_infixl(left, op);
|
||||
case fixity::Infixr: return parse_infixr(left, op);
|
||||
case fixity::Mixfixr: return parse_mixfixr(left, op);
|
||||
case fixity::Mixfixo: return parse_mixfixo(left, op);
|
||||
default: lean_unreachable(); return expr();
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -495,9 +495,11 @@ class pp_fn {
|
|||
case fixity::Prefix: case fixity::Postfix:
|
||||
return app.get_num_args() == 1;
|
||||
case fixity::Mixfixl: case fixity::Mixfixr:
|
||||
return app.get_num_args() == length(op.get_op_name_parts()) + 1;
|
||||
case fixity::Mixfixc:
|
||||
return app.get_num_args() == length(op.get_op_name_parts());
|
||||
case fixity::Mixfixc:
|
||||
return app.get_num_args() == length(op.get_op_name_parts()) - 1;
|
||||
case fixity::Mixfixo:
|
||||
return app.get_num_args() == length(op.get_op_name_parts()) + 1;
|
||||
}
|
||||
lean_unreachable();
|
||||
return false;
|
||||
|
@ -530,14 +532,22 @@ class pp_fn {
|
|||
p_arg = pp_mixfix_child(op, app.get_arg(0), depth);
|
||||
return mk_result(group(format{p_arg.first, space(), format(op.get_op_name())}),
|
||||
p_arg.second + 1);
|
||||
case fixity::Mixfixr: {
|
||||
case fixity::Mixfixr: case fixity::Mixfixo: {
|
||||
// _ ID ... _ ID
|
||||
// _ ID ... _ ID _
|
||||
list<name> parts = op.get_op_name_parts();
|
||||
auto it = parts.begin();
|
||||
unsigned num = app.get_num_args();
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
result p_arg = pp_mixfix_child(op, app.get_arg(i), depth);
|
||||
if (i == num - 1) {
|
||||
if (op.get_fixity() == fixity::Mixfixo)
|
||||
r_format += p_arg.first;
|
||||
else
|
||||
r_format += format{p_arg.first, space(), format(*it)};
|
||||
} else {
|
||||
r_format += format{p_arg.first, space(), format(*it), line()};
|
||||
}
|
||||
r_weight += p_arg.second;
|
||||
++it;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue