#light
type range = int * int
type input = string * int
type token =
| Char of char
| Identifier of string
| Node of string * token list
| Digit of token list
type rule = input -> (input * token list) option
let (||) r1 r2 a = match r1 a with
| None -> r2 a
| Some b -> Some b
let after res = function
| None -> None
| Some (a, res') -> Some (a, res' @ res)
let (&&) r1 r2 a = match r1 a with
| None -> None
| Some (a', res) -> after res (r2 a')
let char c (str:string, pos) =
try
if str.[pos] = c then Some ((str, pos + 1), [Char c]) else None
with _ -> None
let rec loop rule a = (rule && loop rule || rule) a
let nnode c rule a = match rule a with
| None -> None
| Some (a', res) -> Some (a', [c (res)])
let bin =
let digit = char '0' || char '1' in
nnode (function x -> Digit x) (loop digit)