2014-06-03 09:34:12 +00:00
|
|
|
/*
|
|
|
|
Copyright (c) 2014 Microsoft Corporation. All rights reserved.
|
|
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
|
|
|
|
|
|
Author: Leonardo de Moura
|
|
|
|
*/
|
2014-06-14 00:30:35 +00:00
|
|
|
#include <limits>
|
2014-06-05 20:10:50 +00:00
|
|
|
#include <utility>
|
2014-06-10 16:11:45 +00:00
|
|
|
#include "frontends/lean/token_table.h"
|
2014-06-03 09:34:12 +00:00
|
|
|
|
|
|
|
namespace lean {
|
2014-06-13 22:13:32 +00:00
|
|
|
static unsigned g_arrow_prec = 25;
|
2014-06-14 00:30:35 +00:00
|
|
|
static unsigned g_max_prec = std::numeric_limits<unsigned>::max();
|
|
|
|
static unsigned g_plus_prec = 65;
|
2014-06-14 01:00:52 +00:00
|
|
|
static unsigned g_cup_prec = 60;
|
2014-06-25 19:50:47 +00:00
|
|
|
unsigned get_max_prec() { return g_max_prec; }
|
2014-06-13 22:13:32 +00:00
|
|
|
unsigned get_arrow_prec() { return g_arrow_prec; }
|
2014-06-10 16:11:45 +00:00
|
|
|
token_table add_command_token(token_table const & s, char const * token) {
|
2014-06-05 19:40:31 +00:00
|
|
|
return insert(s, token, token_info(token));
|
2014-06-03 09:34:12 +00:00
|
|
|
}
|
2014-06-10 16:11:45 +00:00
|
|
|
token_table add_command_token(token_table const & s, char const * token, char const * val) {
|
2014-06-18 16:14:50 +00:00
|
|
|
return insert(s, token, token_info(token, val));
|
2014-06-05 20:05:40 +00:00
|
|
|
}
|
2014-06-10 16:11:45 +00:00
|
|
|
token_table add_token(token_table const & s, char const * token, unsigned prec) {
|
2014-06-05 19:40:31 +00:00
|
|
|
return insert(s, token, token_info(token, prec));
|
|
|
|
}
|
2014-06-10 16:11:45 +00:00
|
|
|
token_table add_token(token_table const & s, char const * token, char const * val, unsigned prec) {
|
2014-06-18 16:14:50 +00:00
|
|
|
return insert(s, token, token_info(token, val, prec));
|
2014-06-05 19:40:31 +00:00
|
|
|
}
|
2014-06-10 16:11:45 +00:00
|
|
|
token_table const * find(token_table const & s, char c) {
|
2014-06-05 19:40:31 +00:00
|
|
|
return s.find(c);
|
|
|
|
}
|
2014-06-10 16:11:45 +00:00
|
|
|
token_info const * value_of(token_table const & s) {
|
2014-06-05 19:40:31 +00:00
|
|
|
return s.value();
|
2014-06-03 09:34:12 +00:00
|
|
|
}
|
2014-06-15 05:13:25 +00:00
|
|
|
optional<unsigned> get_precedence(token_table const & s, char const * token) {
|
|
|
|
auto it = find(s, token);
|
|
|
|
return it ? optional<unsigned>(it->precedence()) : optional<unsigned>();
|
|
|
|
}
|
2014-06-10 16:11:45 +00:00
|
|
|
void for_each(token_table const & s, std::function<void(char const *, token_info const &)> const & fn) {
|
2014-06-09 23:49:22 +00:00
|
|
|
s.for_each([&](unsigned num, char const * keys, token_info const & info) {
|
|
|
|
buffer<char> str;
|
|
|
|
str.append(num, keys);
|
|
|
|
str.push_back(0);
|
|
|
|
fn(str.data(), info);
|
|
|
|
});
|
|
|
|
}
|
2014-07-07 16:31:42 +00:00
|
|
|
void display(std::ostream & out, token_table const & s) {
|
|
|
|
for_each(s, [&](char const * token, token_info const & info) {
|
|
|
|
out << "`" << token << "`:" << info.precedence();
|
|
|
|
if (info.is_command())
|
|
|
|
out << " [command]";
|
|
|
|
if (info.value() != info.token())
|
|
|
|
out << " " << info.value();
|
|
|
|
out << "\n";
|
|
|
|
});
|
|
|
|
}
|
2014-06-09 23:49:22 +00:00
|
|
|
|
2014-06-03 09:34:12 +00:00
|
|
|
static char const * g_lambda_unicode = "\u03BB";
|
|
|
|
static char const * g_pi_unicode = "\u03A0";
|
|
|
|
static char const * g_forall_unicode = "\u2200";
|
|
|
|
static char const * g_arrow_unicode = "\u2192";
|
2014-06-12 16:08:38 +00:00
|
|
|
static char const * g_cup = "\u2294";
|
|
|
|
|
2014-06-11 17:56:04 +00:00
|
|
|
token_table init_token_table() {
|
|
|
|
token_table t;
|
2014-06-14 00:30:35 +00:00
|
|
|
std::pair<char const *, unsigned> builtin[] =
|
2014-06-20 18:57:01 +00:00
|
|
|
{{"fun", 0}, {"Pi", 0}, {"let", 0}, {"in", 0}, {"have", 0}, {"show", 0}, {"by", 0}, {"then", 0},
|
2014-06-16 17:41:08 +00:00
|
|
|
{"from", 0}, {"(", g_max_prec}, {")", 0}, {"{", g_max_prec}, {"}", 0}, {"_", g_max_prec},
|
2014-06-29 19:24:13 +00:00
|
|
|
{"[", g_max_prec}, {"]", 0}, {"⦃", g_max_prec}, {"⦄", 0}, {".{", 0}, {"Type", g_max_prec}, {"|", 0}, {"!", 0}, {"with", 0},
|
2014-06-23 23:10:36 +00:00
|
|
|
{"...", 0}, {",", 0}, {".", 0}, {":", 0}, {"calc", 0}, {":=", 0}, {"--", 0}, {"#", 0},
|
2014-07-05 01:33:46 +00:00
|
|
|
{"(*", 0}, {"(--", 0}, {"proof", 0}, {"qed", 0}, {"@", g_max_prec}, {"including", 0},
|
2014-06-14 00:30:35 +00:00
|
|
|
{"+", g_plus_prec}, {g_cup, g_cup_prec}, {"->", g_arrow_prec}, {nullptr, 0}};
|
2014-06-05 20:05:40 +00:00
|
|
|
|
2014-06-26 15:08:39 +00:00
|
|
|
char const * commands[] = {"theorem", "axiom", "variable", "definition", "coercion",
|
2014-07-06 01:58:20 +00:00
|
|
|
"variables", "[private]", "[inline]", "[fact]", "[instance]", "[class]", "[module]",
|
|
|
|
"abbreviation", "opaque_hint", "evaluate", "check", "print", "end", "namespace", "section", "import",
|
2014-06-12 16:08:38 +00:00
|
|
|
"abbreviation", "inductive", "record", "structure", "module", "universe",
|
2014-07-04 04:37:56 +00:00
|
|
|
"precedence", "infixl", "infixr", "infix", "postfix", "prefix", "notation",
|
|
|
|
"exit", "set_option", "using", "calc_subst", "calc_refl", "calc_trans",
|
2014-07-04 21:25:44 +00:00
|
|
|
"add_proof_qed", "reset_proof_qed", "#setline", "class", "instance", nullptr};
|
2014-06-05 20:05:40 +00:00
|
|
|
|
2014-06-11 17:56:04 +00:00
|
|
|
std::pair<char const *, char const *> aliases[] =
|
|
|
|
{{g_lambda_unicode, "fun"}, {"forall", "Pi"}, {g_forall_unicode, "Pi"}, {g_pi_unicode, "Pi"},
|
2014-06-13 22:13:32 +00:00
|
|
|
{nullptr, nullptr}};
|
2014-06-05 20:05:40 +00:00
|
|
|
|
2014-06-11 17:56:04 +00:00
|
|
|
std::pair<char const *, char const *> cmd_aliases[] =
|
|
|
|
{{"parameter", "variable"}, {"parameters", "variables"}, {"lemma", "theorem"},
|
|
|
|
{"hypothesis", "axiom"}, {"conjecture", "axiom"}, {"corollary", "theorem"},
|
|
|
|
{nullptr, nullptr}};
|
2014-06-05 20:05:40 +00:00
|
|
|
|
2014-06-11 17:56:04 +00:00
|
|
|
auto it = builtin;
|
2014-06-14 00:30:35 +00:00
|
|
|
while (it->first) {
|
|
|
|
t = add_token(t, it->first, it->second);
|
2014-06-11 17:56:04 +00:00
|
|
|
it++;
|
|
|
|
}
|
2014-06-05 20:05:40 +00:00
|
|
|
|
2014-06-14 00:30:35 +00:00
|
|
|
auto it2 = commands;
|
|
|
|
while (*it2) {
|
|
|
|
t = add_command_token(t, *it2);
|
|
|
|
++it2;
|
2014-06-11 17:56:04 +00:00
|
|
|
}
|
2014-06-05 20:05:40 +00:00
|
|
|
|
2014-06-14 00:30:35 +00:00
|
|
|
auto it3 = aliases;
|
|
|
|
while (it3->first) {
|
|
|
|
t = add_token(t, it3->first, it3->second);
|
|
|
|
it3++;
|
2014-06-11 17:56:04 +00:00
|
|
|
}
|
2014-06-13 22:13:32 +00:00
|
|
|
t = add_token(t, g_arrow_unicode, "->", get_arrow_prec());
|
2014-06-05 20:05:40 +00:00
|
|
|
|
2014-06-14 00:30:35 +00:00
|
|
|
auto it4 = cmd_aliases;
|
|
|
|
while (it4->first) {
|
|
|
|
t = add_command_token(t, it4->first, it4->second);
|
|
|
|
++it4;
|
2014-06-03 09:34:12 +00:00
|
|
|
}
|
2014-06-11 17:56:04 +00:00
|
|
|
return t;
|
|
|
|
}
|
|
|
|
|
|
|
|
token_table mk_default_token_table() {
|
|
|
|
static optional<token_table> r;
|
|
|
|
if (!r)
|
|
|
|
r = init_token_table();
|
|
|
|
return *r;
|
|
|
|
}
|
|
|
|
|
|
|
|
static token_table g_init(mk_default_token_table());
|
|
|
|
|
2014-06-10 16:11:45 +00:00
|
|
|
token_table mk_token_table() { return token_table(); }
|
2014-06-09 23:49:22 +00:00
|
|
|
|
2014-06-10 16:11:45 +00:00
|
|
|
DECL_UDATA(token_table)
|
|
|
|
static int mk_token_table(lua_State * L) { return push_token_table(L, mk_token_table()); }
|
|
|
|
static int mk_default_token_table(lua_State * L) { return push_token_table(L, mk_default_token_table()); }
|
2014-06-09 23:49:22 +00:00
|
|
|
static int add_command_token(lua_State * L) {
|
|
|
|
int nargs = lua_gettop(L);
|
|
|
|
if (nargs == 2)
|
2014-06-10 16:11:45 +00:00
|
|
|
return push_token_table(L, add_command_token(to_token_table(L, 1), lua_tostring(L, 2)));
|
2014-06-09 23:49:22 +00:00
|
|
|
else
|
2014-06-10 16:11:45 +00:00
|
|
|
return push_token_table(L, add_command_token(to_token_table(L, 1), lua_tostring(L, 2), lua_tostring(L, 3)));
|
2014-06-09 23:49:22 +00:00
|
|
|
}
|
|
|
|
static int add_token(lua_State * L) {
|
|
|
|
int nargs = lua_gettop(L);
|
|
|
|
if (nargs == 3)
|
2014-06-10 16:11:45 +00:00
|
|
|
return push_token_table(L, add_token(to_token_table(L, 1), lua_tostring(L, 2), lua_tonumber(L, 3)));
|
2014-06-09 23:49:22 +00:00
|
|
|
else
|
2014-06-10 16:11:45 +00:00
|
|
|
return push_token_table(L, add_token(to_token_table(L, 1), lua_tostring(L, 2), lua_tostring(L, 3), lua_tonumber(L, 4)));
|
2014-06-09 23:49:22 +00:00
|
|
|
}
|
|
|
|
static int merge(lua_State * L) {
|
2014-06-10 16:11:45 +00:00
|
|
|
return push_token_table(L, merge(to_token_table(L, 1), to_token_table(L, 2)));
|
2014-06-09 23:49:22 +00:00
|
|
|
}
|
|
|
|
static int find(lua_State * L) {
|
|
|
|
char k;
|
|
|
|
if (lua_isnumber(L, 2)) {
|
|
|
|
k = lua_tonumber(L, 2);
|
|
|
|
} else {
|
|
|
|
char const * str = lua_tostring(L, 2);
|
|
|
|
if (strlen(str) != 1)
|
|
|
|
throw exception("arg #2 must be a string of length 1");
|
|
|
|
k = str[0];
|
|
|
|
}
|
2014-06-10 16:11:45 +00:00
|
|
|
auto it = to_token_table(L, 1).find(k);
|
2014-06-09 23:49:22 +00:00
|
|
|
if (it)
|
2014-06-10 16:11:45 +00:00
|
|
|
return push_token_table(L, *it);
|
2014-06-09 23:49:22 +00:00
|
|
|
else
|
|
|
|
return push_nil(L);
|
|
|
|
}
|
|
|
|
static int value_of(lua_State * L) {
|
2014-06-10 16:11:45 +00:00
|
|
|
auto it = value_of(to_token_table(L, 1));
|
2014-06-09 23:49:22 +00:00
|
|
|
if (it) {
|
|
|
|
push_boolean(L, it->is_command());
|
|
|
|
push_name(L, it->value());
|
|
|
|
push_integer(L, it->precedence());
|
|
|
|
return 3;
|
|
|
|
} else {
|
|
|
|
push_nil(L);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static int for_each(lua_State * L) {
|
2014-06-10 16:11:45 +00:00
|
|
|
token_table const & t = to_token_table(L, 1);
|
2014-06-09 23:49:22 +00:00
|
|
|
luaL_checktype(L, 2, LUA_TFUNCTION); // user-fun
|
|
|
|
for_each(t, [&](char const * k, token_info const & info) {
|
|
|
|
lua_pushvalue(L, 2);
|
|
|
|
lua_pushstring(L, k);
|
|
|
|
lua_pushboolean(L, info.is_command());
|
|
|
|
push_name(L, info.value());
|
|
|
|
lua_pushinteger(L, info.precedence());
|
|
|
|
pcall(L, 4, 0, 0);
|
|
|
|
});
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-06-10 16:11:45 +00:00
|
|
|
static const struct luaL_Reg token_table_m[] = {
|
|
|
|
{"__gc", token_table_gc},
|
2014-06-09 23:49:22 +00:00
|
|
|
{"add_command_token", safe_function<add_command_token>},
|
|
|
|
{"add_token", safe_function<add_token>},
|
|
|
|
{"merge", safe_function<merge>},
|
|
|
|
{"find", safe_function<find>},
|
|
|
|
{"value_of", safe_function<value_of>},
|
|
|
|
{"for_each", safe_function<for_each>},
|
|
|
|
{0, 0}
|
|
|
|
};
|
|
|
|
|
2014-06-10 16:11:45 +00:00
|
|
|
void open_token_table(lua_State * L) {
|
|
|
|
luaL_newmetatable(L, token_table_mt);
|
2014-06-09 23:49:22 +00:00
|
|
|
lua_pushvalue(L, -1);
|
|
|
|
lua_setfield(L, -2, "__index");
|
2014-06-10 16:11:45 +00:00
|
|
|
setfuncs(L, token_table_m, 0);
|
2014-06-09 23:49:22 +00:00
|
|
|
|
2014-06-10 16:11:45 +00:00
|
|
|
SET_GLOBAL_FUN(token_table_pred, "is_token_table");
|
|
|
|
SET_GLOBAL_FUN(mk_default_token_table, "default_token_table");
|
|
|
|
SET_GLOBAL_FUN(mk_token_table, "token_table");
|
2014-06-09 23:49:22 +00:00
|
|
|
}
|
2014-06-03 09:34:12 +00:00
|
|
|
}
|