近期忽然有兴趣写个文法解释器,因而SPAS就出炉了。其实最初是看到boost.spirit的强大才想研究下如何去实现一个文法解释器的。在看了一些关于boost.spirit库的相关资料后,个人头脑中逐渐构建起了一个文法解释的框架,因而我便试着去实现它。 shell
语言能够从产生和接收两个角度进行定义,从产生的角度就是形式语言,而从接收的角度就是自动机。本人以前按照自动机写了一个浮点数的识别程序,可是以为实现颇为繁琐。用自动机来描述语言不够简洁,语法稍微复杂一点,状态就会不少,实现起来也很不容易。因此本人就想仿照boost.spirit库,经过定义语法来实现语言的解释。 框架
一个语言是有字母表、语法构成的,对咱们来讲字母表其实并非很重要,字母表只是一个符号表而已,重要的是语法。在SPAS中,字母表就是char/wchar_t的数值空间,语法就是定义的一条条规则。下面来看一个使用SPAS定义的四则运算解释计算示例。 ui
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地址的语法。 google
SPAS地址:https://code.google.com/p/spas/ spa