編譯原理-詞法分析
阿新 • • 發佈:2018-12-22
實驗內容
通過對PL/0詞法分析程式(GETSYM)的分析,並在此基礎上按照附錄A中給出的PL/0語言的語法描述,編寫一個PL/0語言的詞法分析程式。此程式應具有如下功能:
輸入為字串(待進行詞法分析的源程式),輸出為單詞串,即由(單詞、類別)所組成的二元組序列。
有一定檢查錯誤的能力,例如發現2A這類不能作為單詞的字串。
實驗程式碼如下:
# include<iostream>
#include <bits/stdc++.h>
using namespace std;
bool key_words(string s)//關鍵字
{
static vector<string> keyVec = { "main", "int", "float", "double", "char",
"if", "then","else", "switch", "case", "break", "continue", "while",
"do", "for" ,"#include","using","namespace","std","return"};
vector<string>::iterator result = find(keyVec.begin(), keyVec.end(),s);
if (result != keyVec. end())
return true;
else return false;
}
bool ident(string s)//識別符號
{
if (!key_words(s))//識別符號不能是關鍵字
{
if ((s[0] >= 'a'&&s[0] <= 'z') || (s[0] >= 'A'&&s[0] <= 'Z'))//是字母
{
for (int i = 1; i < s.length(); i++)
{
if ((s[i] >= 'a'&&s[i] <= 'z') || (s[i] >= 'A'&&s[i] <= 'Z')
|| (s[i] >= '0'&&s[i] <= '9'))
continue;
else return false;
}
return true;
}
return false;
}
return false;
}
bool digit(string s)//整數
{
if (s[0] >= '0'&&s[0] <= '9')
{
for (int i = 1; i < s.length(); ++i)
if (s[i] >= '0'&&s[i] <= '9')
continue;
else return false;
return true;
}
return false;
}
bool points(string s)//小數
{
if (s[0] >= '0'&&s[0] <= '9')
{
for (int i = 1; i < s.length(); ++i)
if ((s[i] >= '0'&&s[i] <= '9')||s[i]=='.')
continue;
else return false;
return true;
}
return false;
}
bool is_operator(string s)//運算子
{
static vector<string> opeVec = { "=","+","-","*","/","<","<=","==","!=",
">",">=",";","(",")","?",":",",","+=","-=" };
vector<string>::iterator result = find(opeVec.begin(), opeVec.end(), s);
if (result != opeVec.end())
return true;
else return false;
}
bool is_operator(char c)//運算子
{
static vector<char> opeVec = { '=','+','-','*','/','<','>',';','(',')','?',':',',' };
vector<char>::iterator result = find(opeVec.begin(), opeVec.end(), c);
if (result != opeVec.end())
return true;
else return false;
}
string result(string s)//根據傳入的引數s產生對應的輸出
{
//識別符號
if (ident(s))
return "(識別符號,"+s+")";
//關鍵字
if (key_words(s))
return "(關鍵字,"+s+")";
//整型常量
if (digit(s))
return "(整數,"+s+")";
//小數
if (points(s))
return "(小數,"+s+")";
//運算子
static map<string, string> opeMap;
opeMap["="] = "(等號,=)";
opeMap["<"] = "(小於號,<)";
opeMap["<="] = "(小於等於號,<=)";
opeMap["+="] = "(加等於號,+=)";
opeMap["-="] = "(減等於號,-=)";
opeMap["=="] = "(賦值運算子,==)";
opeMap["!="] = "(不等於號,!=)";
opeMap[">"] = "(大於號,>)";
opeMap[">="] = "(大於等於號,>=)";
opeMap[";"] = "(分號,;)";
opeMap["+"] = "(加號,+)";
opeMap["("] = "(左括號,( )";
opeMap["-"] = "(減號,-)";
opeMap[")"] = "(右括號,) )";
opeMap[">"] = "(大於號,>)";
opeMap["*"] = "(星號,*)";
opeMap["?"] = "(問號,?)";
opeMap["/"] = "(除號,/)";
opeMap[":"] = "(冒號,:)";
opeMap[","] = "(逗號,,)";
if (is_operator(s))
return opeMap[s];
return "Error";
}
int main()
{
string file = ("C:\\test.txt");
ifstream input(file);
ofstream output("C:\\Result.txt",ofstream::app);
//先將testData.txt內容拷貝到Result.txt中
string copy;
getline(input, copy, '\0');
cout<< copy << endl;//測試是否正確
//此時input已經指到了檔案尾,為了後面的讀取,需要關閉再開啟
input.close();
input.open(file);
output << "原資料:\n";
output << copy;
output << "處理後結果:\n";
string str;
string words;
cout << "處理後結果:\n";
int l=0;//計算行數
while (getline(input, str)) //讀取檔案每一次讀取一行,遇到EOF結束
{
l++;
//從輸入流中獲取單詞,需要用到輸入流物件,即istringstream
istringstream strCin(str);
string s;
while (strCin >> words)
{
//關鍵字肯定是單獨作為一個單詞的
if (key_words(words))
{
s = result(words);
cout <<"Line "<<l<<":"<< s << endl;
output <<"Line "<<l<<":"<< s << endl;
continue;
}
//對單詞進行掃描,肯定是識別符號,運算子,逗號分號,數字等等混合在一起的單詞
vector<int> index = {0};
vector<string> mulWords;//將words分解為多個單詞
for (int i = 0; i < words.length(); i++)
{
//運算子有兩位的,比如"<=",">=","==","!=","-=","+="
if ((i < words.length() - 1) && is_operator(words[i]) && is_operator(words[i + 1]))
{
//但是要注意只有以上6種兩位運算子,比如+-,))就不是,但是))還是要輸出),)
if (string(words.begin() + i, words.begin() + i + 2) == "<=" ||
string(words.begin() + i, words.begin() + i + 2) == ">=" ||
string(words.begin() + i, words.begin() + i + 2) == "==" ||
string(words.begin() + i, words.begin() + i + 2) == "-=" ||
string(words.begin() + i, words.begin() + i + 2) == "+=" ||
string(words.begin() + i, words.begin() + i + 2) == "!=")
{
index.push_back(i);
index.push_back(i + 2);
++i;
}
else if (is_operator(words[i]))
{
if (find(index.begin(), index.end(), i) == index.end())
index.push_back(i);
if (find(index.begin(), index.end(), i + 1) == index.end())
index.push_back(i + 1);
}
}
//逗號,運算子作為分隔
else if (is_operator(words[i]))
{
if (find(index.begin(), index.end(), i) == index.end())
//比如遇到"a,b"這裡下標0和1將a分開,1到2將逗號分開,2到3將b分開
index.push_back(i);
if (find(index.begin(), index.end(), i+1) == index.end())
index.push_back(i + 1);
}
}
for (int i = 0; i < index.size()-1; i++)
{
string rel;
//比如遇到"<=",需要提取”<=“
rel=result(string(words.begin() + index[i], words.begin() + index[i + 1]));
output <<"Line "<<l<<":"<< rel << endl;
cout <<"Line "<<l<<":"<< rel<<endl;
}
}
}
output << endl;
output.close();
input.close();
system("pause");
return 0;
}