feat(frontends/lean/parser): add parse_id method

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2014-06-11 15:07:20 -07:00
parent 1a67cc7293
commit 959c3ffc68
2 changed files with 145 additions and 5 deletions

View file

@ -5,11 +5,17 @@ Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura Author: Leonardo de Moura
*/ */
#include <string> #include <string>
#include <limits>
#include "util/interrupt.h" #include "util/interrupt.h"
#include "util/script_exception.h" #include "util/script_exception.h"
#include "util/sstream.h" #include "util/sstream.h"
#include "kernel/for_each_fn.h"
#include "library/io_state_stream.h" #include "library/io_state_stream.h"
#include "library/parser_nested_exception.h" #include "library/parser_nested_exception.h"
#include "library/aliases.h"
#include "library/private.h"
#include "library/choice.h"
#include "library/deep_copy.h"
#include "library/error_handling/error_handling.h" #include "library/error_handling/error_handling.h"
#include "frontends/lean/parser.h" #include "frontends/lean/parser.h"
@ -127,8 +133,36 @@ tag parser::get_tag(expr e) {
return t; return t;
} }
void parser::save_pos(expr e, pos_info p) { expr parser::save_pos(expr e, pos_info p) {
m_pos_table->insert(mk_pair(get_tag(e), p)); m_pos_table->insert(mk_pair(get_tag(e), p));
return e;
}
expr parser::rec_save_pos(expr const & e, pos_info p) {
unsigned m = std::numeric_limits<unsigned>::max();
pos_info dummy(m, 0);
for_each(e, [&](expr const & e, unsigned) {
if (pos_of(e, dummy).first == m) {
save_pos(e, p);
return true;
} else {
return false;
}
});
return e;
}
/** \brief Create a copy of \c e, and the position of new expression with p */
expr parser::copy_with_new_pos(expr const & e, pos_info p) {
return rec_save_pos(deep_copy(e), p);
}
pos_info parser::pos_of(expr const & e, pos_info default_pos) {
auto it = m_pos_table->find(get_tag(e));
if (it == m_pos_table->end())
return default_pos;
else
return it->second;
} }
bool parser::curr_is_token(name const & tk) const { bool parser::curr_is_token(name const & tk) const {
@ -137,13 +171,100 @@ bool parser::curr_is_token(name const & tk) const {
get_token_info().value() == tk; get_token_info().value() == tk;
} }
static name g_period("."); expr parser::mk_app(expr fn, expr arg, pos_info const & p) {
return save_pos(::lean::mk_app(fn, arg), p);
}
expr parser::parse_expr(unsigned /* rbp */) { // expr parser::copy_expr(expr const & e, pos_info const & p) {
// TODO(Leo): // return replace(e, [](
// }
expr parser::parse_nud_keyword() {
// TODO(Leo)
return expr(); return expr();
} }
expr parser::parse_led_keyword(expr /* left */) {
// TODO(Leo)
return expr();
}
expr parser::parse_id() {
auto p = pos();
name id = get_name_val();
next();
auto it1 = m_local_decls.find(id);
// locals
if (it1 != m_local_decls.end())
return copy_with_new_pos(it1->second.first, p);
// globals
if (m_env.find(id))
return save_pos(mk_constant(id), p);
// private globals
if (auto prv_id = user_to_hidden_name(m_env, id))
return save_pos(mk_constant(*prv_id), p);
// aliases
auto as = get_aliases(m_env, id);
if (!is_nil(as)) {
buffer<expr> new_as;
for (auto const & e : as)
new_as.push_back(copy_with_new_pos(e, p));
return mk_choice(new_as.size(), new_as.data());
}
throw parser_error(sstream() << "unknown identifier '" << id << "'", p);
}
expr parser::parse_numeral_expr() {
// TODO(Leo)
return expr();
}
expr parser::parse_decimal_expr() {
// TODO(Leo)
return expr();
}
expr parser::parse_string_expr() {
// TODO(Leo)
return expr();
}
expr parser::parse_nud() {
switch (curr()) {
case scanner::token_kind::Keyword: return parse_nud_keyword();
case scanner::token_kind::Identifier: return parse_id();
case scanner::token_kind::Numeral: return parse_numeral_expr();
case scanner::token_kind::Decimal: return parse_decimal_expr();
case scanner::token_kind::String: return parse_string_expr();
default: throw parser_error("invalid expression, unexpected token", pos());
}
}
expr parser::parse_led(expr left) {
switch (curr()) {
case scanner::token_kind::Keyword: return parse_led_keyword(left);
case scanner::token_kind::Identifier: return mk_app(left, parse_id(), pos_of(left));
case scanner::token_kind::Numeral: return mk_app(left, parse_numeral_expr(), pos_of(left));
case scanner::token_kind::Decimal: return mk_app(left, parse_decimal_expr(), pos_of(left));
case scanner::token_kind::String: return mk_app(left, parse_string_expr(), pos_of(left));
default: return left;
}
}
unsigned parser::curr_lbp() const {
if (curr() == scanner::token_kind::Keyword)
return get_token_info().precedence();
else
return 0;
}
expr parser::parse_expr(unsigned rbp) {
expr left = parse_nud();
while (rbp < curr_lbp()) {
left = parse_led(left);
}
return left;
}
expr parser::parse_scoped_expr(unsigned num_locals, expr const * locals, unsigned rbp) { expr parser::parse_scoped_expr(unsigned num_locals, expr const * locals, unsigned rbp) {
local_decls::mk_scope scope(m_local_decls); local_decls::mk_scope scope(m_local_decls);
for (unsigned i = 0; i < num_locals; i++) { for (unsigned i = 0; i < num_locals; i++) {
@ -184,7 +305,10 @@ void parser::parse_script(bool as_expr) {
}); });
} }
static name g_period(".");
bool parser::parse_commands() { bool parser::parse_commands() {
// We disable hash-consing while parsing to make sure the pos-info are correct.
scoped_expr_caching disable(false);
try { try {
bool done = false; bool done = false;
while (!done) { while (!done) {

View file

@ -86,15 +86,28 @@ class parser {
} }
tag get_tag(expr e); tag get_tag(expr e);
expr copy_with_new_pos(expr const & e, pos_info p);
void updt_options(); void updt_options();
parser_config const & cfg() const { return get_parser_config(env()); } parser_config const & cfg() const { return get_parser_config(env()); }
cmd_table const & cmds() const { return cfg().m_cmds; } cmd_table const & cmds() const { return cfg().m_cmds; }
parse_table const & nud() const { return cfg().m_nud; }
parse_table const & led() const { return cfg().m_led; }
void parse_command(); void parse_command();
void parse_script(bool as_expr = false); void parse_script(bool as_expr = false);
bool parse_commands(); bool parse_commands();
unsigned curr_lbp() const;
expr parse_nud();
expr parse_led(expr left);
expr parse_nud_keyword();
expr parse_led_keyword(expr left);
expr parse_id();
expr parse_numeral_expr();
expr parse_decimal_expr();
expr parse_string_expr();
expr mk_app(expr fn, expr arg, pos_info const & p);
public: public:
parser(environment const & env, io_state const & ios, parser(environment const & env, io_state const & ios,
@ -115,7 +128,10 @@ public:
/** \brief Return the current position information */ /** \brief Return the current position information */
pos_info pos() const { return pos_info(m_scanner.get_line(), m_scanner.get_pos()); } pos_info pos() const { return pos_info(m_scanner.get_line(), m_scanner.get_pos()); }
void save_pos(expr e, pos_info p); expr save_pos(expr e, pos_info p);
expr rec_save_pos(expr const & e, pos_info p);
pos_info pos_of(expr const & e, pos_info default_pos);
pos_info pos_of(expr const & e) { return pos_of(e, pos()); }
/** \brief Read the next token. */ /** \brief Read the next token. */
void scan() { m_curr = m_scanner.scan(m_env); } void scan() { m_curr = m_scanner.scan(m_env); }