我的编译器 C3编译器

C3编译器
 
2.1 结构
 
       其实,既然语言已经确定了,剩下的事情就好办了。接下来我们要做的事情就是手工实现C3的编译器,而后面我们将使用我们的自动分析器来处理其他语言,这样我们就可以看到它们的区别。
       由于要表示成一种内部表示,也就意味着要设计一个类集,来分别表示这些东西。首当其冲的就是Rule,这是毫无疑问的。
       Class Rule
              Public Name As String
              Public RuleText As String
       End Class
我想谁也不会使用这样的类。这样编译出来的结果根没有编译是一样的——都是文本格式的规则说明。我们需要一个语法规则的表示方法!再经过了长期的思考与试验之后,我选择了一个我称之为 路线图的方法(在后来的进一步学习当中我发现这与Wirth在1976年提出的一方法有异曲同工之处)。
左图就是一个基本图元。但是只是这样的话它并不好使,原因与上面的Rule类是一样的——太简单了,我们需要一些实用的东西以及后面的编译器用得到的有用的信息——就因为这是一个服务程序。我们要使它改变并使它尽量接近C3并尽量接近计算机语言的表示,经过大量尝试性的开发使其不断的完善从而得到了下面的表示方案。
 
 
 
 
 
路线图的基本图元的表示方法
普通图元:
可选图元:
*闭包图元:
+闭包图元:
注:非法出口一律不予表示。
右下角标有小方块的图元表示这是一个可选的图元即可以匹配也可以不匹配。
闭包的匹配出口都是指向自己的,这是由于只要匹配,就要继续进行匹配,而只有不再匹配的时候才由不匹配出口转到下一个图元。而正闭包其实就是星闭包之前加上一个副本,并且要求必须匹配,这与其数学含义是相同的。
 
下面是几个经过路线图化的规则:
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 RuleMapItem
End 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 Rule
End Class
由于Class与Section唯一的区别只是名称不同,位置不同,所以又在Section中加入了IsClass属性。
 
 
       路线图的内部最重要的一点就是编译过程中路线图的合法与非法出口都应当指向何处?比如: (a|(b[c]))d
 
a分析完了之后是b,为什么放在不匹配出口?因为他们是或的关系,只有a不匹配时才会考虑b路径上的匹配。于是有
那c呢?由于其与b为联结关系所以应该在b的合法出口,也就是匹配出口。那又为什么a的匹配出口不指向c呢?因为a与c根本就不在一个表达式里!又不对了——a与b也不在一个表达式里呀。没错,但是a、b所在的表达式在同一表达式里。而实际上可选的c也是一个表达式只不过只有一项。
之后就是最复杂和麻烦的地方:d,它与前面的表达式为联结关系,那么应该放在合法出口。那么那里是合法出口?按照C3的定义可选图元的不匹配出口也是合法的出口。都指向d?分析一下可选的含义吧, 匹配不匹配都要匹配下一个。也就是说,匹配出口与不匹配出口都要指向后继图元,也就是d。
完了吗?如果输入是一个以a开头的字符串,又如何?按照这个规则ad是可以接受的。但是如果按照上面的路线图扫描的话,只有a被接受,d并没有被接受。这显然是错误的。所以a的匹配出口也应当指向d。
       但是,这个问题并不指向上面说的那么简单——如何找到所有这3个合法出口?显然我们需要查找 所有的合法出口,并且对所有的合法出口进行赋值。其间有两个问题,其一,由于路线图是网状结构,如何遍历,这其实在算法类书籍中都有描述,这里不再详细说明;其二就是如何判断那个出口是合法的,当然匹配出口只要不指向任何图元永远都是合法的,主要就是不匹配出口的问题——上面的c就是一个典型的例子——解决方案就是,可选图元的不匹配出口为合法出口。
 
       基本上框架设计完成了,来考虑一下实现问题、软件工程问题以及逻辑问题。首先是实现问题,由于类、接口与重点、难点的算法都已经设计完成,剩下的只是填写代码,比较简单。然后是软件工程问题,是否有健壮性、可维护性以及可扩展性,最值得注意的是可扩展性,因为这个试验性质的项目并不是一个成熟的技术,所以可扩展性显得非常重要,因为我们不清楚什么时候我们可能忘了点什么东西没有添加进去。而且逻辑上则可以非常清楚。
       其实现阶段考虑上面的问题除了可扩展性之外没有太多需要在意的地方。在具体的实现上,我采取了将编译部分的代码集成在这些类中。但实际上这并不是一个好主意,因为这样就需要一个专门的类来处理编译问题,并且由于编译代码的分散时维护起来有些麻烦。相对的使用完全的分体式的C3编译器来处理虽然可能比较复杂(相对而言),但可维护性要好得多。
       上面提到的专门处理编译问题的类就是后来诞生的Grammar类。它全权负责C3的编译工作以及编译后的序列化/反序列化工作。较详细地说明见 匹配规则说明文档
      
       之后在制作分析器的过程中我们需要出错信息,这样就在上面的架构下添加函数及相应的类实现了出错信息的自动生成。但是,既然在这里能够自动生成,那么在分析其运行时当然也可以自动生成,于是这些代码实际上用处并不大,但为了防止将来又需要,从1.0版本即一直保留至今,但是在1.2版以后已经不再使用。
      
       在上述工作完成之后,我写了一个C-,一个C的简化版本,并针对.NET作了相应的改变,详见 程序测试报告1,当然这份报告是在扫描器与分析器都完成之后才出来的,之前只是测试其功能是否能够实现、序列化/反序列化是否正确。通过这一点也可以了解到测试用例是多么的重要,没有用例我们甚至不能对我们的代码有半点信任——根本没有测试,怎么知道对不对?
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: ESP32-C3是一款由乐鑫推出的低功耗Wi-Fi和蓝牙芯片,它内置了强大的处理能力和丰富的外设接口。为了开发和使用ESP32-C3,我们需要使用适当的编译器。 对于ESP32-C3芯片的编译,乐鑫提供了一个名为ESP-IDF的开发框架,其中包含了该芯片的编译器。ESP-IDF是一个完整而强大的开发工具链,适用于ESP32和ESP32-C3等芯片。它基于FreeRTOS操作系统,提供了许多API和库函数,使得开发者可以轻松地实现各种功能。 ESP-IDF使用了GCC编译器作为默认的编译工具。GCC是一个广泛使用的编译器集合,支持多种编程语言和平台,包括C、C++和汇编语言等。通过这个编译器,我们可以将我们的C或C++代码编译成可在ESP32-C3上运行的二进制文件。 除了GCC,ESP-IDF还提供了其他一些编译器选项,如Clang等。这些编译器都具有优秀的代码生成能力,能够为ESP32-C3芯片提供高效的代码运行环境。 总的来说,ESP32-C3编译器是开发者在开发ESP32-C3项目时必需的工具,通过这个编译器,我们可以将高级语言代码转化为芯片可识别的指令,实现各种功能。通过乐鑫提供的ESP-IDF开发框架,我们可以方便地进行开发和调试工作,让我们能够更加高效地利用ESP32-C3芯片的功能。 ### 回答2: ESP32-C3是一款由乐鑫科技推出的高性能单芯片Wi-Fi和蓝牙5.0 SoC解决方案。它集成了一个灵活多用途的RISC-V处理器内核,具有较低功耗和高集成度的优点。 在ESP32-C3的软件开发过程中,编译器扮演着非常重要的角色。编译器是将人类可读的高级语言(如C、C++)转化为机器可执行的代码的工具。为了充分利用ESP32-C3的功能,开发者需要使用特定的编译器进行软件开发。目前,乐鑫科技为ESP32-C3提供了多个编译器选择。 其中,较为常用的是乐鑫自家开发的ESP-IDF编译器套件。ESP-IDF是专门为ESP32系列开发的官方软件开发框架,包含了编译器、库函数以及丰富的代码示例和开发文档。使用ESP-IDF能够充分发挥ESP32-C3的性能,并且具有丰富的功能和易用性。 此外,ESP32-C3还可以与其他编译器进行配合使用,例如GCC(GNU编译器套件)和Clang(基于LLVM的编译器前端)。这些编译器都是开源的,并具有广泛的应用。 总之,ESP32-C3编译器是开发者在进行软件开发时必不可少的工具。乐鑫科技提供了ESP-IDF编译器套件,并支持其他常用的编译器,使开发者能够根据自己的需求选择最合适的编译器进行软件开发。 ### 回答3: ESP32-C3是一种高度集成的Wi-Fi + Bluetooth MCU,适用于物联网应用。编译器是用于将源代码转换为可执行文件的软件工具。对于ESP32-C3,开发者可以选择使用不同的编译器,如ESP-IDF(Espressif IoT Development Framework)。 ESP-IDF是一套为ESP32系列开发的官方开发框架,它支持C和C++编程语言,并提供了丰富的API和组件,简化了ESP32-C3开发的过程。ESP-IDF使用GCC作为默认的编译器,并提供了丰富的编译和调试选项。 GCC(GNU Compiler Collection)是一个开源的编译器套件,支持多种编程语言,包括C、C++、Java等。并且,GCC是跨平台的,可以在不同的操作系统上使用,如Windows、Linux、Mac OS等。在ESP32-C3开发中,GCC能够将开发者编写的源代码编译成针对ESP32-C3硬件平台的可执行文件。 除了GCC,开发者还可以选择其他编译器,如Clang。Clang是另一个可选的开源编译器,与GCC类似,支持多种编程语言,并提供了高性能和较低的内存占用。 总而言之,ESP32-C3编译器是用于将开发者编写的源代码转换为可执行文件的工具。对于ESP32-C3开发,开发者可以选择使用不同的编译器,如GCC和Clang,以实现更高效、可靠的代码编译和执行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值