前景提示:
個(gè)人覺(jué)得單純是用來(lái)完成實(shí)驗(yàn)報(bào)告的話還行,但僅做參考,因?yàn)楸救说木幊趟接邢?,怕誤人子弟。
本次代碼支持以下操作:
單行注釋
多行注釋
文件形式輸入
種別碼可以在文件中自由修改
單詞字符串識(shí)別支持:
部分關(guān)鍵字(可手動(dòng)在程序外部---reference.txt文件添加,),
標(biāo)識(shí)符,
無(wú)符號(hào)整形數(shù)字(僅可識(shí)別整形,其他類型需要自主添加別的函數(shù)支持),
界符(,{}()[]),
全部運(yùn)算符(+、=、-、*、/、<、>,以及這些的兩兩組合)
代碼程序:
// 編譯原理詞法分析器
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <map>
using namespace std;
string getFormFile(string filePath);
bool isLetter(char ch);
bool isNumber(char ch);
bool isOperator(char ch);
bool isDelimiter(char ch);
string rmExegesis(const string);
string rmExegesis_1(const string str);
string rmExegesis_2(const string str);
vector<string> compile();
vector<string> compile(const string originpath, const string targetpath);
map<string, string> getMap();
void showTime(map<string, string> refer, vector<string> key);
int main()
{
?? ?map<string, string> refer = getMap();?? ??? ??? ??? ??? ??? ??? ?//從配置文件中拿到鍵值對(duì)
?? ?cout << "請(qǐng)?jiān)谖募?input.txt 中輸入待編譯程序" << endl;
?? ?system("pause");
?? ?vector<string> key = compile();?? ??? ??? ??? ??? ??? ??? ??? ??? ?//拿到待識(shí)別字符
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?
?? ?showTime(refer, key);
?? ?cout << "編譯成功!" << endl;
}
string getFormFile(string filePath)
{
?? ?ifstream ifs;
?? ?ifs.open(filePath);
?? ?if (!ifs.is_open())
?? ??? ?cout << filePath << "打開(kāi)失?。? << endl;
?? ?ifs.seekg(0, ios::end);
?? ?int size = ifs.tellg();?? ??? ??? ??? ?//得到文件大小?? ??? ??? ??? ?
?? ?string str;
?? ?str.resize(size);
?? ?ifs.seekg(0, ios::beg);
?? ?ifs.read((char*)str.c_str(), size);
?? ?ifs.close();?? ??? ??? ??? ??? ??? ?//關(guān)閉了!
?? ?return str;
}
//單詞
bool isLetter(char ch)
{
?? ?if (ch > ('a' - 1) && ch < ('z' + 1))
?? ??? ?return true;
?? ?else if (ch > ('A' - 1) && ch < ('Z' + 1))
?? ??? ?return true;
?? ?else if (ch == '_')
?? ??? ?return true;
?? ?else
?? ??? ?return false;
}
//數(shù)字
bool isNumber(char ch)
{
?? ?if (ch > ('0' - 1) && ch < ('9' + 1))
?? ??? ?return true;
?? ?else
?? ??? ?return false;
}
//算術(shù)運(yùn)算符
bool isOperator(char ch)
{
?? ?if (ch == '=' || ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == ':' || ch == '<' || ch == '>')
?? ??? ?return true;
?? ?else
?? ??? ?return false;
}
//界符
bool isDelimiter(char ch)
{
?? ?if (ch == ';' || ch == ',' || ch == '(' || ch == ')' || ch == '{' || ch == '}' || ch == '[' || ch == ']')
?? ??? ?return true;
?? ?else
?? ??? ?return false;
}
//去單行注釋函數(shù)
string rmExegesis_1(const string str)
{
?? ?string temp = str;
?? ?string result = temp;
?? ?string str1;
?? ?string str2;
?? ?int len = temp.length();
?? ?for (int i = 0; i < len;)
?? ?{
?? ??? ?auto be = temp.find("http://", i);
?? ??? ?auto en = temp.find("\n", be) + 1;
?? ??? ?if (be == string::npos || en == string::npos)
?? ??? ?{
?? ??? ??? ?break;
?? ??? ?}
?? ??? ?str1.assign(temp, 0, be);
?? ??? ?str2.assign(temp, en, len - en);
?? ??? ?result = str1 + str2;
?? ??? ?temp = result;
?? ??? ?len = temp.length();
?? ?}
?? ?return result;
}
//去多行注釋函數(shù)
string rmExegesis_2(const string str)
{
?? ?string temp = str;
?? ?string result = temp;
?? ?string str1;
?? ?string str2;
?? ?int len = temp.length();
?? ?for (int i = 0; i < len;)
?? ?{
?? ??? ?auto be = temp.find("/*", i);
?? ??? ?auto en = temp.find("*/", i) + 2;
?? ??? ?if (en < be)
?? ??? ?{
?? ??? ??? ?i = be;
?? ??? ??? ?en = temp.find("*/", i) + 2;
?? ??? ?}
?? ??? ?if (be == string::npos || en == string::npos)
?? ??? ?{
?? ??? ??? ?break;
?? ??? ?}
?? ??? ?str1.assign(temp, 0, be);
?? ??? ?str2.assign(temp, en, len - en);
?? ??? ?result = str1 + str2;
?? ??? ?temp = result;
?? ??? ?len = temp.length();
?? ?}
?? ?return result;
}
//去單行和多行注釋
string rmExegesis(const string str)
{
?? ?string result = rmExegesis_1(str);
?? ?return rmExegesis_2(result);
}
vector<string> compile()
{
?? ?string origin = "input.txt";
?? ?string target = "output.txt";
?? ?return compile(origin, target);
}
vector<string> compile(const string originpath, const string targetpath)
{
?? ?string str = getFormFile(originpath);
?? ?str = rmExegesis(str);?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?//去注釋
?? ?cout << str << endl;?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?//輸出去注釋之后的文本
?? ?vector<string> v;?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?//存儲(chǔ)字符
?? ?int pos = 0;
?? ?int len = str.find("#~");
?? ?v.push_back("");
?? ?for (int i = 0; i < len; i++)
?? ?{
?? ??? ?if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n')?? ?//空格,tab鍵,換行鍵作為分割符
?? ??? ?{
?? ??? ??? ?if (v[pos] != "")
?? ??? ??? ?{
?? ??? ??? ??? ?v.push_back("");
?? ??? ??? ??? ?pos++;
?? ??? ??? ?}
?? ??? ?}
?? ??? ?else if (isLetter(str[i]))
?? ??? ?{
?? ??? ??? ?v[pos] = v[pos] + str[i];
?? ??? ??? ?if (i + 1 < len && !isLetter(str[i + 1]))
?? ??? ??? ?{
?? ??? ??? ??? ?v[pos] = v[pos] + "$ident";
?? ??? ??? ??? ?v.push_back("");
?? ??? ??? ??? ?pos++;
?? ??? ??? ?}
?? ??? ?}
?? ??? ?else if (isNumber(str[i]))
?? ??? ?{
?? ??? ??? ?v[pos] = v[pos] + str[i];
?? ??? ??? ?if (i + 1 < len && !isNumber(str[i + 1]))
?? ??? ??? ?{
?? ??? ??? ??? ?v[pos] = v[pos] + "$idconst";
?? ??? ??? ??? ?v.push_back("");
?? ??? ??? ??? ?pos++;
?? ??? ??? ?}
?? ??? ?}
?? ??? ?else if (isOperator(str[i]))
?? ??? ?{
?? ??? ??? ?v[pos] = v[pos] + str[i];
?? ??? ??? ?if (i + 1 < len && isOperator(str[i + 1]))
?? ??? ??? ?{
?? ??? ??? ??? ?i = i + 1;
?? ??? ??? ??? ?v[pos] = v[pos] + str[i];
?? ??? ??? ??? ?v.push_back("");
?? ??? ??? ??? ?pos++;
?? ??? ??? ?}
?? ??? ??? ?else
?? ??? ??? ?{
?? ??? ??? ??? ?v.push_back("");
?? ??? ??? ??? ?pos++;
?? ??? ??? ?}
?? ??? ?}
?? ??? ?else if(isDelimiter(str[i]))
?? ??? ?{
?? ??? ??? ?v[pos] = v[pos] + str[i];
?? ??? ??? ?v.push_back("");
?? ??? ??? ?pos++;
?? ??? ?}
?? ??? ?else
?? ??? ?{
?? ??? ??? ?v[pos] = v[pos] + str[i];
?? ??? ??? ?v.push_back("");
?? ??? ??? ?pos++;
?? ??? ?}
?? ?}
?? ?return v;
}
map<string, string> getMap()
{
?? ?string str = getFormFile("reference.txt");?? ??? ??? ??? ??? ?//讀取匹配文件
?? ?map<string, string> refer;
?? ?pair<string, string> p;
?? ?string bpattern = "<reference>";
?? ?string epattern = "</reference>";
?? ?int ben = str.find(bpattern) + bpattern.size();
?? ?int end = str.find(epattern);
?? ?string key;
?? ?string value;
?? ?int flag1;
?? ?int flag2;
?? ?for (int i = ben; i < end; i++)
?? ?{
?? ??? ?if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n')
?? ??? ??? ?continue;
?? ??? ?flag1 = i;
?? ??? ?flag2 = (str.find(' ', i) < str.find('\t', i) ? str.find(' ', i) : str.find('\t', i));
?? ??? ?key.assign(str, flag1, flag2 - flag1);
?? ??? ?flag1 = str.find('$', flag2) + 1;
?? ??? ?flag2 = str.find('\n', i);
?? ??? ?value.assign(str, flag1, flag2 - flag1);
?? ??? ?p = make_pair(key, value);
?? ??? ?refer.insert(p);
?? ??? ?i = flag2;
?? ?}
?? ?return refer;
}
void showTime(map<string, string> refer, vector<string> key)
{?? ?
?? ?cout << "符號(hào)\t\t\t" << "種別碼\t\t\t" << "說(shuō)明" << endl;
?? ?int len = key.size();
?? ?for (int i = 0; i < len; i++)
?? ?{
?? ??? ?auto pos = key[i].find('$');
?? ??? ?if (pos != string::npos)
?? ??? ?{
?? ??? ??? ?string key1;
?? ??? ??? ?string key2;
?? ??? ??? ?key1.assign(key[i], 0, pos);
?? ??? ??? ?key2.assign(key[i], pos + 1, key[i].length() - pos);
?? ??? ??? ?map<string, string>::iterator iter = refer.find(key1);
?? ??? ??? ?if (iter != refer.end())
?? ??? ??? ?{
?? ??? ??? ??? ?cout << key1 << "\t\t\t" << iter->second << "\t\t\t" << "關(guān)鍵字" << endl;
?? ??? ??? ?}
?? ??? ??? ?else
?? ??? ??? ?{
?? ??? ??? ??? ?cout << key2 << "\t\t\t" << refer[key2] << "\t\t\t" << key1 << endl;
?? ??? ??? ?}
?? ??? ?}
?? ??? ?else
?? ??? ?{
?? ??? ??? ?if (key[i] == "")
?? ??? ??? ??? ?continue;
?? ??? ??? ?cout << key[i] << "\t\t\t" << refer[key[i]] << "\t\t\t" << key[i] << endl;
?? ??? ?}
?? ?}
}
運(yùn)行示例:
文件結(jié)構(gòu):
?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-445415.html
示例1:
input.txt文件:
begin
?? ?begin
?? ?
?? ??? ?begin?
?? ??? ? a:=1
??? ??? ?end;
??? ??? ?
??? ? ?begin?
?? ??? ? b:=1
? ? end;
? ? q:=10
?? ?end;
?? ?
?? ?x:=9;
?? ?y:=11;
?? ?z:=12
end
#~
reference.txt文件
<reference>
?? ?if?? ??? ?$0
?? ?then?? ?$1
?? ?else?? ?$2
?? ?while?? ?$3
?? ?begin?? ?$4
?? ?do?? ??? ?$5
?? ?end?? ??? ?$6
?? ?a?? ??? ?$7
?? ?:=?? ??? ?$8
?? ?+?? ??? ?$9
?? ?-?? ??? ?$10
?? ?*?? ??? ?$11
?? ?/?? ??? ?$12
?? ?+=?? ??? ?$13
?? ?-=?? ??? ?$14
?? ?*=?? ??? ?$15
?? ?/=?? ??? ?$16
?? ?,?? ??? ?$17
?? ?;?? ??? ?$22
?? ?(?? ??? ?$18
?? ?)?? ??? ?$19
?? ?{?? ??? ?$20
?? ?}?? ??? ?$21
?? ?ident?? ?$100
?? ?idconst?? ?$101
</reference>
?輸出
?文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-445415.html
示例2:
input.txt文件:
#include <iostream>
using namespace std;
void main()
{
?? ?cout<<"hello world!!!"<<endl;?? ??? ??? ?//單行注釋在這里?。?! ?/*eryedhds
}
#~?? ??? ??? ??? ??? ??? ?//#~為結(jié)束標(biāo)志符
/*
多行注釋在這里!!
asbhfafs
afs
adfsdfcdc
cs
csCSZ
C
ZXC
Scxcds ? ?sfasf saf sd f afd sfd a14 1 411:36 2022/11/711:36 2022/11/7
wr
#~
*/
reference.txt文件
<reference>
?? ?if?? ??? ?$0
?? ?then?? ??? ?$1
?? ?else?? ??? ?$2
?? ?while?? ?$3
?? ?begin?? ?$4
?? ?do?? ??? ?$5
?? ?end?? ??? ?$6
?? ?:=?? ??? ?$8
?? ?+?? ??? ?$9
?? ?-?? ??? ?$10
?? ?*?? ??? ?$11
?? ?/?? ??? ?$12
?? ?+=?? ??? ?$13
?? ?-=?? ??? ?$14
?? ?*=?? ??? ?$15
?? ?/=?? ??? ?$16
?? ?>?? ??? ?$30
?? ?<?? ??? ?$31
?? ?,?? ??? ?$17
?? ?;?? ??? ?$22
?? ?(?? ??? ?$18
?? ?)?? ??? ?$19
?? ?{?? ??? ?$20
?? ?}?? ??? ?$21
?? ?#?? ??? ?$1111
?? ?include?? ?$1112
?? ?iostream?? ?$1113
?? ?using?? ?$1114
?? ?namespace?? ?$1115
?? ?std?? ??? ?$1116
?? ?int?? ??? ?$1117
?? ?main?? ??? ?$1118
?? ?cout?? ??? ?$1119
?? ?endl?? ??? ?$1120
?? ?void?? ??? ?$1121
?? ?"?? ??? ?$1122
?? ?ident?? ?$100
?? ?idconst?? ?$101
?? ?!?? ??? ?$1123
?? ?<<?? ??? ?$1124
?? ?>>?? ??? ?$1125
</reference>
輸出
?
?
?
?
到了這里,關(guān)于詞法分析器(c++)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!