更多表达式的Parsing
简介
上一章节讲述并验证了Parse和Translate普通数学表达式的技术。最后以一个简单Parser作为成果而结束,该parser可以解析任意复杂的数学表达式,但有两个限制:
- 不支持变量,只支持数字字面量
- 数字字面量只支持单个数字
变量
b * b + 4 * a * c
其中a、b、c皆是变量。
要支持变量,只需要在之前的设计上扩展<factor>即可。 之前是:
<factor> ::= <number> | (<expression>)
现在要扩展为:
<factor> ::= <number> | (<expression>) | <variable>
代码改动非常小,只需要在factor解析那儿增加一种peek操作即可实现。
函数
除了现有的<factor>形式,还剩一种factor是几乎所有编程语言都会支持的:函数调用。
教程进行到这里就开始增加对函数的Parsing似乎有点太早,因为目前尚未触及到参数传递之类的问题。而且真实世界的编程语言通常都会有type机制,支持多种type如function type之类,而type也是目前尚未触及的问题。
但是作者还是决定现在就踏足对函数的Parsing,原因有:
- 让编译器在某些事情上与最终版很相近
- 引入一个很值得讨论的新问题
截至目前完成的Parser可以归类为一种叫“predictive parser”的概念:在需要之处通过Peek到的字符来决定动作。但对函数的处理不能如此。 原因其实是人为造成的:每一门编程语言都有所谓的标识符(identifier)的概念,并约定了一套合规法则。而变量标识符与函数标识符通常有相同的合规法则。因此,parse到标识符时,无法区分是变量还是函数。
怎么办呢?有两种方式处理这个问题:
- 标识符在使用前必须前置声明。Pascal采用的这种方式
- 在函数标识符后面追加一个(可能为空的)参数列表。C采用的这种方式
由于目前尚无声明类型的机制,因此这里暂且采用C的方式来处理这个问题。也由于目前尚无参数机制,这里暂且约定只支持空参数列表。妥协之后,当下支持的函数,只是形如X()之流。
===