有人可以给我一些帮助,使用语法为语言构建一个ocaml解释器:
Prog ::= Def* Expr
Def ::= id id* = Expr
Expr ::= int | id | Expr '+' Expr | Expr '*' Expr | id Expr* | if Expr then Expr else Expr
到目前为止,我做到了这一点:
type expr = I of int
| Id of string
| Add of expr * expr
| Multiply of expr * expr
| If of expr * expr * expr
let rec evaluate = function
| I n -> n
| Add(e1,e2) -> evaluate e1 + evaluate e2
| Multiply(e1,e2) -> evaluate e1 * evaluate e2
| If(a,b,c) -> if evaluate a<>0 then evaluate b else evaluate c
这有什么用吗?
答案 0 :(得分:6)
在您的语法中,单个ID可以与作品Expr ::= id
或Expr ::= id Expr*
匹配。换句话说,没有办法区分一个nullary函数应用程序(假设id Expr*
生成应该与函数应用程序匹配)和变量。也许你的意思是id Expr+
(禁止使用nullary函数应用程序)。
您现有的代码看起来很好,但它不完整:
您的expr
类型缺少id Expr*
语法生成的构造函数,即您缺少表示函数应用程序的构造函数。您应该添加一个,然后将其添加到evaluate
函数中。
在evaluate
函数中,您错过了Id
构造函数的大小写。这种情况应该在从标识符到值(int)的映射中查找给定标识符的值。为此,您的evaluate
函数应该将此映射作为附加参数。它还应该从标识符到函数的另一个映射,然后您可以使用它来为函数应用程序循环函数名称。
说到这些映射,您目前没有任何代码来表示或处理定义。您应该提出一个表示定义的类型和另一个表示函数的类型。后一种类型应包含函数参数的名称,而正文应包含expr
。
然后你应该编写一个函数,它接受一个定义列表并创建变量和函数的映射。对于每个变量定义,它应评估右侧的表达式并将结果值添加到变量映射中。对于每个函数定义,您应该将函数类型的值添加到函数映射中。在处理定义之后,您应该通过调用带有该表达式的evaluate
函数和您创建的两个映射作为参数来评估最终表达式。
最后你没有任何实际解析程序的代码,但我认为这可能是故意的。