(* Generated by re2ocaml *)
(* re2ocaml $INPUT -o $OUTPUT -i *)

open String

type state = {
    yyinput: string;
    mutable yycursor: int;
    mutable yymarker: int;
    yylimit: int;
    yyend: int;
}

exception Fill




let rec yy0 (yyrecord : state) : int =
    if (yyrecord.yylimit <= yyrecord.yycursor) then (
        (yy8 [@tailcall]) yyrecord
    ) else (
        let yych = unsafe_get yyrecord.yyinput yyrecord.yycursor in
        yyrecord.yycursor <- yyrecord.yycursor + 1;
        match yych with
            | 'a' -> (yy3 [@tailcall]) yyrecord
            | 'b' -> (yy4 [@tailcall]) yyrecord
            | 'c' -> (yy5 [@tailcall]) yyrecord
            | _ -> (yy1 [@tailcall]) yyrecord
    )

and yy1 (yyrecord : state) : int =
    (yy2 [@tailcall]) yyrecord

and yy2 (yyrecord : state) : int =
    1

and yy3 (yyrecord : state) : int =
    if (yyrecord.yylimit <= yyrecord.yycursor) then (yy9 [@tailcall]) yyrecord
    else 3

and yy4 (yyrecord : state) : int =
    4

and yy5 (yyrecord : state) : int =
    yyrecord.yymarker <- yyrecord.yycursor;
    if (yyrecord.yylimit <= yyrecord.yycursor) then (
        (yy10 [@tailcall]) yyrecord
    ) else (
        let yych = unsafe_get yyrecord.yyinput yyrecord.yycursor in
        match yych with
            | 'c' ->
                yyrecord.yycursor <- yyrecord.yycursor + 1;
                (yy6 [@tailcall]) yyrecord
            | _ -> (yy2 [@tailcall]) yyrecord
    )

and yy6 (yyrecord : state) : int =
    if (yyrecord.yylimit <= yyrecord.yycursor) then (
        (yy10 [@tailcall]) yyrecord
    ) else (
        let yych = unsafe_get yyrecord.yyinput yyrecord.yycursor in
        match yych with
            | 'c' ->
                yyrecord.yycursor <- yyrecord.yycursor + 1;
                (yy6 [@tailcall]) yyrecord
            | _ -> (yy7 [@tailcall]) yyrecord
    )

and yy7 (yyrecord : state) : int =
    yyrecord.yycursor <- yyrecord.yymarker;
    (yy2 [@tailcall]) yyrecord

and yy8 (yyrecord : state) : int =
    0

and yy9 (yyrecord : state) : int =
    2

and yy10 (yyrecord : state) : int =
    5

and lex_simple (yyrecord : state) : int =
    (yy0 [@tailcall]) yyrecord



let test_simple str ret =
    let st = {yyinput = str; yycursor = 0; yymarker = 0; yylimit = length str - 1; yyend = -1} in
    let result = try lex_simple st with Fill -> -1 in
    if not (result = ret) then raise (Failure "error simple")


let rec yy11 (yyrecord : state) : int =
    let yych = unsafe_get yyrecord.yyinput yyrecord.yycursor in
    match yych with
        | 'a' ->
            yyrecord.yycursor <- yyrecord.yycursor + 1;
            (yy14 [@tailcall]) yyrecord
        | 'b' ->
            yyrecord.yycursor <- yyrecord.yycursor + 1;
            (yy15 [@tailcall]) yyrecord
        | 'c' ->
            yyrecord.yycursor <- yyrecord.yycursor + 1;
            (yy16 [@tailcall]) yyrecord
        | _ ->
            if (yyrecord.yylimit <= yyrecord.yycursor) then (
                if (false) then (yy11 [@tailcall]) yyrecord
                else (yy19 [@tailcall]) yyrecord
            ) else (
                yyrecord.yycursor <- yyrecord.yycursor + 1;
                (yy12 [@tailcall]) yyrecord
            )

and yy12 (yyrecord : state) : int =
    (yy13 [@tailcall]) yyrecord

and yy13 (yyrecord : state) : int =
    1

and yy14 (yyrecord : state) : int =
    if (yyrecord.yycursor == yyrecord.yylimit) then (yy20 [@tailcall]) yyrecord
    else 3

and yy15 (yyrecord : state) : int =
    4

and yy16 (yyrecord : state) : int =
    yyrecord.yymarker <- yyrecord.yycursor;
    let yych = unsafe_get yyrecord.yyinput yyrecord.yycursor in
    match yych with
        | 'c' ->
            yyrecord.yycursor <- yyrecord.yycursor + 1;
            (yy17 [@tailcall]) yyrecord
        | _ ->
            if (yyrecord.yylimit <= yyrecord.yycursor) then (
                if (false) then (yy16 [@tailcall]) yyrecord
                else (yy21 [@tailcall]) yyrecord
            ) else (
                (yy13 [@tailcall]) yyrecord
            )

and yy17 (yyrecord : state) : int =
    let yych = unsafe_get yyrecord.yyinput yyrecord.yycursor in
    match yych with
        | 'c' ->
            yyrecord.yycursor <- yyrecord.yycursor + 1;
            (yy17 [@tailcall]) yyrecord
        | _ ->
            if (yyrecord.yylimit <= yyrecord.yycursor) then (
                if (false) then (yy17 [@tailcall]) yyrecord
                else (yy21 [@tailcall]) yyrecord
            ) else (
                (yy18 [@tailcall]) yyrecord
            )

and yy18 (yyrecord : state) : int =
    yyrecord.yycursor <- yyrecord.yymarker;
    (yy13 [@tailcall]) yyrecord

and yy19 (yyrecord : state) : int =
    0

and yy20 (yyrecord : state) : int =
    2

and yy21 (yyrecord : state) : int =
    5

and lex_eof (yyrecord : state) : int =
    (yy11 [@tailcall]) yyrecord



let test_eof str ret =
    let st = {yyinput = str; yycursor = 0; yymarker = 0; yylimit = length str - 1; yyend = -1} in
    let result = try lex_eof st with Fill -> -1 in
    if not (result = ret) then raise (Failure "error eof")

let yymaxfill = 2



let rec yy22 (yyrecord : state) : int =
    if (yyrecord.yycursor == yyrecord.yyend) then (
        (yy30 [@tailcall]) yyrecord
    ) else (
        if ((yyrecord.yylimit - yyrecord.yycursor) < 2) then raise Fill;
        let yych = unsafe_get yyrecord.yyinput yyrecord.yycursor in
        yyrecord.yycursor <- yyrecord.yycursor + 1;
        match yych with
            | 'a' -> (yy25 [@tailcall]) yyrecord
            | 'b' -> (yy26 [@tailcall]) yyrecord
            | 'c' -> (yy27 [@tailcall]) yyrecord
            | _ -> (yy23 [@tailcall]) yyrecord
    )

and yy23 (yyrecord : state) : int =
    (yy24 [@tailcall]) yyrecord

and yy24 (yyrecord : state) : int =
    1

and yy25 (yyrecord : state) : int =
    if (yyrecord.yycursor == yyrecord.yyend) then (yy31 [@tailcall]) yyrecord
    else 3

and yy26 (yyrecord : state) : int =
    4

and yy27 (yyrecord : state) : int =
    yyrecord.yymarker <- yyrecord.yycursor;
    if (yyrecord.yycursor == yyrecord.yyend) then (
        (yy32 [@tailcall]) yyrecord
    ) else (
        let yych = unsafe_get yyrecord.yyinput yyrecord.yycursor in
        match yych with
            | 'c' ->
                yyrecord.yycursor <- yyrecord.yycursor + 1;
                (yy28 [@tailcall]) yyrecord
            | _ -> (yy24 [@tailcall]) yyrecord
    )

and yy28 (yyrecord : state) : int =
    if (yyrecord.yycursor == yyrecord.yyend) then (
        (yy32 [@tailcall]) yyrecord
    ) else (
        if (yyrecord.yylimit <= yyrecord.yycursor) then raise Fill;
        let yych = unsafe_get yyrecord.yyinput yyrecord.yycursor in
        match yych with
            | 'c' ->
                yyrecord.yycursor <- yyrecord.yycursor + 1;
                (yy28 [@tailcall]) yyrecord
            | _ -> (yy29 [@tailcall]) yyrecord
    )

and yy29 (yyrecord : state) : int =
    yyrecord.yycursor <- yyrecord.yymarker;
    (yy24 [@tailcall]) yyrecord

and yy30 (yyrecord : state) : int =
    0

and yy31 (yyrecord : state) : int =
    2

and yy32 (yyrecord : state) : int =
    5

and lex_scc (yyrecord : state) : int =
    (yy22 [@tailcall]) yyrecord



let test_scc str ret =
    let buf = cat str (make yymaxfill '\x00') in
    let st = {yyinput = buf; yycursor = 0; yymarker = 0; yylimit = length buf; yyend = length str - 1} in
    let result = try lex_scc st with Fill -> -1 in
    if not (result = ret) then raise (Failure "error scc")

let test str ret =
    test_simple str ret;
    test_eof str ret;
    test_scc str ret

let main () =
    test "\x00" 0;
    test "a\x00" 2;
    test "ax\x00" 3;
    test "b\x00" 4;
    test "bx\x00" 4;
    test "ccc\x00" 5

let _ = main ()
