2013-08-03 17:58:05 +00:00
|
|
|
/*
|
|
|
|
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
|
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
|
|
|
|
|
|
Author: Leonardo de Moura
|
|
|
|
*/
|
2013-08-10 21:15:13 +00:00
|
|
|
#include <cstdio>
|
2013-08-13 17:55:41 +00:00
|
|
|
#include <string>
|
|
|
|
#include <algorithm>
|
2013-09-13 03:04:10 +00:00
|
|
|
#include "util/debug.h"
|
|
|
|
#include "util/exception.h"
|
2013-09-13 03:09:35 +00:00
|
|
|
#include "frontends/lean/scanner.h"
|
2013-08-03 17:58:05 +00:00
|
|
|
|
|
|
|
namespace lean {
|
|
|
|
|
2013-08-13 10:40:51 +00:00
|
|
|
static name g_lambda_unicode("\u03BB");
|
|
|
|
static name g_pi_unicode("\u03A0");
|
|
|
|
static name g_arrow_unicode("\u2192");
|
|
|
|
static name g_lambda_name("fun");
|
2013-08-13 10:52:08 +00:00
|
|
|
static name g_type_name("Type");
|
2013-08-13 17:55:41 +00:00
|
|
|
static name g_pi_name("Pi");
|
2013-08-18 22:03:58 +00:00
|
|
|
static name g_let_name("let");
|
|
|
|
static name g_in_name("in");
|
2013-08-13 10:40:51 +00:00
|
|
|
static name g_arrow_name("->");
|
2013-10-29 23:20:02 +00:00
|
|
|
static name g_eq_name("==");
|
2013-08-19 22:08:52 +00:00
|
|
|
static name g_forall_name("forall");
|
2013-12-29 10:44:49 +00:00
|
|
|
static name g_Forall_name("Forall");
|
2013-08-19 22:45:40 +00:00
|
|
|
static name g_forall_unicode("\u2200");
|
2013-08-19 22:08:52 +00:00
|
|
|
static name g_exists_name("exists");
|
2013-12-29 10:44:49 +00:00
|
|
|
static name g_Exists_name("Exists");
|
2013-08-19 22:08:52 +00:00
|
|
|
static name g_exists_unicode("\u2203");
|
2013-08-25 17:34:19 +00:00
|
|
|
static name g_placeholder_name("_");
|
2013-12-06 22:42:49 +00:00
|
|
|
static name g_show_name("show");
|
|
|
|
static name g_by_name("by");
|
2013-08-13 10:40:51 +00:00
|
|
|
|
2013-08-13 14:16:46 +00:00
|
|
|
static char g_normalized[256];
|
|
|
|
|
2013-08-15 17:46:13 +00:00
|
|
|
/** \brief Auxiliary class for initializing global variable \c g_normalized. */
|
2013-08-13 10:40:51 +00:00
|
|
|
class init_normalized_table {
|
2013-09-03 17:09:19 +00:00
|
|
|
void set(int i, char v) { g_normalized[static_cast<unsigned char>(i)] = v; }
|
2013-08-13 10:40:51 +00:00
|
|
|
public:
|
|
|
|
init_normalized_table() {
|
|
|
|
// by default all characters are in group c,
|
|
|
|
for (int i = 0; i <= 255; i++)
|
2013-08-13 14:16:46 +00:00
|
|
|
set(i, 'c');
|
2013-08-13 10:40:51 +00:00
|
|
|
|
|
|
|
// digits normalize to '0'
|
|
|
|
for (int i = '0'; i <= '9'; i++)
|
2013-08-13 14:16:46 +00:00
|
|
|
set(i, '0');
|
2013-08-13 10:40:51 +00:00
|
|
|
|
|
|
|
// characters that can be used to create ids of group a
|
|
|
|
for (int i = 'a'; i <= 'z'; i++)
|
2013-08-13 14:16:46 +00:00
|
|
|
set(i, 'a');
|
2013-08-13 10:40:51 +00:00
|
|
|
for (int i = 'A'; i <= 'Z'; i++)
|
2013-08-13 14:16:46 +00:00
|
|
|
set(i, 'a');
|
|
|
|
|
2013-09-07 00:12:35 +00:00
|
|
|
set('_', 'a');
|
|
|
|
set('\'', 'a');
|
2013-12-22 01:02:16 +00:00
|
|
|
set('@', 'a');
|
2013-12-30 11:29:20 +00:00
|
|
|
set('-', '-');
|
2013-08-13 10:40:51 +00:00
|
|
|
|
|
|
|
// characters that can be used to create ids of group b
|
2013-12-30 11:29:20 +00:00
|
|
|
for (unsigned char b : {'=', '<', '>', '^', '|', '&', '~', '+', '*', '/', '\\', '$', '%', '?', ';', '[', ']', '#'})
|
2013-08-13 14:16:46 +00:00
|
|
|
set(b, 'b');
|
2013-08-13 10:40:51 +00:00
|
|
|
|
|
|
|
// punctuation
|
2013-08-13 14:16:46 +00:00
|
|
|
set('(', '(');
|
|
|
|
set(')', ')');
|
|
|
|
set('{', '{');
|
|
|
|
set('}', '}');
|
|
|
|
set(':', ':');
|
|
|
|
set('.', '.');
|
|
|
|
set(',', ',');
|
2013-08-13 10:40:51 +00:00
|
|
|
|
|
|
|
// spaces
|
2013-08-13 14:16:46 +00:00
|
|
|
set(' ', ' ');
|
|
|
|
set('\t', ' ');
|
|
|
|
set('\r', ' ');
|
2013-08-13 10:40:51 +00:00
|
|
|
|
|
|
|
// new line
|
2013-08-13 14:16:46 +00:00
|
|
|
set('\n', '\n');
|
2013-08-13 10:40:51 +00:00
|
|
|
|
2013-08-13 17:55:41 +00:00
|
|
|
// double quotes for strings
|
|
|
|
set('\"', '\"');
|
|
|
|
|
2013-08-13 10:40:51 +00:00
|
|
|
// eof
|
2013-08-13 14:16:46 +00:00
|
|
|
set(255, -1);
|
2013-08-13 10:40:51 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static init_normalized_table g_init_normalized_table;
|
|
|
|
|
|
|
|
char normalize(char c) {
|
|
|
|
return g_normalized[static_cast<unsigned char>(c)];
|
|
|
|
}
|
|
|
|
|
|
|
|
scanner::scanner(std::istream& stream):
|
2013-08-03 17:58:05 +00:00
|
|
|
m_spos(0),
|
|
|
|
m_curr(0),
|
|
|
|
m_line(1),
|
|
|
|
m_pos(0),
|
2013-11-07 23:19:26 +00:00
|
|
|
m_stream(stream),
|
|
|
|
m_script_line(1),
|
|
|
|
m_script_pos(0) {
|
2013-08-13 10:40:51 +00:00
|
|
|
next();
|
2013-08-03 17:58:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
scanner::~scanner() {
|
|
|
|
}
|
|
|
|
|
2013-08-13 17:55:41 +00:00
|
|
|
void scanner::add_command_keyword(name const & n) {
|
|
|
|
m_commands = cons(n, m_commands);
|
|
|
|
}
|
|
|
|
|
|
|
|
void scanner::throw_exception(char const * msg) {
|
|
|
|
throw parser_exception(msg, m_line, m_spos);
|
|
|
|
}
|
|
|
|
|
2013-08-03 17:58:05 +00:00
|
|
|
void scanner::next() {
|
|
|
|
lean_assert(m_curr != EOF);
|
2013-08-13 10:40:51 +00:00
|
|
|
m_curr = m_stream.get();
|
|
|
|
m_spos++;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool scanner::check_next(char c) {
|
|
|
|
lean_assert(m_curr != EOF);
|
|
|
|
bool r = m_stream.get() == c;
|
|
|
|
m_stream.unget();
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2013-08-21 18:57:22 +00:00
|
|
|
bool scanner::check_next_is_digit() {
|
|
|
|
lean_assert(m_curr != EOF);
|
|
|
|
char c = m_stream.get();
|
|
|
|
bool r = '0' <= c && c <= '9';
|
|
|
|
m_stream.unget();
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2013-08-13 10:40:51 +00:00
|
|
|
void scanner::read_comment() {
|
|
|
|
int nest = 1;
|
|
|
|
while (true) {
|
|
|
|
if (curr() == '*') {
|
|
|
|
next();
|
|
|
|
if (curr() == ')') {
|
|
|
|
next();
|
|
|
|
nest--;
|
|
|
|
if (nest == 0)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else if (curr() == '(') {
|
|
|
|
next();
|
|
|
|
if (curr() == '*') {
|
|
|
|
next();
|
|
|
|
nest++;
|
|
|
|
}
|
|
|
|
} else if (curr() == '\n') {
|
|
|
|
new_line();
|
|
|
|
next();
|
|
|
|
} else if (curr() == EOF) {
|
2013-08-13 17:55:41 +00:00
|
|
|
throw_exception("unexpected end of comment");
|
2013-08-13 10:40:51 +00:00
|
|
|
} else {
|
|
|
|
next();
|
2013-08-03 17:58:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-05 16:52:46 +00:00
|
|
|
void scanner::read_single_line_comment() {
|
|
|
|
while (true) {
|
|
|
|
if (curr() == '\n') {
|
|
|
|
new_line();
|
|
|
|
next();
|
|
|
|
return;
|
|
|
|
} else if (curr() == EOF) {
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
next();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-13 10:40:51 +00:00
|
|
|
bool scanner::is_command(name const & n) const {
|
2013-08-13 17:55:41 +00:00
|
|
|
return std::any_of(m_commands.begin(), m_commands.end(), [&](name const & c) { return c == n; });
|
|
|
|
}
|
|
|
|
|
|
|
|
/** \brief Auxiliary function for #read_a_symbol */
|
|
|
|
name scanner::mk_name(name const & curr, std::string const & buf, bool only_digits) {
|
|
|
|
if (curr.is_anonymous()) {
|
|
|
|
lean_assert(!only_digits);
|
|
|
|
return name(buf.c_str());
|
|
|
|
} else if (only_digits) {
|
|
|
|
mpz val(buf.c_str());
|
|
|
|
if (!val.is_unsigned_int())
|
|
|
|
throw_exception("invalid hierarchical name, numeral is too big");
|
|
|
|
return name(curr, val.get_unsigned_int());
|
|
|
|
} else {
|
|
|
|
return name(curr, buf.c_str());
|
|
|
|
}
|
2013-08-03 17:58:05 +00:00
|
|
|
}
|
|
|
|
|
2013-08-13 10:40:51 +00:00
|
|
|
scanner::token scanner::read_a_symbol() {
|
|
|
|
lean_assert(normalize(curr()) == 'a');
|
|
|
|
m_buffer.clear();
|
|
|
|
m_buffer += curr();
|
|
|
|
m_name_val = name();
|
|
|
|
next();
|
2013-08-13 17:55:41 +00:00
|
|
|
bool only_digits = false;
|
2013-08-13 10:40:51 +00:00
|
|
|
while (true) {
|
|
|
|
if (normalize(curr()) == 'a') {
|
2013-08-13 17:55:41 +00:00
|
|
|
if (only_digits)
|
|
|
|
throw_exception("invalid hierarchical name, digit expected");
|
|
|
|
m_buffer += curr();
|
|
|
|
next();
|
|
|
|
} else if (normalize(curr()) == '0') {
|
2013-08-13 10:40:51 +00:00
|
|
|
m_buffer += curr();
|
|
|
|
next();
|
|
|
|
} else if (curr() == ':' && check_next(':')) {
|
|
|
|
next();
|
|
|
|
lean_assert(curr() == ':');
|
|
|
|
next();
|
2013-08-13 17:55:41 +00:00
|
|
|
m_name_val = mk_name(m_name_val, m_buffer, only_digits);
|
|
|
|
m_buffer.clear();
|
|
|
|
only_digits = (normalize(curr()) == '0');
|
2013-08-13 10:40:51 +00:00
|
|
|
} else {
|
2013-08-13 17:55:41 +00:00
|
|
|
m_name_val = mk_name(m_name_val, m_buffer, only_digits);
|
2013-12-29 10:44:49 +00:00
|
|
|
if (m_name_val == g_lambda_name) {
|
2013-08-13 10:40:51 +00:00
|
|
|
return token::Lambda;
|
2013-12-29 10:44:49 +00:00
|
|
|
} else if (m_name_val == g_pi_name) {
|
2013-08-13 10:40:51 +00:00
|
|
|
return token::Pi;
|
2013-12-29 10:44:49 +00:00
|
|
|
} else if (m_name_val == g_forall_name) {
|
2013-08-19 22:08:52 +00:00
|
|
|
return token::Forall;
|
2013-12-29 10:44:49 +00:00
|
|
|
} else if (m_name_val == g_exists_name) {
|
2013-08-19 22:08:52 +00:00
|
|
|
return token::Exists;
|
2013-12-29 10:44:49 +00:00
|
|
|
} else if (m_name_val == g_type_name) {
|
2013-08-13 10:52:08 +00:00
|
|
|
return token::Type;
|
2013-12-29 10:44:49 +00:00
|
|
|
} else if (m_name_val == g_let_name) {
|
2013-08-18 22:03:58 +00:00
|
|
|
return token::Let;
|
2013-12-29 10:44:49 +00:00
|
|
|
} else if (m_name_val == g_in_name) {
|
2013-08-18 22:03:58 +00:00
|
|
|
return token::In;
|
2013-12-29 10:44:49 +00:00
|
|
|
} else if (m_name_val == g_placeholder_name) {
|
2013-08-25 17:34:19 +00:00
|
|
|
return token::Placeholder;
|
2013-12-29 10:44:49 +00:00
|
|
|
} else if (m_name_val == g_show_name) {
|
2013-12-06 22:42:49 +00:00
|
|
|
return token::Show;
|
2013-12-29 10:44:49 +00:00
|
|
|
} else if (m_name_val == g_by_name) {
|
2013-12-06 22:42:49 +00:00
|
|
|
return token::By;
|
2013-12-29 10:44:49 +00:00
|
|
|
} else if (m_name_val == g_Forall_name) {
|
|
|
|
m_name_val = g_forall_name;
|
|
|
|
return token::Id;
|
|
|
|
} else if (m_name_val == g_Exists_name) {
|
|
|
|
m_name_val = g_exists_name;
|
|
|
|
return token::Id;
|
|
|
|
} else {
|
2013-08-13 10:40:51 +00:00
|
|
|
return is_command(m_name_val) ? token::CommandId : token::Id;
|
2013-12-29 10:44:49 +00:00
|
|
|
}
|
2013-08-13 10:40:51 +00:00
|
|
|
}
|
|
|
|
}
|
2013-08-03 17:58:05 +00:00
|
|
|
}
|
|
|
|
|
2013-12-30 11:29:20 +00:00
|
|
|
scanner::token scanner::read_b_symbol(char prev) {
|
|
|
|
lean_assert(normalize(curr()) == 'b' || curr() == '-');
|
2013-08-13 10:40:51 +00:00
|
|
|
m_buffer.clear();
|
2013-12-30 11:29:20 +00:00
|
|
|
if (prev != 0)
|
|
|
|
m_buffer += prev;
|
2013-08-13 10:40:51 +00:00
|
|
|
m_buffer += curr();
|
|
|
|
next();
|
|
|
|
while (true) {
|
2013-12-30 11:29:20 +00:00
|
|
|
if (normalize(curr()) == 'b' || curr() == '-') {
|
2013-08-13 10:40:51 +00:00
|
|
|
m_buffer += curr();
|
|
|
|
next();
|
|
|
|
} else {
|
|
|
|
m_name_val = name(m_buffer.c_str());
|
|
|
|
if (m_name_val == g_arrow_name)
|
|
|
|
return token::Arrow;
|
2013-08-13 10:52:08 +00:00
|
|
|
else if (m_name_val == g_eq_name)
|
|
|
|
return token::Eq;
|
2013-08-13 10:40:51 +00:00
|
|
|
else
|
|
|
|
return token::Id;
|
|
|
|
}
|
|
|
|
}
|
2013-08-03 17:58:05 +00:00
|
|
|
}
|
|
|
|
|
2013-08-13 10:40:51 +00:00
|
|
|
scanner::token scanner::read_c_symbol() {
|
|
|
|
lean_assert(normalize(curr()) == 'c');
|
|
|
|
m_buffer.clear();
|
|
|
|
m_buffer += curr();
|
|
|
|
next();
|
|
|
|
while (true) {
|
|
|
|
if (normalize(curr()) == 'c') {
|
|
|
|
m_buffer += curr();
|
|
|
|
next();
|
|
|
|
} else {
|
|
|
|
m_name_val = name(m_buffer.c_str());
|
|
|
|
if (m_name_val == g_arrow_unicode)
|
|
|
|
return token::Arrow;
|
|
|
|
else if (m_name_val == g_lambda_unicode)
|
|
|
|
return token::Lambda;
|
|
|
|
else if (m_name_val == g_pi_unicode)
|
|
|
|
return token::Pi;
|
2013-08-19 22:45:40 +00:00
|
|
|
else if (m_name_val == g_forall_unicode)
|
2013-08-19 22:08:52 +00:00
|
|
|
return token::Forall;
|
2013-08-19 22:45:40 +00:00
|
|
|
else if (m_name_val == g_exists_unicode)
|
2013-08-19 22:08:52 +00:00
|
|
|
return token::Exists;
|
2013-08-13 10:40:51 +00:00
|
|
|
else
|
|
|
|
return token::Id;
|
|
|
|
}
|
|
|
|
}
|
2013-08-03 17:58:05 +00:00
|
|
|
}
|
|
|
|
|
2013-12-30 11:29:20 +00:00
|
|
|
scanner::token scanner::read_number(bool pos) {
|
2013-08-13 10:40:51 +00:00
|
|
|
lean_assert('0' <= curr() && curr() <= '9');
|
|
|
|
mpq q(1);
|
|
|
|
m_num_val = curr() - '0';
|
|
|
|
next();
|
|
|
|
bool is_decimal = false;
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
char c = curr();
|
|
|
|
if ('0' <= c && c <= '9') {
|
|
|
|
m_num_val = 10*m_num_val + (c - '0');
|
|
|
|
if (is_decimal)
|
|
|
|
q *= 10;
|
|
|
|
next();
|
|
|
|
} else if (c == '.') {
|
2013-08-21 18:57:22 +00:00
|
|
|
// Num. is not a decimal. It should be at least Num.0
|
|
|
|
if (check_next_is_digit()) {
|
|
|
|
if (is_decimal)
|
|
|
|
break;
|
|
|
|
is_decimal = true;
|
|
|
|
next();
|
|
|
|
} else {
|
2013-08-13 10:40:51 +00:00
|
|
|
break;
|
2013-08-21 18:57:22 +00:00
|
|
|
}
|
2013-08-13 10:40:51 +00:00
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (is_decimal)
|
|
|
|
m_num_val /= q;
|
2013-12-30 11:29:20 +00:00
|
|
|
if (!pos)
|
|
|
|
m_num_val.neg();
|
|
|
|
return is_decimal ? token::DecimalVal : token::IntVal;
|
2013-08-03 17:58:05 +00:00
|
|
|
}
|
|
|
|
|
2013-08-13 17:55:41 +00:00
|
|
|
scanner::token scanner::read_string() {
|
|
|
|
lean_assert(curr() == '\"');
|
|
|
|
next();
|
|
|
|
m_buffer.clear();
|
|
|
|
while (true) {
|
|
|
|
char c = curr();
|
|
|
|
if (c == EOF) {
|
|
|
|
throw_exception("unexpected end of string");
|
|
|
|
} else if (c == '\"') {
|
|
|
|
next();
|
2013-08-18 01:13:55 +00:00
|
|
|
return token::StringVal;
|
2013-08-13 17:55:41 +00:00
|
|
|
} else if (c == '\n') {
|
|
|
|
new_line();
|
|
|
|
} else if (c == '\\') {
|
|
|
|
next();
|
|
|
|
c = curr();
|
|
|
|
if (c == EOF)
|
|
|
|
throw_exception("unexpected end of string");
|
2013-08-20 15:34:37 +00:00
|
|
|
if (c != '\\' && c != '\"' && c != 'n')
|
2013-08-13 17:55:41 +00:00
|
|
|
throw_exception("invalid escape sequence");
|
2013-08-20 15:34:37 +00:00
|
|
|
if (c == 'n')
|
|
|
|
c = '\n';
|
2013-08-13 17:55:41 +00:00
|
|
|
}
|
|
|
|
m_buffer += c;
|
|
|
|
next();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-07 21:56:04 +00:00
|
|
|
scanner::token scanner::read_script_block() {
|
2013-11-07 23:19:26 +00:00
|
|
|
m_script_line = m_line;
|
|
|
|
m_script_pos = m_pos;
|
2013-11-07 21:56:04 +00:00
|
|
|
m_buffer.clear();
|
|
|
|
while (true) {
|
2013-11-13 00:05:46 +00:00
|
|
|
char c1 = curr();
|
|
|
|
if (c1 == EOF)
|
2013-11-07 21:56:04 +00:00
|
|
|
throw_exception("unexpected end of script");
|
2013-11-13 00:05:46 +00:00
|
|
|
next();
|
|
|
|
if (c1 == '*') {
|
|
|
|
char c2 = curr();
|
2014-01-05 18:32:47 +00:00
|
|
|
next();
|
2013-11-13 00:05:46 +00:00
|
|
|
if (c2 == EOF)
|
2013-11-07 21:56:04 +00:00
|
|
|
throw_exception("unexpected end of script");
|
2014-01-05 18:32:47 +00:00
|
|
|
if (c2 == ')') {
|
|
|
|
return token::ScriptBlock;
|
2013-11-07 21:56:04 +00:00
|
|
|
} else {
|
2013-11-13 00:05:46 +00:00
|
|
|
if (c2 == '\n')
|
|
|
|
new_line();
|
|
|
|
m_buffer += c1;
|
|
|
|
m_buffer += c2;
|
2013-11-07 21:56:04 +00:00
|
|
|
}
|
|
|
|
} else {
|
2013-11-13 00:05:46 +00:00
|
|
|
if (c1 == '\n')
|
|
|
|
new_line();
|
|
|
|
m_buffer += c1;
|
2013-11-07 21:56:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-13 10:40:51 +00:00
|
|
|
scanner::token scanner::scan() {
|
|
|
|
while (true) {
|
|
|
|
char c = curr();
|
|
|
|
m_pos = m_spos;
|
|
|
|
switch (normalize(c)) {
|
|
|
|
case ' ': next(); break;
|
|
|
|
case '\n': next(); new_line(); break;
|
2013-08-13 10:52:08 +00:00
|
|
|
case ':': next();
|
|
|
|
if (curr() == '=') {
|
|
|
|
next();
|
|
|
|
return token::Assign;
|
|
|
|
} else {
|
|
|
|
return token::Colon;
|
|
|
|
}
|
2013-08-13 10:40:51 +00:00
|
|
|
case ',': next(); return token::Comma;
|
2014-01-02 18:53:14 +00:00
|
|
|
case '.':
|
|
|
|
next();
|
|
|
|
if (curr() == '.') {
|
|
|
|
next();
|
|
|
|
if (curr() != '.')
|
|
|
|
throw_exception("invalid character sequence, '...' ellipsis expected");
|
|
|
|
next();
|
|
|
|
return token::Ellipsis;
|
|
|
|
} else {
|
|
|
|
return token::Period;
|
|
|
|
}
|
2013-08-13 10:40:51 +00:00
|
|
|
case '(':
|
|
|
|
next();
|
|
|
|
if (curr() == '*') {
|
2013-11-13 00:05:46 +00:00
|
|
|
next();
|
2014-01-05 18:32:47 +00:00
|
|
|
return read_script_block();
|
2013-08-13 10:40:51 +00:00
|
|
|
} else {
|
|
|
|
return token::LeftParen;
|
|
|
|
}
|
2013-08-13 17:55:41 +00:00
|
|
|
case ')': next(); return token::RightParen;
|
2013-11-13 00:05:46 +00:00
|
|
|
case '{': next(); return token::LeftCurlyBracket;
|
2013-08-13 17:55:41 +00:00
|
|
|
case '}': next(); return token::RightCurlyBracket;
|
|
|
|
case 'a': return read_a_symbol();
|
2013-12-30 11:29:20 +00:00
|
|
|
case 'b': return read_b_symbol(0);
|
2013-08-13 17:55:41 +00:00
|
|
|
case 'c': return read_c_symbol();
|
2013-12-30 11:29:20 +00:00
|
|
|
case '-':
|
|
|
|
next();
|
|
|
|
if (normalize(curr()) == '0') {
|
|
|
|
return read_number(false);
|
2014-01-05 16:52:46 +00:00
|
|
|
} else if (curr() == '-') {
|
|
|
|
read_single_line_comment();
|
|
|
|
break;
|
|
|
|
} else if (normalize(curr()) == 'b') {
|
2013-12-30 11:29:20 +00:00
|
|
|
return read_b_symbol('-');
|
|
|
|
} else {
|
|
|
|
m_name_val = name("-");
|
|
|
|
return token::Id;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '0': return read_number(true);
|
2013-08-13 17:55:41 +00:00
|
|
|
case '\"': return read_string();
|
|
|
|
case -1: return token::Eof;
|
2013-11-11 17:19:38 +00:00
|
|
|
default: lean_unreachable(); // LCOV_EXCL_LINE
|
2013-08-13 10:40:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-08-13 17:55:41 +00:00
|
|
|
|
2013-08-13 10:40:51 +00:00
|
|
|
std::ostream & operator<<(std::ostream & out, scanner::token const & t) {
|
|
|
|
switch (t) {
|
|
|
|
case scanner::token::LeftParen: out << "("; break;
|
|
|
|
case scanner::token::RightParen: out << ")"; break;
|
|
|
|
case scanner::token::LeftCurlyBracket: out << "{"; break;
|
|
|
|
case scanner::token::RightCurlyBracket: out << "}"; break;
|
|
|
|
case scanner::token::Colon: out << ":"; break;
|
|
|
|
case scanner::token::Comma: out << ","; break;
|
|
|
|
case scanner::token::Period: out << "."; break;
|
|
|
|
case scanner::token::Lambda: out << g_lambda_unicode; break;
|
|
|
|
case scanner::token::Pi: out << g_pi_unicode; break;
|
2013-08-19 22:08:52 +00:00
|
|
|
case scanner::token::Forall: out << g_forall_unicode; break;
|
|
|
|
case scanner::token::Exists: out << g_exists_unicode; break;
|
2013-08-13 10:40:51 +00:00
|
|
|
case scanner::token::Arrow: out << g_arrow_unicode; break;
|
2013-08-18 22:03:58 +00:00
|
|
|
case scanner::token::Let: out << "let"; break;
|
|
|
|
case scanner::token::In: out << "in"; break;
|
2013-08-13 10:40:51 +00:00
|
|
|
case scanner::token::Id: out << "Id"; break;
|
|
|
|
case scanner::token::CommandId: out << "CId"; break;
|
2013-12-30 11:29:20 +00:00
|
|
|
case scanner::token::IntVal: out << "Int"; break;
|
2013-08-18 01:13:55 +00:00
|
|
|
case scanner::token::DecimalVal: out << "Dec"; break;
|
|
|
|
case scanner::token::StringVal: out << "String"; break;
|
2013-10-29 23:20:02 +00:00
|
|
|
case scanner::token::Eq: out << "=="; break;
|
2013-08-13 10:40:51 +00:00
|
|
|
case scanner::token::Assign: out << ":="; break;
|
2013-08-13 10:52:08 +00:00
|
|
|
case scanner::token::Type: out << "Type"; break;
|
2013-08-25 17:34:19 +00:00
|
|
|
case scanner::token::Placeholder: out << "_"; break;
|
2013-11-07 21:56:04 +00:00
|
|
|
case scanner::token::ScriptBlock: out << "Script"; break;
|
2013-12-06 22:42:49 +00:00
|
|
|
case scanner::token::Show: out << "show"; break;
|
|
|
|
case scanner::token::By: out << "by"; break;
|
2014-01-02 18:53:14 +00:00
|
|
|
case scanner::token::Ellipsis: out << "..."; break;
|
2013-08-13 10:40:51 +00:00
|
|
|
case scanner::token::Eof: out << "EOF"; break;
|
|
|
|
}
|
|
|
|
return out;
|
|
|
|
}
|
2013-08-03 17:58:05 +00:00
|
|
|
}
|