首页 > 编程语言 >词法分析程序的设计与实现

词法分析程序的设计与实现

时间:2023-11-14 16:55:06浏览次数:27  
标签:std regex 分析程序 分析器 词法 sourceCode 设计

设计原理

词法分析是编译过程的第一阶段。它的任务就是对输入的字符串形式的源程序按顺序进行扫描,根据源程序的词法规则识别具有独立意义的单词(符号),并输出与其等价的Token序列。

有限自动机是描述程序设计语言单词构成的工具,而状态转换图是有限自动机的比较直观的描述方法。我们使用确定的有限状态自动机,简记为DFA。

PL0的语言的词法分析器将要完成以下工作:

(1) 跳过分隔符(如空格,回车,制表符);

(2) 识别诸如begin,end,if,while等保留字;

(3) 识别非保留字的一般标识符,此标识符值(字符序列)赋给全局量id,而全局量sym赋值为SYM_IDENTIFIER。

(4) 识别数字序列,当前值赋给全局量NUM,sym则置为SYM_NUMBER;

(5) 识别:=,<=,>=之类的特殊符号,全局量sym则分别被赋值为SYM_BECOMES,SYM_LEQ,SYM_GEQ等。

相关过程(函数)有getsym(),getch(),其中getch()为获取单个字符的过程,除此之外,它还完成:

(1) 识别且跳过行结束符;

(2) 将输入源文件复写到输出文件;

(3) 产生一份程序列表,输出相应行号或指令计数器的值。

根据语言的词法规则构造出识别其单词的确定有限自动机DFA, 仅仅是词法分析程序的一个形式模型,距离词法分析程序的真正实现还有一定的距离。状态转换图的程序实现通常是采用直接转向法。

直接转向法又称为程序中心法,是把状态转换图看成一个流程图,从状态转换图的初态开始,对它的每一个状态结点都编写一段相应的程序。

以下是我所实现的简单词法分析程序:

#include <iostream>
#include <string>
#include <regex>
#include <vector>

// 定义词法规则
struct TokenRule {
    std::string name;
    std::regex pattern;
};

std::vector<TokenRule> rules = {
    {"INTEGER", std::regex("\\d+")},     // 匹配整数
    {"PLUS", std::regex("\\+")},         // 匹配加号
    {"MINUS", std::regex("-")},          // 匹配减号
    {"MULTIPLY", std::regex("\\*")},     // 匹配乘号
    {"DIVIDE", std::regex("/")},         // 匹配除号
    {"LPAREN", std::regex("\\(")},       // 匹配左括号
    {"RPAREN", std::regex("\\)")}        // 匹配右括号
};

// 输入源代码
std::string sourceCode = "3 + 4 * (2 - 1)";

// 词法分析器
std::vector<std::pair<std::string, std::string>> lexer(const std::vector<TokenRule>& rules, const std::string& sourceCode) {
    std::vector<std::pair<std::string, std::string>> tokens;
    size_t position = 0;

    while (position < sourceCode.length()) {
        std::smatch match;
        bool found = false;

        for (const TokenRule& rule : rules) {
            if (std::regex_search(sourceCode.begin() + position, sourceCode.end(), match, rule.pattern)) {
                std::string value = match.str(0);
                tokens.push_back(std::make_pair(rule.name, value));
                position += value.length();
                found = true;
                break;
            }
        }

        if (!found) {
            throw std::runtime_error("Invalid token: " + sourceCode.substr(position, 1));
        }
    }

    return tokens;
}

int main() {
    // 调用词法分析器
    std::vector<std::pair<std::string, std::string>> tokens = lexer(rules, sourceCode);

    // 输出词法单元
    for (const auto& token : tokens) {
        std::cout << token.first << ": " << token.second << std::endl;
    }

    return 0;
}

总结

如果要实现一个简单的词法分析程序可以参考下我的理解,如下:

确定词法规则:首先,你需要确定编程语言或领域特定语言的词法规则。这些规则描述了有效的标识符、关键字、运算符、常量等。例如,在C语言中,标识符由字母、数字和下划线组成,且不能以数字开头。

使用正则表达式定义词法规则:使用正则表达式来描述每个词法单元的模式。例如,你可以使用正则表达式[a-zA-Z_][a-zA-Z0-9_]*来匹配标识符。

构建词法分析器:根据词法规则,构建一个词法分析器。词法分析器可以是手动编写的状态机,也可以使用词法分析生成器(如Lex、Flex等)来生成。词法分析器的作用是将输入的源代码按照词法规则进行分解,生成一个个词法单元(token)。

定义词法单元:为每个词法单元定义一个数据结构,其中包含词法单元的类型(如标识符、关键字、常量等)和对应的值。

实现词法分析器的逻辑:根据词法规则和词法单元的定义,编写词法分析器的逻辑。词法分析器读取源代码的字符流,根据词法规则匹配字符序列,生成相应的词法单元。

错误处理:在词法分析过程中,如果遇到无法匹配的字符序列,应该进行错误处理。你可以定义错误类型,并在词法分析器中进行相应的处理,如抛出异常或打印错误信息。

下面给出能够识别PL0语言中各类单词的DFA:

标签:std,regex,分析程序,分析器,词法,sourceCode,设计
From: https://www.cnblogs.com/ywx1207/p/17832008.html

相关文章

  • 设计思路-消费MQ
    消费端收到消息持久化到redis或者数据库,状态为待处理。然后ack确认再处理通过线程池异步消费消息,提高吞吐量1.如redis先通过zset放入redis  消费成功删除redis未删除的等redis过期的补偿队列进行补偿......
  • iPhone SE 4即将到来:瞄准CQ9更大电子游戏屏幕与现代化设计
    据新消息透露,预计苹果将于2025年推出全新一代iPhoneSE,标志着4代经济型手机的到来。据称,这款新机的外观将与iPhone14非常相似,而且将带来更现代化的设计风格和更大的屏幕畅玩CQ9在线娱乐游戏。据MacRumors的报道,这款新型号iPhoneSE预计将采用与最近发布的iPhone系列相似的平面设......
  • 软件设计Tutorial 6_原型模式
    [实验任务一]:向量的原型用C++完成数学中向量的封装,其中,用指针和动态申请支持向量长度的改变,使用浅克隆和深克隆复制向量类,比较这两种克隆方式的异同。实验要求:1. 画出对应的类图;  2. 提交源代码(用C++完成); #include<iostream>#include<cstring>classVec......
  • 软件设计实验12:外观模式
    [实验任务一]:计算机开启在计算机主机(Mainframe)中,只需要按下主机的开机按钮(on()),即可调用其他硬件设备和软件的启动方法,如内存(Memory)的自检(check())、CPU的运行(run())、硬盘(HardDisk)的读取(read())、操作系统(OS)的载入(load()),如果某一过程发生错误则计算机启动失败。......
  • 软件设计Tutorial 13_享元模式
    [实验任务一]:围棋设计一个围棋软件,在系统中只存在一个白棋对象和一个黑棋对象,但是它们可以在棋盘的不同位置显示多次。实验要求:1. 提交类图;  2.提交源代码;3.注意编程规范;4.要求用简单工厂模式和单例模式实现享元工厂类的设计。 packageXiang;publicclassBla......
  • 数字滤波器设计---IIR 滤波器设计
    数字滤波器设计---IIR滤波器设计IIR与FIR滤波器的比较与FIR滤波器相比,IIR滤波器的主要优点是,要满足同一组设定,它的滤波器阶数通常远远低于FIR滤波器。虽然IIR滤波器具有非线性相位,但MATLAB® 软件中的数据处理通常是“离线”执行的,即整个数据序列在滤波之前是可用的。......
  • Unity MMORPG 背包系统如何设计
    前言MMORPG游戏中背包系统是很重要的一个模块,大部分的背包系统的讲解,都是讲如何设计UI,如何显示这些,其实这些东西并不是背包系统的核心,接下来我们来分析一下背包系统的数据结构如何设计,能让策划和程序很好的工作,以及非常方便的扩展。对惹,这里有一个游戏开发交流小组,希望大家可......
  • 图的最小生成树算法设计
    二叉树设计实验名称:二叉树设计(1)实验目的:1)掌握二叉树的逻辑结构。2)掌握二叉树的二叉链表存储结构;3)掌握基于二叉链表存储的二叉树的遍历等操作的实现。(2)主要内容:1)定义二叉链存储结构。2)实现二叉树的建立(利用扩展先序序列建立二叉链表存储的二叉树)、二叉树的遍历、统计二叉树结点......
  • Python搞怪UI设计
    importtkinterastkfromtkinterimportmessageboxfromrandomimportrandomwindow=tk.Tk()window.title('请我吃饭!!')window.geometry('350x300+100+100')window.resizable(False,False)window.iconbitmap(bitmap=r"C:\Users\Download......
  • rust程序设计(3)结构体相关概念和疑问
    结构体//如何定义结构体structUser{active:bool,username:String,email:String,sign_in_count:u64,}//如何使用结构体letuser=User{ active:true,username:String::from("someusername123"),email:String::from("someone@exampl......