将源转换为AST并返回的数据模型



我正在开发一种自定义编程语言。在编译它时,解析器首先将文本转换为一个简单的令牌流。然后将令牌转换为一个简单的树。然后,树被转换为对象图(其中有洞,因为类型还没有完全弄清楚(。然后将多孔树转换为紧凑对象图。

然后我们可以更进一步,把它编译成JavaScript。然后将紧凑对象图转换为JavaScriptAST。JS AST然后被转换为"AST";混凝土;语法树(带有空格等(,然后将其转换为JS文本。

因此,在从文本到紧凑对象图的过程中,有5个转换步骤(text->token_list->tree->holey_graph->graph(。在其他情况下(其他语言(,您可能会或多或少地使用。

我现在进行这种转换的方式非常特别,不跟踪行号,所以不可能真正判断错误的来源。我想解决这个问题。

在我的案例中,我想知道如何创建一个数据模型来跟踪定义内容的文本行。通过这种方式,您可以很好地向开发人员报告任何编译错误。到目前为止,我建模的方式是用一种";折叠";我称之为模型;折叠";在文本上->token_list转换。对于每个标记,它跟踪3件事:标记的行、列和文本长度。一开始你可以这样建模:

{
token: 'function',
line: 10,
column: 2,
size: 8
}

但这是将两个概念绑定到一个对象中:令牌本身和";折叠";正如我所说的那样。真的,它会像这样更好:

fold = {
line: 10,
column: 2,
size: 8
}
token = {
value: 'function'
}
// bind the two together.
fold.data = token
token.fold = fold

然后,在简单树中从标记转换为AST节点。这可能类似于:

treeNode = {
type: 'function'
}
fold = {
previous: tokenFold,
data: treeNode
}

这样连接这些点。最后,你会有一个折叠列表,可以从紧凑对象图到文本进行理论遍历,因此,例如,如果在进行类型检查时有编译错误,你可以向开发人员报告确切的行号和所有内容。导航看起来像这样:

data = compactObjectGraph
.fold
.previous.previous.previous.previous
.data
data.line
data.column
data.size

理论上。但问题是;紧凑对象图";可能不是从简单的线性输入链创建的,而是从一组输入创建的。虽然到目前为止,我已经在纸上对此进行了建模,但我开始认为,实际上并没有一种明确的方法来映射从一个对象到另一个对象是如何转换的,使用这种";折叠";某种系统。

问题是,如果从一个数据结构到下一个数据架构有一系列复杂的转换,我如何定义数据模型以允许返回源文本的行号/列号也就是说,在高层,有什么方法可以对此进行建模,使您能够隔离转换数据结构,同时能够从上一个生成的数据结构映射到第一个,以找到一些紧凑的对象图节点在原始源文本中的实际表示方式?

我会创建一个包含文件名、行和列的数据结构。在C++中,存储对该结构的引用可能很好,而不是将其复制到许多地方。

解决这个问题的方法并不多,但拥有一个可在其他数据结构中重复使用的单一结构几乎肯定是正确的解决方案。

我7月份在Quora上回答了你的问题,所以也许你错过了:https://qr.ae/pvkrwJ

基本上,您必须用派生它们的源信息来标记所有编译器工件。最好代表某种结构(Mats的响应(。是的,这需要努力,因为你必须在编译器的任何地方都这样做。

要做一个完美的工作,你需要用完整的源项集来标记它,这些源项导致了它的生成;您本质上是在生成一个依赖关系图。(您可以将这样的集合表示为子集树,以最大限度地实现共享(。然后,编译器发出的任何投诉都可以清楚地确定原因。

要做一个不太完美的工作,您可以选择任何有贡献的项,并将其用作源位置依赖项。这意味着编译器投诉只会确定一个可能是原因的源位置,如果这不是问题的主要来源,读者将不得不猜测其他位置。明智地选择哪种原因的来源信息可以安排它,所以答案在大多数时候都是正确的,这可能已经足够好了。

最新更新