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

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

    // Final tag variables available in semantic action.
    
//line "v/submatch/03_captures.v":23
mut yytl0 := 0
mut yytl1 := 0
mut yytl2 := 0
mut yytl3 := 0
mut yytr0 := 0
mut yytr1 := 0
mut yytr2 := 0
mut yytr3 := 0
//line "v/submatch/03_captures.re":19


    // Intermediate tag variables used by the lexer (must be autogenerated).
    
//line "v/submatch/03_captures.v":37
mut yyt1 := 0
mut yyt2 := 0
mut yyt3 := 0
mut yyt4 := 0
mut yyt5 := 0
//line "v/submatch/03_captures.re":22


    
//line "v/submatch/03_captures.v":47
    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/03_captures.re":38
    return none
//line "v/submatch/03_captures.v":62
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
    yytl1 = yyt1
    yytl2 = yyt2
    yytr2 = yyt3
    yytl3 = yyt5
    yytr3 = yyt4
    yytl0 = yyt1
    yytr0 = yycursor
    yytr1 = yyt2
    yytr1-= 1
//line "v/submatch/03_captures.re":30
    
            _ := yytl0; _ := yytr0 // some variables are unused
            return SemVer {
                major: s2n(yyinput[yytl1..yytr1]),
                minor: s2n(yyinput[yytl2..yytr2]),
                patch: if yytl3 == -1 {0} else {s2n(yyinput[yytl3 + 1..yytr3])}
            }

//line "v/submatch/03_captures.v":131
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/03_captures.re":39

}

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)
}
