2026-10-02 20:31:24 +03:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <iostream>
|
2026-10-02 22:14:03 +03:00
|
|
|
#include <sstream>
|
2026-10-02 20:31:24 +03:00
|
|
|
#include <memory>
|
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
|
|
namespace Expression {
|
|
|
|
|
|
|
|
|
|
class Token {
|
|
|
|
|
public:
|
|
|
|
|
enum TokenType {
|
|
|
|
|
VAR,
|
|
|
|
|
CONST,
|
2026-10-05 11:17:48 +03:00
|
|
|
OPERATOR,
|
|
|
|
|
CV, // compound value (result of an operation)
|
|
|
|
|
NAT, // not a token
|
2026-10-02 20:31:24 +03:00
|
|
|
} t;
|
|
|
|
|
|
|
|
|
|
enum Operator {
|
|
|
|
|
OPA, // opening parentheses
|
|
|
|
|
CPA, // closing parentheses
|
|
|
|
|
ADD,
|
|
|
|
|
SUB,
|
|
|
|
|
MUL,
|
|
|
|
|
DIV,
|
|
|
|
|
POW
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
union TokenValue {
|
|
|
|
|
std::shared_ptr<std::string> s;
|
|
|
|
|
double d;
|
|
|
|
|
Operator o;
|
2026-10-05 11:17:48 +03:00
|
|
|
struct {
|
|
|
|
|
int w; // weight
|
|
|
|
|
int i; // index in operation vector
|
|
|
|
|
} cv;
|
2026-10-02 20:31:24 +03:00
|
|
|
|
|
|
|
|
explicit TokenValue(std::string& s)
|
|
|
|
|
: s(std::make_shared<std::string>(s))
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
explicit TokenValue(double d)
|
|
|
|
|
: d(d)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
explicit TokenValue(enum Operator o)
|
|
|
|
|
: o(o)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
explicit TokenValue(void)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~TokenValue(void)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
} v;
|
|
|
|
|
|
2026-10-04 14:13:14 +03:00
|
|
|
Token(void)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2026-10-02 20:31:24 +03:00
|
|
|
Token(std::string s)
|
|
|
|
|
: v(s)
|
|
|
|
|
{
|
|
|
|
|
t = VAR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Token(double d)
|
|
|
|
|
: v(d)
|
|
|
|
|
{
|
|
|
|
|
t = CONST;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Token(enum Operator o)
|
|
|
|
|
: v(o)
|
|
|
|
|
{
|
|
|
|
|
t = OPERATOR;
|
|
|
|
|
}
|
|
|
|
|
|
2026-10-05 11:17:48 +03:00
|
|
|
Token(const Expression::Token& other)
|
|
|
|
|
{
|
|
|
|
|
t = other.t;
|
|
|
|
|
|
|
|
|
|
switch (t)
|
|
|
|
|
{
|
|
|
|
|
case VAR:
|
|
|
|
|
v.s = other.v.s;
|
|
|
|
|
break;
|
|
|
|
|
case CONST:
|
|
|
|
|
v.d = other.v.d;
|
|
|
|
|
break;
|
|
|
|
|
case OPERATOR:
|
|
|
|
|
v.o = other.v.o;
|
|
|
|
|
break;
|
2026-10-05 20:24:09 +03:00
|
|
|
case CV:
|
|
|
|
|
v.cv.w = other.v.cv.w;
|
|
|
|
|
v.cv.i = other.v.cv.i;
|
|
|
|
|
break;
|
|
|
|
|
case NAT:
|
|
|
|
|
break;
|
2026-10-05 11:17:48 +03:00
|
|
|
default:
|
|
|
|
|
std::cout << "Warning: token type is invalid\n";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-10-02 20:31:24 +03:00
|
|
|
Token(Expression::Token&& other)
|
|
|
|
|
{
|
|
|
|
|
t = other.t;
|
|
|
|
|
|
|
|
|
|
switch (t)
|
|
|
|
|
{
|
|
|
|
|
case VAR:
|
|
|
|
|
v.s = other.v.s;
|
|
|
|
|
break;
|
|
|
|
|
case CONST:
|
|
|
|
|
v.d = other.v.d;
|
|
|
|
|
break;
|
|
|
|
|
case OPERATOR:
|
|
|
|
|
v.o = other.v.o;
|
|
|
|
|
break;
|
2026-10-05 20:24:09 +03:00
|
|
|
case CV:
|
|
|
|
|
v.cv.w = other.v.cv.w;
|
|
|
|
|
v.cv.i = other.v.cv.i;
|
|
|
|
|
break;
|
|
|
|
|
case NAT:
|
|
|
|
|
break;
|
2026-10-02 20:31:24 +03:00
|
|
|
default:
|
|
|
|
|
std::cout << "Warning: token type is invalid\n";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-10-05 20:24:09 +03:00
|
|
|
Expression::Token& operator=(const Expression::Token& other)
|
|
|
|
|
{
|
|
|
|
|
t = other.t;
|
|
|
|
|
|
|
|
|
|
switch (t)
|
|
|
|
|
{
|
|
|
|
|
case VAR:
|
|
|
|
|
v.s = other.v.s;
|
|
|
|
|
break;
|
|
|
|
|
case CONST:
|
|
|
|
|
v.d = other.v.d;
|
|
|
|
|
break;
|
|
|
|
|
case OPERATOR:
|
|
|
|
|
v.o = other.v.o;
|
|
|
|
|
break;
|
|
|
|
|
case CV:
|
|
|
|
|
v.cv.w = other.v.cv.w;
|
|
|
|
|
v.cv.i = other.v.cv.i;
|
|
|
|
|
break;
|
|
|
|
|
case NAT:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
std::cout << "Warning: token type is invalid\n";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return const_cast<Expression::Token&>(other);
|
|
|
|
|
}
|
|
|
|
|
|
2026-10-02 22:14:03 +03:00
|
|
|
std::shared_ptr<std::string> to_str(void) const
|
|
|
|
|
{
|
|
|
|
|
switch (t)
|
|
|
|
|
{
|
|
|
|
|
case VAR:
|
|
|
|
|
return v.s;
|
|
|
|
|
case CONST:
|
|
|
|
|
{
|
|
|
|
|
char buffer[128] = {0};
|
|
|
|
|
return std::make_shared<std::string>((std::ostringstream() << v.d).str());
|
|
|
|
|
}
|
|
|
|
|
case OPERATOR:
|
|
|
|
|
return std::make_shared<std::string>("OP " + std::string(op_str()));
|
|
|
|
|
default:
|
|
|
|
|
return std::make_shared<std::string>("Not a valid token!");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-10-05 11:17:48 +03:00
|
|
|
std::shared_ptr<std::string> to_math_str(void) const
|
|
|
|
|
{
|
|
|
|
|
switch (t)
|
|
|
|
|
{
|
|
|
|
|
case VAR:
|
|
|
|
|
return v.s;
|
|
|
|
|
case CONST:
|
|
|
|
|
{
|
|
|
|
|
char buffer[128] = {0};
|
|
|
|
|
return std::make_shared<std::string>((std::ostringstream() << v.d).str());
|
|
|
|
|
}
|
|
|
|
|
case OPERATOR:
|
|
|
|
|
return std::make_shared<std::string>(op_math_str());
|
|
|
|
|
default:
|
|
|
|
|
return std::make_shared<std::string>("Not a valid token!");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-10-02 22:14:03 +03:00
|
|
|
const char *type_str(void) const
|
2026-10-02 20:31:24 +03:00
|
|
|
{
|
|
|
|
|
switch (t)
|
|
|
|
|
{
|
|
|
|
|
case VAR:
|
|
|
|
|
return "VAR";
|
|
|
|
|
case CONST:
|
|
|
|
|
return "CONST";
|
|
|
|
|
case OPERATOR:
|
|
|
|
|
return "OPERATOR";
|
|
|
|
|
default:
|
|
|
|
|
return "Not a valid type";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-10-02 22:14:03 +03:00
|
|
|
const char *op_str(void) const
|
2026-10-02 20:31:24 +03:00
|
|
|
{
|
|
|
|
|
if (t != OPERATOR)
|
|
|
|
|
{
|
|
|
|
|
return "Token is not an operator!";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (v.o)
|
|
|
|
|
{
|
|
|
|
|
case OPA:
|
|
|
|
|
return "OPA";
|
|
|
|
|
case CPA:
|
|
|
|
|
return "CPA";
|
|
|
|
|
case ADD:
|
|
|
|
|
return "ADD";
|
|
|
|
|
case SUB:
|
|
|
|
|
return "SUB";
|
|
|
|
|
case MUL:
|
|
|
|
|
return "MUL";
|
|
|
|
|
case DIV:
|
|
|
|
|
return "DIV";
|
|
|
|
|
case POW:
|
|
|
|
|
return "POW";
|
|
|
|
|
default:
|
|
|
|
|
return "Invalid operator";
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-10-05 11:17:48 +03:00
|
|
|
|
|
|
|
|
const char *op_math_str(void) const
|
|
|
|
|
{
|
|
|
|
|
if (t != OPERATOR)
|
|
|
|
|
{
|
|
|
|
|
return "Token is not an operator!";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (v.o)
|
|
|
|
|
{
|
|
|
|
|
case OPA:
|
|
|
|
|
return "(";
|
|
|
|
|
case CPA:
|
|
|
|
|
return ")";
|
|
|
|
|
case ADD:
|
|
|
|
|
return "+";
|
|
|
|
|
case SUB:
|
|
|
|
|
return "-";
|
|
|
|
|
case MUL:
|
|
|
|
|
return "*";
|
|
|
|
|
case DIV:
|
|
|
|
|
return "/";
|
|
|
|
|
case POW:
|
|
|
|
|
return "^";
|
|
|
|
|
default:
|
|
|
|
|
return "Invalid operator";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct Operation
|
|
|
|
|
{
|
|
|
|
|
Token o; // operator
|
|
|
|
|
|
|
|
|
|
enum Type
|
|
|
|
|
{
|
|
|
|
|
NORMAL,
|
|
|
|
|
DERIVED,
|
|
|
|
|
} tl, tr; // type left, type right
|
|
|
|
|
|
|
|
|
|
int il, ir; // index left, index right
|
|
|
|
|
int w; // operation weight
|
|
|
|
|
|
|
|
|
|
Operation(enum Expression::Token::Operator o, enum Type tl, int il, enum Type tr, int ir, int w)
|
|
|
|
|
: o(o), tl(tl), tr(tr), il(il), ir(ir), w(w)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
2026-10-02 20:31:24 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class TreeNode {
|
2026-10-04 14:13:14 +03:00
|
|
|
public:
|
|
|
|
|
TreeNode *l; // left hand
|
|
|
|
|
TreeNode *r; // right hand
|
2026-10-07 16:15:42 +03:00
|
|
|
Token o; // if operator, left and right hands are valid
|
|
|
|
|
// if value, left and right hands should be null
|
|
|
|
|
|
|
|
|
|
explicit TreeNode(void)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
explicit TreeNode(const Token t)
|
|
|
|
|
: o(t)
|
|
|
|
|
{
|
|
|
|
|
}
|
2026-10-04 14:13:14 +03:00
|
|
|
|
|
|
|
|
~TreeNode()
|
|
|
|
|
{
|
|
|
|
|
if (l != nullptr)
|
|
|
|
|
{
|
|
|
|
|
delete l;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (r != nullptr)
|
|
|
|
|
{
|
|
|
|
|
delete r;
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-10-02 20:31:24 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
}
|