最后一次實驗!
目錄
實驗四 語義分析與中間代碼生成
實驗目的
- 通過上機實習,加深對語法制導翻譯原理的理解,掌握將語法分析所識別的語法范疇變換為某種中間代碼的語義翻譯方法。
- 掌握目前普遍采用的語義分析方法──語法制導翻譯技術。
- 給出 PL/0 文法規范,要求在語法分析程序中添加語義處理,對於語法正確的表達式,輸出其中間代碼;對於語法正確的算術表達式,輸出其計算值。
題目
【問題描述】
在實驗二或實驗三的表達式語法分析程序里,添加語義處理部分。 對於語法正確的表達式,輸出其中間代碼,用四元式序列表示;對於語法正確的算術表達式,輸出其計算值。例如:當輸入為2+35時,程序輸出為17;當輸入為a(b+c)時,程序輸出為四元式:
(+,b,c,t1)
(,a,t1,t2)
要求源程序能智能判斷這兩種情況,並輸出相應結果。
【輸入形式】
(1) PL/0算術表達式的語義計算。PL/0算術表達式,例如:2+35作為輸入。
(2)PL/0表達式的中間代碼表示。輸入:PL/0表達式,例如: a*(b+c)。
【輸出形式】
2+35作為輸入時,輸出為17
a(b+c)作為輸入時,輸出為
(+,b,c,t1)
(*,a,t1,t2)
源程序
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
/**詞法分析及其結果存儲**/
pair<string, string> lexRes[50]; // 詞法分析結果,每個pair的first如"ident",second如"a"
int lexI = 0; // lexRes的指針
void lexical()
/*詞法分析:讀入一行字符串,處理該字符串的詞法分析結果至lexRes*/
/*lexI終為lexRes的長度,即單詞數*/
{
// 讀入輸入串
string inputs; // 如,a*(b+c)
cin >> inputs;
// 初始化詞典
map<string,string> words;
std::map<string,string>::iterator it;
words["+"]="plus";
words["-"]="minus";
words["*"]="times";
words["/"]="slash";
words["="]="eql";
words["("]="lparen";
words[")"]="rparen";
// 開始分析
int insize=inputs.length();
string word; // 輸入符號,如"a"/"123"
for(int i=0; i<insize; i++)
{
// 空白符跳過
while(inputs[i] == ' ' || inputs[i] == '\n')
i++;
// 標志符/基本字捕捉
if(isalpha(inputs[i])){
// 拿出一個標志符/基本字
word = inputs[i++];
while(isalpha(inputs[i]) || isdigit(inputs[i]))
word += inputs[i++];
// 在map中找到相應的詞性,並輸出
it = words.find(word);
if(it != words.end())
lexRes[lexI++] = make_pair(words[word], word);
// cout << "(" << words[word] << "," << word << ")" << endl;
else
lexRes[lexI++] = make_pair("ident", word);
// cout << "(ident" << "," << word << ")" << endl;
i--;
}
// 常數
else if(isdigit(inputs[i])){
// 拿出常數
word=inputs[i++];
while(isdigit(inputs[i]))
word+=inputs[i++];
lexRes[lexI++] = make_pair("number", word);
//cout << "(number" << "," << word << ")" << endl;
i--;
}
// <、<=號
else if(inputs[i]=='<'){
word=inputs[i++];
if(inputs[i]=='>'){
word+=inputs[i];
lexRes[lexI++] = make_pair(words[word], word);
// cout << "(" << words[word] << "," << word << ")" << endl;
}else if(inputs[i]=='='){
word+=inputs[i];
lexRes[lexI++] = make_pair(words[word], word);
// cout << "(" <<words[word] << "," << word << ")" << endl;
}else if(inputs[i]!=' '||!isdigit(inputs[i])||!isalpha(inputs[i])){
lexRes[lexI++] = make_pair(words[word], word);
// cout << "(" << words[word] << "," << word << ")" << endl;
}else{
//cout << "error!" << endl;
}
i--;
}
// >、>=
else if(inputs[i]=='>'){
word=inputs[i++];
if(inputs[i]=='='){
word+=inputs[i];
lexRes[lexI++] = make_pair(words[word], word);
// cout<<"("<<words[word]<<","<<word<<")"<<endl;
}else if(inputs[i]!=' '||!isdigit(inputs[i])||!isalpha(inputs[i])){
lexRes[lexI++] = make_pair(words[word], word);
// cout<<"("<<words[word]<<","<<word<<")"<<endl;
}else{
//cout<<"error!"<<endl;
}
i--;
}
//:=
else if(inputs[i]==':'){
word=inputs[i++];
if(inputs[i]=='='){
word+=inputs[i];
lexRes[lexI++] = make_pair(words[word], word);
// cout<<"("<<words[word]<<","<<word<<")"<<endl;
}else{
//cout<<"error!"<<endl;
}
//i--;
}
//其他的基本字
else{
word=inputs[i];
it=words.find(word);
if(it!=words.end()){
lexRes[lexI++] = make_pair(words[word], word);
// cout<<"("<<words[word]<<","<<word<<")"<<endl;
}else{
//cout<<"error!"<<endl;
}
}
}
}
/**四元式相關,被調用**/
struct quad{
string result;
string arg1;
string arg2;
string op;
};
struct quad quad[50]; // 四元式數組
int quaI = 0; // 指向四元式的指針
void emit(string op, string arg1, string arg2, string result)
/*發射一行四元式*/
{
quad[quaI].op = op;
quad[quaI].arg1 = arg1;
quad[quaI].arg2 = arg2;
quad[quaI].result = result;
quaI++;
}
int tI = 1; // 記錄當前是t1/t2...t幾了
string newT()
/*產生一個t1/t2...*/
{
stringstream ss;
ss << tI;
string ti = "t" + ss.str();
tI++;
return ti;
}
/**非算數表達式的遞歸下降分析及四元式生成**/
// 指針前進
int sym=0; // 正在處理的單詞
void advance()
{
++sym;
if(sym > lexI){
cout << "ERROR!sym指針越界";
exit(0);
}
}
string E();
string T();
string F();
string F()
/*因子分析*/
{
string arg;
if(lexRes[sym].first == "ident"){
arg = lexRes[sym].second;
advance();
}
else if(lexRes[sym].first == "number"){
arg = lexRes[sym].second;
advance();
}
else if(lexRes[sym].first == "lparen"){
advance();
arg = E();
if(lexRes[sym].first == "rparen"){
advance();
}
else{
cout << "ERROR!未能匹配右括號!語法錯誤\n";
exit(0);
}
}
return arg;
}
string T()
/*項分析*/
{
string op, arg1, arg2, result;
arg1 = F();
while(lexRes[sym].first == "times" || lexRes[sym].first == "slash"){
op = lexRes[sym].second;
advance();
arg2 = F();
result = newT();
emit(op, arg1, arg2, result);
arg1 = result;
}
return arg1;
}
string E()
/*表達式分析*/
{
string op, arg1, arg2, result;
if(lexRes[sym].first == "plus" || lexRes[sym].first == "minus"){
advance();
}
arg1 = T();
while(lexRes[sym].first == "plus" || lexRes[sym].first == "minus"){
op = lexRes[sym].second;
advance();
arg2 = T();
result = newT();
emit(op, arg1, arg2, result);
arg1 = result;
}
return arg1;
}
/**算數表達式的遞歸下降分析及四元式生成**/
int E_();
int T_();
int F_();
int F_()
{
int arg;
if(lexRes[sym].first == "ident"){
cout << "算數表達式含變量,無法計算\n";
exit(0);
}
else if(lexRes[sym].first == "number"){
arg = atoi(lexRes[sym].second.c_str());
advance();
}
else if(lexRes[sym].first == "lparen"){
advance();
arg = E_();
if(lexRes[sym].first == "rparen"){
advance();
}
else{
cout << "ERROR!未能匹配右括號!語法錯誤\n";
exit(0);
}
}
return arg;
}
int T_()
/*項分析*/
{
string op;
int arg1, arg2, result;
arg1 = F_();
while(lexRes[sym].first == "times" || lexRes[sym].first == "slash"){
op = lexRes[sym].second;
advance();
arg2 = F_();
if(op == "*"){
result = arg1 * arg2;
arg1 = result;
}
else{
if(arg2 != 0){
result = arg1 / arg2;
arg1 = result;
}
else {
cout << "除數為0,出錯!\n";
exit(0);
}
}
}
return arg1;
}
int E_()
/*表達式分析*/
{
string op;
int arg1, arg2, result;
if(lexRes[sym].first == "plus" || lexRes[sym].first == "minus"){
advance();
}
arg1 = T_();
while(lexRes[sym].first == "plus" || lexRes[sym].first == "minus"){
op = lexRes[sym].second;
advance();
arg2 = T_();
if(op == "+"){
result = arg1 + arg2;
arg1 = result;
}
else{
result = arg1 - arg2;
arg1 = result;
}
}
return arg1;
}
int main()
{
lexical();
if(lexRes[0].first == "number"){
cout << E_();
}
else{
E();
for(int i=0; i<quaI; i++){
cout<<'('<<quad[i].op<<','<<quad[i].arg1<<','<<quad[i].arg2<<','<<quad[i].result<<')'<<endl;
}
}
return 0;
}