-let g_symbol_of_literal =
- function
- | `Symbol s -> symbol s
- | `Keyword s -> ident s
- | `Number s -> number s
-
-type env_type = (string * (value_type * value)) list
-
-type binding =
- | NoBinding
- | Binding of string * value_type
- | Env of (string * value_type) list
-
-let rec pp_value =
- function
-(* | TermValue (CicNotationPt.AttributedTerm (_, CicNotationPt.Num (s, _)))
- | TermValue (CicNotationPt.Num (s, _)) ->
- sprintf "@TERM[%s]@" s *)
- | TermValue _ -> "@TERM@"
- | StringValue s -> sprintf "\"%s\"" s
- | NumValue n -> n
- | OptValue (Some v) -> "Some " ^ pp_value v
- | OptValue None -> "None"
- | ListValue l -> sprintf "[%s]" (String.concat "; " (List.map pp_value l))
-
-let rec pp_value_type =
- function
- | TermType -> "Term"
- | StringType -> "String"
- | NumType -> "Number"
- | OptType t -> "Maybe " ^ pp_value_type t
- | ListType l -> "List " ^ pp_value_type l
-
-let pp_env env =
- String.concat "; "
- (List.map
- (fun (name, (ty, value)) ->
- sprintf "%s : %s = %s" name (pp_value_type ty) (pp_value value))
- env)
-
-let make_action action bindings =
- let rec aux (vl : env_type) =
- function
- [] ->
- prerr_endline "aux: make_action";
- Gramext.action (fun (loc: location) -> action vl loc)
- | NoBinding :: tl ->
- prerr_endline "aux: none";
- Gramext.action (fun _ -> aux vl tl)
- (* LUCA: DEFCON 2 BEGIN *)
- | Binding (name, TermType) :: tl ->
- prerr_endline "aux: term";
- Gramext.action
- (fun (v:term) -> aux ((name, (TermType, (TermValue v)))::vl) tl)
- | Binding (name, StringType) :: tl ->
- prerr_endline "aux: string";
- Gramext.action
- (fun (v:string) ->
- aux ((name, (StringType, (StringValue v))) :: vl) tl)
- | Binding (name, NumType) :: tl ->
- prerr_endline "aux: num";
- Gramext.action
- (fun (v:string) -> aux ((name, (NumType, (NumValue v))) :: vl) tl)
- | Binding (name, OptType t) :: tl ->
- prerr_endline "aux: opt";
- Gramext.action
- (fun (v:'a option) ->
- aux ((name, (OptType t, (OptValue v))) :: vl) tl)
- | Binding (name, ListType t) :: tl ->
- prerr_endline "aux: list";
- Gramext.action
- (fun (v:'a list) ->
- aux ((name, (ListType t, (ListValue v))) :: vl) tl)
- | Env _ :: tl ->
- prerr_endline "aux: env";
- Gramext.action (fun (v:env_type) -> aux (v @ vl) tl)
- (* LUCA: DEFCON 2 END *)
- in
- aux [] (List.rev bindings)
-
-let flatten_opt =
- let rec aux acc =
- function
- [] -> List.rev acc
- | NoBinding :: tl -> aux acc tl
- | Env names :: tl -> aux (List.rev names @ acc) tl
- | Binding (name, ty) :: tl -> aux ((name, ty) :: acc) tl
- in
- aux []
-
-let opt_binding_some (n, (ty, v)) = (n, (OptType ty, OptValue (Some v)))
-let opt_binding_none (n, (ty, v)) = (n, (OptType ty, OptValue None))
-
-let opt_binding_of_name (n, ty) = (n, (OptType ty, OptValue None))
-let list_binding_of_name (n, ty) = (n, (ListType ty, ListValue []))
-
-let opt_name (n, ty) = (n, OptType ty)
-let list_name (n, ty) = (n, ListType ty)
-
- (* given a level 1 pattern computes the new RHS of "term" grammar entry *)
-let extract_term_production pattern =
- let rec aux = function
- | Literal l -> aux_literal l
- | Layout l -> aux_layout l
- | Magic m -> aux_magic m
- | Variable v -> aux_variable v
- | _ -> assert false
- and aux_literal =
- function
- | `Symbol s -> [NoBinding, symbol s]
- | `Keyword s -> [NoBinding, ident s]
- | `Number s -> [NoBinding, number s]
- and aux_layout = function
- | Sub (p1, p2) -> aux p1 @ [NoBinding, symbol "\\SUB"] @ aux p2
- | Sup (p1, p2) -> aux p1 @ [NoBinding, symbol "\\SUP"] @ aux p2
- | Below (p1, p2) -> aux p1 @ [NoBinding, symbol "\\BELOW"] @ aux p2
- | Above (p1, p2) -> aux p1 @ [NoBinding, symbol "\\ABOVE"] @ aux p2
- | Frac (p1, p2) -> aux p1 @ [NoBinding, symbol "\\FRAC"] @ aux p2
- | Atop (p1, p2) -> aux p1 @ [NoBinding, symbol "\\ATOP"] @ aux p2
- | Over (p1, p2) -> aux p1 @ [NoBinding, symbol "\\OVER"] @ aux p2
- | Root (p1, p2) ->
- [NoBinding, symbol "\\ROOT"] @ aux p2 @ [NoBinding, symbol "\\OF"]
- @ aux p1
- | Sqrt p -> [NoBinding, symbol "\\SQRT"] @ aux p
- | Break -> []
- | Box (_, pl) -> List.flatten (List.map aux pl)
- and aux_magic magic =
- match magic with
- | Opt p ->
- let p_bindings, p_atoms, p_names, p_action = inner_pattern p in
- let action (env_opt : env_type option) (loc : location) =
- match env_opt with
- | Some env -> List.map opt_binding_some env
- | None -> List.map opt_binding_of_name p_names
- in
- [ Env (List.map opt_name p_names),
- Gramext.srules
- [ [ Gramext.Sopt (Gramext.srules [ p_atoms, p_action ]) ],
- Gramext.action action ] ]
- | List0 (p, _)
- | List1 (p, _) ->
- let p_bindings, p_atoms, p_names, p_action = inner_pattern p in
- let env0 = List.map list_binding_of_name p_names in
- let grow_env_entry env n v =
- prerr_endline "grow_env_entry";
- List.map
- (function
- | (n', (ty, ListValue vl)) as entry ->
- if n' = n then n', (ty, ListValue (v :: vl)) else entry
- | _ -> assert false)
- env
- in
- let grow_env env_i env =
- prerr_endline "grow_env";
- List.fold_left
- (fun env (n, (_, v)) -> grow_env_entry env n v)
- env env_i
- in
- let action (env_list : env_type list) (loc : location) =
- prerr_endline "list action";
- List.fold_right grow_env env_list env0
- in
- let g_symbol s =
- match magic with
- | List0 (_, None) -> Gramext.Slist0 s
- | List1 (_, None) -> Gramext.Slist1 s
- | List0 (_, Some l) -> Gramext.Slist0sep (s, g_symbol_of_literal l)
- | List1 (_, Some l) -> Gramext.Slist1sep (s, g_symbol_of_literal l)
- | _ -> assert false
- in
- [ Env (List.map list_name p_names),
- Gramext.srules
- [ [ g_symbol (Gramext.srules [ p_atoms, p_action ]) ],
- Gramext.action action ] ]
- | _ -> assert false
- and aux_variable =
- function
- | NumVar s -> [Binding (s, NumType), number ""]
- | TermVar s -> [Binding (s, TermType), term]
- | IdentVar s -> [Binding (s, StringType), ident ""]
- | Ascription (p, s) -> assert false (* TODO *)
- | FreshVar _ -> assert false
- and inner_pattern p =
- let p_bindings, p_atoms = List.split (aux p) in
- let p_names = flatten_opt p_bindings in
- let _ = prerr_endline ("inner names: " ^ String.concat " " (List.map fst p_names)) in
- let action =
- make_action (fun (env : env_type) (loc : location) -> prerr_endline "inner action"; env) p_bindings
- in
- p_bindings, p_atoms, p_names, action
- in
- aux pattern
-
-let level_of_int precedence =
- (* TODO "mod" test to be removed as soon as we add all 100 levels *)
- if precedence mod 10 <> 0 || precedence < 0 || precedence > 100 then
- raise (Level_not_found precedence);
- string_of_int precedence
-
-type rule_id = Token.t Gramext.g_symbol list
-
-let extend level1_pattern ?(precedence = 0) ?associativity action =
- let p_bindings, p_atoms =
- List.split (extract_term_production level1_pattern)
- in
- let level = level_of_int precedence in
- let p_names = flatten_opt p_bindings in
- let entry = Grammar.Entry.obj (l2_pattern: 'a Grammar.Entry.e) in
- let _ =
- prerr_endline (string_of_int (List.length p_bindings));
- Grammar.extend
- [ entry, Some (Gramext.Level level),
- [ Some level, (* TODO should we put None here? *)
- associativity,
- [ p_atoms,
- (make_action
- (fun (env: env_type) (loc: location) -> (action env loc))
- p_bindings) ]]]
- in
- p_atoms