SPAS文法解释库

近期突然有兴趣写个文法解释器,于是SPAS就出炉了。其实最初是看到boost.spirit的强大才想研究下如何去实现一个文法解释器的。在看了一些关于boost.spirit库的相关资料后,我的头脑中逐渐构建起了一个文法解释的框架,于是我便试着去实现它。

语言可以从产生和接收两个角度进行定义,从产生的角度就是形式语言,而从接收的角度就是自动机。本人之前按照自动机写了一个浮点数的识别程序,但是觉得实现颇为繁琐。用自动机来描述语言不够简洁,语法稍微复杂一点,状态就会很多,实现起来也很不容易。所以本人就想仿照boost.spirit库,通过定义语法来实现语言的解释。

一个语言是有字母表、语法构成的,对我们来说字母表其实并不是很重要,字母表只是一个符号表而已,重要的是语法。在SPAS中,字母表就是char/wchar_t的数值空间,语法就是定义的一条条规则。下面来看一个使用SPAS定义的四则运算解释计算示例。

opr2 = _int[arg[1] = ref<int>(arg)] | ('(' >> expr[arg[3] =
            ref<int>(arg)] >> ')');

        mulr = '*' >> opr2[arg[1] = ref<int>(arg)];
        divr = '/' >> opr2[arg[1] = ref<int>(arg)];
        opr1 = opr2[arg[1] = ref<int>(arg)] >> * (mulr[arg[3] = arg[3]
            * ref<int>(arg)] | divr[arg[3] = arg[3] / ref<int>(arg)]);
            
        sumr = '+' >> opr1[arg[1] = ref<int>(arg)];
        subr = '-' >> opr1[arg[1] = ref<int>(arg)];
        expr = opr1[arg[1] = ref<int>(arg)] >> * (sumr[arg[3] = arg[3]
            + ref<int>(arg)] | subr[arg[3] = arg[3] - ref<int>(arg)]);
        
        endr = expr[ref(result) = arg];
将四则表达式使用形式语言写出来,如下:
opr2 -> int | ( expr )

mulr -> *opr2;
divr -> /opr2;
opr1 -> opr2 | opr2 mulr | opr2 divr;
            
sumr -> +opr1;
subr -> -opr1;
expr -> opr1 | opr1 sumr | opr1 subr;
        
endr = expr;
上面这个文法能够产生所有的整数四则运算。SPAS的规则就是根据这个文法来写的,在SPAS中A|B表示A、B二者择一,A >> B表示A后面紧跟着B,*A表示有0个或多个A,+A表示有1个或多个A,repeat<N,M>(A)表示A的个数在N到M之间,repeat<N>(A)表示有N个A。

SPAS不仅能够检查文本是否符合语法,还能够通过在rule中嵌入操作(即上述示例中方括号内内容)来对文法的解释过程进行控制。SPAS中,arg表示rule的值,arg[n]表示rule的第n个父rule的值,ref是引用外部变量,ref<type>(x)是将x转变为type类型。此外还能通过在比较语句对语法进行进一步的限制,例如,_int匹配所有的整型数,而_int[arg < 100]就表示所有小于100的整型数。这种控制很实用,例如,_uint[arg < 256u] >> repeat<3>('.' >> _uint[arg < 256u])这个规则是产生IPv4地址的语法。

SPAS地址:https://code.google.com/p/spas/

你可能感兴趣的:(SPAS文法解释库)