C3编译器 2.1 结构 其实,既然语言已经确定了,剩下的事情就好办了。接下来我们要做的事情就是手工实现C3的编译器,而后面我们将使用我们的自动分析器来处理其他语言,这样我们就可以看到它们的区别。 由于要表示成一种内部表示,也就意味着要设计一个类集,来分别表示这些东西。首当其冲的就是Rule,这是毫无疑问的。 Class Rule Public Name As String Public RuleText As String End Class我想谁也不会使用这样的类。这样编译出来的结果根没有编译是一样的——都是文本格式的规则说明。我们需要一个语法规则的表示方法!再经过了长期的思考与试验之后,我选择了一个我称之为路线图的方法(在后来的进一步学习当中我发现这与Wirth在1976年提出的一方法有异曲同工之处)。


可选图元:

*闭包图元:

+闭包图元:

注:非法出口一律不予表示。右下角标有小方块的图元表示这是一个可选的图元即可以匹配也可以不匹配。闭包的匹配出口都是指向自己的,这是由于只要匹配,就要继续进行匹配,而只有不再匹配的时候才由不匹配出口转到下一个图元。而正闭包其实就是星闭包之前加上一个副本,并且要求必须匹配,这与其数学含义是相同的。 下面是几个经过路线图化的规则:Integer=>Digit+
String=>''''((''''!)|'''''')*''''


Float=>Digit*'.'Digit+

于是产生了RuleMap和RuleMapItem分别对应路线图和图元。因而RuleMap是一个集合类,按照.NET的要求它需要实现IEnumeratable接口。而RuleMapItem需要可选、匹配出口、不匹配出口和名称。Class RuleMap Implements IEnumeratable Public Function GetEnumerator() As IEnumerator Public Name As String Public Count As Integer Public Item(Index As Integer) As RuleMapItem Public Function Add(Name As String) As RuleMapItem End Class Class RulMapItem Public Name As String Public Optional As Boolean Public Match As RuleMapItem Public DisMatch As RuleMapItemEnd Class语法规则的定义基本上完成了,接下来就是规则的容器:Section。由于在语义上Section也是一条规则,只不过其规则的代码是其内部所有成员的或操作,也即可以匹配其内部任何一个规则,所以理所当然的Section继承自Rule。但是作为容器类,它也应当实现Ienumerable接口。Class Section Inherits Rule Implements IEnumerable Public Function GetEnumerator() As IEnumerator Public Count As Integer Public Sub Add(r As Rule) Public Sub Remove(Index As Integer) Public Item(Index As Integer) As RuleEnd Class由于Class与Section唯一的区别只是名称不同,位置不同,所以又在Section中加入了IsClass属性。 2.2路线图的组合原则 路线图的内部最重要的一点就是编译过程中路线图的合法与非法出口都应当指向何处?比如: (a|(b[c]))d a分析完了之后是b,为什么放在不匹配出口?因为他们是或的关系,只有a不匹配时才会考虑b路径上的匹配。于是有



