Add terminal
This commit is contained in:
parent
e6a6de048d
commit
8798ee646d
@ -2,6 +2,7 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "mp/mp.hpp"
|
||||
#include "term/mpterm.hpp"
|
||||
|
||||
template <class T>
|
||||
static void PrintInt(const char* name, const T& val)
|
||||
@ -181,4 +182,7 @@ int main()
|
||||
}
|
||||
}
|
||||
|
||||
MpTerm<mp::UNLIMITED> term;
|
||||
term.run();
|
||||
|
||||
}
|
||||
@ -101,7 +101,7 @@ inline T factorial(const T& n)
|
||||
}
|
||||
|
||||
T result = 1;
|
||||
for (T i = 2; i <= n; ++i)
|
||||
for (T i = 2; i <= n; i += 1)
|
||||
{
|
||||
result *= i;
|
||||
}
|
||||
|
||||
169
src/term/mpterm.hpp
Normal file
169
src/term/mpterm.hpp
Normal file
@ -0,0 +1,169 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <iostream>
|
||||
#include <regex>
|
||||
#include <string>
|
||||
|
||||
#include "mp/int.hpp"
|
||||
#include "mp/lib.hpp"
|
||||
#include "mp/math.hpp"
|
||||
|
||||
template <size_t Size>
|
||||
class MpTerm
|
||||
{
|
||||
public:
|
||||
using MyInt = mp::Int<Size>;
|
||||
|
||||
MpTerm() = default;
|
||||
|
||||
void run()
|
||||
{
|
||||
const std::regex bin_op_regex(R"(^\s*([\-\+]?\d+|\$\d)\s*([\+\-\/\*])\s*([\-\+]?\d+|\$\d)\s*$)");
|
||||
const std::regex un_op_regex(R"(^\s*([\-\+]?\d+|\$\d)\s*([\!])\s*$)");
|
||||
|
||||
while (true)
|
||||
{
|
||||
std::cout << "> ";
|
||||
std::string line;
|
||||
if (!std::getline(std::cin, line))
|
||||
break;
|
||||
|
||||
if (line == "exit" || line == "quit")
|
||||
break;
|
||||
|
||||
if (line == "bank")
|
||||
{
|
||||
print_history();
|
||||
continue;
|
||||
}
|
||||
|
||||
std::smatch match;
|
||||
|
||||
if (std::regex_match(line, match, bin_op_regex))
|
||||
{
|
||||
binary_op(match[1], match[3], match[2].str()[0]);
|
||||
}
|
||||
else if (std::regex_match(line, match, un_op_regex))
|
||||
{
|
||||
if (match[2].str() == "!")
|
||||
{
|
||||
factorial(match[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Unknown unary operator." << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Invalid command format." << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void binary_op(const std::string& lhs_str, const std::string& rhs_str, char op)
|
||||
{
|
||||
MyInt lhs = parse_operand(lhs_str);
|
||||
MyInt rhs = parse_operand(rhs_str);
|
||||
|
||||
MyInt result;
|
||||
|
||||
try
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case '+':
|
||||
result = lhs + rhs;
|
||||
break;
|
||||
case '-':
|
||||
result = lhs - rhs;
|
||||
break;
|
||||
case '*':
|
||||
result = lhs * rhs;
|
||||
break;
|
||||
case '/':
|
||||
result = lhs / rhs;
|
||||
break;
|
||||
default:
|
||||
throw std::invalid_argument("Unknown operator");
|
||||
}
|
||||
|
||||
output(result);
|
||||
}
|
||||
catch (const mp::OverflowErrorOf<MyInt, MyInt>& e)
|
||||
{
|
||||
std::cout << "Warning: Result overflew" << std::endl;
|
||||
output(e.value());
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cout << "Error: " << e.what() << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void factorial(const std::string& operand_str)
|
||||
{
|
||||
MyInt operand = parse_operand(operand_str);
|
||||
|
||||
try
|
||||
{
|
||||
output(mp::factorial(operand));
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cout << "Error: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void output(const MyInt& value)
|
||||
{
|
||||
m_history[m_next] = value;
|
||||
m_next = (m_next + 1) % HISTORY;
|
||||
print_var(1);
|
||||
}
|
||||
|
||||
MyInt parse_operand(const std::string& token)
|
||||
{
|
||||
if (token.size() > 0 && token[0] == '$')
|
||||
{
|
||||
size_t idx = std::stoul(token.substr(1));
|
||||
return m_history[get_memory_idx(idx)];
|
||||
}
|
||||
else
|
||||
{
|
||||
return mp::from_string<Size>(token.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void print_history() const
|
||||
{
|
||||
for (size_t i = 1; i <= HISTORY; ++i)
|
||||
{
|
||||
print_var(i);
|
||||
}
|
||||
}
|
||||
|
||||
void print_var(size_t num) const
|
||||
{
|
||||
std::cout << '$' << num << " = " << mp::to_string(m_history[get_memory_idx(num)]) << std::endl;
|
||||
}
|
||||
|
||||
size_t get_memory_idx(size_t num) const
|
||||
{
|
||||
if (num == 0 || num > HISTORY)
|
||||
{
|
||||
throw std::out_of_range("Memory index out of range");
|
||||
}
|
||||
return (m_next + HISTORY - num) % HISTORY;
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr size_t HISTORY = 5;
|
||||
|
||||
std::array<MyInt, HISTORY> m_history;
|
||||
size_t m_next = 0;
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user