必看:据我所知这种题目分为语法分析和语义分析根据老师的要求不同具体的内容还有一些差别,两年前我做这个实验的时候网上只有一个全是bug的语法分析。不要担心,我已经把bug改好了,并且提供了不同的实现方法,还有语义分析我也写在下边了。能帮助到你的话,给我点个赞吧,球球了。
实验要求:通过设计、编写和调试词法分析程序,了解词法扫描器的组成结构、不同种类单词的识别方法,掌握由单词的词法规则出发,利用程序实现词法扫描器的方法。通过设计、编写和调试语法分析程序,了解语法分析器的组成结构以及对文法的要求,掌握基于LL(1)文法和算符优先文法的语法分析程序的实现方法。通过设计、编写和调试语法制导翻译程序,掌握从语句的语法出发,构造相应的语义子程序,实现自定义语言的语法制导翻译。
语法分析器
第一种,我加了注释很容易看懂,c++能直接跑
#include<fstream>
#include <iostream>
#include <string>
#include<cstring>
#include<map>
using namespace std;
#include <stdio.h>
#include<vector>
//保留字
const string KeyWord[6] = { "main","int","float","if","else","while" };
int syn; //单词种别码
string token; //单词自身字符串.用于在程序整体中找到每个单位字符串
//增加一个数组存变量;
map<int, string>arr;
//string arr[100]=;
int l = 1;
int constant[200];//存储常量;
int sum; //INT整型里的码内值,整型数据的值(本来是字符串)
int i = 0;//循环索引(注意索引是共用的)
int x = 0;//对标识符计数
int y = 100;//对整型数计数
int z = 0;//对关键字与符号不计数
//bool IsLetter(char ch); //判断是否为字母(空格后首字符是字母可能是关键字或者标识符)
bool IsLetter(char ch) //判断是否为字母
{
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
return true;
else
return false;
}
//bool IsDigit(char ch); //判断是否为数字
bool IsDigit(char ch) //判断是否为数字
{
if (ch >= '0' && ch <= '9')
return true;
else
return false;
}
//void scanf_s(char s[]); //扫描
void scanf_s(char s[]) //扫描
{
token = ""; //清空当前字符串(每次判断前都要清空上一次的记录)
// 1.判断字符是否为数字
if (IsDigit(s[i]))//空格后第一个字符是数字,则整个单元字符串一定是数
{
token = ""; //清空当前字符串
sum = 0;
while (IsDigit(s[i])) {
sum = sum * 10 + (s[i] - '0');
i++; //字符位置++
syn = 11; //INT种别码为11
}
y++;//从100开始计数
}
// 2.字符为字符串,表现为字母开头衔接任意个数字或字母
else if (IsLetter(s[i]))//空格后第一个字符是字母,是标识符或者关键字(先判断标识符再在其基础上判断关键字)
{
token = ""; //清空当前字符串
while (IsDigit(s[i]) || IsLetter(s[i])) {
token += s[i]; //加入token字符串
i++;
}
int flag = 0;
//如果是关键字,则用for循环将token与keyword比较找对应的种别码
for (int j = 0; j < 6; j++)
{
if (token == KeyWord[j]) //如果都是string类型,可以直接=相比较,若相等则返回1,否则为0
{
syn = j + 1; //种别码从1开始所以要加1(在syn=10的基础上更新)
flag = 1;
//x--; //关键字不计数
//break;
}
}
if (flag == 0)
{
syn = 10; // 如果是标识符,种别码为10
//x++;
int flag1 = 0;
for (int i = 1; i < 100; i++)
{
if (token == arr[i])
{
x = i;
flag1 = 1;
}
}
if (flag1 == 0)
{
arr[l++] = token;
x++;
}
}
}
//3. 判断为符号
else {
token = ""; //清空当前字符串
switch (s[i]) {
case'=' :
syn = 13;
i++;
token = "=";
if (s[i] == '=') {
syn = 22;
i++;
token = "==";
}
break;
case'+':
syn = 14;
i++;
token = "+";
break;
case'-':
syn = 15;
i++;
token = "-";
break;
case'*':
syn = 16;
i++;
token = "*";
break;
case'/':
syn = 17;
i++;
token = "/";
break;
case'(':
syn = 26;
i++;
token = "(";
break;
case')':
syn = 27;
i++;
token = ")";
break;
case'{':
syn = 28;
i++;
token = "[";
break;
case'}':
syn = 29;
i++;
token = "]";
break;
case',':
syn = 25;
i++;
token = ",";
break;
case';':
syn = 24;
i++;
token = ";";
break;
case'>':
syn = 20;
i++;
token = ">";
if (s[i] == '=')
{
syn = 21;
i++;
token = ">=";
}
break;
case'<':
syn = 18;
i++;
token = "<";
if (s[i] == '=')
{
syn = 19;
i++;
token = "<=";
}
break;
case'!':
syn = 9;
i++;
if (s[i] == '=')
{
syn = 23;
i++;
token = "!=";
}
break;
//case'||'://平台编译过不了
case'|':
i++;
if (s[i] == '|')
{
syn = 7;
i++;
token = "||";
}
break;
//case'&&':
case'&':
i++;
if (s[i] == '&')
{
syn = 8;
i++;
token = "&&";
}
break;
default:
syn = -1;
break;
}
}
}
int main()
{
char str[200];
ifstream infile;
ofstream outfile1, outfile2;
//输入文件scource
infile.open("source.txt", ios::in);
//输出文件token与symble
outfile1.open("token.txt", ios::out);
outfile2.open("symble.txt", ios::out);
if (!infile)
{
cout << "读取文件失败!";
}
while (infile >> str) {
do {
scanf_s(str);
if (syn <= 9 || (syn <= 29 && syn >= 13))
outfile1 << syn << " " << z << endl;//对关键字跟符号不计数(z恒等于0)
else if (syn == 10) {
//if(token!= token.txt)
outfile1 << syn << " " << x << " " << endl;//标识符从0计数
outfile2 << x << " " << token << endl;
}
else if (syn == 11 || syn == 12) {
outfile1 << syn << " " << y << " " << endl;//实(整)数从100计数
outfile2 << y << " " << sum << endl;
}
} while (i < strlen(str));
i = 0;
}
infile.close();
outfile1.close();
outfile2.close();
}
//关键就在于scan()扫描函数(结合各种条件与提前定义好的函数判断程序中每个单位字符串的种类,并且指定相应的syn种别码)
第二种 网上找的也能实现功能,但是函数名混乱阅读困难
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <fstream>
using namespace std;
const string CodeFileName = "./source.txt";
string keywords[6];//关键字表 种别码1-6
string operate[14];//运算符表 种别码7-9 13-23
string delimiter[6];//界符表 种别码24-29
const string op = "+-*/%=!&|<>";
const int _EOF_ = -2;
const int _ERROR_ = -1;
map<string, int> categoryCode;//种别码表
int pos, len;//当前字符的位置和长度
string code,tempToken;
int count1=0,count2=100;//符号记录 常数记录
enum {
_ID_, _INT_, _DOUBLE_, _OPERATOR_, _DELIMITER_, _KEYWORD_, _SPACE_
}; // 类型
string cat[7] = { "id", "int", "double", "operator", "delimiter", "keyword", "space" };
//读文件
string type2[100];
string constant[100];
int tcount = 0,ccount=0;
int temp = 0;
map<string, int> idList;
map<string, int> conList;
int Ccount=101;//常数开始记录的值
struct Token1 { // 1 0 (main)
int type1;//种别码
int massage1;//属性信息
//string value;// 关键字/运算符/界符/变量名/常数
//string category;// 种别码对应的类型名称
/*Token1(int type1,int massage1,string value,string category):type1(type1),value(value), massage1(massage1),category(category){}
friend ostream& operator<<(ostream& os, const Token1& t) {
os << t.type1 << " " << t.massage1;
return os;
}*/
};
//struct Token2 {
// int type2;//种别码 1 i
// string message2;
// Token2(int type2, string message2) :type2(type2),message2(message2) {}
// friend ostream& operator<<(ostream& os, const Token2& t) {
// os << t.type2 << " " << t.message2;
// return os;
// }
//};
//struct Token3 {
// int type3;//种别码 101 0
// int message3;
// Token3(int type3, int message3) :type3(type3), message3(message3) {}
// friend ostream& operator<<(ostream& os, const Token3& t) {
// os << t.type3 << " " << t.message3;
// return os;
// }
//};
Token1 tokenList1[100];
//vector<Token2> tokenList2;
//vector<Token3> tokenList3;
vector<string> readfile(string filename) {
vector<string> res;
try {
ifstream fin;
fin.open(filename.c_str());
string temp;
while (getline(fin, temp))
res.push_back(temp);
return res;
}
catch (const exception& e) {
cerr << e.what() << "\n";
return res;
}
}
void init() {
keywords[0] = "main";categoryCode["main"] = 1;
keywords[1] = "int";categoryCode["int"] = 2;
keywords[2] = "float";categoryCode["float"] = 3;
keywords[3] = "if";categoryCode["if"] = 4;
keywords[4] = "else";categoryCode["else"] = 5;
keywords[5] = "while";categoryCode["while"] = 6;
operate[0] = "||";categoryCode["||"] = 7;
operate[1] = "&&";categoryCode["&&"] = 8;
operate[2] = "!";categoryCode["!"] = 9;
operate[3] = "=";categoryCode["="] = 13;
operate[4] = "+";categoryCode["+"] = 14;
operate[5] = "-";categoryCode["-"] = 15;
operate[6] = "*";categoryCode["*"] = 16;
operate[7] = "/";categoryCode["/"] = 17;
operate[8] = "<";categoryCode["<"] = 18;
operate[9] = "<=";categoryCode["<="] = 19;
operate[10] = ">";categoryCode[">"] = 20;
operate[11] = ">=";categoryCode[">="] = 21;
operate[12] = "==";categoryCode["=="] = 22;
operate[13] = "!=";categoryCode["!="] = 23;
delimiter[0] = ";"; categoryCode[";"] = 24;
delimiter[1] = ","; categoryCode[","] = 25;
delimiter[2] = "("; categoryCode["("] = 26;
delimiter[3] = ")"; categoryCode[")"] = 27;
delimiter[4] = "{"; categoryCode["{"] = 28;
delimiter[5] = "}"; categoryCode["}"] = 29;
vector<string> res = readfile(CodeFileName);
int size = res.size();
for (int i = 0; i < size; i++) {
code += res[i] + '\n';
}
len = code.size();
}
char peek() {
//探测下一个字符,若存在则返回该字符,否则返回\0即字符串结束符
if (pos + 1 < len) return code[pos + 1];
else return '\0';
}
inline bool isDigit(char ch) {
//判断字符ch是否为数字0-9
return ch >= '0' && ch <= '9';
}
inline bool isLetter(char ch) {
//判断字符ch是否为字母或下划线(即A-Z a-z _)
return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_';
}
bool isKeyword(string s) {
//判断字符串s是否为关键字
for (int i = 0; i < 6; i++) {
if (s == keywords[i]){
return true;
}
}
return false;
}
bool isOP(char ch) {
return op.find(ch) != string::npos;
}
bool isOperator(string s) {
//判断字符s是否为运算符
for (int i = 0; i < 14; i++) {
if (s == operate[i]) {
return true;
}
}
return false;
}
bool isDelimiter(char ch) {
//判断字符ch是否为界符
for (int i = 0; i < 6; i++) {
if (ch == delimiter[i][0]) return true;
}
return false;
}
int judge(char ch) {
//核心函数,判断并返回当前字符(code[pos])的枚举类型,并对一些特殊的token进行处理后直接放入tokenList(如字符和字符串常量)
if (ch == '\n' || ch == ' ') return _SPACE_;
if (isDigit(ch)) {
char nextChar = peek();
//if (ch == '0' && nextChar == '.') {//看看是0.多少
// ++pos;
// if (!isDigit(peek()))
// return _ERROR_;
// tempToken = '0.';
// while (isDigit(peek())) {
// tempToken += peek();
// ++pos;
// }
// return _DOUBLE_;
//}
if (ch == '0' && !isDigit(nextChar)) {//不是数字也不是. 说明是单纯的一个0
tempToken = "0";
return _INT_;
}
else if (ch != '0') {//大于1的数
tempToken = ch;
while (isDigit(peek())) {
tempToken += peek();
++pos;
}
char nextChar = peek();
if (nextChar == '.') {//是否是小数
tempToken += nextChar;
++pos;
nextChar = peek();
if (isDigit(nextChar)) {
tempToken += peek();
++pos;
while (isDigit(peek())) {
tempToken += peek();
++pos;
}
return _DOUBLE_;
}
else return _ERROR_;
}
else return _INT_;
}
else {//开头为数字的错误形式
++pos;
return _ERROR_;
}
}
if (isLetter(ch)) {
tempToken = ch;
char nextChar = peek();
while (isLetter(nextChar)) {
tempToken += nextChar;
++pos;
nextChar = peek();
}
return isKeyword(tempToken) ? _KEYWORD_ : _ID_;
}
if (isDelimiter(ch)) {
tempToken = "";
tempToken += ch;
return _DELIMITER_;
}
if (isOP(ch)) {
tempToken = "";
tempToken += ch;
char nextchar = peek();
if (isOP(nextchar)) {
if (isOperator(tempToken + nextchar)) {
tempToken += nextchar;
++pos;
return _OPERATOR_;
}
else return _OPERATOR_;
}
else return _OPERATOR_;
}
return _ERROR_;
}
bool isRepeat(string s) {//是否已经出现过
for (int i = 0; i < tcount; i++) {
if (s == type2[i]) {
return false;
}
}
return true;
}
void writeType2(string s) {//写入不重复的_ID_
if (isRepeat(s)) {
type2[tcount] = s;
tcount++;
idList[s] = tcount;
}
}
bool isRepeat1(string con) {//是否已经出现过
for (int i = 0; i < ccount; i++) {
if (con == constant[i]) {
return false;
}
}
return true;
}
void writeType1(string con) {//写入不重复的常数
if (isRepeat1(con)) {
constant[ccount] = con;
ccount++;
conList[con] = Ccount;
Ccount++;
}
}
int read_next() {
int type = judge(code[pos]);
while (pos < len && type == _SPACE_) {
++pos;
type = judge(code[pos]);
}
if (pos >= len) return _EOF_;
++pos;
if (type == _ERROR_) return _ERROR_;
if (type == _DOUBLE_) {
count2++;
writeType1(tempToken);
//tokenList3.push_back(Token3(count2, type));
tokenList1[temp].type1 = 12;
tokenList1[temp].massage1 = count2;
temp++;
//tokenList1.push_back(Token1(12, count2, tempToken, cat[type]));
return _DOUBLE_;
}
if (type == _INT_) {
count2++;
writeType1(tempToken);
tokenList1[temp].type1 = 11;
tokenList1[temp].massage1 = count2;
temp++;
//tokenList3.push_back(Token3(count2, type));
//tokenList1.push_back(Token1(11, count2, tempToken, cat[type]));
return _INT_;
}
if (type == _ID_) {
writeType2(tempToken);
/*tokenList2.push_back(Token2(idList[tempToken], tempToken));*/
/*tokenList1.push_back(Token1(10, idList[tempToken], tempToken, cat[type]));*/
tokenList1[temp].type1 = 10;
tokenList1[temp].massage1 = idList[tempToken];
temp++;
return _ID_;
}
if (type == _OPERATOR_ || type == _KEYWORD_ || type == _DELIMITER_) {
//tokenList1.push_back(Token1(categoryCode[tempToken], 0, tempToken, cat[type]));
tokenList1[temp].type1 = categoryCode[tempToken];
tokenList1[temp].massage1 = 0;
temp++;
}
return _ERROR_;
}
int main() {
init();
while (pos < len) {
int flag = read_next();
if (flag == _EOF_) break;
else if (flag == _ERROR_) continue;
}
ofstream outFileToToken;
ofstream outFileToSymble;
outFileToToken.open("token.txt", ios_base::trunc);
outFileToSymble.open("symble.txt", ios_base::trunc);
//outFile << "Hello" << endl;
for (int i = 0; i < temp;i++) {
outFileToToken << tokenList1[i].type1 <<" "<<tokenList1[i].massage1<< endl;
}
for (int i = 0; i < tcount; i++) {
outFileToSymble << i + 1 << " " << type2[i] << endl;
}
for (int i = 0; i < ccount; i++) {
outFileToSymble << conList[constant[i]] << " " << constant[i] << endl;
}
outFileToToken.close();
outFileToSymble.close();
return 0;
}
第三种就是上边说的bug版本,我记错了,我当时并没有改出来嘻嘻。所以也不放上来了,我印象当中老代码最大的问题是输入输出那里的文件打开关闭,可以自己改改。
语义分析是最难的,代码很长要慢慢看,我这儿也是祖传的,但是我加了注释。
#include<iostream>
#include<vector>
#include<cstring>
#include<string>
#include<fstream>
#include<map>
using namespace std;
char ch; int sym; int c = 0; int now; int flag = 0;
int nextquad = 1;
int tempnumcount = 0;
int p[100];
int token1[300];
int token2[300]; //now记录的就是指向行号的指针
string symble[300]; //存储symble表,
struct quadruple //四元组
{
int op;
int arg1;
int arg2;
int result;
};
vector <quadruple>interable;
struct Node {
int place;
int type;
vector<int> True;
vector<int> False;
vector<int>next;
int judge;
int Firstquad;
};
struct symbol {
int number;
int addr; //临时变量的地址要从201开始
string name;
};
void getSymble() {
c++;
sym = token1[c];//指针指向下一个还没被比过的
now = c - 1;
}
bool match(int expectedSym) {
if (sym == expectedSym) {
getSymble();
return true;
}
else
{
return false;
}
}
void ProgrammeBody();
void StateGroup();
void StateGroup2();
void SingleSentence();
void StateSentence();
void StateSentence2();
void GiveValue();
Node IfSentence();
Node IfSentence2();
Node WhileSentence();
void TypeDef();
Node Type();
void VarList();
void VarList2();
Node AlgorithmnSentence();
Node AlgorithmnSentence2(int& previousAddr);
Node Item();
Node Item2(int& previousAddr);
Node Factor();
Node Algri();
Node BoolSentence();
void Bool_or();
Node BoolItem();
void Bool_and();
Node BoolFactor();
Node RelateSentence();
Node RelateSymbol();
Node M();
void N();
void Na();
void P();
void Va();
void emit(int op, int arg1, int arg2, int result) { //操作符,第一操作数,第二操作数,结果的符号地址
quadruple q;
q.arg1 = arg1;
q.arg2 = arg2;
q.op = op;
q.result = result;
interable.push_back(q);
nextquad++;
}
int newtemp() {//产生新的临时变量;
symbol s;
char ch[4];
sprintf(ch, "%d", tempnumcount);
s.name = "t";
s.name.append(ch);
tempnumcount++;
s.addr = tempnumcount + 200; //记录temp的地址
return s.addr;
}
void backpatch(vector<int> p, int addr) {
for (int i = 0; i < p.size(); i++) {
interable[p[i] - 1].result = addr;
}
}
vector<int> merge(vector<int> p1, vector<int> p2) {
vector<int> p;
for (int i = 0; i < p1.size(); i++) {
p.push_back(p1[i]);
}
for (int i = 0; i < p2.size(); i++) {
p.push_back(p2[i]);
}
return p;
}
void P() {
if (match(1)) {
if (match(26)) {
if (match(27)) {
if (match(28)) {
ProgrammeBody();
if (match(29))
{
return;
}
}
}
}
}
}
void ProgrammeBody() {
StateGroup();
}
void StateGroup() {
SingleSentence();
StateGroup2();
}
void StateGroup2() {
if (sym == 2 || sym == 3 || sym == 4 || sym == 6 || sym == 10) {
StateGroup();
}
else//(sym == 29)
return;
}
void SingleSentence() {
if (sym == 2 || sym == 3)
StateSentence();
else if (sym == 10)
GiveValue();
else if (sym == 4)
IfSentence();
else//(sym == 6)
WhileSentence();
}
void StateSentence() {
TypeDef();
StateSentence2();
}
void StateSentence2() {
if (sym == 2 || sym == 3)
StateSentence();
else
return;// (sym == 29 || sym == 5 || sym == 2 || sym == 3 || sym == 4 || sym == 6 || sym == 10)
}
void TypeDef() {
Node a;
a = Type();
VarList();
if (match(24)) {
return;
}
}
void VarList() {
if (match(10)) {
VarList2();
}
}
void VarList2() {
if (match(25)) {
VarList();
}
else if (sym == (2 || sym == 3 || sym == 24)) {
return;
}
}
Node Type() {
Node a;
if (match(3)) {
a.type = 3;
return a;
}
else if (match(2)) {
a.type = 2;
return a;
}
}
void GiveValue() {
Node a;
if (match(10)) { //这里match的即为等号左边的数
int seq = now;
if (match(13)) {
a = AlgorithmnSentence(); //记录Newtmp的地址和类型。
if (match(24)) {
emit(13, a.place, 0, token2[seq]);
return;
}
}
}
}
Node IfSentence() {
Node a, b, d, c;
if (match(4)) {
if (match(26)) {
a = BoolSentence(); //E
if (match(27)) {
int judge;
int tmpquad = nextquad; //M1
d = M(); //S1
Node N; //N
N.next.push_back(nextquad);
emit(30, 0, 0, 0);
b = IfSentence2(); //S2
if (b.judge == 0) { //IfSentence2()生成空
backpatch(a.True, tmpquad);
c.next = merge(a.False, d.next);
interable.pop_back();
nextquad--;
return c;
}
else {
backpatch(a.True, tmpquad);
backpatch(a.False, b.Firstquad);
c.next = merge(d.next, N.next);
c.next = merge(c.next, b.next);
backpatch(c.next, nextquad);
return c;
}
}
}
}
}
Node IfSentence2() {
Node a, b, c;
if (match(5)) {
int tmpquad = nextquad; //记录M2
a = M();
c = a;
c.Firstquad = tmpquad;
c.judge = 1;
return c;
}
else { //否则一定为空
c.judge = 0;
return c;
}
}
Node WhileSentence() {
Node a, b, c;
if (match(6)) {
if (match(26)) {
int tmpquad = nextquad; //M1,记录S.begin的值
a = BoolSentence(); //E
if (match(27)) {
int tmpquad2 = nextquad; //M2
b = M(); //S1,即语句块
backpatch(b.next, tmpquad);
backpatch(a.True, tmpquad2);
c.next = a.False;
emit(30, 0, 0, tmpquad);
backpatch(c.next, nextquad);
return c;
}
}
}
}
Node M() {
if (match(3)) { //声明
VarList();
StateSentence2();
}
if (match(2)) { //声明
VarList();
StateSentence2();
}
if (match(4)) {
Node a, b, c, d;
if (match(26)) {
a = BoolSentence(); //E
if (match(27)) {
int judge;
int tmpquad = nextquad; //M1
d = M(); //S1
Node N;
N.next.push_back(nextquad);
b = IfSentence2(); //S2
if (b.judge == 0) { //IfSentence2()生成空
backpatch(a.True, tmpquad);
c.next = merge(a.False, d.next);
return c;
}
else {
backpatch(a.True, tmpquad);
backpatch(a.False, b.Firstquad);
c.next = merge(d.next, N.next);
c.next = merge(c.next, b.next);
backpatch(c.next, nextquad);
return c;
}
}
}
}
if (match(10)) {
Node a, b, c;
int seq = now;
if (match(13)) {
a = AlgorithmnSentence(); //记录Newtmp的地址和类型。
if (match(24)) {
emit(13, a.place, 0, token2[seq]);
c.next.clear(); //初始化
return c;
}
}
}
if (match(6)) {
Node a, b, c;
if (match(26)) {
int tmpquad = nextquad; //M1
a = BoolSentence(); //E
if (match(27)) {
int tmpquad2 = nextquad; //M2
b = M(); //S1
backpatch(b.next, tmpquad);
backpatch(a.True, tmpquad2);
c.next = a.False;
emit(30, 0, 0, tmpquad);
}
}
}
if (match(28)) {
Node a;
StateGroup();
if (match(29))
{
a.next.clear();
return a;
}
}
}
Node AlgorithmnSentence() {
Node a, b, c;
a = Item();
b = AlgorithmnSentence2(a.place);
c = b;
return c;
}
Node AlgorithmnSentence2(int& previousAddr) {
Node a; Node b; Node c;
if (match(14)) {
a = Item();
b.place = previousAddr;
c.place = newtemp();
emit(14, b.place, a.place, c.place);
c = AlgorithmnSentence2(c.place);
return c;
}
else if (match(15)) {
a = Item();
b.place = previousAddr;
c.place = newtemp();
emit(15, b.place, a.place, c.place);
c = AlgorithmnSentence2(c.place);
return c;
}
else { //包含 所有退出的情况
c.place = previousAddr;
return c;
}
}
Node Item() {
Node a, b, c;
a = Factor();
b = Item2(a.place); //参数存入Factor的地址
c = b;
return c;
}
Node Item2(int& previousAddr) {
Node a, b, c;
if (match(16)) {
a = Factor();
b.place = previousAddr;
c.place = newtemp();
emit(16, b.place, a.place, c.place);
c = Item2(c.place);
return c;
}
else if (match(17)) {
a = Factor();
b = Item2(previousAddr);
c.place = newtemp();
emit(17, b.place, a.place, c.place);
return c;
}
else
{
c.place = previousAddr;
return c; //因为遇到了空,传回去第二个操作数的值是0
}
}
Node Factor() {//赋值语句
Node a; Node b;
if (match(26)) {
b = AlgorithmnSentence();
if (match(27)) {
a.place = b.place;
return a;
}
}
else {
a = Algri();
return a;
}
}
Node BoolSentence() {
Node a, b, c;
a = BoolItem();
if (match(7)) {
//nextquad++;
int tmpquad = nextquad;
b = BoolSentence();
backpatch(a.False, tmpquad);
c.True = merge(a.True, b.True);
c.False = b.False;
return c;
}
else {
c.True = a.True;
c.False = a.False;
return c;
}
}
Node BoolItem() {
Node a, b, c;
a = BoolFactor();
if (match(8)) {
//nextquad++;
int tmpquad = nextquad;
b = BoolItem();
backpatch(a.True, tmpquad);
c.True = b.True;
c.False = merge(a.False, b.False);
return c;
}
else {
c.True = a.True;
c.False = a.False;
return c;
}
}
Node RelateSentence() {
Node a, b, op, c;
vector<int> T;
vector<int> F;
a = Algri();
op = RelateSymbol();
b = Algri();
T.push_back(nextquad);
F.push_back(nextquad + 1);
c.True = T;
c.False = F;
emit(op.place, a.place, b.place, 0);
emit(30, 0, 0, 0);
return c;
}
Node BoolFactor() {
Node a, b, c;
if (match(9)) {
a = RelateSentence();
c.True = a.False;
c.False = a.True;
return c;
}
else {
a = RelateSentence();
c.True = a.True;
c.False = a.False;
return c;
}
}
Node RelateSymbol() {
Node a;
if (match(18)) {
a.place = 18;
return a;
}
else if (match(19))
{
a.place = 19;
return a;
}
else if (match(20))
{
a.place = 20;
return a;
}
else if (match(21))
{
a.place = 21;
return a;
}
else if (match(22))
{
a.place = 22;
return a;
}
else//match 23
{
match(23);
a.place = 23;
return a;
}
}
Node Algri() {
Node a;
if (match(10)) {
a.place = token2[now];
return a;
}
else if (match(11)) {
a.place = token2[now];
return a;
}
else {
match(12); //match 12
a.place = token2[now];
return a;
}
}
int main()
{
for (int t = 0; t < 100; t++)
p[t] = t + 1;
string str;
int k = 0; int sum; int sum2;
ifstream istrm1, istrm2;
ofstream ostrm;
istrm1.open("token.txt", ios::in);
istrm2.open("symble.txt", ios::in);
ostrm.open("quad.txt", ios::out);
int flag = 0;
while (istrm1 >> str) {
sum = 0; sum2 = 0; int mid = 0; int i = 0;//i记录每行的列号
if (flag == 0) {
while (i < str.length()) {
sum = sum * 10;
sum = sum + (int)(str[i] - 48);
i++;
}
token1[k] = sum;
flag = 1;
i = 0;
}
else {
while (i < str.length()) {
sum2 = sum2 * 10;
sum2 = sum2 + (int)(str[i] - 48);
i++;
}
token2[k] = sum2;
k++;
flag = 0;
}
}
flag = 0;
while (istrm2 >> str) {
int number = 0; string name; int i = 0;
if (flag == 0) {
while (i < str.length()) {
number = number * 10;
number = number + (int)(str[i] - 48);
i++;
}
i = 0;
flag = 1;
}
else {
while (i < str.length()) {
name = name + str[i];
i++;
}
flag = 0;
}
symble[number] = name;
i = 0;
}
sym = token1[0];
P();
emit(88, 0, 0, 0);
int end = interable.size();
for (int i = 0; i < end; i++) {
if (interable[i].result == 0 && i != end - 1)
interable[i].result = p[end - 1];
if (p[i] == 8 && interable[i].op == 30)
interable[i].result = 10;
ostrm << p[i] << " " << interable[i].op << " " << interable[i].arg1 << " " << interable[i].arg2 << " " << interable[i].result << endl;
}
istrm1.close();
istrm2.close();
ostrm.close();
return 0;
}
第二种方法
#include<iostream>
#include<string>
#include<fstream>
#include<sstream>
using namespace std;
typedef struct token {
int code = 0;
int addr;
}token;
typedef struct symbol {
int number;
string name;
};
struct symbol symbol[500];
struct token temp[500];
typedef struct equ {
int op = 0; //操作数
int arg1 = 0;
int arg2 = 0;
int result = 0;//操作结果
int type = 0;
int out_port = 0;
int basical = 0;
}equ;
int mtrue[200], mfalse[200];
int mt = 0, mf = 0;
struct equ sys[500];
int equ1 = 1;
int st = 0;
int temp1 = 200;
int p = 0;
int mx = 0;
void emit(int op, int arg1, int arg2, int result)
{
sys[equ1].op = op;
sys[equ1].arg1 = arg1;
sys[equ1].arg2 = arg2;
sys[equ1].result = result;
equ1++;
}
int CreatTemp() {
temp1++;
st++;
return temp1;
}
void token1() {
fstream fin;
int a = 0;
int j = 0;
int t1;
fin.open("token.txt");
while (!fin.eof()) { //文件没有结束
if (a == 0) {
fin >> t1;
temp[j].code = t1; //二元组中单词种别存储在code数组
a = 1;
mx++;
}
else {
fin >> t1;
temp[j].addr = t1; //二元组中单词属性存储在addr数组
j++;
a = 0;
}
}
fin.close();
}
void backpatch(int p, int t) {
int q = p;
while (q != 0)
{
int m = sys[q].result; //m为进四元式第四分量内容
sys[q].result = t; //t填进四元式第四分量
q = m;
}
}
int merge(int p1, int p2)
{
if (sys[p2].result == 0)
return p1;
else {
int p = p2;
while (sys[p].result != 0) //若四元式第四分量不为0
p = sys[p].result;
sys[p].result = p1 + 1; //将p1填进四元式的第四分量
return p2;
}
}
void zsens();
int expression();
void bool_sen();
void sens();
void value();
void yujukuai();
void stable();
void shuomingyuju();
//bool因子
void bool_val() {
int op = 0, arg1 = 0, arg2 = 0, result = 0;
if (temp[p].code == 10)//非 ! token是not
{
p++; //读取下一个token字
bool_val();
}
else if (temp[p].code == 18 || temp[p].code == 19 || temp[p].code == 20) //标识符,整数,实数
{
arg1 = temp[p].addr;
p++; //读取下一个token字
if (temp[p].code >= 32 && temp[p].code <= 37)
{ //运算符<、<=、>、>=、==、!=
if (temp[p].code == 32)
op = 56;
if (temp[p].code == 33)
op = 54;
if (temp[p].code == 34)
op = 53;
if (temp[p].code == 35)
op = 55;
if (temp[p].code == 36)
op = 57;
if (temp[p].code == 37)
op = 58;
p++; //读取下一个token字
if (temp[p].code == 18 || temp[p].code == 19 || temp[p].code == 20) {//标识符,整数,实数
arg2 = temp[p].addr;
p++;
}
else if (temp[p].code == 21) // (
{
p++;
arg2 = expression(); //处理括号中的表达式
if (temp[p].code == 22) // )
p++;
}
}
}
else if (temp[p].code == 21)//(
{
arg1 = expression();
p++;
if (temp[p].code >= 32 && temp[p].code <= 37) {
if (temp[p].code == 32)
op = 56;
if (temp[p].code == 33)
op = 54;
if (temp[p].code == 34)
op = 53;
if (temp[p].code == 35)
op = 55;
if (temp[p].code == 36)
op = 57;
if (temp[p].code == 37)
op = 58;
p++;
if (temp[p].code == 18 || temp[p].code == 19 || temp[p].code == 20) {//标识符,整数,实数
arg2 = temp[p].addr;
p++;
}
else if (temp[p].code == 11)
{
p++;
arg2 = expression();
if (temp[p].code == 12)
p++;
}
}
}
mtrue[mt] = equ1; //真出口
mt++;
sys[equ1].type = 1;
emit(op, arg1, arg2, 0); //无运算数
mfalse[mf] = equ1;
mf++;
sys[equ1].type = 2;
emit(52, 0, 0, 0); //无条件跳转
}
//bool项
void bool_term() {
bool_val(); //处理单个因子
while (temp[p].code == 1)//and,&& t→t and f
{
if (mf > 0) {
backpatch(mtrue[mt - 1], equ1); //回填假出口 //equ四元式序号
mt--;
}
p++; //处理and之后的bool量
bool_val();
sys[equ1].result = merge(mfalse[mf], mfalse[mf - 1]); //合并假出口T.false=merge(T and.false,F,false)
}
}
//bool句
void bool_sen() {
bool_term(); //处理单个项
while (temp[p].code == 11)//or,||
{
p++;
backpatch(mfalse[mf - 1], equ1); //equ四元式序号 ,回填假出口
mf--;
bool_term(); //处理or后的bool表达式
sys[equ1].result = merge(mtrue[mt], mtrue[mt - 1]); //合并真出口
}
}
//因子
int factor() {
int arg;
if (temp[p].code == 18 || temp[p].code == 19 || temp[p].code == 20)//标识符,整数,实数
{
arg = temp[p].addr;
p++;
}
else if (temp[p].code == 21)//()
{
p++;
arg = expression();
if (temp[p].code == 22) {
p++;
}
}
return arg;
}
//项
int term() {
int op = 0, arg1 = 0, arg2 = 0, result = 0;
arg1 = factor();
while (temp[p].code == 25 || temp[p].code == 26) {//乘除,* /
if (temp[p].code == 25) {
op = 41;
}
if (temp[p].code == 26) {
op = 48;
}
p++;
arg2 = factor();
result = CreatTemp();
emit(op, arg1, arg2, result);
arg1 = result;
}
return arg1;
}//变量说明
//表达式
int expression() {
int op = 0, arg1 = 0, arg2 = 0, result = 0;
arg1 = term();
if (temp[p].code == 23 || temp[p].code == 24)//加减,+-
{
if (temp[p].code == 23) {
op = 43;
}
if (temp[p].code == 24) {
op = 45;
}
p++;
arg2 = term();
result = CreatTemp();
emit(op, arg1, arg2, result);
return result;
}
else
{
return arg1;
}
}
//if句
void if_sen() {
if (temp[p].code == 8)//if
{
p = p + 1;//省去if(
int t = mt;
int f = mf;
bool_sen();
//p++;//省去)
while (mt > t)
{
backpatch(mtrue[mt - 1], equ1);
mt--;
}
yujukuai();
if (temp[p].code == 5)//else
{
p++;
int t = equ1;
emit(52, 0, 0, 0);
while (mf > f)
{
backpatch(mfalse[mf - 1], equ1);
mf--;
}
yujukuai();
sys[t].result = equ1;
}
//}
while (mf > f)
{
backpatch(mfalse[mf - 1], equ1);
mf--;
}
}
}
//while句
void while_sen() {
if (temp[p].code == 17)//while
{
int t = equ1;
p = p + 1;//省去while (
bool_sen();
p++;//省去 )
//if (temp[p].code == 4)//do
//{
while (mt > 0)
{
backpatch(mtrue[mt - 1], equ1);
mt--;
}
yujukuai();
emit(52, 0, 0, t);
//}
while (mf > 0)
{
backpatch(mfalse[mf - 1], equ1);
mf--;
}
}
}
//赋值语句,简单句
void simple() {
if (temp[p].code != 18)
p++;
int op = 0, arg1 = 0, arg2 = 0, result = 0;
if (temp[p].code == 18)//标识符
{
p++;
if (temp[p].code == 31)//=
{
result = temp[p - 1].addr;
op = 51;
arg2 = 0;
p++;
arg1 = expression();
emit(op, arg1, arg2, result);
}
if (temp[p].code == 30)//;
p++;
}
}
void yujukuai()
{
if (temp[p].code == 2)//{
{
p++;//省去{
stable();
p++;//省去}
}
else
zsens();
}
//单语句
void zsens() {
if (p >= mx - 1)
return;
if (temp[p].code == 9 || temp[p].code == 13)//int,real
{
shuomingyuju();
return;
}
else if (temp[p].code == 8)//if
{
if_sen();
return;
}
else if (temp[p].code == 17)//while
{
while_sen();
return;
}
else if (temp[p].code == 14)//then
{
simple();
return;
}
else if (temp[p].code == 5) {//else
simple();
return;
}
else if (temp[p].code == 38) {
}
else {
simple();
return;
}
}
//类型定义
void type() {
if (temp[p].code == 9 || temp[p].code == 13)//int,real
{
p++;
}
}
//符号表
void table() {
if (temp[p].code == 18)
{
p++;
while (temp[p].code == 28 || temp[p].code == 18) {//逗号或标识符
p++;
}
}
if (temp[p].code == 20)//;
p++;
}
void shuomingyuju()
{
value();
if (temp[p].code == 9 || temp[p].code == 13)//int,real
shuomingyuju();
}
//变量定义
void value() {
type();
table();
}
//语句组
void stable() {
if (p >= mx - 1) {
return;
}
zsens();
if (temp[p].code != 6) //不是}
stable();
}
//程序体
void proc() {
stable();
}
//语法分析
void gramma_analysis()
{
if (temp[p].code == 12)//main
{
p = p + 3;
proc();
//p++;
if (temp[p].code == 6) //省去}
p++;
}
else if (temp[p].code == 18 && temp[p].addr == 1) {
p = p + 2;
proc();
if (temp[p].code == 6) //省去}
p++;
}
}
int main() {
token1(); //读token文件
gramma_analysis(); //语法分析
emit(60, 0, 0, 0); //程序终止
ofstream fout;
fout.open("quad.txt");
for (int i = 1; i < equ1; i++) {
fout << i << " " << sys[i].op << " " << sys[i].arg1 << " " << sys[i].arg2 << " " << sys[i].result << endl;
}
return 0;
}