Ragel学习笔记(一)

Ragel是一个状态机编译器,类似Lex, 主要是用来处理字符输入,用于语法解析。简单的文本处理工作一般用正则表达式,或者用awk/sed这些工具就可以处理。之所以用Ragel是为了这样的场景,你的代码的核心任务是解析文本,而且需要高效的处理,比如一个SMTP引擎, HTTP引擎。那么Ragel可以按你定义好的语法,生成一个状态机嵌入到你的代码中。因为这个状态机是专门针对你预定义的语法,且以你的原生代码执行,效率自然比正则表达式,awk这些通用工具高的多。Ragel支持生成C/C++/Java/Ruby/D/C#等各种语言。

这篇文章我们来学习下如何使用Ragel生成状态机。Ragel的安装是很简单的,
sudo apt install ragel

或者下载源代码 http://www.colm.net/open-source/ragel/ 编译。

Ragel构造状态机是以字符匹配和正则表达式为基础的。从模型上说,有3中状态机构造模型:1) Regular Expression 2) Scanner 3) State Chart
我们看个Regular Expression的例子:

#include  
#include  
%%{             
machine foo;    
write data;     
}%%             

int main( int argc, char **argv ) 
{
	int cs; 
	if ( argc > 1 ) 
	{ 
		char *p = argv[1];                    
		char *pe = p + strlen( p );           
		%%{
			main := [0-9]+ ( '.' [0-9]+ )?;   
			
			write init;                       
			write exec;                       
		}%% 
	}
	printf("result = %i\n", cs >= foo_first_final ); 
	return 0;
}

第3行 %%{ 表示 ragel 代码块开始
第4行 machine 定义一个状态机machine
write data 指示ragel在代码的这个位置写入ragel运行需要的静态数据
}%% 表示ragel 代码块结束
变量ppe状态机处理的buffer起始和终止地址。状态机运行时就从这个buffer依次读入字符。变量名很重要,必须为ppe, ragel生成的代码里面使用这两个变量名

main := [0-9]+ ( '.' [0-9]+ )? 定义正则表达式,main是个关键字,表示状态机入口
write init 指示ragel在代码的这个位置写入ragel运行需要的初始化代码
write exec 指示ragel在代码的这个位置写入运行状态机的代码

在cygwin环境下面编译运行这个状态机:

# ragel -n -p -o test1.c test.rl
# gcc test1.c
# ./a.exe 12
result = 1
# ./a.exe 123a
result = 0

这个状态机用来判断输入的参数是否是一个有效的整数或者浮点数。
如果要从代码里面访问状态机处理过程中的数据,比如上面例子里输入的12, 就要用ragel的Action功能。

你可能感兴趣的:(脚本,C++编程)