我正在从ANTLR2.7.7移植(或实际上从头开始重写)SystemVerilog语法到ANTLR4.7
SystemVerilog有很多从Verilog继承的指令。它们可以在源代码中的任何位置显示出来。因此,他们无法处理 解析器。有些是由词法分析器解释而且从未进一步扩展(控制源加密),有些是用于预处理器(宏,条件编译等),但有一些超出了该阶段。这些需要解析器和处理它们的直接令牌源之间的双向通信。解析器在遇到可能受其影响的构造时会询问这些指令的状态(当访问者用于操作时,解析器需要请求该信息以将其记住为上下文的一部分)。另一方面,令牌源需要在处理这些指令时向解析器请求当前作用域,因为有些指令不能在任何单元内使用。
考虑以下示例:
`timescale 1ns/1ps
module m;
`resetall
initial $printtimescale; //Time scale of (m) is 1ns / 1ps
endmodule
在旧的ANTLR2中,我确切地知道在执行源和解析器之间的通信的动作之前将从源中提取多少令牌。这些知识意味着不需要花哨的同步,令牌源可以在指令到达时解释指令,并且解析器可以在需要时请求指令状态,因为只要没有使用语法谓词,令牌创建和消耗就会并行发生。 / p>
据我所知,在执行任何操作之前,ANTLR4可以提取任意数量的令牌。如果解析器在处理模块头时拉出太多令牌,则会导致令牌源“执行”resetall指令,从而使先前使用的时间刻度无效。
如果没有其他选项,解决问题的方法很可能是令牌源记住与其遇到的指令相关的令牌,并将它们与相关操作一起打包给某个仿函数。一旦它需要向解析器发出实际令牌并且至少有一个函数尚未发出,它将创建一个常规令牌的子类,它将记住常规令牌之上的仿函数。这种方式解析器可以做任何它想要的预测解析路径并从令牌源中提取新令牌 - 到目前为止不会执行任何与指令相关的操作。最后一点是重新定义标准consume
例程。它必须询问令牌是否属于“carying directive action”类型并执行该操作 - 这样,指令操作(以及指令状态)将与令牌消耗同步,而不是与令牌创建同步。
问题是我现在无法测试上述工作,因为最终令牌发射的所有内容都在新旧解析器之间共享。只有最后一点创建实际令牌是不同的。这意味着要测试解决方案,我还需要将它应用于旧解析器。
最后,问题:
consume
还是有一些其他例程可以解决需要触及的令牌流?如果内部解析器更改流f.e中的标记。通过使用其他一些令牌类重新创建它们,我的特殊仿函数数据会在这种情况下丢失(这可能只是我的偏执狂)。