多元多项式的链式表式见严蔚敏数据结构教材
本文只给出基于这种表示的运算实现,包括加法和乘法
C++代码:(注意代码未经全面严格测试可能存在bug,在此列出代码仅为取得抛砖引玉的作用,笔者可能没有时间精力修改代码中的错误了)
#include <iostream>
#include <vector>
#include <string>
#include <memory>
#include <list>
#include "parse.h"
using namespace std;
struct Node
{
enum class type {sub, leaf} flag;
size_t order;
union
{
Node* sub_p;
long long cof;
};
Node* next = nullptr;
Node(size_t order, long long cof) :flag(type::leaf), order(order), cof(cof) {}
Node(size_t order) :flag(type::sub), order(order), sub_p(nullptr) {}
Node(Node& copy) :order(copy.order), flag(copy.flag)
{
if (flag == type::leaf)
{
cof = copy.cof;
}
else
{
sub_p = nullptr;
}
}
};
Node* constructPFromStr(const string& str, size_t level, size_t vary_num)
{
map<size_t, pair<list<pair<string,string>>, bool>> order_to_sub; //size_t 项的阶数左string系数,右string子项,bool list<pair<string,string>>里的pair是否为常数
size_t i = 0;
pair<token, string> result;
while (true)
{
size_t pre = i;
result = gettoken(str, i);
string cof = "";
if (result.first != token::identifier)
{
cof += str.substr(pre, i - pre);
result = gettoken(str, i);
}
else
{
cof = "1";
}
skip_token(str, i);
result = gettoken(str, i);
size_t order = stoul(result.second);
pre = i;
bool is_const = true;
for (size_t j = level + 1; j < vary_num; ++j)
{
skip_token(str, i);
skip_token(str, i);
result = gettoken(str, i);
if (result.second != "0")
is_const = false;
}
string sub_p = "";
sub_p += str.substr(pre, i - pre);
list<pair<string, string>> sub_p_list;
sub_p_list.push_back(make_pair(cof, sub_p));
pair<map<size_t, pair<list<pair<string, string>>, bool>>::iterator, bool> r;
if (is_const)
{
r = order_to_sub.insert(make_pair(order, make_pair(sub_p_list, true)));
}
else
{
r = order_to_sub.insert(make_pair(order, make_pair(sub_p_list, false)));
}
if (r.second == false)
{
r.first->second.first.push_back(make_pair(cof, sub_p));
if (is_const == false)
r.first->second.second = false;
}
result = gettoken(str, i);
if (result.first == token::end)
break;
}
Node* head = new Node(level);
Node* run = head;
for (map<size_t, pair<list<pair<string, string>>, bool>>::reverse_iterator it = order_to_sub.rbegin(); it != order_to_sub.rend(); ++it)
{
if (it->second.second == false)
{
string _str = "";
for (list<pair<string, string>>::iterator it2 = it->second.first.begin(); it2 != it->second.first.end(); ++it2)
{
if (it2 != it->second.first.begin())
{
_str += "+";
}
_str += (it2->first + it2->second);
}
Node* s_node = new Node(it->first);
s_node->sub_p = constructPFromStr(_str, level + 1, vary_num);
run->next = s_node;
run = s_node;
}
else
{
long long cof = 0;
for (list<pair<string, string>>::iterator it2 = it->second.first.begin(); it2 != it->second.first.end(); ++it2)
{
cof += stoll(it2->first);
}
Node* leaf = new Node(it->first, cof);
run->next = leaf;
run = leaf;
}
}
return head;
}
enum class Token {left_bracket, right_bracket, comma, digit, end};
pair<Token, long long> getNextToken(const string &str, string::size_type &i)
{
if (i == str.size())
{
return { Token::end, 0 };
}
if (str[i] == '(')
{
++i;
return { Token::left_bracket, 0 };
}
else if (str[i] == ')')
{
++i;
return { Token::right_bracket, 0 };
}
else if (str[i] == ',')
{
++i;
return {Token::comma, 0};
}
else if (str[i] == '-' || '0' <= str[i] && str[i] <='9')
{
string::size_type start = i;
++i;
if (str[start] == '-')
{
if (!(i < str.size() && ('1' <= str[i] && str[i] <= '9')))
{
cout << "-在上下文中非法!" << endl;
exit(-1);
}
++i;
}
else if (str[start] == '0')
{
return { Token::digit, 0 };
}
while (i < str.size() && ('0' <= str[i] && str[i] <= '9'))
{
++i;
}
return { Token::digit, stoll(str.substr(start, i - start)) };
}
else
{
cout << "非法字符!" << endl;
exit(-1);
}
}
void expectToken(const string& str, string::size_type& i, Token e, pair<Token, long long> &result)
{
string::size_type j = i;
result = getNextToken(str, i);
if (result.first == e)
return;
switch (e)
{
case Token::left_bracket: { cout << "索引" << j << "处非预期的词法记号,预期为左圆括号" << endl; exit(-1); }
case Token::right_bracket: { cout << "索引" << j << "处非预期的词法记号,预期为右圆括号" << endl; exit(-1); }
case Token::comma: { cout << "索引" << j << "处非预期的词法记号,预期为逗号" << endl; exit(-1); }
case Token::digit: { cout << "索引" << j << "处非预期的词法记号,预期为数字" << endl; exit(-1); }
case Token::end: { cout << "索引" << j << "处非预期的词法记号,预期为结束" << endl; exit(-1); }
}
}
void skipToken(const string& str, string::size_type& i)
{
if (getNextToken(str, i).first == Token::end)
{
cout << "ERROR:已没有更多的词法记号,skip失败!" << endl;
exit(-1);
}
} //该函数也可以设计为遇到错误返回false,而不是直接退出
void genPolynomialLegal(const string& str, string::size_type& i, size_t level, shared_ptr<size_t> *pre_leaf_level) //找到了叶子层数就在堆中分配否则为空指针pre_leaf_level
{
pair<Token, long long> result;
shared_ptr<size_t> pre_order = nullptr;
if (level == 0)
{
expectToken(str, i, Token::left_bracket, result);
}
size_t sub_start = i;
bool all_is_leaf = true;
while (true)
{
size_t pre = i;
result = getNextToken(str, i);
if (result.first == Token::digit || result.first == Token::left_bracket)
{
size_t order;
Token flag = result.first;
if (result.first == Token::left_bracket)
{
pre = i;
expectToken(str, i, Token::digit, result);
long long cof = result.second;
if (cof == 0)
{
cout << "位置:" << pre << "ERROR:系数不能等于0!" << endl;
exit(-1);
}
expectToken(str, i, Token::comma, result);
pre = i;
expectToken(str, i, Token::digit, result);
}
if (result.second < 0)
{
cout << "位置:" << pre << "ERROR:阶数不能小于0!" << endl;
exit(-1);
}
order = result.second;
if (pre_order == nullptr)
{
pre_order = make_shared<size_t>(order);
}
else
{
if (order >= *pre_order)
{
cout << "位置:" << pre << "ERROR:该阶数不能小于等于前一个阶数!" << endl;
exit(-1);
}
}
if (flag == Token::digit)
{
expectToken(str, i, Token::left_bracket, result);
genPolynomialLegal(str, i, level + 1, pre_leaf_level);
all_is_leaf = false;
}
else
{
expectToken(str, i, Token::right_bracket, result);
}
}
else
{
cout << "位置:" << pre << "ERROR:非预期的词法记号,预期为左括号或数字!" << endl;
exit(-1);
}
pre = i;
result = getNextToken(str, i);
if (result.first == Token::right_bracket)
{
if (all_is_leaf)
{
if (*pre_leaf_level == nullptr)
{
*pre_leaf_level = make_shared<size_t>(level);
}
else
{
if (**pre_leaf_level < level)
{
**pre_leaf_level = level;
}
}
}
return;
}
else if (result.first != Token::comma)
{
cout << "位置:" << pre << "ERROR:非预期的词法记号,预期为逗号或右括号!" << endl;
exit(-1);
}
}
}
//广义表外围大括号子表阶数从左至右从大到小排列,所有叶子在同一层,阶数不能为负,不允许空表
Node *genPolynomialList(const string& str, string::size_type& i, size_t level) //该函数假定表示多项式的广义表是合法的,故跳过最开始左括号,i从1开始, level从0开始
{
Node* head = new Node(level);
Node* run = head;
pair<Token, long long> result;
while (true)
{
result = getNextToken(str, i);
if (result.first == Token::digit)
{
size_t order = result.second;
Node* branch = new Node(order);
skipToken(str, i);
branch->sub_p = genPolynomialList(str, i, level + 1);
run->next = branch;
run = branch;;
}
else //此时token一定为左括号
{
long long cof = getNextToken(str, i).second;
skipToken(str, i);
size_t order = getNextToken(str, i).second;
Node* leaf = new Node(order, cof);
run->next = leaf;
run = leaf;
skipToken(str, i);
}
result = getNextToken(str, i);
if (result.first == Token::right_bracket)
{
return head;
}
}
}
struct PolynomialSeqExpressNode //2x^2y^3z^4 阶数234依次从左至右存放在order_list,cof为系数2
{
long long cof;
vector<size_t> order_list;
PolynomialSeqExpressNode(long long c, size_t o) :cof(c), order_list(o, 0) {}
};
//合法的用于初始化多元多项式链表表示的广义表字符串示例:(3((1,2),4((4,5),(2,4))),(9,8))
//3(---)表示子多项式,公因子变元阶数为3,括号内是子多项式的广义表表示,是递归定义的(9,8)表示系数为9阶数为8的叶子多项式表示
//同一层各表用,连接
class Polynomial
{
public:
Polynomial() = default;
Polynomial(const string& gen_str);
Polynomial(const string &gen_str, const vector<string> &variable_symbols);
Polynomial(const Polynomial& copy);
~Polynomial();
bool p_add(const Polynomial &add, Polynomial &result);
bool p_multiply(const Polynomial& add, Polynomial& result);
void print();
private:
Node* add(Node* left_head, Node* right_head);
Node* multiply(Node* left_head, Node* right_head);
Node* copy_polynomial(Node* head);
void delete_polynomial(Node *head);
Node* convert_leaf_to_sub(Node* leaf, size_t variable_symbols_index); //把一个leaf的Node节点转化为由一系列分支节点和最底层叶节点链接而成的多项式链表表示,变元索引variable_symbols_index
void compute_sub_p(Node* add_r, vector<Node*>& multiply_list, size_t m_order, Node* left_head);//从当前值开始往下递增
shared_ptr<list<PolynomialSeqExpressNode>> convert(Node* head);
Node* head = nullptr; //head不是实际头结点而是附加头结点,order域记录变元数目,sub_p域指向实际头结点
vector<string> variable_symbols; //顺序为zyx逆序排列 链表中的阶由大至小从左至右排列
};
Polynomial::Polynomial(const string& gen_str) //2x^2y^3z^1+---字符串,每一项固定为顺序xyz,xyz必须都有即便阶数为0,各项之间顺序任意,允许相同项
{
parse(gen_str, variable_symbols);
for (size_t i = 0; i < variable_symbols.size(); ++i)
{
for (size_t j = i + 1; j < variable_symbols.size(); ++j)
{
if (variable_symbols[i] == variable_symbols[j])
{
cout << "ERROR:不能有相同的变元标识符!" << endl;
exit(-1);
}
}
}
head = new Node(variable_symbols.size());
head->sub_p = constructPFromStr(gen_str, 0, variable_symbols.size());
}
shared_ptr<list<PolynomialSeqExpressNode>> Polynomial::convert(Node *_head) //head不是附加而是实际头结点
{
shared_ptr<list<PolynomialSeqExpressNode>> _list = make_shared<list<PolynomialSeqExpressNode>>();
Node* run = _head->next;
while (run != nullptr)
{
if (run->flag == Node::type::sub)
{
shared_ptr<list<PolynomialSeqExpressNode>> temp = convert(run->sub_p);
for (list<PolynomialSeqExpressNode>::iterator it = temp->begin(); it != temp->end(); ++it)
{
_list->push_back(*it);
_list->back().order_list.push_back(run->order);
}
}
else
{
PolynomialSeqExpressNode t(run->cof, head->order - _head->order);
t.order_list.back() = run->order;
_list->push_back(t);
}
run = run->next;
}
return _list;
}
void Polynomial::print()
{
if (head == nullptr)
cout << "NULL" << endl;
shared_ptr<list<PolynomialSeqExpressNode>> _list = convert(head->sub_p);
for (list<PolynomialSeqExpressNode>::iterator it = _list->begin(); it != _list->end(); ++it)
{
if (it != _list->begin())
cout << "+";
if (it->cof != 1)
cout << it->cof;
vector<size_t>& temp = it->order_list;
size_t index = head->order;
for (size_t i = 0; i < temp.size(); ++i)
{
--index;
if (temp[i] != 0)
cout << variable_symbols[index] << "^" << temp[i];
}
}
}
bool Polynomial::p_add(const Polynomial& be_add, Polynomial& result)
{
if (result.head != nullptr)
return false;
if (head != nullptr)
{
if (be_add.head != nullptr)
{
if (variable_symbols.size() != be_add.variable_symbols.size())
return false;
for (size_t i = 0; i < variable_symbols.size(); ++i)
{
if (variable_symbols[i] != be_add.variable_symbols[i])
{
return false;
}
}
Node *r = add(head->sub_p, be_add.head->sub_p);
if (r->next != nullptr)
{
result.head = new Node(variable_symbols.size());
result.head->sub_p = r;
}
}
else
{
result.head = new Node(variable_symbols.size());
result.head->sub_p = copy_polynomial(head->sub_p);
}
result.variable_symbols = variable_symbols;
}
else
{
if (be_add.head != nullptr)
{
result.head = new Node(be_add.variable_symbols.size());
result.head->sub_p = copy_polynomial(be_add.head->sub_p);
result.variable_symbols = be_add.variable_symbols;
}
}
return true;
}
bool Polynomial::p_multiply(const Polynomial& be_multiply, Polynomial& result)
{
if (result.head != nullptr)
return false;
if (head != nullptr)
{
if (be_multiply.head != nullptr)
{
if (variable_symbols.size() != be_multiply.variable_symbols.size())
return false;
for (size_t i = 0; i < variable_symbols.size(); ++i)
{
if (variable_symbols[i] != be_multiply.variable_symbols[i])
{
return false;
}
}
result.head = new Node(variable_symbols.size());
result.head->sub_p = multiply(head->sub_p, be_multiply.head->sub_p);
result.variable_symbols = variable_symbols;
}
}
return true;
}
Polynomial::~Polynomial()
{
if (head != nullptr)
{
delete_polynomial(head->sub_p);
delete head;
}
}
Polynomial::Polynomial(const string& gen_str, const vector<string>& variable_symbols) :variable_symbols(variable_symbols)
{
if (variable_symbols.empty())
{
cout << "ERROR:变元数组不能为空!" << endl;
exit(-1);
}
for (size_t i = 0; i < variable_symbols.size(); ++i)
{
if (variable_symbols[i].empty())
{
cout << "ERROR:变元标识符为空字符串!" << endl;
exit(-1);
}
if (!(variable_symbols[i][0] == '_' || isalpha(variable_symbols[i][0])))
{
cout << "ERROR:变元标识符必须以大小写字符或下划线开头!" << endl;
exit(-1);
}
for (string::size_type j = 1; j < variable_symbols[i].size(); ++j)
{
if (!(variable_symbols[i][j] == '_' || isalnum(variable_symbols[i][j])))
{
cout << "ERROR:变元标识符除首字符外的其他字符包含非下划线大小写字母或数字的字符!" << endl;
exit(-1);
}
}
}
for (size_t i = 0; i < variable_symbols.size(); ++i)
{
for (size_t j = i + 1; j < variable_symbols.size(); ++j)
{
if (variable_symbols[i] == variable_symbols[j])
{
cout << "ERROR:不能有相同的变元标识符!" << endl;
exit(-1);
}
}
}
string::size_type i = 0;
shared_ptr<size_t> pre_leaf_level = nullptr;
genPolynomialLegal(gen_str, i, 0, &pre_leaf_level);
if (i != gen_str.size())
{
cout << "ERROR:完整的广义表字符串后存在冗余字符!" << endl;
exit(-1);
}
if (*pre_leaf_level + 1 != variable_symbols.size())
{
cout << "ERROR:初始化字符串指定的变元个数和vector指示的变元个数不等!" << endl;
exit(-1);
}
i = 1;
Node *h = genPolynomialList(gen_str, i, 0);
head = new Node(variable_symbols.size());
head->sub_p = h;
}
Polynomial::Polynomial(const Polynomial& copy)
{
if (copy.head != nullptr)
{
variable_symbols = copy.variable_symbols;
head = new Node(variable_symbols.size());
head->sub_p = copy_polynomial(copy.head->sub_p);
}
}
Node* Polynomial::convert_leaf_to_sub(Node *leaf, size_t variable_symbols_index)
{
Node* _head = new Node(variable_symbols_index);
Node* run = _head;
while (variable_symbols_index < variable_symbols.size() - 1)
{
Node* _new = new Node(0);
run->next = _new;
_new->sub_p = new Node(++variable_symbols_index);
run = _new->sub_p;
}
run->next = new Node(0, leaf->cof);
return _head;
}
void Polynomial::compute_sub_p(Node* add_r, vector<Node*> &multiply_list, size_t m_order, Node* left_head)
{
if (multiply_list[m_order] == nullptr)
{
multiply_list[m_order] = add_r;
}
else
{
Node* r = nullptr;
if (multiply_list[m_order]->flag == Node::type::leaf)
{
r = convert_leaf_to_sub(multiply_list[m_order], left_head->order + 1);
delete multiply_list[m_order];
}
else
{
r = multiply_list[m_order];
}
Node* temp = add(r, add_r);
delete_polynomial(r);
delete_polynomial(add_r);
if (temp->next == nullptr)
{
delete_polynomial(temp);
multiply_list[m_order] = nullptr;
}
else
{
multiply_list[m_order] = temp;
}
}
}
Node* Polynomial::multiply(Node* left_head, Node* right_head)
{
Node* left = left_head->next;
Node* right = right_head->next;
size_t _order = left->order + right->order;
vector<Node*> multiply_list(_order + 1, nullptr);
while (left != nullptr)
{
while (right != nullptr)
{
size_t m_order = left->order + right->order;
Node* add_r = nullptr;
if (left->flag == Node::type::leaf)
{
if (right->flag == Node::type::leaf)
{
if (multiply_list[m_order] == nullptr)
{
multiply_list[m_order] = new Node(0, left->cof * right->cof);
}
else
{
if (multiply_list[m_order]->flag == Node::type::leaf)
{
long long d = left->cof * right->cof + multiply_list[m_order]->cof;
if (d == 0)
{
delete multiply_list[m_order];
multiply_list[m_order] = nullptr;
}
else
{
multiply_list[m_order]->cof = d;
}
}
else
{
Node *l = new Node(0, left->cof * right->cof);
Node* temp = convert_leaf_to_sub(l, left_head->order + 1);
delete l;
add_r = add(temp, multiply_list[m_order]);
delete_polynomial(temp);
delete_polynomial(multiply_list[m_order]);
if (add_r->next == 0)
{
delete_polynomial(add_r);
multiply_list[m_order] = nullptr;
}
else
{
multiply_list[m_order] = add_r;
}
}
}
right = right->next;
continue;
}
else
{
Node* temp = convert_leaf_to_sub(left, left_head->order + 1);
add_r = multiply(temp, right->sub_p);
delete_polynomial(temp);
}
}
else
{
if (right->flag == Node::type::leaf)
{
Node* temp = convert_leaf_to_sub(right, right_head->order + 1);
add_r = multiply(temp, left->sub_p);
delete_polynomial(temp);
}
else
{
add_r = multiply(left->sub_p, right->sub_p);
}
}
compute_sub_p(add_r, multiply_list, m_order, left_head);
right = right->next;
}
left = left->next;
}
Node* multiply_result_head = new Node(*left_head);
Node* run_on_result = multiply_result_head;
for (size_t i = multiply_list.size() - 1; ; --i)
{
if (multiply_list[i] == nullptr)
{
if (i == 0)
break;
continue;
}
Node* n = nullptr;
if (multiply_list[i]->flag == Node::type::sub)
{
n = new Node(i);
n->sub_p = multiply_list[i];
}
else
{
n = multiply_list[i];
n->order = i;
}
run_on_result->next = n;
run_on_result = n;
if (i == 0)
break;
}
return multiply_result_head;
}
Node* Polynomial::add(Node *left_head, Node* right_head)
{
Node* add_result_head = new Node(*left_head);
Node* run_on_result = add_result_head;
Node* left = left_head->next;
Node* right = right_head->next;
Node* _temp = nullptr;
while (left != nullptr && right != nullptr)
{
if (left->order == right->order)
{
if (left->flag == Node::type::leaf)
{
if (right->flag == Node::type::leaf)
{
if (left->cof + right->cof == 0)
{
left = left->next;
right = right->next;
continue;
}
_temp = new Node(left->order, left->cof + right->cof);
}
else
{
Node* temp = convert_leaf_to_sub(left, left_head->order + 1);
Node* add_r = add(temp, right->sub_p);
delete_polynomial(temp);
if (add_r->next == nullptr)
{
left = left->next;
right = right->next;
continue;
}
_temp = new Node(right->order);
_temp->sub_p = add_r;
}
}
else
{
Node* add_r = nullptr;
if (right->flag == Node::type::leaf)
{
Node* temp = convert_leaf_to_sub(right, left_head->order + 1);
add_r = add(temp, left->sub_p);
delete_polynomial(temp);
if (add_r->next == nullptr)
{
left = left->next;
right = right->next;
continue;
}
}
else
{
add_r = add(left->sub_p, right->sub_p);
if (add_r->next == nullptr)
{
left = left->next;
right = right->next;
continue;
}
}
_temp = new Node(left->order);
_temp->sub_p = add_r;
}
left = left->next;
right = right->next;
}
else if (left->order < right->order)
{
if (left->flag == Node::type::leaf)
{
_temp = new Node(left->order, left->cof);
}
else
{
Node* copy = copy_polynomial(left->sub_p);
_temp = new Node(left->order);
_temp->sub_p = copy;
}
right = right->next;
}
else
{
if (right->flag == Node::type::leaf)
{
_temp = new Node(right->order, right->cof);
}
else
{
Node* copy = copy_polynomial(right->sub_p);
_temp = new Node(right->order);
_temp->sub_p = copy;
}
left = left->next;
}
run_on_result->next = _temp;
run_on_result = _temp;
}
while (left != nullptr)
{
if (left->flag == Node::type::leaf)
{
_temp = new Node(left->order, left->cof);
}
else
{
Node* copy = copy_polynomial(left->sub_p);
_temp = new Node(left->order);
_temp->sub_p = copy;
}
run_on_result->next = _temp;
run_on_result = _temp;
left = left->next;
}
while (right != nullptr)
{
if (right->flag == Node::type::leaf)
{
_temp = new Node(right->order, right->cof);
}
else
{
Node* copy = copy_polynomial(right->sub_p);
_temp = new Node(right->order);
_temp->sub_p = copy;
}
run_on_result->next = _temp;
run_on_result = _temp;
right = right->next;
}
return add_result_head;
}
void Polynomial::delete_polynomial(Node* head)
{
while (head->next != nullptr)
{
Node* run = head->next;
head->next = run->next;
if (run->flag == Node::type::sub)
{
delete_polynomial(run->sub_p);
}
delete run;
}
delete head;
}
Node* Polynomial::copy_polynomial(Node* head)
{
Node* _head = new Node(*head);
Node* run = head->next;
Node* copy_run = _head;
while (run != nullptr)
{
Node* copy_result = new Node(*run);
copy_run->next = copy_result;
copy_run = copy_result;
if (run->flag == Node::type::sub)
{
copy_result = copy_polynomial(run->sub_p);
copy_run->sub_p = copy_result;
}
run = run->next;
}
return _head;
}
int main()
{
vector<string> vs = {"z", "y", "x"};
string test_str = "(3(4((4,5),(2,4)),(1,2)),(9,2))";
string test_str_2 = "z^2y^2x^2+z^2y^1x^2+z^2y^1x^1+2z^1y^3x^2+3z^1y^3x^1+14z^2y^0x^0+2z^1y^0x^0";
Polynomial obj1(test_str, vs);
Polynomial obj2(test_str_2);
Polynomial copy(obj1);
Polynomial result1;
Polynomial result2;
obj1.p_add(obj2, result1);
obj1.p_multiply(obj2, result2);
cout << "加法结果" << endl;
result1.print();
cout << endl;
cout << "乘法结果" << endl;
result2.print();
cout << endl;
cout << "拷贝结果" << endl;
copy.print();
cout << endl;
return 0;
}
parse.h头文件的内容
```cpp
#pragma once
#include <iostream>
#include <string>
#include <map>
#include <vector>
using namespace std;
enum class token {plus, digit, identifier, pow, end};
pair<token, string> gettoken(const string& str, string::size_type& i)
{
if (i == str.size())
{
return { token::end, ""};
}
if (str[i] == '+')
{
++i;
return { token::plus, "" };
}
if (str[i] == '^')
{
++i;
return { token::pow, "" };
}
if (str[i] == '_' || isalpha(str[i]))
{
size_t start = i;
do
{
++i;
} while (i < str.size() && (str[i] == '_' || isalnum(str[i])));
return { token::identifier, str.substr(start, i - start) };
}
if (str[i] == '-' || '0' <= str[i] && str[i] <= '9')
{
size_t start = i;
++i;
if (str[start] == '-')
{
if (!(i < str.size() && ('1' <= str[i] && str[i] <= '9')))
{
cout << "-在上下文中非法!" << endl;
exit(-1);
}
++i;
}
else if (str[start] == '0')
{
return { token::digit, "0" };
}
while (i < str.size() && ('0' <= str[i] && str[i] <= '9'))
{
++i;
}
return { token::digit, str.substr(start, i - start) };
}
cout << "非法字符!" << endl;
exit(-1);
}
void expect(const string& str, string::size_type& i, token e, pair<token, string>& result)
{
string::size_type j = i;
result = gettoken(str, i);
if (result.first == e)
return;
switch (e)
{
case token::plus: { cout << "索引" << j << "处非预期的词法记号,预期为加号" << endl; exit(-1); }
case token::digit: { cout << "索引" << j << "处非预期的词法记号,预期为数字" << endl; exit(-1); }
case token::identifier: { cout << "索引" << j << "处非预期的词法记号,预期为标识符" << endl; exit(-1); }
case token::pow: { cout << "索引" << j << "处非预期的词法记号,预期为幂" << endl; exit(-1); }
case token::end: { cout << "索引" << j << "处非预期的词法记号,预期为结束" << endl; exit(-1); }
}
}
void skip_token(const string& str, string::size_type& i)
{
if (gettoken(str, i).first == token::end)
{
cout << "ERROR:已没有更多的词法记号,skip失败!" << endl;
exit(-1);
}
}
void parse(const string& str, vector<string> & variable_symbols) //variable_symbols初始为空
{
size_t i = 0;
pair<token, string> result;
while (true)
{
size_t pre = i;
result = gettoken(str, i);
if (result.first == token::digit)
{
if (result.second == "0")
{
cout << "位置:" << pre << "ERROR:系数不能为0" << endl;
exit(-1);
}
pre = i;
expect(str, i, token::identifier, result);
}
else if (result.first != token::identifier)
{
cout << "位置:" << pre << "ERROR:非预期的词法记号预期为数字或标识符" << endl;
exit(-1);
}
bool has_get = !variable_symbols.empty();
size_t index = 0;
while (true)
{
if (has_get == false)
{
variable_symbols.push_back(result.second);
}
else
{
if (index >= variable_symbols.size())
{
cout << "位置:" << pre << "ERROR:不同的项的变量标识符数目不匹配,出错的标识符为"<< result.second << endl;
exit(-1);
}
if (variable_symbols[index++] != result.second)
{
cout << "位置:" << pre << "ERROR:不匹配的变量标识符"<< result.second << endl;
exit(-1);
}
}
expect(str, i, token::pow, result);
pre = i;
expect(str, i, token::digit, result);
if (result.second[0] == '-')
{
cout << "位置:" << pre << "ERROR:变量的幂不能为负值" << endl;
exit(-1);
}
pre = i;
result = gettoken(str, i);
if (result.first == token::end)
{
if (has_get && index < variable_symbols.size())
{
cout << "ERROR:最后一项变量标识符数目不匹配" << endl;
exit(-1);
}
return;
}
if (result.first == token::plus)
{
if (has_get && index < variable_symbols.size())
{
cout << "位置:" << pre << "ERROR:加号前的项的变量标识符数目不匹配" << endl;
exit(-1);
}
break;
}
if (result.first != token::identifier)
{
cout << "位置:" << pre << "ERROR:非预期的词法记号预期为结束或加号或标识符" << endl;
exit(-1);
}
}
}
}