WHILE循环语句的翻译程序设计(优先法、输出三地址码)

一、设计目的、功能与要求

  1. 写出符合给定的语法分析方法的文法及属性文法。
  2. 完成题目要求的中间代码(三地址码或四元式)的描述。
  3. 写出给定的语法分析方法的思想,完成语法分析和语义分析程序设计。
  4. 实现程序,设计若干用例测试程序。
  5. 设计报告格式按附件要求书写。

        课程设计报告书正文的内容应包括:

        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,操作更方便哦 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值