用 C 語言使用 ragel


Ragel是個有限狀態機編譯器,它將基於正則表達式的狀態機編譯成傳統語言(C,C++,D,Java,Ruby等)的解析器。

用Ragel可以很方便且很容易的寫出各種FSM,也經常用作語法檢測器。

Ragel State Machine Compiler

 

一個用C語言實現的例子:

#include <stdio.h>
#include <string.h>

%%{
    machine foo; #FSM 名稱

    #定義動作
    action res_true { 
        res=1;
    }
    action res_false {
        res=0;    
    }
    action res_err {
        res=-1;
    }

    #FSM 起點
    main := ( 'true'0 @res_true | 'false'0 @res_false | any @res_err); 

    #寫入 FSM 數據
    write data; 
}%%


int GetRes(char *pbuf)
{
    int res;
    char *p=pbuf; //初始化 p 指向需要做 FSM 處理的數組起始地址
    char *pe=p+strlen(pbuf)+1; //初始化 pe 指向 p 的結束地址
    int cs; // cs 用來保存 FSM 運行中狀態

    //寫入初始化代碼
    %%write init;

    //寫入執行代碼
    %%write exec;
    return res;
}

int main()
{
    int cs;
    char buf[256];
    while (scanf("%s",buf)) {
        printf("res=%d\n",GetRes(buf));
    }
    return 0;
}

編譯

上面的代碼還不能直接用gcc編譯,需要先用ragel編譯成C語言代碼,再用gcc編譯成可執行程序。

ragel -o main.c main.rl
gcc -o test main.c

上面例子實現的是把字符串"true" "false"轉換成C語言1 0的形式,如果既不是"true"也不是"false"則結果為-1。

執行結果

輸入

true

false

truefalse

輸出

res=1

res=0

res=-1

基本語法

多行的FSM定義以 %%{ 開始 %%} 結束。單行的FSM定義在行首以 %% 開始。

machine foo; 狀態機的名稱。

 

action 定義匹配動作,動作內寫入匹配后所要執行的代碼。

上面代碼有3個動作,分別是 res_true, res_false, res_err 用來得出結果 。

 

main := 正則表達式;  表示FSM起始點,匹配先從這里開始。

上面代碼中( 'true'0 @res_true | 'false'0 @res_false | any @res_err)表示

(如果成功匹配 "true\0" 執行動作res_true) 或則 (如果成功匹配 "false\0" 執行動作res_false) 或則 (如果成功匹配 任意字符 執行動作res_err )

any是Ragel 的關鍵字,類似的還有

關鍵字 描述
any 所有字符.
ascii ascii字符.0~127
extend ascii擴展的字符.有符號-128~127或無符號0~255
alpha 字母.[a~z A~Z]
digit 數字.[0~9]
alnum 字母和數字.[a~z A~Z 0~9]
lower 小寫字母.[a~z]
upper 大寫字母.[A~Z]
xdigit 16進制數字.[0~9 a~f A~F]
cntrl 控制字符.0~31
graph 可視字符.[!-~]
print 可打印字符.[ -~]
punct 非字母數字可視字符.[!-/:-@[-‘{-~]
space 空白字符.[\t\v\f\n\r ]
zlen 空字符串.""
empty 空集.^any

 

%%write data; 寫入FSM運行中需要的狀態數據,可以放在任何地方,但必須要在 %%write exec 之上。

%%write init; 寫入FSM的初始化代碼,放在函數之內,需要先定義 int cs。

%%write exec; 寫入FSM的執行代碼,放在函數之內,需要先定義 char *p 和 char *pe

結束語

雖然使用Ragel很輕松的解決平常我們 if else if 功能,而且效率也不錯,但是會使生成的源代碼和程序體積變大(19K生成30M源碼),所以使用前還是需要考慮考慮。

更詳細的使用說明可以在Ragel State Machine Compiler下載使用手冊。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM