MicroPython编译过程包括以下步骤:
- 词法分析器将MicroPython程序文本流转换为标记。
- 语法解释器将标记转换为抽象语法(语法树)。
- 根据语法书输出字节码或本地代码。
本文以给MicroPython增加一个简单的语言特性为例来说明这一过程:
>>> add1 3
4
>>>
add1
语句以整数作为参数,将其加 1。
添加语法规则
MicroPython 的语法基于CPython 语法,并在py/grammar.h
中定义。该语法用于解析MicroPython源码文件。
要定义语法规则,需要关注两个宏:DEF_RULE
和 DEF_RULE_NC
。DEF_RULE
允许您定义一个带有相关编译函数的规则,而 DEF_RULE_NC
则没有编译 (no compile NC) 函数。
对于新增的语句 add1
,带有编译函数的简单语法定义如下:
DEF_RULE(add1_stmt, c(add1_stmt), and(2), tok(KW_ADD1), rule(testlist))
第二个参数 c(add1_stmt)
是相应的编译函数,需要在 py/compile.c
中实现,以便将此规则转化为可执行代码。
第三个必要参数可以是 or
或 and
,它指定了与语句相关的节点数。在本例中,add1
语句类似于汇编语言中的ADD1
,它需要一个数字参数,因此add1_stmt
有两个相关节点:一个节点是语句本身,即与KW_ADD1
对应的字面 add1
;另一个节点是它的参数,即作为顶层表达式规则的testlist
规则。
注意:
这里的add1
规则只是一个示例,并非MicroPython标准语法的一部分。
本例中的第四个参数是与规则KW_ADD1
相关的标记,可以通过编辑py/lexer.h
在词典中定义该标记。
使用DEF_RULE_NC
宏可省略编译函数参数,即在不使用编译函数的情况下定义相同的规则:
DEF_RULE_NC(add1_stmt, and(2), tok(KW_ADD1), rule(testlist))
其余参数的含义相同,无编译函数的规则必须由所有以该规则为节点的规则明确处理。这种 NC 规则通常用于表达复杂语法结构的子部分,这些子部分无法用一条规则表达。
注意:
宏DEF_RULE
和DEF_RULE_NC
需要其他参数,要深入了解支持的参数,请参阅 py/grammar.h。
添加词法标记
语法中定义的每条规则都应与py/lexer.h
中定义的标记相关联,通过编辑 _mp_token_kind_t 枚举来添加该标记:
typedef enum _mp_token_kind_t {
...
MP_TOKEN_KW_OR,
MP_TOKEN_KW_PASS,
MP_TOKEN_KW_RAISE,
MP_TOKEN_KW_RETURN,
MP_TOKEN_KW_TRY,
MP_TOKEN_KW_WHILE,
MP_TOKEN_KW_WITH,
MP_TOKEN_KW_YIELD,
MP_TOKEN_KW_ADD1,
...
} mp_token_kind_t;
然后编辑py/lexer.c
,添加新关键字的字面文本:
STATIC const char *const tok_kw[