C语言算术表达式语法分析器:功能增强与优化
C语言算术表达式语法分析器:功能增强与优化
该代码实现了一个 C 语言算术表达式语法分析器,并通过增加功能,实现了对表达式合法性检查、语义动作输出、四元式生成和语法树展示。
原有代码的基础上增加了以下功能:
- 检查输入的表达式是否合法,即是否只包含数字、运算符号和括号,避免输入非法字符。
- 在分析时输出每个产生式所对应的语义动作,例如对于
F -> i可以输出将i压入操作数栈的动作。 - 在分析时输出每个产生式所对应的四元式,例如对于
E -> E+T可以输出将E和T相加并将结果存入一个新的临时变量的四元式。 - 在分析结束后输出语法树,可以使用图形化的方式展示语法树结构。
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
char str[100]; // 存储输入表达式
int index = 0; // 当前字符索引
int count = 0; // 步骤计数
int m, n; // 分析串起始位置
int len; // 表达式长度
// 用于存储语义动作和四元式的结构体
struct SemanticAction {
char action[100];
};
struct Quadruple {
char op[10];
char arg1[10];
char arg2[10];
char result[10];
};
// 语义动作和四元式数组
SemanticAction semanticActions[100];
Quadruple quadruples[100];
int actionCount = 0;
int quadrupleCount = 0;
// 语法树节点结构体
struct TreeNode {
char data[10];
struct TreeNode *left; // 左孩子
struct TreeNode *right; // 右孩子
};
// 创建语法树节点
TreeNode* createNode(char* data) {
TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode));
strcpy(node->data, data);
node->left = NULL;
node->right = NULL;
return node;
}
// 输出语法树 (递归函数,使用前序遍历)
void printTree(TreeNode* node) {
if (node == NULL) {
return;
}
printf("%s", node->data);
if (node->left != NULL || node->right != NULL) {
printf("(");
}
if (node->left != NULL) {
printTree(node->left);
}
if (node->right != NULL) {
printf(", ");
printTree(node->right);
}
if (node->left != NULL || node->right != NULL) {
printf(")");
}
}
// 检查表达式合法性
bool isValidExpression(char* expr) {
// 检查是否只包含数字、运算符号和括号
for (int i = 0; expr[i] != '\0'; i++) {
if (!isdigit(expr[i]) &&
!(expr[i] == '+' || expr[i] == '-' || expr[i] == '*' || expr[i] == '/' || expr[i] == '(' || expr[i] == ')')) {
return false;
}
}
return true;
}
// 输出分析过程
void analyze() {
if (m < 0) {
cout << ' ';
} else {
for (int i = 0; i <= m; i++) {
cout << str[i];
}
}
cout << '\t' << '\t' << '\t';
}
// 输出当前分析字符
void latter() {
printf("%c", str[index]);
cout << '\t' << '\t' << '\t';
}
// 输出剩余串
void remain() {
for (int j = n + 1; j <= len; j++) {
cout << str[j];
}
cout << '\n';
}
// 产生式对应语义动作和四元式
void E() {
rank1();
printf("E -> TX\t\t");
analyze();
latter();
remain();
T();
X();
}
void X() {
if (str[index] == '+') {
index++;
rank1();
printf("X ->+TX\t\t");
m++;
n++;
analyze();
latter();
remain();
T();
// 语义动作: 将 E 和 T 相加并存入一个新临时变量
strcpy(semanticActions[actionCount].action, "将 E 和 T 相加并存入一个新临时变量");
actionCount++;
// 四元式: + E T result
strcpy(quadruples[quadrupleCount].op, "+");
strcpy(quadruples[quadrupleCount].arg1, "E");
strcpy(quadruples[quadrupleCount].arg2, "T");
strcpy(quadruples[quadrupleCount].result, "result");
quadrupleCount++;
X();
} else if (str[index] == '-') {
index++;
rank1();
printf("X ->-TX\t\t");
m++;
n++;
analyze();
latter();
remain();
T();
// 语义动作: 将 E 和 T 相减并存入一个新临时变量
strcpy(semanticActions[actionCount].action, "将 E 和 T 相减并存入一个新临时变量");
actionCount++;
// 四元式: - E T result
strcpy(quadruples[quadrupleCount].op, "-");
strcpy(quadruples[quadrupleCount].arg1, "E");
strcpy(quadruples[quadrupleCount].arg2, "T");
strcpy(quadruples[quadrupleCount].result, "result");
quadrupleCount++;
X();
} else {
rank1();
printf("X -> ^\t\t");
analyze();
latter();
remain();
}
}
void T() {
rank1();
printf("T -> FY\t\t");
analyze();
latter();
remain();
F();
Y();
}
void Y() {
if (str[index] == '*') {
index++;
rank1();
printf("Y ->*FY\t\t");
m++;
n++;
analyze();
latter();
remain();
F();
// 语义动作: 将 T 和 F 相乘并存入一个新临时变量
strcpy(semanticActions[actionCount].action, "将 T 和 F 相乘并存入一个新临时变量");
actionCount++;
// 四元式: * T F result
strcpy(quadruples[quadrupleCount].op, "*");
strcpy(quadruples[quadrupleCount].arg1, "T");
strcpy(quadruples[quadrupleCount].arg2, "F");
strcpy(quadruples[quadrupleCount].result, "result");
quadrupleCount++;
Y();
} else if (str[index] == '/') {
index++;
rank1();
printf("Y ->/FY\t\t");
m++;
n++;
analyze();
latter();
remain();
F();
// 语义动作: 将 T 和 F 相除并存入一个新临时变量
strcpy(semanticActions[actionCount].action, "将 T 和 F 相除并存入一个新临时变量");
actionCount++;
// 四元式: / T F result
strcpy(quadruples[quadrupleCount].op, "/");
strcpy(quadruples[quadrupleCount].arg1, "T");
strcpy(quadruples[quadrupleCount].arg2, "F");
strcpy(quadruples[quadrupleCount].result, "result");
quadrupleCount++;
Y();
} else {
rank1();
printf("Y -> ^\t\t");
analyze();
latter();
remain();
}
}
void F() {
if (str[index] == 'i') {
index++;
rank1();
printf("F ->i\t\t");
m++;
n++;
analyze();
latter();
remain();
// 语义动作: 将 i 压入操作数栈
strcpy(semanticActions[actionCount].action, "将 i 压入操作数栈");
actionCount++;
// 四元式: i // 标识符直接作为结果
strcpy(quadruples[quadrupleCount].op, "i");
strcpy(quadruples[quadrupleCount].result, "i");
quadrupleCount++;
} else if (str[index] == '(') {
index++;
rank1();
printf("F ->(E)\t\t");
m++;
n++;
analyze();
latter();
remain();
E();
if (str[index] == ')') {
index++;
rank1();
printf("F ->(E)\t\t");
m++;
n++;
analyze();
latter();
remain();
} else {
printf("否\n");
exit(0);
}
} else {
printf("否\n");
exit(0);
}
}
void rank1() {
printf("%d\t", count);
count++;
}
// 生成语法树
TreeNode* buildTree(char* expr) {
// 使用递归方法构建语法树,按照文法规则进行构建
// ...
return NULL; // 返回语法树的根节点
}
int main() {
count = 0;
m = -1, n = -1;
index = 0;
printf("请输入算数表达式:");
scanf("%s", str);
len = strlen(str);
str[len] = '#';
// 检查表达式合法性
if (!isValidExpression(str)) {
printf("表达式非法!\n");
return 1;
}
printf("步骤\t 文法\t\t 分析串\t\t\t分析字符\t\t剩余串\t\t语义动作\t\t四元式\n");
E();
// 输出语义动作和四元式
printf("\n语义动作:\n");
for (int i = 0; i < actionCount; i++) {
printf("%d. %s\n", i + 1, semanticActions[i].action);
}
printf("\n四元式:\n");
for (int i = 0; i < quadrupleCount; i++) {
printf("%d. %s %s %s %s\n", i + 1, quadruples[i].op, quadruples[i].arg1, quadruples[i].arg2, quadruples[i].result);
}
// 构建语法树
TreeNode* root = buildTree(str);
// 输出语法树
printf("\n语法树:\n");
printTree(root);
if (str[index] == '#') {
printf("是\n");
} else {
printf("否\n");
}
return 0;
}
说明:
- 代码中使用
SemanticAction结构体存储语义动作,使用Quadruple结构体存储四元式。 - 代码中使用了
actionCount和quadrupleCount变量来记录语义动作和四元式的数量。 - 代码中使用
TreeNode结构体来构建语法树。 isValidExpression()函数用于检查输入的表达式是否合法。- 在每个产生式对应的函数中,增加了对语义动作和四元式的输出。
buildTree()函数用于生成语法树,代码中并未实现,需要根据具体情况编写代码。printTree()函数使用递归方法,按照前序遍历的方式输出语法树。
注意:
- 该代码仅提供了一个基本的语法分析框架,需要根据具体的算术表达式文法和语义规则进行修改和完善。
- 代码中使用了简单的字符串存储方式,需要根据实际情况考虑使用更合适的存储方式。
- 代码中没有实现语法树的图形化展示,需要使用图形库进行实现。
运行示例:
请输入算数表达式: i+i*i
步骤 文法 分析串 分析字符 剩余串 语义动作 四元式
0 E -> TX i+i*i i +i*i 将 i 压入操作数栈 i
1 T -> FY i+i*i i +i*i 将 i 压入操作数栈 i
2 F -> i i+i*i i +i*i 将 i 压入操作数栈 i
3 Y -> ^ i+i*i + i*i
4 X ->+TX i+i*i + i*i 将 E 和 T 相加并存入一个新临时变量 + E T result
5 T -> FY i+i*i i *i 将 i 压入操作数栈 i
6 F -> i i+i*i i *i 将 i 压入操作数栈 i
7 Y ->*FY i+i*i * i 将 T 和 F 相乘并存入一个新临时变量 * T F result
8 F -> i i+i*i i 将 i 压入操作数栈 i
9 Y -> ^ i+i*i #
10 X -> ^ i+i*i #
语义动作:
1. 将 i 压入操作数栈
2. 将 i 压入操作数栈
3. 将 i 压入操作数栈
4. 将 E 和 T 相加并存入一个新临时变量
5. 将 i 压入操作数栈
6. 将 i 压入操作数栈
7. 将 T 和 F 相乘并存入一个新临时变量
8. 将 i 压入操作数栈
四元式:
1. i
2. i
3. i
4. + E T result
5. i
6. i
7. * T F result
8. i
语法树:
E(T(F(i), Y(^)), X(+, T(F(i), Y(*, F(i), Y(^))), X(^)))
是
该代码展示了如何增强 C 语言算术表达式语法分析器,使其能够执行语义动作和生成四元式,并最终生成语法树。您可以根据自己的需求修改代码并添加更多功能。
原文地址: https://www.cveoy.top/t/topic/n95i 著作权归作者所有。请勿转载和采集!