// re2swift $INPUT -o $OUTPUT

struct SemVer: Equatable { var major: Int, minor: Int, patch: Int }

func lex(_ yyinput: UnsafePointer<UInt8>) -> SemVer? {
  let tagNone = -1

  var yycursor = 0, yymarker = 0

  // Final tag variables available in semantic action.
  /*!svars:re2c format = "  var @@: Int\n"; */

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

  /*!re2c
    re2c:yyfill:enable = 0;
    re2c:captvars = 1;

    num = [0-9]+;

    (num) "." (num) ("." num)? [\x00] {
      let _ = yytl0; _ = yytr0  // Some variables are unused.
      return SemVer(
        major: s2n(yytl1..<yytr1),
        minor: s2n(yytl2..<yytr2),
        patch: yytl3 != tagNone ? s2n((yytl3 + 1)..<yytr3) : 0)
    }
    * { return nil }
  */

  func s2n(_ range: Range<Int>) -> Int {
    range.reduce(0) { accum, idx in
      accum * 10 + Int(yyinput[idx] - UInt8(ascii: "0"))
    }
  }
}

assert(lex("23.34") == SemVer(major: 23, minor: 34, patch: 0))
assert(lex("1.2.999") == SemVer(major: 1, minor: 2, patch: 999))
assert(lex("1.a") == nil)
