用C++设计简单算数表达式语法分析器算法;(LR来实现)输入表达式不带#号,输出为TRue或者False
时间: 2024-01-24 22:17:54 浏览: 80
LR(1) 算法可以用于实现简单算数表达式语法分析器。下面是一个用 C++ 设计的算法实现:
```c++
#include <iostream>
#include <string>
#include <stack>
#include <map>
#include <vector>
using namespace std;
const int MAXN = 1000;
// 符号类别
enum TokenType {
TOKEN_PLUS, // +
TOKEN_MINUS, // -
TOKEN_MULTIPLY, // *
TOKEN_DIVIDE, // /
TOKEN_LPAREN, // (
TOKEN_RPAREN, // )
TOKEN_NUMBER // 数字
};
// 符号项
struct Token {
TokenType type; // 符号类别
int value; // 数字值
};
// LR(1) 项
struct LR1Item {
int production; // 产生式编号
int dot; // 点的位置
vector<int> lookahead; // 向前看符号
};
// 产生式
struct Production {
TokenType left; // 左部
vector<TokenType> right; // 右部
};
// LR(1) 项目集族
vector<vector<LR1Item>> item_sets;
// ACTION 表
map<pair<int, TokenType>, pair<char, int>> action;
// GOTO 表
map<pair<int, TokenType>, int> goto_table;
// 产生式序列
vector<Production> productions = {
{TOKEN_NUMBER, {TOKEN_NUMBER}},
{TOKEN_NUMBER, {TOKEN_NUMBER, TOKEN_PLUS, TOKEN_NUMBER}},
{TOKEN_NUMBER, {TOKEN_NUMBER, TOKEN_MINUS, TOKEN_NUMBER}},
{TOKEN_NUMBER, {TOKEN_NUMBER, TOKEN_MULTIPLY, TOKEN_NUMBER}},
{TOKEN_NUMBER, {TOKEN_NUMBER, TOKEN_DIVIDE, TOKEN_NUMBER}},
{TOKEN_NUMBER, {TOKEN_LPAREN, TOKEN_NUMBER, TOKEN_RPAREN}}
};
// 符号优先级表
int priority_table[MAXN][MAXN] = {
// + - * / ( ) number
{ 1, 1, -1, -1, -1, 1, -1}, // +
{ 1, 1, -1, -1, -1, 1, -1}, // -
{ 1, 1, 1, 1, -1, 1, -1}, // *
{ 1, 1, 1, 1, -1, 1, -1}, // /
{-1, -1, -1, -1, -1, 0, -1}, // (
{ 1, 1, 1, 1, -1, 1, -1}, // )
{-1, -1, -1, -1, -1, -1, 0} // number
};
// 将符号转化为字符串
string tokenToString(TokenType type) {
switch (type) {
case TOKEN_PLUS:
return "+";
case TOKEN_MINUS:
return "-";
case TOKEN_MULTIPLY:
return "*";
case TOKEN_DIVIDE:
return "/";
case TOKEN_LPAREN:
return "(";
case TOKEN_RPAREN:
return ")";
case TOKEN_NUMBER:
return "number";
default:
return "";
}
}
// 判断一个符号是否为终结符
bool isTerminal(TokenType type) {
return type == TOKEN_PLUS || type == TOKEN_MINUS || type == TOKEN_MULTIPLY || type == TOKEN_DIVIDE
|| type == TOKEN_LPAREN || type == TOKEN_RPAREN || type == TOKEN_NUMBER;
}
// 计算表达式的值
int calculate(vector<Token> tokens) {
stack<int> value_stack;
stack<TokenType> op_stack;
for (size_t i = 0; i < tokens.size(); i++) {
Token token = tokens[i];
if (token.type == TOKEN_NUMBER) {
value_stack.push(token.value);
} else {
while (!op_stack.empty() && priority_table[op_stack.top()][token.type] >= 0) {
TokenType op = op_stack.top();
op_stack.pop();
int b = value_stack.top();
value_stack.pop();
int a = value_stack.top();
value_stack.pop();
switch (op) {
case TOKEN_PLUS:
value_stack.push(a + b);
break;
case TOKEN_MINUS:
value_stack.push(a - b);
break;
case TOKEN_MULTIPLY:
value_stack.push(a * b);
break;
case TOKEN_DIVIDE:
value_stack.push(a / b);
break;
}
}
if (token.type == TOKEN_RPAREN) {
op_stack.pop();
} else {
op_stack.push(token.type);
}
}
}
while (!op_stack.empty()) {
TokenType op = op_stack.top();
op_stack.pop();
int b = value_stack.top();
value_stack.pop();
int a = value_stack.top();
value_stack.pop();
switch (op) {
case TOKEN_PLUS:
value_stack.push(a + b);
break;
case TOKEN_MINUS:
value_stack.push(a - b);
break;
case TOKEN_MULTIPLY:
value_stack.push(a * b);
break;
case TOKEN_DIVIDE:
value_stack.push(a / b);
break;
}
}
return value_stack.top();
}
// 获取产生式字符串
string productionToString(Production production) {
string result = tokenToString(production.left) + " ->";
for (size_t i = 0; i < production.right.size(); i++) {
result += " " + tokenToString(production.right[i]);
}
return result;
}
// 获取 LR(1) 项目字符串
string lr1ItemToString(LR1Item item) {
string result = productionToString(productions[item.production]) + ", dot = " + to_string(item.dot);
result += ", lookahead = { ";
for (size_t i = 0; i < item.lookahead.size(); i++) {
result += tokenToString(item.lookahead[i]) + " ";
}
result += "}";
return result;
}
// 获取项目集字符串
string itemSetToString(int index) {
string result = "{\n";
for (size_t i = 0; i < item_sets[index].size(); i++) {
result += " " + lr1ItemToString(item_sets[index][i]) + "\n";
}
result += "}";
return result;
}
// 获取 ACTION 表字符串
string actionTableToString() {
string result = "ACTION TABLE:\n";
for (auto it = action.begin(); it != action.end(); it++) {
int state = it->first.first;
TokenType token = it->first.second;
char action_type = it->second.first;
int action_param = it->second.second;
result += " [" + to_string(state) + ", " + tokenToString(token) + "] = ";
if (action_type == 's') {
result += "SHIFT " + to_string(action_param) + "\n";
} else if (action_type == 'r') {
result += "REDUCE " + productionToString(productions[action_param]) + "\n";
} else if (action_type == 'a') {
result += "ACCEPT\n";
}
}
return result;
}
// 获取 GOTO 表字符串
string gotoTableToString() {
string result = "GOTO TABLE:\n";
for (auto it = goto_table.begin(); it != goto_table.end(); it++) {
int state = it->first.first;
TokenType symbol = it->first.second;
int next_state = it->second;
result += " [" + to_string(state) + ", " + tokenToString(symbol) + "] = " + to_string(next_state) + "\n";
}
return result;
}
// 初始化符号项
void initItem(Token token, vector<int>& lookahead, vector<LR1Item>& items) {
for (size_t i = 0; i < productions.size(); i++) {
Production production = productions[i];
if (production.left == token.type) {
LR1Item item;
item.production = i;
item.dot = 0;
item.lookahead = lookahead;
items.push_back(item);
}
}
}
// 计算闭包
void closure(vector<LR1Item>& items) {
bool changed = true;
while (changed) {
changed = false;
for (size_t i = 0; i < items.size(); i++) {
LR1Item item = items[i];
if (item.dot < productions[item.production].right.size() && !isTerminal(productions[item.production].right[item.dot])) {
TokenType symbol = productions[item.production].right[item.dot];
vector<int> lookahead = item.lookahead;
if (item.dot + 1 < productions[item.production].right.size()) {
lookahead.clear();
lookahead.push_back(productions[item.production].right[item.dot + 1]);
}
vector<LR1Item> new_items;
initItem({symbol, 0}, lookahead, new_items);
for (size_t j = 0; j < new_items.size(); j++) {
if (find(items.begin(), items.end(), new_items[j]) == items.end()) {
items.push_back(new_items[j]);
changed = true;
}
}
}
}
}
}
// 计算转移
void gotoState(vector<LR1Item> items, TokenType symbol, vector<LR1Item>& new_items) {
for (size_t i = 0; i < items.size(); i++) {
LR1Item item = items[i];
if (item.dot < productions[item.production].right.size() && productions[item.production].right[item.dot] == symbol) {
LR1Item new_item = item;
new_item.dot++;
new_items.push_back(new_item);
}
}
closure(new_items);
}
// 计算项目集族
void calculateItemSets() {
vector<LR1Item> initial_items;
initItem({TOKEN_NUMBER, 0}, {TOKEN_NUMBER}, initial_items);
closure(initial_items);
item_sets.push_back(initial_items);
bool changed = true;
while (changed) {
changed = false;
for (size_t i = 0; i < item_sets.size(); i++) {
vector<LR1Item> items = item_sets[i];
map<TokenType, vector<LR1Item>> next_items;
for (size_t j = 0; j < items.size(); j++) {
LR1Item item = items[j];
if (item.dot < productions[item.production].right.size()) {
TokenType symbol = productions[item.production].right[item.dot];
vector<LR1Item> new_items;
gotoState(items, symbol, new_items);
next_items[symbol] = new_items;
}
}
for (auto it = next_items.begin(); it != next_items.end(); it++) {
TokenType symbol = it->first;
vector<LR1Item> new_items = it->second;
if (new_items.size() > 0 && find(item_sets.begin(), item_sets.end(), new_items) == item_sets.end()) {
item_sets.push_back(new_items);
changed = true;
goto_table[{i, symbol}] = item_sets.size() - 1;
}
}
}
}
}
// 计算 ACTION 表和 GOTO 表
void calculateTables() {
for (size_t i = 0; i < item_sets.size(); i++) {
vector<LR1Item> items = item_sets[i];
for (size_t j = 0; j < items.size(); j++) {
LR1Item item = items[j];
if (item.dot == productions[item.production].right.size()) {
if (item.production == 0) {
action[{i, TOKEN_NUMBER}] = {'a', 0};
} else {
for (size_t k = 0; k < item.lookahead.size(); k++) {
TokenType lookahead = item.lookahead[k];
if (action.count({i, lookahead}) > 0) {
cout << "ERROR: Reduce-Reduce conflict!\n";
return;
} else {
action[{i, lookahead}] = {'r', item.production};
}
}
}
}
}
for (auto it = productions.begin(); it != productions.end(); it++) {
TokenType symbol = it->left;
vector<LR1Item> new_items;
gotoState(items, symbol, new_items);
if (new_items.size() > 0) {
int j = find(item_sets.begin(), item_sets.end(), new_items) - item_sets.begin();
goto_table[{i, symbol}] = j;
}
}
for (size_t j = 0; j < items.size(); j++) {
LR1Item item = items[j];
if (item.dot < productions[item.production].right.size()) {
TokenType symbol = productions[item.production].right[item.dot];
if (isTerminal(symbol)) {
vector<LR1Item> new_items;
gotoState(items, symbol, new_items);
if (new_items.size() > 0) {
int j = find(item_sets.begin(), item_sets.end(), new_items) - item_sets.begin();
if (action.count({i, symbol}) > 0) {
cout << "ERROR: Shift-Reduce conflict!\n";
return;
} else {
action[{i, symbol}] = {'s', j};
}
}
}
}
}
}
}
// 将表达式转化为符号串
vector<Token> expressionToTokens(string expr) {
vector<Token> tokens;
int i = 0;
while (i < expr.length()) {
if (isdigit(expr[i])) {
int j = i;
while (j < expr.length() && isdigit(expr[j])) {
j++;
}
tokens.push_back({TOKEN_NUMBER, stoi(expr.substr(i, j - i))});
i = j;
} else if (expr[i] == '+') {
tokens.push_back({TOKEN_PLUS, 0});
i++;
} else if (expr[i] == '-') {
tokens.push_back({TOKEN_MINUS, 0});
i++;
} else if (expr[i] == '*') {
tokens.push_back({TOKEN_MULTIPLY, 0});
i++;
} else if (expr[i] == '/') {
tokens.push_back({TOKEN_DIVIDE, 0});
i++;
} else if (expr[i] == '(') {
tokens.push_back({TOKEN_LPAREN, 0});
i++;
} else if (expr[i] == ')') {
tokens.push_back({TOKEN_RPAREN, 0});
i++;
} else {
i++;
}
}
return tokens;
}
// 使用算法分析表达式
bool analyzeExpression(string expr) {
vector<Token> tokens = expressionToTokens(expr);
tokens.push_back({TOKEN_NUMBER, 0});
stack<int> state_stack;
stack<TokenType> symbol_stack;
state_stack.push(0);
symbol_stack.push(TOKEN_NUMBER);
size_t i = 0;
while (!state_stack.empty()) {
int state = state_stack.top();
TokenType symbol = symbol_stack.top();
if (action.count({state, symbol}) == 0) {
return false;
}
char action_type = action[{state, symbol}].first;
int action_param = action[{state, symbol}].second;
if (action_type == 's') {
state_stack.push(action_param);
symbol_stack.push(symbol);
state_stack.push(0);
symbol_stack.push(tokens[i].type);
i++;
} else if (action_type == 'r') {
Production production = productions[action_param];
for (size_t j = 0; j < production.right.size(); j++) {
state_stack.pop();
symbol_stack.pop();
}
int top_state = state_stack.top();
TokenType top_symbol = symbol_stack.top();
if (goto_table.count({top_state, production.left}) == 0) {
return false;
}
int next_state = goto_table[{top_state, production.left}];
state_stack.push(next_state);
symbol_stack.push(production.left);
} else if (action_type == 'a') {
return true;
} else {
return false;
}
}
return false;
}
int main() {
calculateItemSets();
calculateTables();
cout << actionTableToString() << endl;
cout << gotoTableToString() << endl;
string expr;
cout << "Enter an expression: ";
cin >> expr;
if (analyzeExpression(expr)) {
vector<Token> tokens = expressionToTokens(expr);
cout << "Result: " << calculate(tokens) << endl;
} else {
cout << "ERROR: Invalid expression!\n";
}
return 0;
}
```
这里使用了一个简单的算数表达式语法,只包含加、减、乘、除和括号运算,并且没有考虑优先级和结合性。算法输出 ACTION 表和 GOTO 表,并且可以解析输入的表达式并计算其值。
阅读全文