在格式化程序中存储位置的常用方法

时间:2016-06-02 00:48:29

标签: frontend lex code-formatting pretty-print ocamllex

我想为特定语言编写一个小编辑器。在编辑器中,我们将能够indent一行或几行(即在每行的左侧添加空格);我们还可以format整个代码(即,改变适当位置的空格和换行符)。

鉴于某个程序,ocamllexocamlyacc的前端可以构建Abstract Syntax Tree (AST)。我想知道在AST中存储元素位置的常用方法是什么。

我猜测的一种方法是将(开始)position附加到AST的每个元素。例如,如果表达式的类型定义如下:

type expression =
  ...
  | E_int of int
  | E_function_EEs of Function.t * (expression list)

它将成为:

type expression =
  ...
  | E_int of position * int
  | E_function_EEs of position * Function.t * (expression list)

然后,如果我们知道每个元素的长度,我们就可以在编辑器中推断出所有元素的位置。这是一种常见的方式吗?我觉得不太好......

1 个答案:

答案 0 :(得分:0)

您不必为每种模式重复position。你最后可以写一个:

type expression = 
  ...
  | E_int of int
  | E_function_EEs of Function.t * (expression list)
  | E_loc of position * expression

因此,对于expression以上的现有功能,您只需为E_loc添加一个案例,而无需触及现有案例。

要在解析时自动构建E_loc,您可以添加.mly例如:

loc(EXPRESSION):
| t = EXPRESSION { E_loc (($startpos, $endpos), t) }

(* immediate construction: *)
expression:
| INT { E_loc (($startpos, $endpos), E_int $1) }

(* or delay construction: *)
expression:
| e0 = loc(expression) PLUS e1 = loc(expression) { E_function_EEs (Function.PLUS, [e0; e1]) }