一、设计目的、功能与要求
- 写出符合给定的语法分析方法的文法及属性文法。
- 完成题目要求的中间代码(三地址码或四元式)的描述。
- 写出给定的语法分析方法的思想,完成语法分析和语义分析程序设计。
- 实现程序,设计若干用例测试程序。
- 设计报告格式按附件要求书写。
课程设计报告书正文的内容应包括:
1)课设任务概述
2)编译程序分析
词法、语法分析方法描述,文法及属性文法的描述,分析表的定义等。
3)编译程序设计
写出流程图或伪代码;按给定的题目给出中间代码形式的描述及中间代码序列的结构设计。
4)编译程序实现和测试。
5)实践总结
本次设计的特点、体会等。
二、源代码及运行结果
common.h
#include <iostream>
#include <fstream>
#include <vector>
#include <cctype>
#include <stack>
#include <algorithm>
#include <iomanip>
#include<queue>
#include<string>
using namespace std;
#define N 9999
// Token类型
enum TokenType {
K, // KEYWORD
I, // IDENTIFIER
C, // CONSTANT
A, // 算数运算符
L, // 逻辑运算符
D, // DELIMITER
U // UNKNOWN
};
// 词法分析结构体
struct Token {
TokenType type;
string lexeme;
};
// 文法的产生式
struct Production {
// 左部
char left;
// 右部
vector<char> right;
};
// 三地址码
struct ThreeAddressCode {
int num;
string code;
};
// 词法分析函数
bool isKeyword(const string& word);
bool isAOperator(char ch);
bool isLOperator(char ch);
bool isDelimiter(char ch);
bool isConstant(const string& str);
bool isIdentifier(const string& str);
vector<Token> tokenize(const string& input);
void printInfo(vector<Token> t);
vector<Token> lexical_analyzer();
// 语法分析函数
void syntax_analyzer(vector<Token> tokens);
void printSet();
void printPriorityTable();
string initString(vector<Token> tokens, vector<string>& values);
void reverseStackPrint(stack<char> S);
void genCode(string handle);
void addCode(vector<string>& values);
string handleReduction(stack<char>& S);
void setProductions();
void parse(stack<char>& S, vector<Token> tokens, vector<string>& values);
void printThreeeAddressCodes();
lexical_analyzer.cpp
#include"common.h"
// 判断是否为关键字
bool isKeyword(const string& word) {
// 这里简化为检查是否为某个关键字,实际可根据PL/0语言的规则扩展
vector<string> keywords = { "const", "var", "procedure", "begin", "end", "if", "then", "while", "do", "call", "read", "write", "else" };
return find(keywords.begin(), keywords.end(), word) != keywords.end();
}
// 判断是否为算数运算符(+、-、 *、/、+=、-=、*=、/=)
bool isAOperator(const char ch) {
// 修改为判断整个字符串是否为运算符
return ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '=';
}
// 判断是否为逻辑运算符(>、<、=、==、!=、>=、<=、||、&&)
bool isLOperator(const char ch) {
// 修改为判断整个字符串是否为运算符
return ch == '<' || ch == '>' || ch == '!' || ch == '|' || ch == '&' || ch == '=';
}
// 判断是否为界符
bool isDelimiter(char ch) {
return ch == ';' || ch == ',' || ch == '(' || ch == ')' || ch == '{' || ch == '}';
}
// 判断是否为常量
bool isConstant(const string& str) {
// 简化为判断是否为数字
return all_of(str.begin(), str.end(), isdigit);
}
// 判断是否为标识符
bool isIdentifier(const string& str) {
// 简化为判断是否以字母开头,后跟字母或数字
return isalpha(str[0]) && all_of(str.begin() + 1, str.end(), isalnum);
}
vector<Token> tokens;
vector<Token> tokenize(const string& input) {
string currentLexeme;
vector<Token> t;
for (size_t j = 0; j < input.size(); ++j) {
char ch = input[j];
if (isspace(ch) || isDelimiter(ch) || isAOperator(ch) || isLOperator(ch)) {
// 遇到空白字符、界符或运算符,判断并处理之前的单词
if (!currentLexeme.empty()) {
Token token;
token.lexeme = currentLexeme;
// 判断单词类型
if (isKeyword(currentLexeme)) {
token.type = K;
t.push_back(token);
}
else if (isConstant(currentLexeme)) {
token.type = C;
t.push_back(token);
}
else if (isIdentifier(currentLexeme)) {
token.type = I;
t.push_back(token);
}
else {
token.type = U;
cout << "词法分析有误,出现非法字符: " << currentLexeme <<" !!!请先修改源代码!" << endl << endl;
break;
}
currentLexeme.clear();
}
// 处理界符
if (isDelimiter(ch)) {
Token token;
token.type = D;
token.lexeme = ch;
t.push_back(token);
}
// 处理算数运算符
else if (isAOperator(ch)) {
Token token;
token.type = A;
// +=、-=、*=、/=
if (input[j + 1] == '=') {
token.lexeme = string(1, ch) + string(1, input[++j]);
t.push_back(token);
}
// ++、--
else if(ch == input[j + 1] && (ch == '+' || ch == '-')) {
token.lexeme = string(1, ch) + string(1, input[++j]);
t.push_back(token);
}
// +、-、 *、/
else {
token.lexeme = string(1, ch);
t.push_back(token);
}
}
// 处理逻辑运算符
else if (isLOperator(ch)) {
Token token;
token.type = L;
// ==、!=、>=、<=
if (input[j + 1] == '=') {
token.lexeme = string(1, ch) + string(1, input[++j]);
t.push_back(token);
}
// ||、&&
else if (ch == input[j + 1]) {
token.lexeme = string(1, ch) + string(1, input[++j]);
t.push_back(token);
}
// >、<、=
else {
token.lexeme = string(1, ch);
t.push_back(token);
}
}
}
else {
// 字母、数字等其他字符,构成单词的一部分
currentLexeme += ch;
}
}
// 处理最后一个单词
if (!currentLexeme.empty()) {
Token token;
token.lexeme = currentLexeme;
// 判断单词类型
if (isKeyword(currentLexeme)) {
token.type = K;
}
else if (isConstant(currentLexeme)) {
token.type = C;
}
else if (isIdentifier(currentLexeme)) {
token.type = I;
}
else {
token.type = U;
}
t.push_back(token);
}
return t;
}
void printInfo(vector<Token> t) {
cout << "词法分析结果(源程序的Token序列):" << endl;
for (const Token& token : t) {
cout << "[";
switch (token.type) {
case K:
cout << "关键字\t, \t";
break;
case I:
cout << "标识符\t, \t";
break;
case C:
cout << "常量\t, \t";
break;
case A:
cout << "操作符\t, \t";
break;
case L:
cout << "操作符\t, \t";
break;
case D:
cout << "界符\t, \t";
break;
case U:
cout << "非法\t, \t";
break;
}
cout << token.lexeme << "\t]" << endl;
}
cout << endl;
}
vector<Token> lexical_analyzer() {
cout << "**************************** 词法分析子程序 ****************************" << endl;
// 从文件读取源程序
ifstream inputFile("SourceCode.txt");
if (!inputFile.is_open()) {
cerr << "源代码文件打不开!" << endl;
return tokens;
}
// 读取整个文件内容
string program((istreambuf_iterator<char>(inputFile)), istreambuf_iterator<char>());
cout << "源程序代码:" << endl << program << endl << endl;
inputFile.close();
// 对源程序进行词法分析
tokens = tokenize(program);
// 输出词法分析结果
printInfo(tokens);
return tokens;
}
syntax_analyzer.cpp
#include"common.h"
// 属性表
vector<string> values;
int NUM = 100;
int FREQUENCY = 1;
// 产生式
vector<Production> Productions;
// 三地址码
vector<ThreeAddressCode> ThreeAddressCodes;
// 句柄
stack<string> Handles;
// 栈S
stack<char> S;
bool success = true;
void setProductions() {
// 将产生式按照相应格式存储
Productions.push_back({ 'S', {'w', '(', 'T', ')', '{', 'E', '}'} });
Productions.push_back({ 'E', {'S'} });
Productions.push_back({ 'E', {'i', '=', 'A'} });
Productions.push_back({ 'A', {'i', 'l', 'A'}});
Productions.push_back({ 'A', {'n', 'l', 'A'}});
Productions.push_back({ 'A', {'i', ';'}});
Productions.push_back({ 'A', {'n', ';'}});
Productions.push_back({ 'T', {'i', 'b', 'i'}});
}
// 简单优先关系表
int priorityTable[16][16] =
{ // N表示空,1表示>,0表示=,-1表示<
//S E A T { } w ( ) i = l ; n b #
/*S*/ {N,N,N,N,N,1,N,N,N,N,N,N,N,N,N,1},
/*E*/ {N,N,N,N,N,0,N,N,N,N,N,N,N,N,N,N},
/*A*/ {N,N,N,N,N,1,N,N,N,N,N,N,N,N,N,N},
/*T*/ {N,N,N,N,N,N,N,N,0,N,N,N,N,N,N,N},
/*{*/ {-1,0,N,N,N,N,-1,N,N,-1,N,N,N,N,N,N},
/*}*/ {N,N,N,N,N,1,N,N,N,N,N,N,N,N,N,1},
/*w*/ {N,N,N,N,N,N,N,0,N,N,N,N,N,N,N,N},
/*(*/ {N,N,N,0,N,N,N,N,N,-1,N,N,N,N,N,N},
/*)*/ {N,N,N,N,0,N,N,N,N,N,N,N,N,N,N,N},
/*i*/ {N,N,N,N,N,N,N,N,1,N,0,0,0,N,0,N},
/*=*/ {N,N,0,N,N,N,N,N,N,-1,N,N,N,-1,N,N},
/*l*/ {N,N,0,N,N,N,N,N,N,-1,N,N,N,-1,N,N},
/*;*/ {N,N,N,N,N,1,N,N,N,N,N,N,N,N,N,N},
/*n*/ {N,N,N,N,N,N,N,N,N,N,N,0,0,N,N,N},
/*b*/ {N,N,N,N,N,N,N,N,N,0,N,N,N,N,N,N},
/*#*/ {-1,N,N,N,N,N,-1,N,N,N,N,N,N,N,N,N}
};
int compare(char a, char b) {
int row;
int line;
switch (a) {
case 'S':row = 0; break;
case 'E':row = 1; break;
case 'A':row = 2; break;
case 'T':row = 3; break;
case '{':row = 4; break;
case '}':row = 5; break;
case 'w':row = 6; break;
case '(':row = 7; break;
case ')':row = 8; break;
case 'i':row = 9; break;
case '=':row = 10; break;
case 'l':row = 11; break;
case ';':row = 12; break;
case 'n':row = 13; break;
case 'b':row = 14; break;
case '#':row = 15; break;
}
switch (b) {
case 'S':line = 0; break;
case 'E':line = 1; break;
case 'A':line = 2; break;
case 'T':line = 3; break;
case '{':line = 4; break;
case '}':line = 5; break;
case 'w':line = 6; break;
case '(':line = 7; break;
case ')':line = 8; break;
case 'i':line = 9; break;
case '=':line = 10; break;
case 'l':line = 11; break;
case ';':line = 12; break;
case 'n':line = 13; break;
case 'b':line = 14; break;
case '#':line = 15; break;
}
return priorityTable[row][line];
}
char redefine(Token t,vector<string>& values) {
if (t.lexeme == "while") {
return 'w';
}
else if ((t.lexeme == "+") || (t.lexeme == "-") || (t.lexeme == "*") || (t.lexeme == "/")) {
values.push_back(t.lexeme);
return 'l';
}
else if (t.type == L) {
values.push_back(t.lexeme);
return 'b';
}
else if (t.type == C) {
values.push_back(t.lexeme);
return 'n';
}
else if (t.type == I) {
values.push_back(t.lexeme);
return 'i';
}
else {
return t.lexeme[0];
}
}
// 输出文法的HEAD和LAST集合
void printSet(){
cout << "************** while循环语句的文法 **************" << endl;
cout << "S’ -> # S #\n" << "S -> while ( T ) { E }\n" << "E -> S\n" << "E -> i = A\n" << "A -> i l A\n" << "A -> n l A\n" <<"A -> i ;\n"<<"A -> n ;\n"<<"T -> i b i\n";
cout << "i:标识符\tl:算数运算符\t\tn:常数\t\tb:比较运算符" << endl << endl;
cout << "************** 文法中非终结符的HEAD集和LAST集 **************" << endl;
cout << "\t" << "T\tA\tE\t\tS\tS'" << endl;
cout << "HEAD" << "\ti\ti,n\tS,w,i\t\tw\t#" << endl;
cout << "LAST" << "\ti\tA,;\tS,A,},;\t\t}\t#" << endl;
cout << endl;
}
// 打印优先关系表
void printPriorityTable(){
cout << "***************************************************** 文法的优先关系表 *****************************************************" << endl;
cout << "\tS\tE\tA\tT\t{\t}\tw\t(\t)\ti\t=\tl\t;\tn\tb\t#\t" << endl;
string s = "SEAT{}w()i=l;nb#";
int c;
for (size_t i = 0; i < 16; i++)
{
cout << s[i];
for (size_t j = 0; j < 16; j++)
{
c = priorityTable[i][j];
switch (c)
{
case 0:
cout << "\t=";
break;
case 1:
cout << "\t>";
break;
case -1:
cout << "\t<";
break;
default:
cout << "\t ";
break;
}
}
cout << endl;
}
cout << endl;
}
// 初始化输入流(把Token序列中的字符串换成文法中的字符)
string initString(vector<Token> tokens, vector<string>& values) {
string s = "";
for (Token t:tokens)
{
char c = redefine(t,values);
s += c;
}
return s;
}
void parse(stack<char>& S, vector<Token> tokens, vector<string>& values) {
cout << "****************************************************** 规约过程 *****************************************************" << endl << endl;
// 将 # 入栈
S.push('#');
// 将token中的序列转换成文法中的字符
string s = initString(tokens,values) + '#';
int step = 0;
cout << "步骤\t分析栈\t\t\t\t\t优先级\t\t\t\t 输入串\t\t动作" << endl;
do {
// 读取栈顶和输入串的第一个字符
char inputChar = s[0];
char stackTop = S.top();
// 获取栈顶和输入字符的优先关系
int relation = compare(stackTop, inputChar);
if (relation == N) {
cout << endl << "无" << stackTop << " 和 " << inputChar << "之间的优先级,语法分析无法继续进行!" << endl;
success = false;
break;
}
// 规约操作
if (relation == 1) {
cout << ++step << "\t";
// 输出分析栈(逆序)
reverseStackPrint(S);
cout << " > " << setw(40) << right << s;
// 根据栈顶的句柄进行规约
string production = handleReduction(S);
cout<< "\t\t规约:"<< production << endl;
}
// 移进操作
else {
cout << ++step << "\t";
// 输出分析栈(逆序)
reverseStackPrint(S);
if (relation == -1) {
cout << " < " << setw(40) << right << s << "\t\t移进" << endl;
}
else if (relation == 0) {
cout <<" = " << setw(40) << right << s << "\t\t移进" << endl;
}
S.push(inputChar);
s = s.substr(1);
}
} while (s[0] != '#'||S.size()>2);
if (s[0] == '#') {
cout << ++step << "\t";
// 输出分析栈(逆序)
reverseStackPrint(S);
cout << " " << setw(40) << right << s << "\t\t成功" << endl <<"该句子满足语法结构!" << endl << endl;
}
}
void reverseStackPrint(stack<char> S) {
int count = 0;
// 输出分析栈(逆序)
stack<char> tempStack = S;
stack<char> reversedStack;
while (!tempStack.empty()) {
reversedStack.push(tempStack.top());
tempStack.pop();
}
while (!reversedStack.empty()) {
count++;
cout << reversedStack.top();
reversedStack.pop();
}
for (size_t i = 0; i < 40 - count; i++)
{
cout << " ";
}
}
// 生成三地址码
void genCode(string handle) {
if (handle == "ibi") {
ThreeAddressCode t;
for (size_t i = 0; i < 3; i++)
{
string s = values.front();
values.erase(values.begin());
t.code = t.code +s;
}
t.num = NUM++;
t.code = "if " + t.code + " goto " + to_string(NUM + 1);
ThreeAddressCodes.push_back(t);
t.num = NUM++;
t.code = "goto " + to_string(100);
ThreeAddressCodes.push_back(t);
}
}
// 为赋值语句添加三地址码
void addCode(vector<string>& values) {
ThreeAddressCode t;
// 先乘除
auto it_mul_div = find_if(values.begin(), values.end(), [](const string& value) {
return value == "*" || value == "/";
});
while (it_mul_div!=values.end()) {
t.num = NUM++;
t.code = "T" + to_string(FREQUENCY) + "=" + *(prev(it_mul_div)) + *(it_mul_div)+*(next(it_mul_div));
ThreeAddressCodes.push_back(t);
*(it_mul_div - 1) = "T" + to_string(FREQUENCY);
auto next_it = it_mul_div + 1;
values.erase(it_mul_div, next_it + 1);
it_mul_div = find_if(values.begin(), values.end(), [](const string& value) {
return value == "*" || value == "/";
});
FREQUENCY++;
}
// 后加减
auto it_add_sub = find_if(values.begin(), values.end(), [](const string& value) {
return value == "+" || value == "-";
});
while (it_add_sub != values.end()) {
t.num = NUM++;
t.code = "T" + to_string(FREQUENCY) + "=" + *(prev(it_add_sub)) + *(it_add_sub)+*(next(it_add_sub));
ThreeAddressCodes.push_back(t);
*(it_add_sub - 1) = "T" + to_string(FREQUENCY);
auto next_it = it_add_sub + 1;
values.erase(it_add_sub, next_it + 1);
it_add_sub = find_if(values.begin(), values.end(), [](const string& value) {
return value == "+" || value == "-";
});
FREQUENCY++;
}
t.num = NUM++;
t.code = *(values.begin()) + "=" + *(values.begin()+1);
ThreeAddressCodes.push_back(t);
// 添加第一个while条件为假时的出口
t.num = NUM++;
t.code =" ";
ThreeAddressCodes.push_back(t);
int targetNum = 101;
auto it = find_if(ThreeAddressCodes.begin(), ThreeAddressCodes.end(), [targetNum](const ThreeAddressCode& code) {
return code.num == targetNum;
});
it->code = "goto " + to_string(100 + ThreeAddressCodes.size()-1);
}
// 在栈顶找句柄
string handleReduction(stack<char>& S) {
string production;
string handle = "";
bool found = false;
while (!S.empty()) {
char top = S.top();
handle = top + handle;
// 在临时栈中找匹配的产生式右部
for (const Production& prod : Productions) {
string rightStr(prod.right.begin(), prod.right.end());
if (rightStr == handle) {
found = true;
production += prod.left;
S.pop();
S.push(prod.left);
break;
}
}
if (found) {
break;
}
S.pop();
}
production = production +" -> " + handle;
//产生三地址码
genCode(handle);
return production;
}
void printThreeeAddressCodes() {
if (success) {
// 输出三地址码
cout << "**************************** 三地址码序列 ****************************" << endl;
for (ThreeAddressCode t : ThreeAddressCodes) {
cout << t.num << "\t" << t.code << endl;
}
}
else {
cout << "请先进行正确的语法分析!" << endl;
}
cout << endl << endl;
}
// 语法分析总控程序
void syntax_analyzer(vector<Token> tokens) {
cout << "**************************** 语法分析子程序 ****************************" << endl << endl << endl;
// 打印HEAD和LAST
printSet();
// 打印优先关系表
printPriorityTable();
// 初始化文法
setProductions();
//简单优先关系分析
parse(S, tokens,values);
//为赋值语句添加三地址码
addCode(values);
}
main.cpp
#include"common.h"
int main() {
int option;
// 词法分析器的结果(Token序列)
vector<Token> tokens;
bool successFlag1 = true;
bool success2 = false;
do {
cout << "**************************** WHILE循环语句的翻译程序设计(优先法、输出三地址码) ****************************" << endl << endl;
cout << "1. 词法分析 \n2. 语法分析(简单优先法) \n3. 语法制导的翻译(输出三地址码) \n4. 退出\n\n";
cout << "请输入你的选择: ";
cin >> option;
cout << "==============================================" << endl;
switch (option) {
case 1: {
tokens = lexical_analyzer();
break;
}
case 2: {
if (tokens.empty()) {
cout << "请先进行词法分析!" << endl;
break;
}
for (Token t:tokens)
{
if (t.type == U) {
cout << "非法字符 " << t.lexeme << " ,请修改源程序!" << endl;
successFlag1 = false;
break;
}
}
if (successFlag1) {
syntax_analyzer(tokens);
success2 = true;
}
break;
}
case 3: {
if (success2)
printThreeeAddressCodes();
else
cout << "语法分析失败!无法输出三地址码!" << endl;
break;
}
case 4:
cout << "程序退出!" << endl;
return 0;
break;
default:
cout << "无效输入,请重新输入!" << endl;
break;
}
} while (option != 4);
return 0;
}
运行结果演示视频:
编译原理课程设计
三、课程设计完整资料(包括实验报告等)
链接: https://pan.baidu.com/s/1R6pLKSc_9qKcWSbXXS2Xtg?pwd=vsfu 提取码: vsfu 复制这段内容后打开百度网盘手机App,操作更方便哦