如何解决具有循环函数依赖性的递归匹配函数
我不确定标题是否解释了我的问题,但我可以在我想解释我的问题之后改进它,因为有几天我都在为这个问题而心烦意乱。
我正在使用 Ocaml 为我的课程开发静态分析,以检查我的 c(C 语言的子集)程序是否具有真实意义,而且我对这些东西(语言和范式以及编译器)很陌生东西)。
静态分析正在遍历抽象语法树 (Ast) 并对其进行一些检查(检查是 Todo 注释的问题),目前我正在开发数据结构,特别是符号表,并且实现代码以遍历 Ast。
我完整的 Ast。
type binop = Add | Sub | Mult | Div | Mod | Equal | Neq | Less | Leq |
Greater | Geq | And | Or | Comma
[@@deriving show]
type uop = Neg | Not [@@deriving show]
type identifier = string [@@deriving show]
type position = Lexing.position * Lexing.position
let dummy_pos = (Lexing.dummy_pos,Lexing.dummy_pos)
type 'a annotated_node = {loc : position[@opaque]; node : 'a}[@@deriving show]
type typ =
| TypInt (* Type int *)
| TypBool (* Type bool *)
| TypChar (* Type char *)
| TypArray of typ * int option (* Array type *)
| TypPoint of typ (* Pointer type *)
| TypVoid (* Type void *)
[@@deriving show]
and expr = expr_node annotated_node
and expr_node =
| Access of access (* x or *p or a[e] *)
| Assign of access * expr (* x=e or *p=e or a[e]=e *)
| Addr of access (* &x or &*p or &a[e] *)
| ILiteral of int (* Integer literal *)
| CLiteral of char (* Char literal *)
| BLiteral of bool (* Bool literal *)
| UnaryOp of uop * expr (* Unary primitive operator *)
| BinaryOp of binop * expr * expr (* Binary primitive operator *)
| Call of identifier * expr list (* Function call f(...) *)
[@@deriving show]
and access = access_node annotated_node
and access_node =
| AccVar of identifier (* Variable access x *)
| AccDeref of expr (* Pointer dereferencing *p *)
| AccIndex of access * expr (* Array indexing a[e] *)
[@@deriving show]
and stmt = stmt_node annotated_node
and stmt_node =
| If of expr * stmt * stmt (* Conditional *)
| While of expr * stmt (* While loop *)
| For of expr option * expr option * expr option * stmt (* For loop *)
| Expr of expr (* Expression statement e; *)
| Return of expr option (* Return statement *)
| Block of stmtordec list (* Block: grouping and scope *)
[@@deriving show]
and stmtordec = stmtordec_node annotated_node
and stmtordec_node =
| Dec of typ * identifier (* Local variable declaration *)
| Stmt of stmt (* A statement *)
[@@deriving show]
type fun_decl = {
typ : typ;
fname : string;
formals : (tyP*identifier) list;
body : stmt;
}[@@deriving show]
type topdecl = topdecl_node annotated_node
and topdecl_node =
| Fundecl of fun_decl
| Vardec of typ * identifier
[@@deriving show]
type program = Prog of topdecl list [@@deriving show]
我的问题是如何遍历 stmt
因为里面包含 Block of stmtordec list
和 stmtordec
并且有 stmt
,在这种情况下,我处于循环状态我无法使用匹配功能解决的依赖性。
我遍历它的想法是有一个 OCaml 函数 check_stm
-> check_blk
-> check_stm
,但是我如何用代码解决这个想法?
目前我的代码是,但不要编译,因为我无法同时将函数放入 OCaml 范围。
我的代码是那个
open Ast
open Symbol_table
open Easy_logging
let logger = Logging.make_logger "Semant" Debug [Cli Debug]
(* Global Scope: This scope contains all the Global declaration
Global declaration types:
- Int,Bool,Char,Array.
- Struct
- function declaration
*)
let global_scope = empty_table
let check_blk blkstm =
match blkstm.node with
| Ast.Dec(tipe,id) ->
begin
logger#debug "Variable declaration check";
(* Todo: I'm missing the variable duplication *)
Symbol_table.add_entry id tipe global_scope
end
| Ast.Stmt(stm) ->
begin
logger#debug "Stm check (recursive call)";
check_stm stm
end
let check_stm node =
match node with
| Ast.If(ex,ifs,els) -> logger#debug "Todo: If stm check"
| Ast.While(ex,stm) -> logger#debug "Todo: While stm check"
| Ast.For(ex1,ex2,ex3,stm) -> logger#debug "Todo: For stm check"
| Ast.Expr(ex) -> logger#debug "Todo: Expression check"
| Ast.Return(optex) -> logger#debug "Todo: Return stm check"
| Ast.Block(blkstm) -> List.iter check_blk blkstm
let check_fundec node =
match node with
| fun_decl as f ->
begin
logger#debug "Checking function declaration";
(* Todo: how I can managed the parameter of the function?*)
global_scope = Symbol_table.begin_block global_scope;
check_stm f.body.node
end
let rec match_type ast_elem =
match ast_elem.node with
| Vardec(tipe,id) ->
begin
logger#debug "Global variable found";
add_entry id tipe global_scope;
()
end
| Fundecl(fundec) ->
begin
logger#debug "Function analysis found";
Symbol_table.add_entry fundec.fname fundec.typ global_scope;
check_fundec fundec;
end
let check (Ast.Prog(topdecls)) = List.iter match_type topdecls
也许这个问题很愚蠢,也许我的想法有问题,但我想谈谈问题以解决它并学习如何使用OCaml语言
ps:目前 Symbol_table
实现是一个空实现
解决方法
如果我正确理解您的问题,您只需要明确指定相互递归的函数。您可以使用 and
关键字,就像类型定义一样,但也必须使用 rec
关键字,因为函数定义在默认情况下不是递归的,与类型定义不同:
let rec check_blk blkstm = ...
and check_stm node = ...
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。