// Code generated by re2v, DO NOT EDIT.
//line "v/submatch/04_posix_captures.re":1
// re2v $INPUT -o $OUTPUT

// Maximum number of capturing groups among all rules.
//line "v/submatch/04_posix_captures.v":7
const yymaxnmatch = 4
//line "v/submatch/04_posix_captures.re":4


struct SemVer {
    major int
    minor int
    patch int
}

fn s2n(s string) int { // convert pre-parsed string to number
    mut n := 0
    for c in s { n = n * 10 + int(c - 48) }
    return n
}

fn parse(yyinput string) ?SemVer {
    mut yycursor, mut yymarker := 0, 0

    // Allocate memory for capturing parentheses (twice the number of groups).
    mut yypmatch := []int{len: yymaxnmatch * 2}
    mut yynmatch := 0

    // Intermediate tag variables used by the lexer (must be autogenerated).
    
//line "v/submatch/04_posix_captures.v":33
mut yyt1 := 0
mut yyt2 := 0
mut yyt3 := 0
mut yyt4 := 0
mut yyt5 := 0
//line "v/submatch/04_posix_captures.re":26


    
//line "v/submatch/04_posix_captures.v":43
    mut yych := u8(0)
    yych = yyinput[yycursor]
    match yych {
        0x30...0x39 {
            yyt1 = yycursor
            unsafe { goto yy3 }
        }
        else { unsafe { goto yy1 } }
    }
yy1:
    yycursor += 1
yy2:
//line "v/submatch/04_posix_captures.re":46
    return none
//line "v/submatch/04_posix_captures.v":58
yy3:
    yycursor += 1
    yymarker = yycursor
    yych = yyinput[yycursor]
    match yych {
        0x2E { unsafe { goto yy4 } }
        0x30...0x39 { unsafe { goto yy6 } }
        else { unsafe { goto yy2 } }
    }
yy4:
    yycursor += 1
    yych = yyinput[yycursor]
    match yych {
        0x30...0x39 {
            yyt2 = yycursor
            unsafe { goto yy7 }
        }
        else { unsafe { goto yy5 } }
    }
yy5:
    yycursor = yymarker
    unsafe { goto yy2 }
yy6:
    yycursor += 1
    yych = yyinput[yycursor]
    match yych {
        0x2E { unsafe { goto yy4 } }
        0x30...0x39 { unsafe { goto yy6 } }
        else { unsafe { goto yy5 } }
    }
yy7:
    yycursor += 1
    yych = yyinput[yycursor]
    match yych {
        0x00 {
            yyt3 = yycursor
            yyt4 = -1
            yyt5 = -1
            unsafe { goto yy8 }
        }
        0x2E {
            yyt3 = yycursor
            yyt5 = yycursor
            unsafe { goto yy9 }
        }
        0x30...0x39 { unsafe { goto yy7 } }
        else { unsafe { goto yy5 } }
    }
yy8:
    yycursor += 1
    yynmatch = 4
    yypmatch[2] = yyt1
    yypmatch[4] = yyt2
    yypmatch[5] = yyt3
    yypmatch[6] = yyt5
    yypmatch[7] = yyt4
    yypmatch[0] = yyt1
    yypmatch[1] = yycursor
    yypmatch[3] = yyt2
    yypmatch[3]-= 1
//line "v/submatch/04_posix_captures.re":34
    
            // `yynmatch` is the number of capturing groups
            if yynmatch != 4 { panic("expected 4 submatch groups") }

            // Even `yypmatch` values are for opening parentheses, odd values
            // are for closing parentheses, the first group is the whole match.
            return SemVer {
                major: s2n(yyinput[yypmatch[2]..yypmatch[3]]),
                minor: s2n(yyinput[yypmatch[4]..yypmatch[5]]),
                patch: if yypmatch[6] == -1 {0} else {s2n(yyinput[yypmatch[6] + 1..yypmatch[7]])}
            }

//line "v/submatch/04_posix_captures.v":132
yy9:
    yycursor += 1
    yych = yyinput[yycursor]
    if yych <= 0x00 {
        unsafe { goto yy5 }
    }
    unsafe { goto yy11 }
yy10:
    yycursor += 1
    yych = yyinput[yycursor]
yy11:
    match yych {
        0x00 {
            yyt4 = yycursor
            unsafe { goto yy8 }
        }
        0x30...0x39 { unsafe { goto yy10 } }
        else { unsafe { goto yy5 } }
    }
//line "v/submatch/04_posix_captures.re":47

}

fn main() {
    test := fn (result ?SemVer, expect ?SemVer) {
        if r := result {
            if e := expect { if r != e { panic("expected $e, got $r") } }
        } else {
            if _ := result { panic("expected none") }
        }
    }
    test(parse("23.34\0"), SemVer{23, 34, 0})
    test(parse("1.2.9999\0"), SemVer{1, 2, 9999})
    test(parse("1.a\0"), none)
}
