lean4-htt/src/tests/frontends/lean/parser.cpp
Leonardo de Moura ae01d3818d fix(frontends/lean/parser): parse_type method
The parser had a nasty ambiguity. For example,
    f Type 1
had two possible interpretations
    (f (Type) (1))
or
    (f (Type 1))

To fix this issue, whenever we want to specify a particular universe, we have to precede 'Type' with a parenthesis.
Examples:
    (Type 1)
    (Type U)
    (Type M + 1)

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
2013-12-19 15:24:34 -08:00

115 lines
4.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
*/
#include <sstream>
#include <memory>
#include "util/test.h"
#include "util/exception.h"
#include "util/numerics/mpq.h"
#include "kernel/builtin.h"
#include "kernel/printer.h"
#include "library/arith/arith.h"
#include "frontends/lean/parser.h"
#include "frontends/lean/frontend.h"
#include "frontends/lean/pp.h"
using namespace lean;
static void parse(environment const & env, io_state const & ios, char const * str) {
environment child = env->mk_child();
io_state ios_copy = ios;
std::istringstream in(str);
if (parse_commands(child, ios_copy, in)) {
formatter fmt = mk_pp_formatter(env);
std::for_each(child->begin_local_objects(),
child->end_local_objects(),
[&](object const & obj) {
std::cout << fmt(obj) << "\n";
std::cout << obj << "\n";
});
}
}
static void parse_error(environment const & env, io_state const & ios, char const * str) {
try {
parse(env, ios, str);
lean_unreachable();
} catch (exception & ex) {
std::cout << "expected error: " << ex.what() << "\n";
}
}
static void tst1() {
environment env; io_state ios; init_frontend(env, ios);
parse(env, ios, "Variable x : Bool Variable y : Bool Axiom H : x && y || x => x");
parse(env, ios, "Eval true && true");
parse(env, ios, "Show true && false Eval true && false");
parse(env, ios, "Infixl 35 & : and Show true & false & false Eval true & false");
parse(env, ios, "Notation 100 if _ then _ fi : implies Show if true then false fi");
parse(env, ios, "Show Pi (A : Type), A -> A");
parse(env, ios, "Check Pi (A : Type), A -> A");
}
static void check(environment const & env, io_state & ios, char const * str, expr const & expected) {
std::istringstream in(str);
try {
expr got = parse_expr(env, ios, in);
lean_assert(expected == got);
} catch (exception &) {
lean_unreachable();
}
}
static void tst2() {
environment env; io_state ios; init_frontend(env, ios);
env->add_var("x", Bool);
env->add_var("y", Bool);
env->add_var("z", Bool);
expr x = Const("x"); expr y = Const("y"); expr z = Const("z");
check(env, ios, "x && y", And(x, y));
check(env, ios, "x && y || z", Or(And(x, y), z));
check(env, ios, "x || y && z", Or(x, And(y, z)));
check(env, ios, "x || y || x && z", Or(x, Or(y, And(x, z))));
check(env, ios, "x || y || x && z => x && y", Implies(Or(x, Or(y, And(x, z))), And(x, y)));
check(env, ios, "x y x ∧ z ⇒ x ∧ y", Implies(Or(x, Or(y, And(x, z))), And(x, y)));
check(env, ios, "x⇒y⇒z⇒x", Implies(x, Implies(y, Implies(z, x))));
check(env, ios, "x=>y=>z=>x", Implies(x, Implies(y, Implies(z, x))));
check(env, ios, "x=>(y=>z)=>x", Implies(x, Implies(Implies(y, z), x)));
}
static void tst3() {
environment env; io_state ios; init_frontend(env, ios);
parse(env, ios, "Help");
parse(env, ios, "Help Options");
parse_error(env, ios, "Help Echo");
check(env, ios, "10.3", mk_real_value(mpq(103, 10)));
parse(env, ios, "Variable f : Real -> Real. Check f 10.3.");
parse(env, ios, "Variable g : (Type 1) -> Type. Check g Type");
parse_error(env, ios, "Check fun .");
parse_error(env, ios, "Definition foo .");
parse_error(env, ios, "Check a");
parse_error(env, ios, "Check U");
parse(env, ios, "Variable h : Real -> Real -> Real. Notation 10 [ _ ; _ ] : h. Check [ 10.3 ; 20.1 ].");
parse_error(env, ios, "Variable h : Real -> Real -> Real. Notation 10 [ _ ; _ ] : h. Check [ 10.3 | 20.1 ].");
parse_error(env, ios, "SetOption pp::indent true");
parse(env, ios, "SetOption pp::indent 10");
parse_error(env, ios, "SetOption pp::colors foo");
parse_error(env, ios, "SetOption pp::colors \"foo\"");
parse(env, ios, "SetOption pp::colors true");
parse_error(env, ios, "Notation 10 : Int::add");
parse_error(env, ios, "Notation 10 _ : Int::add");
parse(env, ios, "Notation 10 _ ++ _ : Int::add. Eval 10 ++ 20.");
parse(env, ios, "Notation 10 _ -- : Int::neg. Eval 10 --");
parse(env, ios, "Notation 30 -- _ : Int::neg. Eval -- 10");
parse_error(env, ios, "10 + 30");
}
int main() {
save_stack_info();
tst1();
tst2();
tst3();
return has_violations() ? 1 : 0;
}