package ast_generic

  1. Overview
  2. Docs

Source file Raw_tree.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
(*
   Utilities for working with AST_generic.raw_tree
*)

(* Provide hash_* and hash_fold_* for the core ocaml types *)
open Ppx_hash_lib.Std.Hash.Builtin

type 'any t =
  (* Tok.t = Parse_info.t with special equal and hash functions *)
  | Token of (string * Tok.t)
  | List of 'any t list
  | Tuple of 'any t list
  | Case of string * 'any t
  | Option of 'any t option
  | Any of 'any
[@@deriving show { with_path = false }, eq, hash]

(* Find the left-most token in the tree *)
let rec first_tok (x : _ t) =
  match x with
  | Token (_str, tok) -> Some tok
  | List xs -> first_tok_in_list xs
  | Tuple xs -> first_tok_in_list xs
  | Case (_cons, x) -> first_tok x
  | Option opt -> (
      match opt with
      | None -> None
      | Some x -> first_tok x)
  | Any _ ->
      (* We could continue the search in the generic AST but that would
         be a big endeavor. *)
      None

and first_tok_in_list xs =
  match xs with
  | x :: xs -> (
      match first_tok x with
      | None -> first_tok_in_list xs
      | Some _ as res -> res)
  | [] -> None

(* Find the right-most token in the tree *)
let rec last_tok (x : _ t) =
  match x with
  | Token (_str, tok) -> Some tok
  | List xs -> last_tok_in_list xs
  | Tuple xs -> last_tok_in_list xs
  | Case (_cons, x) -> last_tok x
  | Option opt -> (
      match opt with
      | None -> None
      | Some x -> last_tok x)
  | Any _ -> None

and last_tok_in_list xs =
  match xs with
  | [] -> None
  | x :: xs -> (
      match last_tok_in_list xs with
      | None -> last_tok x
      | Some _ as res -> res)

let loc x =
  match (first_tok x, last_tok x) with
  | None, None -> None
  | Some first, Some last -> Some (first, last)
  | None, Some _
  | Some _, None ->
      assert false

let unsafe_loc x =
  match loc x with
  | Some res -> res
  | None ->
      let tok = Parse_info.unsafe_fake_info "" in
      (tok, tok)

let anys x =
  let rec anys acc (x : _ t) =
    match x with
    | Token _tok -> acc
    | List xs -> List.fold_left anys acc xs
    | Tuple xs -> List.fold_left anys acc xs
    | Case (_cons, x) -> anys acc x
    | Option opt -> (
        match opt with
        | None -> acc
        | Some x -> anys acc x)
    | Any any -> any :: acc
  in
  anys [] x |> List.rev

let map ~map_any x =
  let rec map x =
    match x with
    | Token tok -> Token tok
    | List xs -> List (Common.map map xs)
    | Tuple xs -> List (Common.map map xs)
    | Case (cons, x) -> Case (cons, map x)
    | Option opt ->
        Option
          (match opt with
          | None -> None
          | Some x -> Some (map x))
    | Any any -> Any (map_any any)
  in
  map x

let visit ~v_token ~v_any x =
  let rec iter x =
    match x with
    | Token tok -> v_token tok
    | List xs -> List.iter iter xs
    | Tuple xs -> List.iter iter xs
    | Case (_cons, x) -> iter x
    | Option opt -> (
        match opt with
        | None -> ()
        | Some x -> iter x)
    | Any any -> v_any any
  in
  iter x