更加自然的语法规则
mpc
允许我们使用一种更加自然的方式来编写语法规则。我们可以将整个语言的语法规则写在一个长字符串中,而不是使用啰嗦难懂的 C 语句。我们也不再需要关心如何 使用 mpcf_strfold
或是 free
参数组织或删除各个语句。所有的这些工作都是都是自动完成的。
下面,我们使用这个方法重新编写了上面实现过的 Doge 语言:
mpc_parser_t* Adjective = mpc_new("adjective");
mpc_parser_t* Noun = mpc_new("noun");
mpc_parser_t* Phrase = mpc_new("phrase");
mpc_parser_t* Doge = mpc_new("doge");
mpca_lang(MPCA_LANG_DEFAULT,
" \
adjective : \"wow\" | \"many\" \
| \"so\" | \"such\"; \
noun : \"lisp\" | \"language\" \
| \"book\" | \"build\" | \"c\"; \
phrase : <adjective> <noun>; \
doge : <phrase>*; \
",
Adjective, Noun, Phrase, Doge);
/* Do some parsing here... */
mpc_cleanup(4, Adjective, Noun, Phrase, Doge);
即使你现在暂时不理解上面的长字符串的语法规则,也能明显地感觉到这个方法要比之前的清晰的多。下面就来具体的学习一下其中的某些特殊符号的意义及用法。
注意到,现在定义一个语法规则分为两个步骤:
- 使用
mpc_new
函数定义语法规则的名字。 - 使用
mpca_lang
函数具体定义这些语法规则。
mpca_lang
函数的第一个参数是操作标记,在这里我们使用默认选项。第二个参数是 C 语言的一个长字符串。这个字符串中定义了具体的语法。它包含一系列的递归规则。每个规则分为两部分,用冒号 :
隔开,冒号左边是规则的名字,右边是规则的定义,使用 ;
表示规则结束。
定义语法规则的一些特殊符号的作用如下:
语法表示 | 作用 |
---|---|
"ab" |
要求字符串 ab |
'a' |
要求字符 a |
'a' 'b' |
要求先有一个字符 a ,后面紧跟一个字符 b |
'a'|'b' |
要求有字符 a 或字符 b |
'a'* |
要求有 0 个或多个字符 a |
'a'+ |
要求有 1 个或多个字符 a |
<abba> |
要求满足名为 abba 定义的语法规则 |
似曾相识的感觉?
上面的一些语法规则有没有似曾相识的感觉?你没有猜错,
mpca_lang
函数就是用mpc_many
、mpc_and
、mpc_or
这些函数来实现的,干净利落,不拖泥带水。
根据表中给出的规则尝试着理解一下上面的代码,看看是不是等价于之前我们前面用代码定义过的语法解析器?
在后面的章节中,我们会使用这个方法来定义我们的语法规则。刚开始可能并不是那么容易理解,但随着时间的推移,我们练习的越来越多,你也将会更加熟悉,并将知道如何创建和编辑自己的语法规则。
本章更加注重的是理论知识,所以在做彩蛋部分时,不要太在意正确性,思考实现的方式才是最重要的。
当前内容版权归 NoahDragon 译 或其关联方所有,如需对内容或内容相关联开源项目进行关注与资助,请访问 NoahDragon 译 .