2014-09-05 91 views
4

在编写解析器时,我想记住发现词位的位置,以便我可以向程序员报告有用的错误消息,如“第23行的if-less else”或“意外第45行字符,字符6“或”变量未定义“或类似内容。但是,一旦我构建了语法树,我将通过几种方式对其进行转换,优化或扩展某种宏。这些转换会产生或重新排列没有有意义位置的词位。语法树中的位置

因此,表示语法树的类型似乎应该具有两种风格,即具有装饰词位的位置和没有词位的味道的味道。理想情况下,我们愿与纯粹抽象语法树的工作,如在规定的OCaml book

# type unr_op = UMINUS | NOT ;; 
# type bin_op = PLUS | MINUS | MULT | DIV | MOD 
      | EQUAL | LESS | LESSEQ | GREAT | GREATEQ | DIFF 
      | AND | OR ;; 
# type expression = 
    ExpInt of int 
    | ExpVar of string 
    | ExpStr of string 
    | ExpUnr of unr_op * expression 
    | ExpBin of expression * bin_op * expression ;; 
# type command = 
    Rem of string 
    | Goto of int 
    | Print of expression 
    | Input of string 
    | If of expression * int 
    | Let of string * expression ;; 
# type line = { num : int ; cmd : command } ;; 
# type program = line list ;; 

我们应该被允许在该树工作时,和具有特殊功能的映射一个expression回给完全忘记地点它的位置(例如),我们可以在紧急情况下使用。

在OCaml中定义这种类型或处理词位位置的最佳方法是什么?

+0

这个问题对我来说不是很清楚,但是OCaml编译器的解析/和输入/的源代码是一个完整的具有位置+转换的AST的详细示例。 – camlspotter 2014-09-06 03:07:38

+0

用一个额外的插槽* position *定义您的树节点。约定:当位置不为零时,它提供精确的位置信息;当零时,“没有位置”。 – 2014-09-06 07:21:39

+0

@camlspotter我在问题中添加了一些细节。 – 2014-09-11 21:03:53

回答

1

最好的方法是始终使用完全注释位置的AST节点。例如:

type expression = { 
    expr_desc : expr_desc; 
    expr_loc : Lexing.position * Lexing.position; (* start and end *) 
} 

and expr_desc = 
    ExpInt of int 
    | ExpVar of string 
    | ExpStr of string 
    | ExpUnr of unr_op * expression 
    | ExpBin of expression * bin_op * expression 

你的点子,保持AST自由的位置,写一个函数来获取丢失的位置是不是一个好主意,我相信。这样的功能应该需要通过AST节点的指针等价或类似的搜索来进行搜索,这并不真正缩放。

我强烈建议查看OCaml编译器的parser.mly,这是AST位置的完整示例。