以下是OCaml解析器的示例代码:
%{ open Ast %}
%token PLUS MINUS TIMES DIVIDE EOF
%token <int> LITERAL
%left PLUS MINUS
%left TIMES DIVIDE
%start expr
%type < Ast.expr> expr
%%
expr:
expr PLUS expr { Binop($1, Add, $3) }
| expr MINUS expr { Binop($1, Sub, $3) }
| expr TIMES expr { Binop($1, Mul, $3) }
| expr DIVIDE expr { Binop($1, Div, $3) }
| LITERAL { Lit($1) }
我也有扫描程序和AST(抽象语法树)的代码。 这里$ 1和$ 3表示什么?
附录: 我想为变量赋值。 我还想将所有变量的值存储在数组中。 我怎么能这样做?
答案 0 :(得分:1)
它们引用语法规则右侧第一部分和第三部分的解析返回的值。换句话说,对于子表达式的值。在最后一种情况下,$1
指的是文字的值。
<强>更新强>
这里涉及两种语言,所以很难知道你在问什么。我猜你希望你的语言能够包含变量并为它们赋值。为此,您的扫描仪必须具有变量名称标记和分配标记。您需要扩展语法以包含赋值(可能作为具有值的运算符,如在C中)。
我还猜想你想保留一个带有变量值的 OCaml 数组。您可以使用全局变量(不纯但有效)来完成此操作。或者,您可以通过解析树向上传递一个数组,其余部分为解析状态。
哈希表或地图可能更适合表示变量名称及其值。
我想知道你的语言是否允许给定变量在多个地方给出值。
答案 1 :(得分:0)
这实际上是ocamlyacc的语法,如果你开始一个新项目你不应该使用它,在这种情况下你应该使用具有更可读语法的menhir(并且由于许多其他原因而更好)。有些人想用menhir重写OCaml编译器,但似乎还没有人完成它。
menhir语法是:
expr:
e1 = expr PLUS e2 = expr { Binop(e1, Add, e2) }
| e1 = expr MINUS e2 = expr { Binop(e1, Sub, e2) }
| e1 = expr TIMES e2 = expr { Binop(e1, Mul, e2) }
| e1 = expr DIVIDE e2 = expr { Binop(e1, Div, e2) }
| l = LITERAL { Lit(l) }