C语言第三方库Melon开箱即用之词法分析器使用

之前的文章中,笔者介绍了Linux/UNIX C语言库Melon的基本功能及框架使用。

本文将介绍Melon中的词法分析器组件。

Melon的Github仓库为:https://github.com/Water-Melon/Melon
在这里插入图片描述

词法分析器在Melon中并不依赖于自身框架,因此可以在不初始化框架的情况下即可使用。

基础使用

我们先来看一个基本例子:

//lexer.c#include <stdio.h>
#include "mln_lex.h"MLN_DEFINE_TOKEN_TYPE_AND_STRUCT(static, mln_test, TEST);
MLN_DEFINE_TOKEN(mln_test, TEST);int main(int argc, char *argv[])
{if (argc != 2) {fprintf(stderr, "Usage: %s file_path\n", argv[0]);return -1;}mln_string_t path;mln_lex_t *lex = NULL;struct mln_lex_attr lattr;mln_test_struct_t *ts;mln_string_nSet(&path, argv[1], strlen(argv[1]));lattr.pool = mln_alloc_init();if (lattr.pool == NULL) {fprintf(stderr, "init memory pool failed\n");return -1;}lattr.keywords = NULL;lattr.hooks = NULL;lattr.preprocess = 0;lattr.padding = 0;lattr.type = M_INPUT_T_FILE;lattr.data = &path;lattr.env = NULL;mln_lex_initWithHooks(mln_test, lex, &lattr);if (lex == NULL) {fprintf(stderr, "lexer init failed\n");return -1;}while (1) {ts = mln_test_token(lex);if (ts == NULL || ts->type == TEST_TK_EOF)break;write(STDOUT_FILENO, ts->text->data, ts->text->len);printf(" line:%u type:%d\n", ts->line, ts->type);}mln_lex_destroy(lex);mln_alloc_destroy(lattr.pool);return 0;
}

如此,即可完成一个词法解析器程序,它读取程序的参数所指定的文件的内容,然后解析成词素,并将其打印出来。

我们执行:

$ ./lexer lexer.c/ line:1 type:21
/ line:1 type:21
lexer line:1 type:5
. line:1 type:20
c line:1 type:5
# line:3 type:9
include line:3 type:5
< line:3 type:24
stdio line:3 type:5
. line:3 type:20
h line:3 type:5
> line:3 type:26
...

可以看到,这个程序将我们的示例C程序拆解成各种词素,如:/,#,<等等。

进阶使用

上面的例子可以看到,基础的词法解析器解析出的词素过于细碎,有时我们还希望解析器支持我们自定义的关键字、自定义格式的数据,甚至是一些预处理功能,例如引入其他文件的内容解析词素。

那么,我们就将上面的例子进行一番修改:

//lexer.c#include <stdio.h>
#include "mln_lex.h"mln_string_t keywords[] = {mln_string("on"),mln_string("off"),mln_string(NULL)
};MLN_DEFINE_TOKEN_TYPE_AND_STRUCT(static, mln_test, TEST, TEST_TK_ON, TEST_TK_OFF, TEST_TK_STRING);
MLN_DEFINE_TOKEN(mln_test, TEST, {TEST_TK_ON, "TEST_TK_ON"}, {TEST_TK_OFF, "TEST_TK_OFF"}, {TEST_TK_STRING, "TEST_TK_STRING"});static inline int
mln_get_char(mln_lex_t *lex, char c)
{if (c == '\\') {char n;if ((n = mln_lex_getAChar(lex)) == MLN_ERR) return -1;switch ( n ) {case '\"':if (mln_lex_putAChar(lex, n) == MLN_ERR) return -1;break;case '\'':if (mln_lex_putAChar(lex, n) == MLN_ERR) return -1;break;case 'n':if (mln_lex_putAChar(lex, '\n') == MLN_ERR) return -1;break;case 't':if (mln_lex_putAChar(lex, '\t') == MLN_ERR) return -1;break;case 'b':if (mln_lex_putAChar(lex, '\b') == MLN_ERR) return -1;break;case 'a':if (mln_lex_putAChar(lex, '\a') == MLN_ERR) return -1;break;case 'f':if (mln_lex_putAChar(lex, '\f') == MLN_ERR) return -1;break;case 'r':if (mln_lex_putAChar(lex, '\r') == MLN_ERR) return -1;break;case 'v':if (mln_lex_putAChar(lex, '\v') == MLN_ERR) return -1;break;case '\\':if (mln_lex_putAChar(lex, '\\') == MLN_ERR) return -1;break;default:mln_lex_setError(lex, MLN_LEX_EINVCHAR);return -1;}} else {if (mln_lex_putAChar(lex, c) == MLN_ERR) return -1;}return 0;
}static mln_test_struct_t *
mln_test_dblq_handler(mln_lex_t *lex, void *data)
{mln_lex_cleanResult(lex);char c;while ( 1 ) {c = mln_lex_getAChar(lex);if (c == MLN_ERR) return NULL;if (c == MLN_EOF) {mln_lex_setError(lex, MLN_LEX_EINVEOF);return NULL;}if (c == '\"') break;if (mln_get_char(lex, c) < 0) return NULL;}return mln_test_new(lex, TEST_TK_STRING);
}int main(int argc, char *argv[])
{if (argc != 2) {fprintf(stderr, "Usage: %s file_path\n", argv[0]);return -1;}mln_string_t path;mln_lex_t *lex = NULL;struct mln_lex_attr lattr;mln_test_struct_t *ts;mln_lex_hooks_t hooks;memset(&hooks, 0, sizeof(hooks));hooks.dblq_handler = (lex_hook)mln_test_dblq_handler;mln_string_nSet(&path, argv[1], strlen(argv[1]));lattr.pool = mln_alloc_init();if (lattr.pool == NULL) {fprintf(stderr, "init pool failed\n");return -1;}lattr.keywords = keywords;lattr.hooks = &hooks;lattr.preprocess = 1;//支持预处理lattr.padding = 0;lattr.type = M_INPUT_T_FILE;lattr.data = &path;lattr.env = NULL;mln_lex_initWithHooks(mln_test, lex, &lattr);if (lex == NULL) {fprintf(stderr, "lexer init failed\n");return -1;}while (1) {ts = mln_test_token(lex);if (ts == NULL || ts->type == TEST_TK_EOF)break;write(STDOUT_FILENO, ts->text->data, ts->text->len);printf(" line:%u type:%d\n", ts->line, ts->type);}mln_lex_destroy(lex);mln_alloc_destroy(lattr.pool);return 0;
}

这一次,我们增加如下功能:

  • 支持关键字 onoff
  • 支持识别双引号扩住的内容为字符串类型
  • 增加了预处理功能,例如引入其他文件内容

生成可执行程序:

$ cc -o a a.c -I /usr/local/melon/include/ -L /usr/local/melon/lib/ -lmelon -lpthread

创建两个测试文件:

a.ini
#include "b.ini"
test_mode = on
log_level = 'debug'
proc_num = 10
b.ini
conf_name = "b.ini"

运行我们的程序来看看效果:

$ ./lexer a.iniconf_name line:1 type:5
= line:1 type:25
b.ini line:1 type:42
test_mode line:2 type:5
= line:2 type:25
on line:2 type:40
log_level line:3 type:5
= line:3 type:25
' line:3 type:13
debug line:3 type:5
' line:3 type:13
proc_num line:4 type:5
= line:4 type:25
10 line:4 type:2

可以看到,在a.ini中写入include的部分,是b.ini文件内容解析后的词素。并且onoff都被正常解析出来了。且字符串也被正常处理出来了。


Melon的Github仓库为:https://github.com/Water-Melon/Melon

感谢阅读

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/602797.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Core Web Vitals

Core Web Vitals 是 Google 提出的一组用于衡量网页用户体验质量的指标。它们专注于三个方面&#xff1a;加载性能&#xff08;Largest Contentful Paint&#xff0c;LCP&#xff09;、交互性&#xff08;First Input Delay&#xff0c;FID&#xff09;和视觉稳定性&#xff08…

2024 年江苏省职业院校技能大赛高职软件测试赛项规程

2024 年江苏省职业院校技能大赛高职软件测试赛项规程 需要竞赛资源可私信博主&#xff01; 一、赛项名称 赛项编号&#xff1a;JSG202429 赛项名称&#xff1a;软件测试 赛项组别&#xff1a;高职学生组、高职教师组赛项归属专业大类&#xff1a;电子信息 二、竞赛目的 软件是…

详解Keras3.0 Callbacks API : TensorBoard(可视化工具)

TensorBoard TensorBoard是TensorFlow提供的可视化工具。需要安装TensorFlow才能使用此回调。此回调记录TensorBoard的事件&#xff0c;包括&#xff1a;度量汇总图、训练图可视化、重量直方图、采样剖面。 keras.callbacks.TensorBoard(log_dir"logs",histogram_…

vue3防抖函数封装与使用,以指令的形式使用

utils/debounce.js /*** 防抖函数* param {*} fn 函数* param {*} delay 暂停时间* returns */ export function debounce(fn, delay 500) {let timer nullreturn function (...args) {// console.log(arguments);// const args Array.from(arguments)if (timer) {clearTim…

docker部署simpleDocker

1&#xff0c;安装docker&#xff0c;请参考 linux安装docker 2&#xff0c;安装docker-compose&#xff0c;请参考 Docker-Compose 3&#xff0c;安装simpleDocker 准备docker-compose.yml文件 version: 3 services:redis:container_name: redisimage: redis:latestweb:conta…

imgaug库指南(八):从入门到精通的【图像增强】之旅

引言 在深度学习和计算机视觉的世界里&#xff0c;数据是模型训练的基石&#xff0c;其质量与数量直接影响着模型的性能。然而&#xff0c;获取大量高质量的标注数据往往需要耗费大量的时间和资源。正因如此&#xff0c;数据增强技术应运而生&#xff0c;成为了解决这一问题的…

Linux top命令教程:实时监控系统状态和进程(附实例详解和注意事项)

Linux top命令介绍 top命令&#xff08;Table of Processes&#xff09;是Linux中用来监视系统运行状态和查看系统中运行的进程的实时动态管理命令。它可以显示系统的总体信息&#xff0c;包括运行时间、负载、运行的进程数、CPU使用率、内存使用率等。 Linux top命令适用的L…

mysql原理--事务

1.事务的起源 对于大部分程序员来说&#xff0c;他们的任务就是把现实世界的业务场景映射到数据库世界。比如银行为了存储人们的账户信息会建立一个 account 表&#xff1a; CREATE TABLE account (id INT NOT NULL AUTO_INCREMENT COMMENT 自增id,name VARCHAR(100) COMMENT …

java 常⽤的线程池模式ScheduledThreadPool

用于定时或周期性地执行任务。 可以设置任务的延迟执行时间或执行周期。 使用场景&#xff1a;适用于需要定时执行任务的应用程序&#xff0c;如定时清理缓存、定时发送邮件等。 import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorServ…

excel统计分析——两因素有重复方差分析

参考资料&#xff1a;生物统计学 无重复观测值的两因素方差分析只能研究两个因素的主效应&#xff0c;不能考察因素间的交互作用&#xff0c;只有在确定因素间不存在交互作用时才能进行无重复观测值的试验和分析。为了准确估计因素的主效应、交互作用和随机误差&#xff0c;每个…

K8S学习指南(66)-CRD介绍

文章目录 引言什么是自定义资源定义&#xff08;CRD&#xff09;&#xff1f;CRD 对于 Kubernetes 的意义1. 定制资源类型2. 统一管理3. 更好的扩展性4. 与生态系统集成 如何使用 CRDCRD 的规范详解1. apiVersion 和 kind2. metadata.name3. spec.group 和 spec.versions4. spe…

061:vue中通过map修改一维数组,增加一些变量

第061个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下&#xff0c;本专栏提供行之有效的源代码示例和信息点介绍&#xff0c;做到灵活运用。 &#xff08;1&#xff09;提供vue2的一些基本操作&#xff1a;安装、引用&#xff0c;模板使…

K8S-应用部署

1 应用管理解读 2 应用部署实践 资源对象管理关系 资源对象管理实践 手工方式&#xff1a; kubectl run pod名称 --imageimage地址资源清单方式: apiVersion: v1 kind: Pod metadata:labels:run: my-podname: my-pod spec:containers:- image: kubernetes-register.sswang.co…

Ubuntun构建本地源详细教程

联网主机上下载软件包并打包 首先使用一台已连接互联网的同版本ubuntu主机添加国内镜像源 mv /etc/apt/sources.list /etc/apt/sources.list.bak vim /etc/apt/sources.list# 写入下面的内容: deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiv…

jenkins安装报错:No such plugin: cloudbees-folder

jenkins安装报错&#xff1a;No such plugin: cloudbees-folder 原因是缺少cloudbees-folder.hpi插件 解决&#xff1a; 一&#xff0c;重新启动 http://xxx:8800/restart 二&#xff0c;跳到重启界面时&#xff0c;点击系统设置 三&#xff0c;找到安装插件&#xff0c;然…

1-03C语言超基础语法

一、概述 为了更好的进行后续的课程&#xff0c;避免出现"老师&#xff0c;我还没学过的东西&#xff0c;你怎么直接用&#xff1f;"诸如此类疑问&#xff0c;本小节就诞生了。 实际上&#xff0c;整个第一个大章节的所有小节都是"C语言基础语法"&#x…

【js逆向】爬虫之进程,线程,协程

目录 1、进程 1.1 进程定义 1.2 创建进程 1.2.1 创建单个进程 1.2.2 进程池 2、线程 2.1 线程定义 2.2 创建线程 2.2.1 创建单个线程 2.2.2 线程池

C/C++ 枚举

目录 枚举概述 枚举的使用 枚举的大小计算 枚举的优点 C语言中的自定义类型有&#xff1a;结构 位段 枚举 联合 枚举概述 枚举顾名思义就是一一列举&#xff0c;把可能的取值一一列举。 比如我们现实生活中&#xff1a;一周的星期一到星期日是有限的7天&#xff0c…

动手学深度学习之卷积神经网络之池化层

池化层 卷积层对位置太敏感了&#xff0c;可能一点点变化就会导致输出的变化&#xff0c;这时候就需要池化层了&#xff0c;池化层的主要作用就是缓解卷积层对位置的敏感性 二维最大池化 这里有一个窗口&#xff0c;来滑动&#xff0c;每次我们将窗口中最大的值给拿出来 还是上…

【REST2SQL】02 GO连接Oracle数据库

Oracle数据库我用的最多&#xff0c;先研究Oracle,Go连接Oracle并实现REST和SQL服务。 1 Oracle数据库的安装 我这里安装使用的是Oracle 11g , 安装过程省略5217字。 2 安装Go-ora依赖 go get github.com/sijms/go-ora/v2 安装成功后在GOPATH目录可见&#xff1a; 3 创建一…