微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

具有循环函数依赖性的递归匹配函数

如何解决具有循环函数依赖性的递归匹配函数

我不确定标题是否解释了我的问题,但我可以在我想解释我的问题之后改进它,因为有几天我都在为这个问题而心烦意乱。

我正在使用 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 liststmtordec 并且有 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 举报,一经查实,本站将立刻删除。