我刚刚开始学习SML,我对以下代码感到困惑:
type pos = int
datatype prog= Prog of statement option
and statement =... some code..
and expression =
VarExp of symbol * pos
| IntExp of int * pos
| BoolExp of bool * pos
| BopExp of exp * oper * exp * pos
| UopExp of oper * exp * pos
我无法理解的是使用pos
。签名不应该是BopExp of exp * oper * exp
而不是BopExp of exp * oper * exp * pos
吗?
答案 0 :(得分:1)
由于John,molbdnilo和Tai已经在评论中回答你说 pos 可能是某种位置,这表明句法元素的文本表示位于 pos 文件中的第一个字符,这里有更多的想法:
语法树可能会注释各种信息。解析器通常保留错误报告的位置。静态类型检查器也是如此,但它也可能保留可以传递给自身的推断类型信息或后续的代码生成阶段。
您可以做的是参数化语法树:
datatype 'a prog = Prog of 'a stmt list
and 'a stmt = AssignStmt of symbol * 'a exp * 'a
| PrintStmt of 'a exp * 'a
and 'a exp = VarExp of symbol * 'a
| IntExp of int * 'a
| BoolExp of bool * 'a
| BopExp of 'a exp * oper * 'a exp * 'a
| UopExp of oper * 'a exp * 'a
然后像 x:= 2 + true; 这样的程序可能首先被解析并注释为 pos prog :
type pos = int
val hello = Prog [AssignStmt ("x", BopExp (IntExp (2, 6), "+",
BoolExp (true, 10),
6),
0)
]
表示赋值位于0位置,表达式 2 + true 位于第6位,整数 2 位于第6位,布尔值<位置10处的em> true 。当您进行类型检查时,您可能需要(pos×typ)prog :
type typ = Int | Bool | None | Conflict of typ list * typ
val hello = Prog [AssignStmt ("x", BopExp (IntExp (2, (6, Int)), "+",
BoolExp (true, (10, Bool)),
(6, Conflict ([Int, Bool], Int)),
(0, None)
]
保留了体面错误报告的位置信息(如果存在类型错误,仍然需要),但也保留有关冲突类型的位置的信息,例如: Conflict ([Int, Bool], Int)
旨在表明,当期望 Int
时,由于类型Int
和Bool
存在冲突,因此无法导出 {/ 1}}。
然后你只需要一个位置,类型,寄存器的语法树定义,无论你用什么方法来注释你的句法元素。