// Code generated by re2v, DO NOT EDIT.
//line "codegen/v/recursive_functions/advanced.re":1
// re2v $INPUT -o $OUTPUT -cf --recursive-functions -Wno-nondeterministic-tags

import arrays
import log
import os

//line "codegen/v/recursive_functions/advanced.v":10
enum YYCONDTYPE {
    yycmedia_type = 1
    yycheader = 23
}
//line "codegen/v/recursive_functions/advanced.re":7


// Use a small buffer to cover the case when a lexeme doesn't fit.
// In real world use a larger buffer.
const bufsize = 100

const mtag_root = -1
const tag_none = -1

// An m-tag tree is a way to store histories with an O(1) copy operation.
// Histories naturally form a tree, as they have common start and fork at some
// point. The tree is stored as an array of pairs (tag value, link to parent).
// An m-tag is represented with a single link in the tree (array index).
struct MtagElem {
    elem int
    pred int
}
type MtagTrie = []MtagElem

// Append a single value to an m-tag history.
fn add_mtag(mut trie &MtagTrie, mtag int, value int) int {
    trie = arrays.concat(trie, MtagElem{value, mtag})
    return trie.len - 1
}

// Recursively unwind tag histories and collect version components.
fn unwind(trie MtagTrie, x int, y int, str []u8) []string {
    // Reached the root of the m-tag tree, stop recursion.
    if x == mtag_root && y == mtag_root {
        return []
    }

    // Unwind history further.
    mut result := unwind(trie, trie[x].pred, trie[y].pred, str)

    // Get tag values. Tag histories must have equal length.
    if x == mtag_root || y == mtag_root {
        panic("tag histories have different length")
    }
    ex := trie[x].elem
    ey := trie[y].elem

    if ex != tag_none && ey != tag_none {
        // Both tags are valid string indices, extract component.
        result = arrays.concat(result, str[ex..ey].str())
    } else if !(ex == tag_none && ey == tag_none) {
        panic("both tags should be tagNone")
    }
    return result
}

struct State {
mut:
    file     os.File
    yyinput  []u8
    yycursor int
    yymarker int
    yylimit  int
    token    int
    yycond   YYCONDTYPE
    yystate  int
    trie     MtagTrie
    
//line "codegen/v/recursive_functions/advanced.v":79

	yyt1 int
	yyt2 int
//line "codegen/v/recursive_functions/advanced.re":69

    
//line "codegen/v/recursive_functions/advanced.v":86

	yytm1 int
	yytm10 int
	yytm2 int
	yytm3 int
	yytm4 int
	yytm5 int
	yytm6 int
	yytm7 int
	yytm8 int
	yytm9 int
//line "codegen/v/recursive_functions/advanced.re":70

    l1       int
    l2       int
    f1       int
    f2       int
    p1       int
    p2       int
    p3       int
    p4       int
    yyaccept int
}

enum Status {
    lex_end
    lex_ready
    lex_waiting
    lex_bad_packet
    lex_big_packet
}

fn fill(mut st &State) Status {
    shift := st.token
    used := st.yylimit - st.token
    free := bufsize - used

    // Error: no space. In real life can reallocate a larger buffer.
    if free < 1 { return .lex_big_packet }

    // Shift buffer contents (discard already processed data).
    copy(mut &st.yyinput, st.yyinput[shift..shift+used])
    st.yycursor -= shift
    st.yymarker -= shift
    st.yylimit -= shift
    st.token -= shift
    
//line "codegen/v/recursive_functions/advanced.v":134

	if st.yyt1 != tag_none { st.yyt1 -= shift };
	if st.yyt2 != tag_none { st.yyt2 -= shift };
//line "codegen/v/recursive_functions/advanced.re":104


    // Fill free space at the end of buffer with new data.
    pos := st.file.tell() or { 0 }
    if n := st.file.read_bytes_into(u64(pos), mut st.yyinput[st.yylimit..bufsize]) {
        st.yylimit += n
    }
    st.yyinput[st.yylimit] = 0 // append sentinel symbol

    return .lex_ready
}


//line "codegen/v/recursive_functions/advanced.v":152
fn yy1(mut st &State) Status {
    yych := st.yyinput[st.yycursor]
    match yych {
        0x21, 0x23...0x27, 0x2A...0x2B, 0x2D...0x2E, 0x30...0x39, 0x41...0x5A, 0x5E...0x7A, 0x7C, 0x7E {
            st.yyt1 = st.yycursor
            st.yycursor += 1
            return yy4(mut st)
        }
        else {
            if st.yylimit <= st.yycursor {
                st.yystate = 0
                return .lex_waiting
            } else {
                st.yycursor += 1
                return yy2(mut st)
            }
        }
    }
}

fn yy2(mut st &State) Status {
    return yy3(mut st)
}

fn yy3(mut st &State) Status {
    st.yystate = -1
//line "codegen/v/recursive_functions/advanced.re":176
    return .lex_bad_packet
//line "codegen/v/recursive_functions/advanced.v":181
}

fn yy4(mut st &State) Status {
    st.yymarker = st.yycursor
    yych := st.yyinput[st.yycursor]
    match yych {
        0x21, 0x23...0x27, 0x2A...0x2B, 0x2D...0x39, 0x41...0x5A, 0x5E...0x7A, 0x7C, 0x7E { return yy6(mut st, yych) }
        else {
            if st.yylimit <= st.yycursor {
                st.yystate = 1
                return .lex_waiting
            } else {
                return yy3(mut st)
            }
        }
    }
}

fn yy5(mut st &State) Status {
    yych := st.yyinput[st.yycursor]
    return yy6(mut st, yych)
}

fn yy6(mut st &State, yych u8) Status {
    match yych {
        0x21, 0x23...0x27, 0x2A...0x2B, 0x2D...0x2E, 0x30...0x39, 0x41...0x5A, 0x5E...0x7A, 0x7C, 0x7E {
            st.yycursor += 1
            return yy5(mut st)
        }
        0x2F {
            st.yycursor += 1
            return yy8(mut st)
        }
        else {
            if st.yylimit <= st.yycursor {
                st.yystate = 2
                return .lex_waiting
            } else {
                return yy7(mut st)
            }
        }
    }
}

fn yy7(mut st &State) Status {
    st.yycursor = st.yymarker
    return yy3(mut st)
}

fn yy8(mut st &State) Status {
    yych := st.yyinput[st.yycursor]
    match yych {
        0x00, 0x09, 0x0D, 0x20, 0x3B {
            if st.yylimit <= st.yycursor {
                st.yystate = 3
                return .lex_waiting
            } else {
                return yy7(mut st)
            }
        }
        else { return yy10(mut st, yych) }
    }
}

fn yy9(mut st &State) Status {
    yych := st.yyinput[st.yycursor]
    return yy10(mut st, yych)
}

fn yy10(mut st &State, yych u8) Status {
    match yych {
        0x09, 0x20 {
            st.yytm6 = st.yytm10
            st.yytm6 = add_mtag(mut &st.trie, st.yytm6, tag_none)
            st.yytm5 = st.yytm9
            st.yytm5 = add_mtag(mut &st.trie, st.yytm5, tag_none)
            st.yytm4 = st.yytm8
            st.yytm4 = add_mtag(mut &st.trie, st.yytm4, tag_none)
            st.yytm3 = st.yytm7
            st.yytm3 = add_mtag(mut &st.trie, st.yytm3, tag_none)
            st.yyt2 = st.yycursor
            st.yycursor += 1
            return yy11(mut st)
        }
        0x0D {
            st.yytm6 = st.yytm10
            st.yytm6 = add_mtag(mut &st.trie, st.yytm6, tag_none)
            st.yytm5 = st.yytm9
            st.yytm5 = add_mtag(mut &st.trie, st.yytm5, tag_none)
            st.yytm4 = st.yytm8
            st.yytm4 = add_mtag(mut &st.trie, st.yytm4, tag_none)
            st.yytm3 = st.yytm7
            st.yytm3 = add_mtag(mut &st.trie, st.yytm3, tag_none)
            st.yyt2 = st.yycursor
            st.yycursor += 1
            return yy12(mut st)
        }
        0x21, 0x23...0x27, 0x2A...0x2B, 0x2D...0x2E, 0x30...0x39, 0x41...0x5A, 0x5E...0x7A, 0x7C, 0x7E {
            st.yycursor += 1
            return yy9(mut st)
        }
        0x3B {
            st.yyt2 = st.yycursor
            st.yycursor += 1
            return yy13(mut st)
        }
        else {
            if st.yylimit <= st.yycursor {
                st.yystate = 4
                return .lex_waiting
            } else {
                return yy7(mut st)
            }
        }
    }
}

fn yy11(mut st &State) Status {
    yych := st.yyinput[st.yycursor]
    match yych {
        0x09, 0x20 {
            st.yycursor += 1
            return yy11(mut st)
        }
        0x0D {
            st.yycursor += 1
            return yy12(mut st)
        }
        0x3B {
            st.yycursor += 1
            return yy13(mut st)
        }
        else {
            if st.yylimit <= st.yycursor {
                st.yystate = 5
                return .lex_waiting
            } else {
                return yy7(mut st)
            }
        }
    }
}

fn yy12(mut st &State) Status {
    yych := st.yyinput[st.yycursor]
    match yych {
        0x0A {
            st.yycursor += 1
            return yy14(mut st)
        }
        else {
            if st.yylimit <= st.yycursor {
                st.yystate = 6
                return .lex_waiting
            } else {
                return yy7(mut st)
            }
        }
    }
}

fn yy13(mut st &State) Status {
    yych := st.yyinput[st.yycursor]
    match yych {
        0x09, 0x20 {
            st.yycursor += 1
            return yy13(mut st)
        }
        0x21, 0x23...0x27, 0x2A...0x2B, 0x2D...0x2E, 0x30...0x39, 0x41...0x5A, 0x5E...0x7A, 0x7C, 0x7E {
            st.yytm7 = add_mtag(mut &st.trie, st.yytm7, st.yycursor)
            st.yycursor += 1
            return yy15(mut st)
        }
        else {
            if st.yylimit <= st.yycursor {
                st.yystate = 7
                return .lex_waiting
            } else {
                return yy7(mut st)
            }
        }
    }
}

fn yy14(mut st &State) Status {
    st.l1 = st.yyt1
    st.l2 = st.yyt2
    st.p1 = st.yytm3
    st.p2 = st.yytm4
    st.p3 = st.yytm5
    st.p4 = st.yytm6
    st.yystate = -1
//line "codegen/v/recursive_functions/advanced.re":154
    
        mt := st.yyinput[st.l1..st.l2].str()
        log.debug("media type: $mt")

        pnames := unwind(st.trie, st.p1, st.p2, st.yyinput)
        log.debug("pnames: $pnames")

        pvals := unwind(st.trie, st.p3, st.p4, st.yyinput)
        log.debug("pvals: $pvals")

        st.token = st.yycursor
        return lex(mut st)

//line "codegen/v/recursive_functions/advanced.v":388
}

fn yy15(mut st &State) Status {
    yych := st.yyinput[st.yycursor]
    match yych {
        0x21, 0x23...0x27, 0x2A...0x2B, 0x2D...0x2E, 0x30...0x39, 0x41...0x5A, 0x5E...0x7A, 0x7C, 0x7E {
            st.yycursor += 1
            return yy15(mut st)
        }
        0x3D {
            st.yytm8 = add_mtag(mut &st.trie, st.yytm8, st.yycursor)
            st.yycursor += 1
            return yy16(mut st)
        }
        else {
            if st.yylimit <= st.yycursor {
                st.yystate = 8
                return .lex_waiting
            } else {
                return yy7(mut st)
            }
        }
    }
}

fn yy16(mut st &State) Status {
    yych := st.yyinput[st.yycursor]
    match yych {
        0x21, 0x23...0x27, 0x2A...0x2B, 0x2D...0x2E, 0x30...0x39, 0x41...0x5A, 0x5E...0x7A, 0x7C, 0x7E {
            st.yytm9 = add_mtag(mut &st.trie, st.yytm9, st.yycursor)
            st.yycursor += 1
            return yy17(mut st)
        }
        0x22 {
            st.yytm9 = add_mtag(mut &st.trie, st.yytm9, st.yycursor)
            st.yycursor += 1
            return yy18(mut st)
        }
        else {
            if st.yylimit <= st.yycursor {
                st.yystate = 9
                return .lex_waiting
            } else {
                return yy7(mut st)
            }
        }
    }
}

fn yy17(mut st &State) Status {
    yych := st.yyinput[st.yycursor]
    match yych {
        0x09, 0x20 {
            st.yytm10 = add_mtag(mut &st.trie, st.yytm10, st.yycursor)
            st.yycursor += 1
            return yy19(mut st)
        }
        0x0D {
            st.yytm3 = st.yytm7
            st.yytm4 = st.yytm8
            st.yytm5 = st.yytm9
            st.yytm6 = st.yytm10
            st.yytm6 = add_mtag(mut &st.trie, st.yytm6, st.yycursor)
            st.yycursor += 1
            return yy12(mut st)
        }
        0x21, 0x23...0x27, 0x2A...0x2B, 0x2D...0x2E, 0x30...0x39, 0x41...0x5A, 0x5E...0x7A, 0x7C, 0x7E {
            st.yycursor += 1
            return yy17(mut st)
        }
        0x3B {
            st.yytm10 = add_mtag(mut &st.trie, st.yytm10, st.yycursor)
            st.yycursor += 1
            return yy13(mut st)
        }
        else {
            if st.yylimit <= st.yycursor {
                st.yystate = 10
                return .lex_waiting
            } else {
                return yy7(mut st)
            }
        }
    }
}

fn yy18(mut st &State) Status {
    yych := st.yyinput[st.yycursor]
    match yych {
        0x00, 0x01...0x08, 0x0A...0x1F, 0x7F {
            if st.yylimit <= st.yycursor {
                st.yystate = 11
                return .lex_waiting
            } else {
                return yy7(mut st)
            }
        }
        0x22 {
            st.yycursor += 1
            return yy20(mut st)
        }
        0x5C {
            st.yycursor += 1
            return yy21(mut st)
        }
        else {
            st.yycursor += 1
            return yy18(mut st)
        }
    }
}

fn yy19(mut st &State) Status {
    yych := st.yyinput[st.yycursor]
    match yych {
        0x09, 0x20 {
            st.yycursor += 1
            return yy19(mut st)
        }
        0x0D {
            st.yytm3 = st.yytm7
            st.yytm4 = st.yytm8
            st.yytm5 = st.yytm9
            st.yytm6 = st.yytm10
            st.yycursor += 1
            return yy12(mut st)
        }
        0x3B {
            st.yycursor += 1
            return yy13(mut st)
        }
        else {
            if st.yylimit <= st.yycursor {
                st.yystate = 12
                return .lex_waiting
            } else {
                return yy7(mut st)
            }
        }
    }
}

fn yy20(mut st &State) Status {
    yych := st.yyinput[st.yycursor]
    match yych {
        0x09, 0x20 {
            st.yytm10 = add_mtag(mut &st.trie, st.yytm10, st.yycursor)
            st.yycursor += 1
            return yy19(mut st)
        }
        0x0D {
            st.yytm3 = st.yytm7
            st.yytm4 = st.yytm8
            st.yytm5 = st.yytm9
            st.yytm6 = st.yytm10
            st.yytm6 = add_mtag(mut &st.trie, st.yytm6, st.yycursor)
            st.yycursor += 1
            return yy12(mut st)
        }
        0x3B {
            st.yytm10 = add_mtag(mut &st.trie, st.yytm10, st.yycursor)
            st.yycursor += 1
            return yy13(mut st)
        }
        else {
            if st.yylimit <= st.yycursor {
                st.yystate = 13
                return .lex_waiting
            } else {
                return yy7(mut st)
            }
        }
    }
}

fn yy21(mut st &State) Status {
    yych := st.yyinput[st.yycursor]
    match yych {
        0x00, 0x01...0x08, 0x0A...0x1E, 0x7F {
            if st.yylimit <= st.yycursor {
                st.yystate = 14
                return .lex_waiting
            } else {
                return yy7(mut st)
            }
        }
        else {
            st.yycursor += 1
            return yy18(mut st)
        }
    }
}

fn yy22(mut st &State) Status {
    st.yystate = -1
//line "codegen/v/recursive_functions/advanced.re":177
    return .lex_end
//line "codegen/v/recursive_functions/advanced.v":586
}

fn yyfnmedia_type(mut st &State) Status {
    return yy1(mut st)
}

fn yy23(mut st &State) Status {
    yych := st.yyinput[st.yycursor]
    match yych {
        0x00, 0x01...0x0C, 0x0E...0x1E, 0x7F {
            if st.yylimit <= st.yycursor {
                st.yystate = 15
                return .lex_waiting
            } else {
                st.yycursor += 1
                return yy24(mut st)
            }
        }
        0x0D {
            st.yytm3 = add_mtag(mut &st.trie, st.yytm3, st.yycursor)
            st.yycursor += 1
            return yy26(mut st)
        }
        else {
            st.yycursor += 1
            return yy27(mut st)
        }
    }
}

fn yy24(mut st &State) Status {
    return yy25(mut st)
}

fn yy25(mut st &State) Status {
    st.yystate = -1
//line "codegen/v/recursive_functions/advanced.re":176
    return .lex_bad_packet
//line "codegen/v/recursive_functions/advanced.v":625
}

fn yy26(mut st &State) Status {
    st.yyaccept = 0
    st.yymarker = st.yycursor
    yych := st.yyinput[st.yycursor]
    match yych {
        0x0A {
            st.yycursor += 1
            return yy28(mut st)
        }
        else {
            if st.yylimit <= st.yycursor {
                st.yystate = 16
                return .lex_waiting
            } else {
                return yy25(mut st)
            }
        }
    }
}

fn yy27(mut st &State) Status {
    st.yyaccept = 0
    st.yymarker = st.yycursor
    yych := st.yyinput[st.yycursor]
    match yych {
        0x00, 0x01...0x08, 0x0A...0x0C, 0x0E...0x1E, 0x7F {
            if st.yylimit <= st.yycursor {
                st.yystate = 17
                return .lex_waiting
            } else {
                return yy25(mut st)
            }
        }
        0x09 {
            st.yycursor += 1
            return yy30(mut st)
        }
        0x0D {
            st.yytm3 = add_mtag(mut &st.trie, st.yytm3, st.yycursor)
            st.yycursor += 1
            return yy31(mut st)
        }
        else {
            st.yycursor += 1
            return yy32(mut st)
        }
    }
}

fn yy28(mut st &State) Status {
    yych := st.yyinput[st.yycursor]
    match yych {
        0x09, 0x20 {
            st.yycursor += 1
            return yy33(mut st)
        }
        else {
            if st.yylimit <= st.yycursor {
                st.yystate = 18
                return .lex_waiting
            } else {
                return yy29(mut st)
            }
        }
    }
}

fn yy29(mut st &State) Status {
    st.yycursor = st.yymarker
    if st.yyaccept == 0 {
        return yy25(mut st)
    } else {
        return yy38(mut st)
    }
}

fn yy30(mut st &State) Status {
    yych := st.yyinput[st.yycursor]
    match yych {
        0x00, 0x01...0x08, 0x0A...0x1E, 0x7F {
            if st.yylimit <= st.yycursor {
                st.yystate = 19
                return .lex_waiting
            } else {
                return yy29(mut st)
            }
        }
        0x09 {
            st.yycursor += 1
            return yy30(mut st)
        }
        0x20 {
            st.yycursor += 1
            return yy32(mut st)
        }
        else {
            st.yycursor += 1
            return yy34(mut st)
        }
    }
}

fn yy31(mut st &State) Status {
    yych := st.yyinput[st.yycursor]
    match yych {
        0x0A {
            st.yycursor += 1
            return yy28(mut st)
        }
        else {
            if st.yylimit <= st.yycursor {
                st.yystate = 20
                return .lex_waiting
            } else {
                return yy29(mut st)
            }
        }
    }
}

fn yy32(mut st &State) Status {
    yych := st.yyinput[st.yycursor]
    match yych {
        0x00, 0x01...0x08, 0x0A...0x0C, 0x0E...0x1E, 0x7F {
            if st.yylimit <= st.yycursor {
                st.yystate = 21
                return .lex_waiting
            } else {
                return yy29(mut st)
            }
        }
        0x09 {
            st.yycursor += 1
            return yy30(mut st)
        }
        0x0D {
            st.yytm3 = add_mtag(mut &st.trie, st.yytm3, st.yycursor)
            st.yycursor += 1
            return yy31(mut st)
        }
        else {
            st.yycursor += 1
            return yy32(mut st)
        }
    }
}

fn yy33(mut st &State) Status {
    yych := st.yyinput[st.yycursor]
    match yych {
        0x00, 0x01...0x08, 0x0A...0x0C, 0x0E...0x1E, 0x7F {
            if st.yylimit <= st.yycursor {
                st.yystate = 22
                return .lex_waiting
            } else {
                return yy29(mut st)
            }
        }
        0x09, 0x20 {
            st.yycursor += 1
            return yy33(mut st)
        }
        0x0D {
            st.yytm5 = add_mtag(mut &st.trie, st.yytm5, st.yycursor)
            st.yytm4 = st.yytm3
            st.yytm4 = add_mtag(mut &st.trie, st.yytm4, st.yycursor)
            st.yycursor += 1
            return yy35(mut st)
        }
        else {
            st.yytm5 = add_mtag(mut &st.trie, st.yytm5, st.yycursor)
            st.yycursor += 1
            return yy36(mut st)
        }
    }
}

fn yy34(mut st &State) Status {
    yych := st.yyinput[st.yycursor]
    match yych {
        0x00, 0x01...0x0C, 0x0E...0x1E, 0x7F {
            if st.yylimit <= st.yycursor {
                st.yystate = 23
                return .lex_waiting
            } else {
                return yy29(mut st)
            }
        }
        0x0D {
            st.yytm3 = add_mtag(mut &st.trie, st.yytm3, st.yycursor)
            st.yycursor += 1
            return yy31(mut st)
        }
        else {
            st.yycursor += 1
            return yy32(mut st)
        }
    }
}

fn yy35(mut st &State) Status {
    yych := st.yyinput[st.yycursor]
    match yych {
        0x0A {
            st.yycursor += 1
            return yy37(mut st)
        }
        else {
            if st.yylimit <= st.yycursor {
                st.yystate = 24
                return .lex_waiting
            } else {
                return yy29(mut st)
            }
        }
    }
}

fn yy36(mut st &State) Status {
    yych := st.yyinput[st.yycursor]
    match yych {
        0x00, 0x01...0x08, 0x0A...0x0C, 0x0E...0x1E, 0x7F {
            if st.yylimit <= st.yycursor {
                st.yystate = 25
                return .lex_waiting
            } else {
                return yy29(mut st)
            }
        }
        0x09 {
            st.yycursor += 1
            return yy39(mut st)
        }
        0x0D {
            st.yytm4 = st.yytm3
            st.yytm4 = add_mtag(mut &st.trie, st.yytm4, st.yycursor)
            st.yycursor += 1
            return yy35(mut st)
        }
        else {
            st.yycursor += 1
            return yy36(mut st)
        }
    }
}

fn yy37(mut st &State) Status {
    st.yyaccept = 1
    st.yymarker = st.yycursor
    yych := st.yyinput[st.yycursor]
    match yych {
        0x09, 0x20 {
            st.yytm1 = st.yytm3
            st.yytm2 = st.yytm5
            st.yytm3 = st.yytm4
            st.yycursor += 1
            return yy33(mut st)
        }
        else {
            if st.yylimit <= st.yycursor {
                st.yystate = 26
                return .lex_waiting
            } else {
                st.yytm1 = st.yytm3
                st.yytm2 = st.yytm5
                return yy38(mut st)
            }
        }
    }
}

fn yy38(mut st &State) Status {
    st.f1 = st.yytm1
    st.f2 = st.yytm2
    st.yystate = -1
//line "codegen/v/recursive_functions/advanced.re":168
    
        folds := unwind(st.trie, st.f1, st.f2, st.yyinput)
        log.debug("folds: $folds")

        st.token = st.yycursor
        return lex(mut st)

//line "codegen/v/recursive_functions/advanced.v":911
}

fn yy39(mut st &State) Status {
    yych := st.yyinput[st.yycursor]
    match yych {
        0x00, 0x01...0x08, 0x0A...0x0C, 0x0E...0x1E, 0x7F {
            if st.yylimit <= st.yycursor {
                st.yystate = 27
                return .lex_waiting
            } else {
                return yy29(mut st)
            }
        }
        0x09 {
            st.yycursor += 1
            return yy39(mut st)
        }
        0x0D {
            st.yycursor += 1
            return yy40(mut st)
        }
        0x20 {
            st.yycursor += 1
            return yy36(mut st)
        }
        else {
            st.yycursor += 1
            return yy41(mut st)
        }
    }
}

fn yy40(mut st &State) Status {
    yych := st.yyinput[st.yycursor]
    match yych {
        0x0A {
            st.yycursor += 1
            return yy42(mut st)
        }
        else {
            if st.yylimit <= st.yycursor {
                st.yystate = 28
                return .lex_waiting
            } else {
                return yy29(mut st)
            }
        }
    }
}

fn yy41(mut st &State) Status {
    yych := st.yyinput[st.yycursor]
    match yych {
        0x00, 0x01...0x08, 0x0A...0x0C, 0x0E...0x1E, 0x7F {
            if st.yylimit <= st.yycursor {
                st.yystate = 29
                return .lex_waiting
            } else {
                return yy29(mut st)
            }
        }
        0x09 {
            st.yycursor += 1
            return yy43(mut st)
        }
        0x0D {
            st.yytm4 = st.yytm3
            st.yytm4 = add_mtag(mut &st.trie, st.yytm4, st.yycursor)
            st.yycursor += 1
            return yy35(mut st)
        }
        else {
            st.yycursor += 1
            return yy36(mut st)
        }
    }
}

fn yy42(mut st &State) Status {
    st.yytm1 = st.yytm3
    st.yytm2 = st.yytm5
    return yy38(mut st)
}

fn yy43(mut st &State) Status {
    yych := st.yyinput[st.yycursor]
    match yych {
        0x09, 0x20 {
            st.yycursor += 1
            return yy43(mut st)
        }
        0x0D {
            st.yycursor += 1
            return yy40(mut st)
        }
        else {
            if st.yylimit <= st.yycursor {
                st.yystate = 30
                return .lex_waiting
            } else {
                return yy29(mut st)
            }
        }
    }
}

fn yy44(mut st &State) Status {
    st.yystate = -1
//line "codegen/v/recursive_functions/advanced.re":177
    return .lex_end
//line "codegen/v/recursive_functions/advanced.v":1022
}

fn yyfnheader(mut st &State) Status {
    return yy23(mut st)
}

fn yy0(mut st &State) Status {
    match st.yycond {
        .yycmedia_type { return yyfnmedia_type(mut st) }
        .yycheader { return yyfnheader(mut st) }
    }
}

fn lex(mut st &State) Status {
    match st.yystate {
        -1 { return yy0(mut st) }
        0 {
            if st.yylimit <= st.yycursor {
                return yy22(mut st)
            } else {
                return yy1(mut st)
            }
        }
        1 {
            if st.yylimit <= st.yycursor {
                return yy3(mut st)
            } else {
                return yy4(mut st)
            }
        }
        2 {
            if st.yylimit <= st.yycursor {
                return yy7(mut st)
            } else {
                return yy5(mut st)
            }
        }
        3 {
            if st.yylimit <= st.yycursor {
                return yy7(mut st)
            } else {
                return yy8(mut st)
            }
        }
        4 {
            if st.yylimit <= st.yycursor {
                return yy7(mut st)
            } else {
                return yy9(mut st)
            }
        }
        5 {
            if st.yylimit <= st.yycursor {
                return yy7(mut st)
            } else {
                return yy11(mut st)
            }
        }
        6 {
            if st.yylimit <= st.yycursor {
                return yy7(mut st)
            } else {
                return yy12(mut st)
            }
        }
        7 {
            if st.yylimit <= st.yycursor {
                return yy7(mut st)
            } else {
                return yy13(mut st)
            }
        }
        8 {
            if st.yylimit <= st.yycursor {
                return yy7(mut st)
            } else {
                return yy15(mut st)
            }
        }
        9 {
            if st.yylimit <= st.yycursor {
                return yy7(mut st)
            } else {
                return yy16(mut st)
            }
        }
        10 {
            if st.yylimit <= st.yycursor {
                return yy7(mut st)
            } else {
                return yy17(mut st)
            }
        }
        11 {
            if st.yylimit <= st.yycursor {
                return yy7(mut st)
            } else {
                return yy18(mut st)
            }
        }
        12 {
            if st.yylimit <= st.yycursor {
                return yy7(mut st)
            } else {
                return yy19(mut st)
            }
        }
        13 {
            if st.yylimit <= st.yycursor {
                return yy7(mut st)
            } else {
                return yy20(mut st)
            }
        }
        14 {
            if st.yylimit <= st.yycursor {
                return yy7(mut st)
            } else {
                return yy21(mut st)
            }
        }
        15 {
            if st.yylimit <= st.yycursor {
                return yy44(mut st)
            } else {
                return yy23(mut st)
            }
        }
        16 {
            if st.yylimit <= st.yycursor {
                return yy25(mut st)
            } else {
                return yy26(mut st)
            }
        }
        17 {
            if st.yylimit <= st.yycursor {
                return yy25(mut st)
            } else {
                return yy27(mut st)
            }
        }
        18 {
            if st.yylimit <= st.yycursor {
                return yy29(mut st)
            } else {
                return yy28(mut st)
            }
        }
        19 {
            if st.yylimit <= st.yycursor {
                return yy29(mut st)
            } else {
                return yy30(mut st)
            }
        }
        20 {
            if st.yylimit <= st.yycursor {
                return yy29(mut st)
            } else {
                return yy31(mut st)
            }
        }
        21 {
            if st.yylimit <= st.yycursor {
                return yy29(mut st)
            } else {
                return yy32(mut st)
            }
        }
        22 {
            if st.yylimit <= st.yycursor {
                return yy29(mut st)
            } else {
                return yy33(mut st)
            }
        }
        23 {
            if st.yylimit <= st.yycursor {
                return yy29(mut st)
            } else {
                return yy34(mut st)
            }
        }
        24 {
            if st.yylimit <= st.yycursor {
                return yy29(mut st)
            } else {
                return yy35(mut st)
            }
        }
        25 {
            if st.yylimit <= st.yycursor {
                return yy29(mut st)
            } else {
                return yy36(mut st)
            }
        }
        26 {
            if st.yylimit <= st.yycursor {
                st.yytm1 = st.yytm3
                st.yytm2 = st.yytm5
                return yy38(mut st)
            } else {
                return yy37(mut st)
            }
        }
        27 {
            if st.yylimit <= st.yycursor {
                return yy29(mut st)
            } else {
                return yy39(mut st)
            }
        }
        28 {
            if st.yylimit <= st.yycursor {
                return yy29(mut st)
            } else {
                return yy40(mut st)
            }
        }
        29 {
            if st.yylimit <= st.yycursor {
                return yy29(mut st)
            } else {
                return yy41(mut st)
            }
        }
        30 {
            if st.yylimit <= st.yycursor {
                return yy29(mut st)
            } else {
                return yy43(mut st)
            }
        }
        else { panic("internal lexer error") }
    }
}

//line "codegen/v/recursive_functions/advanced.re":178


fn test(expect Status, packets []string) {
    // Create a "socket" (open the same file for reading and writing).
    fname := "pipe"
    mut fw := os.create(fname) or { panic("cannot create file") }
    mut fr := os.open(fname) or { panic("cannot open file") }

    // Initialize lexer state: `state` value is -1, all offsets are at the end
    // of buffer.
    mut st := &State{
        file:     fr,
        // Sentinel at `yylimit` offset is set to zero, which triggers YYFILL.
        yyinput:  []u8{len: bufsize + 1},
        yycursor: bufsize,
        yymarker: bufsize,
        yylimit:  bufsize,
        token:    bufsize,
        yycond:   .yycmedia_type,
        yystate:  -1,
        trie:     []MtagElem{},
        
//line "codegen/v/recursive_functions/advanced.v":1285

		yyt1: tag_none,
		yyt2: tag_none,
//line "codegen/v/recursive_functions/advanced.re":199

        
//line "codegen/v/recursive_functions/advanced.v":1292

		yytm1: mtag_root,
		yytm10: mtag_root,
		yytm2: mtag_root,
		yytm3: mtag_root,
		yytm4: mtag_root,
		yytm5: mtag_root,
		yytm6: mtag_root,
		yytm7: mtag_root,
		yytm8: mtag_root,
		yytm9: mtag_root,
//line "codegen/v/recursive_functions/advanced.re":200

        l1:       tag_none,
        l2:       tag_none,
        f1:       mtag_root,
        f2:       mtag_root,
        p1:       mtag_root,
        p2:       mtag_root,
        p3:       mtag_root,
        p4:       mtag_root,
        yyaccept: 0,
    }
    // yyinput is zero-initialized, no need to write sentinel

    // Main loop. The buffer contains incomplete data which appears packet by
    // packet. When the lexer needs more input it saves its internal state and
    // returns to the caller which should provide more input and resume lexing.
    mut status := Status.lex_ready
    mut send := 0
    for {
        status = lex(mut &st)
        if status == .lex_end {
            break
        } else if status == .lex_waiting {
            if send < packets.len {
                log.debug("sending packet $send")
                fw.write_string(packets[send]) or { panic("cannot write to file") }
                fw.flush()
                send += 1
            }
            status = fill(mut &st)
            log.debug("filled buffer $st.yyinput, status $status")
            if status != .lex_ready {
                break
            }
        } else if status == .lex_bad_packet {
            break
        }
    }

    // Check results.
    if status != expect {
        panic("expected $expect, got $status")
    }

    // Cleanup: remove input file.
    fr.close()
    fw.close()
    os.rm(fname) or { panic("cannot remove file") }
}

fn main() {
    //log.set_level(.debug)
    test(.lex_end, ["ap", "plication/j", "son;", " charset=\"", "utf\\\"-8\"\r", "\n", ""])
}
