let rec lexer_of_matrix ?(print_trace = false) ?(automaton = default_automaton) (matrix : string array array) : t_token list =
let rec aux (acc : t_token list) (state : t_state) (row : int) (col : int) (stack : t_stack) =
if state = automaton.end_state then acc else
let symbol = symbol_of_matrix row col matrix in
match automaton.transition state symbol stack with
|action, next_state, token_opt, next_stack ->
let _ : unit = if print_trace then trace state row col symbol token_opt next_stack else () in
let next_row, next_col =
match action with
|Up -> row-1, col
|Down -> row+1, col
|Left -> row, col-1
|Right -> row, col+1
|Stay -> row, col
in
match token_opt with
|None -> aux acc next_state next_row next_col next_stack
|Some token -> aux (token::acc) next_state next_row next_col next_stack
in
match last_non_empty_row_of_matrix matrix with
|None -> raise (Error "empty matrix")
|Some i -> List.rev (aux [] (State 0) i 0 (Stack []))