diff --git a/tc/CMakeLists.txt b/tc/CMakeLists.txt index 63812a6..f7c28c9 100644 --- a/tc/CMakeLists.txt +++ b/tc/CMakeLists.txt @@ -3,7 +3,6 @@ add_library(tc include/tc/cosets.hpp include/tc/group.hpp include/tc/groups.hpp - include/tc/lang.hpp include/tc/pair_map.hpp include/tc/util.hpp src/core.cpp @@ -17,9 +16,3 @@ add_library(tc::tc ALIAS tc) add_subdirectory(test) add_subdirectory(bench) - -add_executable(langtest src/langtest.cpp) -target_link_libraries(langtest PUBLIC tc::tc) - -add_executable(pegtest src/pegtest.cpp) -target_link_libraries(pegtest PUBLIC peglib::peglib fmt::fmt) diff --git a/tc/src/langtest.cpp b/tc/src/langtest.cpp deleted file mode 100644 index 1c3a58e..0000000 --- a/tc/src/langtest.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include - -#include -#include - -int main() { - std::vector symbols = { - "5 3 3", - "5 (3 3)", - "[5 3 3]", - "[4 3 [3 5] 3]", - "{3 4 5 6 7 8 9}", - "3 {3 3 [4] 3} 5", - "5 * 3", - "5 * [3]", - "5 * {2 3}", - "5 * [3 2]", - "(5 2) * [3 2]", - "4 [3 * [2 3]] 5", - "{3 * 3} [4] [5]", - }; - - for (const auto &symbol: symbols) { - auto group = tc::coxeter(symbol); - - std::cout << "'" << symbol << "'" << std::endl; - - for (int i = 0; i < group.ngens; ++i) { - for (int j = 0; j < group.ngens; ++j) { - std::cout << group.get(i, j) << " "; - } - std::cout << std::endl; - } - - std::cout << "===========================" << std::endl; - } - - return EXIT_SUCCESS; -} diff --git a/tc/src/pegtest.cpp b/tc/src/pegtest.cpp deleted file mode 100644 index 43a2805..0000000 --- a/tc/src/pegtest.cpp +++ /dev/null @@ -1,280 +0,0 @@ -#include -#include -#include - -#include -#include - -#include - -struct Op { - enum Code { - LINK, - PUSH, - POP, - LOOP, - }; - - Code code: 4; - unsigned int value: 12; - - explicit Op(Code code, unsigned int value = 0) - : code(code), value(value) {} -}; - -template<> -struct fmt::formatter { - template - constexpr auto parse(ParseContext &ctx) { - return ctx.begin(); - } - - template - auto format(const Op &op, FormatContext &ctx) { - switch (op.code) { - case Op::LINK: - return fmt::format_to(ctx.out(), "link({})", - (unsigned int) op.value); - case Op::PUSH: - return fmt::format_to(ctx.out(), "push()"); - case Op::POP: - return fmt::format_to(ctx.out(), "pop()"); - case Op::LOOP: - return fmt::format_to(ctx.out(), "loop()"); - default: - return fmt::format_to(ctx.out(), "[{}]({})", - (unsigned int) op.code, - (unsigned int) op.value); - } - } -}; - -struct Factor { - unsigned int mode; - std::vector orders; -}; - -struct codegen { - std::vector ops; - - void link(unsigned int order) { - ops.emplace_back(Op::LINK, order); - } - - void push() { - ops.emplace_back(Op::PUSH); - } - - void pop() { - ops.emplace_back(Op::POP); - } - - void loop() { - ops.emplace_back(Op::LOOP); - } - - template - void insert(It begin, It end) { - std::copy(begin, end, std::back_inserter(ops)); - } - - void insert(const codegen &o) { - insert(o.ops.begin(), o.ops.end()); - } -}; - -peg::parser build_parser() { - const auto grammar = R"( - root <- term+ - term <- product / op - op <- block / link - block <- '(' root ')' / '{' root '}' / '[' root ']' - link <- int - product <- op '*' factor - factor <- int / '{' int+ '}' / '[' int+ ']' - int <- < [0-9]+ > - - %whitespace <- [ \t\n\r]* - )"; - - peg::parser parser; - parser.set_logger([](size_t line, size_t col, const std::string &msg, const std::string &rule) { - fmt::print(stderr, "{}:{} [{}] {}\n", line, col, rule, msg); - }); - auto ok = parser.load_grammar(grammar); - assert(ok); - - parser["int"] = [](const peg::SemanticValues &vs) -> std::any { - return vs.token_to_number(); - }; - - parser["link"] = [](const peg::SemanticValues &vs) -> std::any { - codegen cg; - - auto order = std::any_cast(vs[0]); - cg.link(order); - - return cg; - }; - - parser["root"] = [](const peg::SemanticValues &vs) -> std::any { - codegen cg; - - for (const auto &sub: vs) { - cg.insert(std::any_cast(sub)); - } - - return cg; - }; - - parser["block"] = [](const peg::SemanticValues &vs) -> std::any { - if (vs.choice() == 0) return vs[0]; - - codegen cg; - - cg.push(); - cg.insert(std::any_cast(vs[0])); - if (vs.choice() == 1) cg.loop(); - cg.pop(); - - return cg; - }; - - parser["factor"] = [](const peg::SemanticValues &vs) -> std::any { - return Factor{ - (unsigned int) vs.choice(), - vs.transform(), - }; - }; - - parser["product"] = [](const peg::SemanticValues &vs) -> std::any { - auto sub = std::any_cast(vs[0]); - auto fac = std::any_cast(vs[1]); - - codegen cg; - - for (const auto &order: fac.orders) { - if (fac.mode == 0) { - for (unsigned int i = 0; i < order; ++i) { - cg.insert(sub); - } - } else { - cg.push(); - for (unsigned int i = 0; i < order; ++i) { - cg.insert(sub); - } - if (fac.mode == 1) cg.loop(); - cg.pop(); - } - } - - return cg; - }; - - return parser; -} - -std::vector compile(const std::string &source) { - static peg::parser parser = build_parser(); - - std::any val; - codegen cg; - - bool success = parser.parse(source, cg); - assert(success); - - return cg.ops; -} - -struct Graph { - size_t rank{}; - std::vector> edges{}; -}; - -Graph eval(const std::vector &ops) { - std::vector> stacks(1); - - Graph g; - stacks.back().emplace(g.rank++); - - for (const auto &op: ops) { - switch (op.code) { - case Op::LINK: { - auto order = op.value; - - auto top = stacks.back().top(); - auto curr = g.rank++; - - stacks.back().emplace(curr); - g.edges.emplace_back(top, curr, order); - - break; - } - case Op::PUSH: { - stacks.emplace_back(); - - auto ptop = stacks[stacks.size() - 2].top(); - stacks.back().emplace(ptop); - - break; - } - case Op::POP: { - stacks.pop_back(); - - break; - } - case Op::LOOP: { - g.rank--; - - auto ptop = stacks[stacks.size() - 2].top(); - auto &[top, _, order] = g.edges.back(); - - stacks.back().pop(); - g.edges.pop_back(); - - g.edges.emplace_back(top, ptop, order); - - break; - } - default: - throw std::runtime_error("Invalid opcode"); - } - } - - return g; -} - -int main() { - std::vector sources = { - "5 3 3", - "5 (3 3)", - "[5 3 3]", - "[4 3 [3 5] 3]", - "{3 4 3 5}", - "3 {3 3 [4] 3} 5", - "5 * 3", - "5 * [3]", - "5 * {2 3}", - "5 * [3 2]", - "(5 2) * [3 2]", - "4 [3 * [2 3]] 5", - "{3 * 3} [4] [5]", - }; - - for (const auto &source: sources) { - fmt::print("source: '{}'\n", source); - - auto ops = compile(source); - for (const auto &op: ops) { - fmt::print("- {}\n", op); - } - auto g = eval(ops); - fmt::print("rank: {}\n", g.rank); - for (const auto &edge: g.edges) { - fmt::print("- {}\n", edge); - } - fmt::print("=======================================\n"); - } - - return 0; -} diff --git a/tc/test/CMakeLists.txt b/tc/test/CMakeLists.txt index 74f7ebf..02fde42 100644 --- a/tc/test/CMakeLists.txt +++ b/tc/test/CMakeLists.txt @@ -6,6 +6,9 @@ target_link_libraries(test_pair_map tc GTest::gtest_main) add_executable(test_solve test_solve.cpp) target_link_libraries(test_solve tc GTest::gtest_main) +add_executable(test_lang test_lang.cpp) +target_link_libraries(test_lang PUBLIC tc::tc GTest::gtest_main) + set(MIN_DEBUG_CPS 200000) set(MIN_RELEASE_CPS 1000000) @@ -16,3 +19,4 @@ target_compile_definitions( gtest_discover_tests(test_pair_map) gtest_discover_tests(test_solve) +gtest_discover_tests(test_lang) diff --git a/tc/test/test_lang.cpp b/tc/test/test_lang.cpp new file mode 100644 index 0000000..fc083a4 --- /dev/null +++ b/tc/test/test_lang.cpp @@ -0,0 +1,45 @@ +#include +#include + +#include + +// "5 3 3" +// "5 (3 3)" +// "[5 3 3]" +// "[4 3 [3 5] 3]" +// "{3 4 5 6 7 8 9}" +// "3 {3 3 [4] 3} 5" +// "5 * 3" +// "5 * [3]" +// "5 * {2 3}" +// "5 * [3 2]" +// "(5 2) * [3 2]" +// "4 [3 * [2 3]] 5" +// "{3 * 3} [4] [5]" + +TEST(coxeter, simple) { + auto g = tc::coxeter("5 3 3"); + + ASSERT_EQ(g.ngens, 4); + + EXPECT_EQ(g.get(0, 1), 5); + EXPECT_EQ(g.get(1, 2), 3); + EXPECT_EQ(g.get(3, 4), 3); + + EXPECT_EQ(g.get(0, 2), 2); + EXPECT_EQ(g.get(0, 3), 2); + EXPECT_EQ(g.get(0, 4), 2); + EXPECT_EQ(g.get(1, 3), 2); + EXPECT_EQ(g.get(1, 4), 2); + EXPECT_EQ(g.get(2, 4), 2); +} + +TEST(coxeter, looping) { + auto g = tc::coxeter("{5 3 4}"); + + ASSERT_EQ(g.ngens, 3); + + EXPECT_EQ(g.get(0, 1), 5); + EXPECT_EQ(g.get(1, 2), 3); + EXPECT_EQ(g.get(2, 0), 4); +}