词法分析器(c++)

这篇具有很好参考价值的文章主要介绍了词法分析器(c++)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前景提示:

个人觉得单纯是用来完成实验报告的话还行,但仅做参考,因为本人的编程水平有限,怕误人子弟。

本次代码支持以下操作:

单行注释

多行注释

文件形式输入

种别码可以在文件中自由修改

单词字符串识别支持:

部分关键字(可手动在程序外部---reference.txt文件添加,),

标识符,

无符号整形数字(仅可识别整形,其他类型需要自主添加别的函数支持),

界符(,{}()[]),

全部运算符(+、=、-、*、/、<、>,以及这些的两两组合)

代码程序:

// 编译原理词法分析器


#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();                            //从配置文件中拿到键值对

    cout << "请在文件 input.txt 中输入待编译程序" << endl;
    system("pause");
    vector<string> key = compile();                                    //拿到待识别字符
                                                            
    showTime(refer, key);
    cout << "编译成功!" << endl;
}


string getFormFile(string filePath)
{

    ifstream ifs;
    ifs.open(filePath);
    if (!ifs.is_open())
        cout << filePath << "打开失败!" << 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();                        //关闭了!

    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;
}

//数字
bool isNumber(char ch)
{
    if (ch > ('0' - 1) && ch < ('9' + 1))
        return true;
    else
        return false;
}

//算术运算符
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;
}


//去单行注释函数
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("//", 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;
}

//去多行注释函数
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;                                            //存储字符
    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 << "符号\t\t\t" << "种别码\t\t\t" << "说明" << 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" << "关键字" << 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;
        }
    }
}

运行示例:

文件结构:

词法分析器(c++)

 文章来源地址https://www.toymoban.com/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>

 输出

词法分析器(c++)

 

示例2:

input.txt文件:

#include <iostream>
using namespace std;

void main()
{
    cout<<"hello world!!!"<<endl;            //单行注释在这里!!!  /*eryedhds
}
#~                        //#~为结束标志符


/*
多行注释在这里!!
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>

输出

词法分析器(c++)
 

 

 

 

到了这里,关于词法分析器(c++)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Lex 生成一个词法分析器

     lex 通过输入一个.l 文件生成一个lex.yy.c 文件,然后通过c 编译器编译成一个可执行的词法分析器。 该词法分析器扫描输入源文件,生成一个token 符号流给后面语法分析器使用。   .l 文件的结构, 分成三个部分,声明, 转换规则, 自定义规则。 三个部分由%%分割 声明段,

    2024年02月19日
    浏览(49)
  • 编译原理词法分析器(C/C++)

            词法分析器不用多说,一开始我还不知道是什么样的,看了下别人的博客,再看看书,原来是输出二元组,这不就是字符串操作嘛。然后细看几篇博客,发现大都是用暴力判断来写的。我对代码重复性比较高的方法不太感冒,不是说我编程有多好,就是单纯的不喜欢

    2024年02月06日
    浏览(60)
  • HNU-编译原理-实验1-利用FLEX构造C-Minus-f词法分析器

    计科210X 甘晴void 202108010XXX 详细的实验项目文档为 https://gitee.com/coderwym/cminus_compiler-2023-fall/tree/master/Documentations/lab1 学习和掌握词法分析程序的逻辑原理与构造方法。通过 FLEX 进行实践, 构造 C-Minus-f 词法分析器。具体完成过程如下: 学习 C-Minus-f 的词法规则 学习 FLEX 工具使

    2024年01月20日
    浏览(55)
  • 分析器:常见问题

    源生成器(增量生成器)由于它特殊的定位,关于它的调试十分困难。在这里分享一些调试它的经验。 另外经常有写类库,然后提供可以生成代码的Attribute给用户的需求,此时需要用到传递引用的知识点。 源生成器项目和普通的项目不同。 普通的会在你按下运行或调试后才

    2024年02月01日
    浏览(67)
  • Elasticsearch 查询分析器简介

    Elasticsearch 是一个开源的分布式搜索和分析引擎,它提供了强大的查询和分析功能。它基于 Apache Lucene 构建,支持大规模数据的实时搜索,并具有高可用性和可扩展性。 在 Elasticsearch 中,查询分析器负责处理用户搜索的输入,将文本进行分词并生成倒排索引。分析器在搜索过

    2024年02月17日
    浏览(43)
  • Elasticsearch 文本分析器(下)

    注意:字符过滤器用于在将字符流传递给分词器之前对其进行预处理 此过滤器会替换掉HTML标签,且会转换HTML实体 如: 会被替换为 。 解析结果: 因为是 p 标签,所以有前后的换行符。如果使用span标签就不会有换行符了。 可配参数说明 escaped_tags (可选,字符串数组)不包

    2024年02月08日
    浏览(123)
  • ElasticSearch 基础(七)之分析器

    就 ES 基础部分来说这暂时就是最后一篇的文章,写完之后就会学习 MQ 了。本篇内容简单了解 ES 的分析器,最重要的还是根据自己需求去定制自定义分析器,自定义分析器自行了解,这里只是基础。其他比较重要的就是中文分词器了,只需要知道常用的几种中文分词器就可以

    2024年02月09日
    浏览(42)
  • Elasticsearch:搜索及索引分析器

    在我之前的文章 “Elasticsearch: analyzer”,我详细介绍了在 Elasticsearch 中的分析器。分析器在 Elasticsearh 中,它在索引文档的时候需要使用,同时,它也在搜索时,也需要针对搜索的文字进行分词。在今天的文章中,我们来详细介绍分析器是如何在索引及搜索时使用的。 可以在

    2024年02月05日
    浏览(84)
  • Android Profiler 内存分析器使用

    Android Profiler是Android Studio的一部分,提供了一个集成的性能分析工具套件,包括内存分析。Android Profiler 工具可提供实时数据,帮助您了解应用的 CPU、内存、网络和电池资源使用情况。 在Android Profiler中,您可以查看内存使用情况的实时图表、堆转储快照、分析内存泄漏等,

    2024年02月08日
    浏览(53)
  • 编译原理-6-LR语法分析器

    自顶向下的、不断归约的、基于句柄识别自动机的、适用于LR(∗) 文法的、LR(∗) 语法分析器 只考虑无二义性的文法 自底向上 构建语法分析树 根节点 是文法的起始符号 S S S 每个中间 非终结符节点 表示 使用它的某条产生式进行归约 叶节点 是词法单元$w$$ 仅包含终结符号与

    2024年02月05日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包