使用C/C++语言编写PL/0编译程序的语法分析程序 预期输入输出如上
时间: 2023-07-30 11:07:01 浏览: 135
很好,PL/0语言的语法分析程序可以分为三个部分:词法分析器、语法分析器和代码生成器。下面是一个简单的C语言实现示例,其中使用了类似于递归下降的方法:
```c
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
// 定义符号表结构体
typedef struct {
char name[10];
int kind;
int value;
int level;
int addr;
} Symbol;
// 定义符号表数组和指针
Symbol symbol_table[100];
int symbol_ptr = 0;
// 定义PL/0语言的关键字
const char *keywords[] = {
"begin", "call", "const", "do", "end", "if", "odd",
"procedure", "read", "then", "var", "while", "write"
};
// 定义PL/0语言的符号
const char *symbols[] = {
"+", "-", "*", "/", "(", ")", "=", ",", ".", "<", ">",
"<=", ">=", "<>", ";", ":="
};
// 定义词法分析器
int lexical_analysis(const char *input, int *value) {
char word[10] = {0}; // 保存识别的单词
int word_ptr = 0; // 单词指针
int num_flag = 0; // 标记是否是数字
int symbol_flag = 0; // 标记是否是符号
// 遍历输入字符串
for (int i = 0; i < strlen(input); i++) {
// 判断是否是空格、换行符或制表符
if (isspace(input[i])) {
if (num_flag) { // 如果之前是数字,则返回
*value = atoi(word);
return 3;
}
if (symbol_flag) { // 如果之前是符号,则返回
for (int j = 0; j < sizeof(symbols) / sizeof(char *); j++) {
if (strcmp(word, symbols[j]) == 0) {
return j + 4;
}
}
}
word_ptr = 0;
num_flag = 0;
symbol_flag = 0;
continue;
}
// 判断是否是数字
if (isdigit(input[i])) {
num_flag = 1;
symbol_flag = 0;
word[word_ptr++] = input[i];
continue;
}
// 判断是否是字母
if (isalpha(input[i])) {
num_flag = 0;
symbol_flag = 0;
word[word_ptr++] = input[i];
continue;
}
// 判断是否是符号
if (!isdigit(input[i]) && !isalpha(input[i])) {
num_flag = 0;
symbol_flag = 1;
word[word_ptr++] = input[i];
// 判断是否是符号
for (int j = 0; j < sizeof(symbols) / sizeof(char *); j++) {
if (strcmp(word, symbols[j]) == 0) {
return j + 4;
}
}
// 如果不是符号,则返回错误
return -1;
}
}
// 如果识别到了数字,则返回
if (num_flag) {
*value = atoi(word);
return 3;
}
// 判断是否为关键字
for (int i = 0; i < sizeof(keywords) / sizeof(char *); i++) {
if (strcmp(word, keywords[i]) == 0) {
return i + 1;
}
}
// 如果不是关键字,则判断为标识符
strcpy(symbol_table[symbol_ptr].name, word);
symbol_table[symbol_ptr].kind = 2; // 标识符种类为2
symbol_ptr++;
return 2;
}
// 定义语法分析器
void syntax_analysis(const char *input) {
int symbol; // 当前读入的符号
int value; // 当前读入的数值
int level = 0; // 当前层级
int addr = 0; // 当前地址
// 读入第一个符号
symbol = lexical_analysis(input, &value);
// 判断是否为begin
if (symbol == 1) {
symbol = lexical_analysis(input, &value);
} else {
printf("Error: 'begin' is expected.\n");
exit(-1);
}
// 开始语法分析
while (symbol != 5) { // 判断是否为end
// 判断是否为常量定义
if (symbol == 3) {
do {
symbol = lexical_analysis(input, &value);
// 判断是否为标识符
if (symbol == 2) {
strcpy(symbol_table[symbol_ptr].name, input);
symbol_table[symbol_ptr].kind = 1; // 常量种类为1
symbol_table[symbol_ptr].value = value;
symbol_ptr++;
} else {
printf("Error: Identifier is expected.\n");
exit(-1);
}
symbol = lexical_analysis(input, &value);
// 判断是否为等号
if (symbol == 9) {
symbol = lexical_analysis(input, &value);
} else {
printf("Error: '=' is expected.\n");
exit(-1);
}
// 判断是否为数字
if (symbol == 3) {
symbol_table[symbol_ptr - 1].value = value;
symbol = lexical_analysis(input, &value);
} else {
printf("Error: Number is expected.\n");
exit(-1);
}
} while (symbol == 4); // 判断是否为逗号
// 判断是否为分号
if (symbol == 18) {
symbol = lexical_analysis(input, &value);
} else {
printf("Error: ';' is expected.\n");
exit(-1);
}
}
// 判断是否为变量定义
if (symbol == 12) {
do {
symbol = lexical_analysis(input, &value);
// 判断是否为标识符
if (symbol == 2) {
strcpy(symbol_table[symbol_ptr].name, input);
symbol_table[symbol_ptr].kind = 3; // 变量种类为3
symbol_table[symbol_ptr].level = level;
symbol_table[symbol_ptr].addr = addr;
symbol_ptr++;
addr++;
} else {
printf("Error: Identifier is expected.\n");
exit(-1);
}
symbol = lexical_analysis(input, &value);
} while (symbol == 4); // 判断是否为逗号
// 判断是否为分号
if (symbol == 18) {
symbol = lexical_analysis(input, &value);
} else {
printf("Error: ';' is expected.\n");
exit(-1);
}
}
// 判断是否为过程定义
if (symbol == 8) {
symbol = lexical_analysis(input, &value);
// 判断是否为标识符
if (symbol == 2) {
strcpy(symbol_table[symbol_ptr].name, input);
symbol_table[symbol_ptr].kind = 4; // 过程种类为4
symbol_table[symbol_ptr].level = level;
symbol_table[symbol_ptr].addr = addr;
symbol_ptr++;
addr++;
} else {
printf("Error: Identifier is expected.\n");
exit(-1);
}
// 判断是否为分号
symbol = lexical_analysis(input, &value);
if (symbol == 18) {
symbol = lexical_analysis(input, &value);
} else {
printf("Error: ';' is expected.\n");
exit(-1);
}
level++;
}
// 判断是否为语句
if (symbol == 2) {
symbol = lexical_analysis(input, &value);
// 判断是否为赋值语句
if (symbol == 20) {
symbol = lexical_analysis(input, &value);
// 判断是否为表达式
// TODO: 添加表达式分析函数
if (symbol == 3 || symbol == 2) {
symbol = lexical_analysis(input, &value);
// 判断是否为分号
if (symbol == 18) {
symbol = lexical_analysis(input, &value);
} else {
printf("Error: ';' is expected.\n");
exit(-1);
}
} else {
printf("Error: Expression is expected.\n");
exit(-1);
}
} else {
printf("Error: ':=' is expected.\n");
exit(-1);
}
}
}
printf("Syntax analysis finished.\n");
}
int main() {
char input[100] = "begin const a=1,b=2; var x,y,z; procedure p; begin x:=a+b; y:=a-b; z:=x*y; end; x:=a+b; end.";
syntax_analysis(input);
return 0;
}
```
这段代码实现了PL/0语言的词法分析器和语法分析器,具体的错误处理和表达式分析等问题还需要进行完善。可以通过修改输入字符串来测试程序的正确性。
阅读全文