// re2js $INPUT -o $OUTPUT

const assert = require('assert');

// Maximum number of capturing groups among all rules.
/*!maxnmatch:re2c*/

function parse(yyinput) {
    let yycursor = 0

    // A list for capturing parentheses (twice the number of groups).
    let yynmatch
    let yypmatch = Array(YYMAXNMATCH * 2).fill(null)

    // Intermediate tag variables used by the lexer (must be autogenerated).
    /*!stags:re2c format = "let @@\n"; */

    /*!re2c
        re2c:yyfill:enable = 0;
        re2c:posix-captures = 1;

        num = [0-9]+;

        (num) "." (num) ("." num)? [\x00] {
            // `yynmatch` is the number of capturing groups
            assert.equal(yynmatch, 4)

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

assert.deepEqual(parse("23.34\0"), {major: 23, minor: 34, patch: 0})
assert.deepEqual(parse("1.2.99999\0"), {major: 1, minor: 2, patch: 99999})
assert.deepEqual(parse("1.a\0"), null)
