This commit is contained in:
atagen 2026-03-18 15:40:47 +11:00
commit ab009ec9af
14 changed files with 386 additions and 0 deletions

0
lib/.ocamlformat Normal file
View file

3
lib/dune Normal file
View file

@ -0,0 +1,3 @@
(library
(name inshellah_parser)
(libraries angstrom angstrom-unix))

77
lib/parser.ml Normal file
View file

@ -0,0 +1,77 @@
(* open Angstrom_unix *)
(* also look for "subcommands" for clapslop *)
(* and other common help patterns *)
open Angstrom
let ( <| ) = ( @@ )
let ( <&> ) p1 p2 = lift2 (fun a b -> (a, b)) p1 p2
let is_whitespace = function ' ' | '\t' | '\n' | '\r' -> true | _ -> false
let is_alphanumeric = function
| 'A' .. 'Z' | 'a' .. 'z' | '0' .. '9' -> true
| _ -> false
let is_long_char = function
| 'A' .. 'Z' | 'a' .. 'z' | '0' .. '9' | '-' -> true
| _ -> false
type switch = Short of char | Long of string | Both of char * string
type param = Mandatory of string | Optional of string
type entry = { switch : switch; param : param option; desc : string }
let whitespace = skip_while is_whitespace
let comma = char ',' *> whitespace
let short_switch = char '-' *> satisfy is_alphanumeric
let long_switch = string "--" *> take_while1 is_long_char
let opt_param =
print_endline "opt param is running";
string "[=" *> take_while is_alphanumeric <* char ']' >>| fun a -> Optional a
let man_param =
print_endline "man param is running";
char '=' *> take_while is_alphanumeric >>| fun a -> Mandatory a
let param_parser =
option None (choice [ opt_param; man_param ] >>| fun a -> Some a)
let switch_parser =
choice
[
(* -a, --all *)
( short_switch >>= fun s ->
comma *> long_switch >>| fun l -> Both (s, l) );
(* -a *)
(short_switch >>| fun s -> Short s);
(* --all *)
(long_switch >>| fun l -> Long l);
]
let description = whitespace *> take_till (fun c -> c = '\n') <* end_of_line
let entry =
skip_while (fun c -> c <> '-')
*> lift3 (fun a b c -> (a, b, c)) switch_parser param_parser description
>>| fun (switch, param, desc) -> { switch; param; desc }
let endline = option () (char '\n' *> return ())
let entry_line = entry <* endline
let help_parser = many entry_line
let parse_help txt =
Angstrom.parse_string ~consume:Consume.Prefix help_parser txt
let print_switch = function
| Short o -> Printf.sprintf "Short: %c" o
| Long o -> Printf.sprintf "Long: %s" o
| Both (s, l) -> Printf.sprintf "Both, short: %c long: %s" s l
let print_opt = function
| Some (Mandatory o) -> Printf.sprintf "Mandatory: %s" o
| Some (Optional o) -> Printf.sprintf "Optional: %s" o
| None -> "None"
let print_entry e =
Printf.printf
"\n\t** ENTRY **\n\tSwitch: %s\n\tParam: %s\n\tDescription: %s\n"
(print_switch e.switch) (print_opt e.param) e.desc