用6502汇编语言编写的JSON解析器

2021-03-01 08:52:04

我当时在看电视,有一个广告宣称“该做您想做的事了!”我回复了电视,是时候用6502汇编语言编写JSON解析器了?我以某种方式不认为他们的想法是正确的,但是电视是正确的,我应该做我想做的事情。

因此,这是我的JSON解析器。核心解析器是完全用6502汇编语言编写的,旨在与ca65进行汇编。但是,它应从C进行调用,并使用cc65调用约定(特别是fastcall约定)。

JSON65可以在6502系列中的任何处理器上运行。 (它不使用任何65C02指令。)

JSON65的汇编语言部分以与C调用约定兼容的方式使用cc65使用的零页面位置。

JSON65应该可以在cc65工具链支持的任何目标上使用。我已经在sim65和未增强的Apple // e上对其进行了测试。

JSON65是事件驱动(SAX样式)的解析器,因此为解析器提供了回调函数,该函数针对每个事件调用该回调函数。

JSON65支持增量解析,因此您可以自由地将其输入任何大小的输入块,并且您无需一次拥有整个文件的内存。

JSON65是完全可重入的,因此您可以根据需要一次增量解析多个文件。

JSON65确实有两个限制:字符串限制为255个字节,并且(嵌套数组或对象的)嵌套深度限制为224。但是,行的长度或文件的长度没有限制。

JSON65为每个解析器使用512字节的内存,必须由调用方分配。 JSON65不使用动态内存分配。

根据JSON规范,JSON65假定其输入是UTF-8编码的。但是,JSON65无法验证UTF-8,因此可以使用任何编码,只要具有高位清除率的所有字节都表示ASCII字符即可。设置高位的字节只允许在字符串中使用。 JSON65假定UTF-8的唯一位置是处理\ u转义序列。根据JSON规范,单个\ u转义符可用于指定基本多语言平面中的代码点,而两个连续的\ u转义符(UTF-16代理对)可用于指定基本多语言平面之外的代码点。 Theseescapes将被转换为适当的UTF-8。

因为JSON仅在允许使用任意空格的地方允许换行,所以JSON65与行尾的类型无关。 (CR,LF或CRLF。)为了计算错误报告的行号,JSON65处理CR,LF或CRLF行尾。

JSON65将解析适合32位有符号长整数的数字,并将长整数提供给回调。将所有其他数字(即浮点数或溢出32位长的整数)作为字符串提供给回调。 (如字符串,数字不能超过255位。)

回调函数可能会返回错误。这将导致解析立即停止,并且回调函数返回的错误代码将由j65_parse()返回。错误代码为负数,用户可以将J65_USER_ERROR到-1(含)之间的代码用于自己的错误代码。

如果您使用事件驱动程序解析器,则需要在事件进入时构建自己的数据结构(或以其他方式处理数据)。如果您不想这样做,则可以使用树接口(json65-tree.h)来为您建立一个数据结构,这仅适用于小型文件,因为整个树必须适合一次记忆。

通常,JSON65是解析器。但是,它确实有一些支持将JSON65打印回文件(位于json65-print.h中)。函数j65_print_tree()将JSON树(从json65-tree.h中的树接口)打印到给定的文件句柄。它将整个JSONtree打印在没有空格的一行上。对于机器可读的JSON文件,这是最紧凑的格式,但并不是人类可读的格式。

如果您编写自己的代码以打印JSON,或者是因为您要漂亮地打印JSON,或者是因为您使用的是j65_node以外的数据结构,那么您可能仍想使用json65-quote.h中的函数j65_print_escaped()。它使用JSON转义序列处理转义字符串。

我没有任何花哨的Doxygen文档,但是API由头文件中的注释记录。如果您希望使用事件驱动的解析器,请阅读json65.h。如果您想使用树形接口,请阅读json65-tree.h。

如果仅希望使用事件驱动的(SAX风格)解析器,则只需要一个头文件(json65.h)和一个程序集文件(json65.s)。但是,otherfiles中有一些帮助程序函数,您可以根据需要选择将其与JSON65一起使用。最值得注意的是JSON65的树接口,您可以使用它代替小文件的事件驱动接口。

每个头文件直接对应于一个实现文件。一些实现文件用汇编语言编写,而有些则用C编写。这是每个文件的描述,以及实现的机器代码的大小(“ CODE”部分加上“ RODATA”部分) ;所有实现文件都没有任何DATA或BSS)。

json65.h(2240字节)-核心,事件驱动的解析器。如果您希望构建自己的数据结构,则这是唯一需要的文件。

json65-string.h(291字节)-该实现一个字符串实习生池,由树接口使用。

json65-tree.h(1300字节)-树接口,在解析文件时建立树数据结构。然后,您可以遍历树上的内容。

json65-quote.h(226字节)-具有打印字符串的功能,用JSON规范中的转义序列替换特殊字符。它由树打印机使用,但是如果您自己打印JSON文件而不使用树接口,也可以独立使用。

json65-print.h(710字节)-将树形文件打印为JSON。如果您正在使用树形接口,请使用此功能,并希望写入和读取JSON文件。

json65-file.h(1378字节)-提供帮助功能,以块的形式将数据从文件中馈送到解析器,并向用户显示错误消息(包括打印异常行,以及打印插入符号以指示异常行的位置) )。

我讨厌构建系统(或至少构建用于C代码的系统),因此我没有提供。 (除了一个la脚的小Perl脚本,它使用sim65来构建和运行测试。)相反,我建议您将所需的源文件和头文件复制到自己的项目中,并使用已经用于该项目的任何构建系统。作为基于GNU Make的cc65构建系统。)

您可以使用以下依赖关系图来确定需要将哪些源文件复制到项目中。 (对于每个源文件,您还需要复制相应的头文件。)没有依赖关系的源文件(例如json65.s)位于图的顶部,而具有最大依赖关系的源文件(json65-print.c )位于图表的底部。

json65.s json65-string.s / \ / / \ / / / \ / json65-file.c json65-tree.c json65-quote.s \ / \ / \ / json65-print.c 如果要构建和运行测试,只需在存储库的顶层运行run-test.plPerl脚本。 (无需争论)。您将需要安装cc65工具链。 注意:sim65的2.17版和更早版本在BIT指令的实现中存在错误,因此测试将失败。 您需要更新的版本才能通过测试。 (这只会影响测试的仿真。如果您计划在实际硬件上或在sim65以外的仿真器上运行JSON65,那么使用cc65的较早版本就可以了。) JSON65已通过OSI和FSF批准的zlib / libpng许可进行许可。