给出A:=B*(-C+D)的自下而上语法制导翻译过程
时间: 2024-03-12 10:45:43 浏览: 21
下面是A:=B*(-C+D)的自下而上语法制导翻译过程:
1. 对于非终极符E,其属性值为E.val
2. 对于终极符,其属性值为终极符本身的值或者空值
3. 产生式S->E,S.val=E.val
4. 产生式E->E1+T,E.val=E1.val+T.val
5. 产生式E->T,E.val=T.val
6. 产生式T->T1*F,T.val=T1.val*F.val
7. 产生式T->F,T.val=F.val
8. 产生式F->(E),F.val=E.val
9. 产生式F->-F1,F.val=-F1.val
10. 产生式F->num,F.val=num.val
11. 产生式F->id,F.val=id.val
按照以上语法制导翻译的规则,对于A:=B*(-C+D),可以按照以下步骤生成中间代码:
1. 将B赋给临时变量t1,即t1=B
2. 将-C赋给临时变量t2,即t2=-C
3. 将t2与D相加并赋给临时变量t3,即t3=t2+D
4. 将t1与t3相乘并赋给A,即A=t1*t3
最终生成的三地址代码为:
```
t1 = B
t2 = -C
t3 = t2 + D
A = t1 * t3
```
相关问题
赋值语句的文法及语义动作描述如下: (1)A→i:=E {gen (:=, E.place,_,entry(i));} (2)E→E1+E2 {E.place:=newtemp;gen(+, E1.place, E2.place, E.place);} (3)E→E1*E2 {E.place:=newtemp; gen(*, E1.place, E2.place, E.place);} (4)E→-E1 {E.place:=newtemp;gen(@,E1.place,_,E.place);} (5)E→(E1) {E.place:=E1.place;} (6)E→i {E.place:=entry(i);} 写出赋值语句X:=-B*(C+D)*A的自下而上的语法制导翻译过程。
下面是赋值语句X:=-B*(C+D)*A的自下而上的语法制导翻译过程:
1. A → i := E,调用 gen( :=, E.place, _, entry(i)) 生成指令:将 E.place 赋值给变量 i。
2. E → - E1,调用 gen(@, E1.place, _, E.place) 生成指令:将 E1.place 取反后的值赋值给新的临时变量 E.place。
3. E → i,调用 entry(i) 将变量 i 的地址赋值给 E.place。
4. E → E1 * E2,调用 newtemp 生成一个新的临时变量 T,调用 gen(*, E1.place, E2.place, T) 生成指令:将 E1.place 和 E2.place 相乘,结果存储在临时变量 T 中,再将 T 的值赋值给 E.place。
5. E → E1 + E2,调用 newtemp 生成一个新的临时变量 T,调用 gen(+, E1.place, E2.place, T) 生成指令:将 E1.place 和 E2.place 相加,结果存储在临时变量 T 中,再将 T 的值赋值给 E.place。
6. E → ( E1 ),将 E1.place 赋值给 E.place。
根据以上语法制导翻译过程,赋值语句X:=-B*(C+D)*A的自下而上的语法制导翻译过程为:
1. entry(B):将变量 B 的地址赋值给 E1.place。
2. entry(C):将变量 C 的地址赋值给 E1.place。
3. entry(D):将变量 D 的地址赋值给 E2.place。
4. E1.place:调用 newtemp 生成一个新的临时变量 T1,调用 gen(+, C, D, T1) 生成指令:将 C 和 D 相加,结果存储在临时变量 T1 中。
5. E.place:调用 newtemp 生成一个新的临时变量 T2,调用 gen(*, B, T1, T2) 生成指令:将 B 和 T1 相乘,结果存储在临时变量 T2 中,再将 T2 的值取反后赋值给 X。
6. entry(A):将变量 A 的地址赋值给 E1.place。
7. E.place:调用 newtemp 生成一个新的临时变量 T3,调用 gen(*, T2, A, T3) 生成指令:将 T2 和 A 相乘,结果存储在临时变量 T3 中,再将 T3 的值赋值给 X。
因此,赋值语句X:=-B*(C+D)*A的自下而上的语法制导翻译过程为:
entry(B)
entry(C)
entry(D)
newtemp T1
gen(+, C, D, T1)
newtemp T2
gen(*, B, T1, T2)
gen(@, T2, _, X)
entry(A)
newtemp T3
gen(*, T2, A, T3)
gen(:=, T3, _, entry(X))
用c语言实现自下而上的边分析边计算功能。 文法为: E-->E+T,E-->T,T-->T*F,T-->F,F-->(E),F-->id
以下是用C语言实现自下而上的边分析边计算功能的示例代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define MAX_STACK_SIZE 100
// 定义操作数栈结构体
typedef struct {
int top;
int data[MAX_STACK_SIZE];
} OperandStack;
// 定义运算符栈结构体
typedef struct {
int top;
char data[MAX_STACK_SIZE];
} OperatorStack;
// 定义操作数和运算符栈的初始化函数
void initOperandStack(OperandStack* stack) {
stack->top = -1;
}
void initOperatorStack(OperatorStack* stack) {
stack->top = -1;
}
// 定义操作数和运算符栈的入栈函数
void pushOperand(OperandStack* stack, int value) {
if (stack->top == MAX_STACK_SIZE - 1) {
printf("Operand stack overflow!\n");
exit(1);
}
stack->data[++stack->top] = value;
}
void pushOperator(OperatorStack* stack, char op) {
if (stack->top == MAX_STACK_SIZE - 1) {
printf("Operator stack overflow!\n");
exit(1);
}
stack->data[++stack->top] = op;
}
// 定义操作数和运算符栈的出栈函数
int popOperand(OperandStack* stack) {
if (stack->top == -1) {
printf("Operand stack underflow!\n");
exit(1);
}
return stack->data[stack->top--];
}
char popOperator(OperatorStack* stack) {
if (stack->top == -1) {
printf("Operator stack underflow!\n");
exit(1);
}
return stack->data[stack->top--];
}
// 定义操作数和运算符栈的查看栈顶元素函数
int peekOperand(OperandStack* stack) {
if (stack->top == -1) {
printf("Operand stack underflow!\n");
exit(1);
}
return stack->data[stack->top];
}
char peekOperator(OperatorStack* stack) {
if (stack->top == -1) {
printf("Operator stack underflow!\n");
exit(1);
}
return stack->data[stack->top];
}
// 定义操作数和运算符栈是否为空的判断函数
int isOperandStackEmpty(OperandStack* stack) {
return stack->top == -1;
}
int isOperatorStackEmpty(OperatorStack* stack) {
return stack->top == -1;
}
// 定义判断一个字符是否为操作符的函数
int isOperator(char ch) {
return ch == '+' || ch == '-' || ch == '*' || ch == '/';
}
// 定义判断一个字符是否为数字的函数
int isDigit(char ch) {
return isdigit(ch);
}
// 定义计算函数,根据操作符计算对应的结果
int calculate(int op1, int op2, char op) {
switch (op) {
case '+': return op1 + op2;
case '-': return op1 - op2;
case '*': return op1 * op2;
case '/': return op1 / op2;
default: return 0;
}
}
// 定义边分析边计算的函数
int evaluate(char* expr) {
OperandStack operandStack;
OperatorStack operatorStack;
initOperandStack(&operandStack);
initOperatorStack(&operatorStack);
int i = 0;
while (expr[i] != '\0') {
if (isDigit(expr[i])) { // 如果当前字符是数字,则将其转换为整数并入操作数栈
int num = 0;
while (isDigit(expr[i])) {
num = num * 10 + (expr[i] - '0');
i++;
}
pushOperand(&operandStack, num);
} else if (isOperator(expr[i])) { // 如果当前字符是操作符,则与运算符栈栈顶元素比较优先级
while (!isOperatorStackEmpty(&operatorStack) && peekOperator(&operatorStack) != '(' &&
((expr[i] == '*' || expr[i] == '/') || (peekOperator(&operatorStack) == '+' || peekOperator(&operatorStack) == '-'))) {
int op2 = popOperand(&operandStack); // 从操作数栈中弹出两个操作数
int op1 = popOperand(&operandStack);
char op = popOperator(&operatorStack); // 从运算符栈中弹出一个运算符
int result = calculate(op1, op2, op); // 根据运算符计算结果
pushOperand(&operandStack, result); // 将计算结果入操作数栈
}
pushOperator(&operatorStack, expr[i]); // 将当前操作符入运算符栈
i++;
} else if (expr[i] == '(') { // 如果当前字符是左括号,则将其入运算符栈
pushOperator(&operatorStack, '(');
i++;
} else if (expr[i] == ')') { // 如果当前字符是右括号,则从运算符栈中弹出运算符,并从操作数栈中弹出两个操作数进行计算,直到遇到左括号为止
while (!isOperatorStackEmpty(&operatorStack) && peekOperator(&operatorStack) != '(') {
int op2 = popOperand(&operandStack);
int op1 = popOperand(&operandStack);
char op = popOperator(&operatorStack);
int result = calculate(op1, op2, op);
pushOperand(&operandStack, result);
}
if (!isOperatorStackEmpty(&operatorStack) && peekOperator(&operatorStack) == '(') {
popOperator(&operatorStack);
} else {
printf("Mismatched parentheses in expression!\n");
exit(1);
}
i++;
} else { // 如果当前字符不是数字、操作符、左括号或右括号,则表示表达式有误
printf("Invalid character in expression!\n");
exit(1);
}
}
// 将剩余的运算符和操作数进行计算
while (!isOperatorStackEmpty(&operatorStack)) {
int op2 = popOperand(&operandStack);
int op1 = popOperand(&operandStack);
char op = popOperator(&operatorStack);
int result = calculate(op1, op2, op);
pushOperand(&operandStack, result);
}
// 返回最终的计算结果
return popOperand(&operandStack);
}
int main() {
char expr[100];
printf("Please enter an expression: ");
scanf("%s", expr);
int result = evaluate(expr);
printf("Result: %d\n", result);
return 0;
}
```
以上代码实现了一个边分析边计算的表达式求值功能,支持加、减、乘、除四种运算符和括号。通过运用操作数栈和运算符栈,可以实现边分析边计算的功能,避免了对表达式进行两次遍历的问题。同时,该代码也支持了错误处理,包括表达式中出现非法字符和括号不匹配等情况。