Parsing 何时使用;及;Ocaml-AST中的运算符

Parsing 何时使用;及;Ocaml-AST中的运算符,parsing,ocaml,abstract-syntax-tree,Parsing,Ocaml,Abstract Syntax Tree,我正在把我的语法规则翻译成AST 在定义AST时是否需要使用“and”运算符 例如,到目前为止,我已将我的语法翻译为: type program = | Decls of typ * identifier * decls_prime type typ = | INT | BOOL | VOID type identifier = string (* decls_prime = vdecl decls | fdecl decls *) type declsprime

我正在把我的语法规则翻译成AST

在定义AST时是否需要使用“and”运算符

例如,到目前为止,我已将我的语法翻译为:

type program =
   |  Decls of typ * identifier * decls_prime

type typ =
   | INT
   | BOOL
   | VOID

type identifier = string

(* decls_prime = vdecl decls | fdecl decls *)
type declsprime =
   | Vdecl of variabledeclaration * decls
   | Fdecl of functiondeclaration * decls

(*“lparen” formals_opt “rparen” “LBRACE” vdecl_list stmt_list “RBRACE”*)
type functiondeclaration =
    | Fdecl of variabledeclarationlist * stmtlist

(*formals_opt = formal_list | epsilon *)
type FormalsOpt =
   |FormalsOpt of formallist

(* typ “ID” formal_list_prime *)
type formalList =
    | FormalList of typ * identifier * formallistprime

type formallistprime =
    | FormalListPrime of formalList

type variabledeclarationlist =
    | VdeclList of variabledeclaration * variabledeclarationlist

(*stmt stmt_list | epsilon*)
type stmtlist =
    | StmtList of stmt * stmtlist
    | StmtlistNil 

(* stmt = “RETURN” stmt_prime| expr SEMI |“LBRACE” stmt_list RBRACE| IF LPAREN expr RPAREN stmt stmt_prime_prime| FOR LPAREN expr_opt SEMI expr SEMI expr_opt RPAREN stmt| WHILE LPAREN expr RPAREN stmt*)
type Stmt
| Return of stmtprime
| Expression of expr
| StmtList of stmtlist
| IF of expr * stmt * stmtprimeprime
| FOR of expropt * expr * expropt * stmt 
| WHILE of expr * stmt

(*stmt_prime = SEMI| expr SEMI*)
type stmtprime
| SEMI 
| Expression of expr 

(*NOELSE | ELSE stmt*)
type stmtprimeprime
| NOELSE 
| ELSE of stmt

(* Expr_opt = expr | epsilon *)
type expropt =
| Expression of expr 
| ExprNil 

type Expr

type ExprPrime

(* Actuals_opt  = actuals_list  | epsilon *)
type ActualsOpt= 
| ActualsList of actualslist 
| ActualsNil

type ActualsList = 
| ActualsList of expr * actualslistprime

(*actualslistprime = COMMA expr actuals_list_prime | epsilon*)
type actualslistprime = 
| ActualsListPrime of expr * actualslistprime
| ALPNil
但这个来自伊利诺伊州的例子似乎使用了一个稍微不同的结构:

type program = Program of (class_decl list)
and class_decl = Class of id * id * (var_decl list) * (method_decl list)
and method_decl = Method....

定义AST时是否需要使用“和”?而且,即使我在解析器中正确调用了AST StmtList方法,但我使用StmtList类型而不是(stmt list)是否错误?

当定义是相互递归的时,您只需要
。也就是说,如果语句可以包含表达式,而表达式又可以包含语句,则
Expr
Stmt
必须与
连接。如果您的代码编译时没有
,则不需要


PS:这与您的问题无关,但我认为使用
列表
选项
类型比为特定类型定义自己的版本(例如
stmntlist
expropt
等)更有意义
stmtprime
是另一种情况:您可以将
Return
定义为
returnofexpr选项
,并去掉
stmtprime
类型。与
stmtprime
相同,当定义是相互递归的时,只需要
。也就是说,如果语句可以包含表达式,而表达式又可以包含语句,则
Expr
Stmt
必须与
连接。如果您的代码编译时没有
,则不需要


PS:这与您的问题无关,但我认为使用
列表
选项
类型比为特定类型定义自己的版本(例如
stmntlist
expropt
等)更有意义
stmtprime
是另一种情况:您可以将
Return
定义为
returnofexpr选项
,并去掉
stmtprime
类型。与
StmtPrime

相同,我必须手工编写解析器(没有解析器生成器),这就是我创建StmtPrime等AST类型的原因。我如何定义选项?非常新的OCaml@Matt我不明白为什么手工编写解析器会影响AST的外观。“如何定义选项?”
option
是标准库中的一种类型-您不需要定义它。您可以只编写
返回stmt选项
而不是
返回stmttime
,就这样。但是stmtprime不需要建立吗?因为StmtPrime=Semi | Expressionso从技术上讲,它不是可选的吗?@Matt我不明白你的意思
stmtprime
是您定义的一种类型,可以包含表达式,也可以不包含任何内容
expr选项
也是一种类型,可以包含表达式,也可以不包含任何内容。因此,这两种类型是完全可互换的,
stmtprime
类型是不必要的。分号是否可选是解析器的属性,而不是AST的属性。您碰巧命名了无表达式构造函数
SEMI
,这一事实并不影响解析器是否需要分号。我必须手动编写解析器(无解析器生成器),这就是我创建StmtPrime等AST类型的原因。我如何定义选项?非常新的OCaml@Matt我不明白为什么手工编写解析器会影响AST的外观。“如何定义选项?”
option
是标准库中的一种类型-您不需要定义它。您可以只编写
返回stmt选项
而不是
返回stmttime
,就这样。但是stmtprime不需要建立吗?因为StmtPrime=Semi | Expressionso从技术上讲,它不是可选的吗?@Matt我不明白你的意思
stmtprime
是您定义的一种类型,可以包含表达式,也可以不包含任何内容
expr选项
也是一种类型,可以包含表达式,也可以不包含任何内容。因此,这两种类型是完全可互换的,
stmtprime
类型是不必要的。分号是否可选是解析器的属性,而不是AST的属性。您碰巧命名了无表达式构造函数
SEMI
,这一事实并不影响解析器是否需要分号。