packages feed

zeolite-lang-0.1.0.0: example/regex/regex-test.0rt

testcase "MatchSingle match" {
  success Test$execute()
}

concrete Test {
  @type execute () -> ()
}

define Test {
  execute () {
    // Pattern: "x"
    MatcherTemplate<Char> template <- MatchSingle<Char>$create('x')
    Matcher<Char> matcher <- template.newMatcher()

    if (template.matchesEmpty()) {
      fail("matches empty")
    }
    if (matcher.matchSatisfied()) {
      fail("match satisfied")
    }

    MatchState state <- matcher.tryNextMatch('x')
    if (!(state `MatchState$equals` MatchState$matchComplete())) {
      fail(state)
    }
    if (!matcher.matchSatisfied()) {
      fail("match not satisfied")
    }

    // Should only match once.
    state <- matcher.tryNextMatch('x')
    if (!(state `MatchState$equals` MatchState$matchFail())) {
      fail(state)
    }
    if (matcher.matchSatisfied()) {
      fail("match satisfied")
    }

    // Should match again after reset.
    matcher <- template.newMatcher()
    state <- matcher.tryNextMatch('x')
    if (!(state `MatchState$equals` MatchState$matchComplete())) {
      fail(state)
    }
  }
}


testcase "MatchSingle non-match" {
  success Test$execute()
}

concrete Test {
  @type execute () -> ()
}

define Test {
  execute () {
    // Pattern: "x"
    MatcherTemplate<Char> template <- MatchSingle<Char>$create('x')
    Matcher<Char> matcher <- template.newMatcher()

    MatchState state <- matcher.tryNextMatch('y')
    if (!(state `MatchState$equals` MatchState$matchFail())) {
      fail(state)
    }

    // Should keep failing to match.
    state <- matcher.tryNextMatch('x')
    if (!(state `MatchState$equals` MatchState$matchFail())) {
      fail(state)
    }
  }
}


testcase "MatchRange match" {
  success Test$execute()
}

concrete Test {
  @type execute () -> ()
}

define Test {
  execute () {
    // Pattern: "[w-y]"
    MatcherTemplate<Char> template <- MatchRange<Char>$create('w','y')
    Matcher<Char> matcher <- template.newMatcher()

    if (template.matchesEmpty()) {
      fail("matches empty")
    }
    if (matcher.matchSatisfied()) {
      fail("match satisfied")
    }

    MatchState state <- matcher.tryNextMatch('x')
    if (!(state `MatchState$equals` MatchState$matchComplete())) {
      fail(state)
    }
    if (!matcher.matchSatisfied()) {
      fail("match not satisfied")
    }

    // Should only match once.
    state <- matcher.tryNextMatch('x')
    if (!(state `MatchState$equals` MatchState$matchFail())) {
      fail(state)
    }
    if (matcher.matchSatisfied()) {
      fail("match satisfied")
    }

    // Should match again after reset.
    matcher <- template.newMatcher()
    state <- matcher.tryNextMatch('x')
    if (!(state `MatchState$equals` MatchState$matchComplete())) {
      fail(state)
    }
  }
}


testcase "MatchRange non-match" {
  success Test$execute()
}

concrete Test {
  @type execute () -> ()
}

define Test {
  execute () {
    // Pattern: "[w-y]"
    MatcherTemplate<Char> template <- MatchRange<Char>$create('w','y')
    Matcher<Char> matcher <- template.newMatcher()

    MatchState state <- matcher.tryNextMatch('a')
    if (!(state `MatchState$equals` MatchState$matchFail())) {
      fail(state)
    }

    // Should keep failing to match.
    state <- matcher.tryNextMatch('x')
    if (!(state `MatchState$equals` MatchState$matchFail())) {
      fail(state)
    }
  }
}


testcase "MatchAny" {
  success Test$execute()
}

concrete Test {
  @type execute () -> ()
}

define Test {
  execute () {
    // Pattern: "."
    MatcherTemplate<Char> template <- MatchAny$create()
    Matcher<Char> matcher <- template.newMatcher()

    if (template.matchesEmpty()) {
      fail("matches empty")
    }
    if (matcher.matchSatisfied()) {
      fail("match satisfied")
    }

    MatchState state <- matcher.tryNextMatch('x')
    if (!(state `MatchState$equals` MatchState$matchComplete())) {
      fail(state)
    }
    if (!matcher.matchSatisfied()) {
      fail("match not satisfied")
    }

    // Should only match once.
    state <- matcher.tryNextMatch('x')
    if (!(state `MatchState$equals` MatchState$matchFail())) {
      fail(state)
    }
    if (matcher.matchSatisfied()) {
      fail("match satisfied")
    }

    // Should match again after reset.
    matcher <- template.newMatcher()
    state <- matcher.tryNextMatch('x')
    if (!(state `MatchState$equals` MatchState$matchComplete())) {
      fail(state)
    }
  }
}


testcase "MatchEmpty" {
  success Test$execute()
}

concrete Test {
  @type execute () -> ()
}

define Test {
  execute () {
    // Pattern: ""
    MatcherTemplate<Char> template <- MatchEmpty$create()
    Matcher<Char> matcher <- template.newMatcher()

    if (!template.matchesEmpty()) {
      fail("doesn't match empty")
    }
    if (!matcher.matchSatisfied()) {
      fail("match not satisfied")
    }

    MatchState state <- matcher.tryNextMatch('x')
    if (!(state `MatchState$equals` MatchState$matchFail())) {
      fail(state)
    }
    if (matcher.matchSatisfied()) {
      fail("match satisfied")
    }

    // Should match again after reset.
    matcher <- template.newMatcher()
    if (!matcher.matchSatisfied()) {
      fail("match not satisfied")
    }
  }
}


testcase "MatchRepeat match" {
  success Test$execute()
}

concrete Test {
  @type execute () -> ()
}

define Test {
  execute () {
    // Pattern: "[w-y]{2,3}"
    MatcherTemplate<Char> template <-
        MatchRepeat<Char>$createRange(2,3,MatchRange<Char>$create('w','y'))
    Matcher<Char> matcher <- template.newMatcher()

    if (template.matchesEmpty()) {
      fail("matches empty")
    }
    if (matcher.matchSatisfied()) {
      fail("match satisfied")
    }

    MatchState state <- MatchState$matchFail()

    // First character.
    state <- matcher.tryNextMatch('x')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (matcher.matchSatisfied()) {
      fail("match satisfied")
    }

    // Second character.
    state <- matcher.tryNextMatch('y')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (!matcher.matchSatisfied()) {
      fail("match not satisfied")
    }

    // Third character.
    state <- matcher.tryNextMatch('x')
    if (!(state `MatchState$equals` MatchState$matchComplete())) {
      fail(state)
    }

    // Fourth character.
    state <- matcher.tryNextMatch('x')
    if (!(state `MatchState$equals` MatchState$matchFail())) {
      fail(state)
    }
    if (!matcher.matchSatisfied()) {
      fail("match not satisfied")
    }

    // Reset to reuse the matcher.
    matcher <- template.newMatcher()

    // Fourth character.
    state <- matcher.tryNextMatch('w')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (matcher.matchSatisfied()) {
      fail("match satisfied")
    }

    // Fifth character.
    state <- matcher.tryNextMatch('w')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (!matcher.matchSatisfied()) {
      fail("match not satisfied")
    }
  }
}


testcase "MatchRepeat nested" {
  success Test$execute()
}

concrete Test {
  @type execute () -> ()
}

define Test {
  execute () {
    // Pattern: "(x*){2,}"
    MatcherTemplate<Char> template <-
        MatchRepeat<Char>$createRange(2,0,
            MatchRepeat<Char>$createZeroPlus(MatchSingle<Char>$create('x')))
    Matcher<Char> matcher <- template.newMatcher()

    if (!template.matchesEmpty()) {
      fail("doesn't match empty")
    }
    if (!matcher.matchSatisfied()) {
      fail("match not satisfied")
    }

    MatchState state <- MatchState$matchFail()

    // First character.
    state <- matcher.tryNextMatch('x')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (!matcher.matchSatisfied()) {
      fail("match not satisfied")
    }

    // Second character.
    state <- matcher.tryNextMatch('x')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (!matcher.matchSatisfied()) {
      fail("match not satisfied")
    }

    // Third character.
    state <- matcher.tryNextMatch('x')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (!matcher.matchSatisfied()) {
      fail("match not satisfied")
    }
  }
}


testcase "MatchRepeat non-match" {
  success Test$execute()
}

concrete Test {
  @type execute () -> ()
}

define Test {
  execute () {
    // Pattern: "[w-y]{2,3}"
    MatcherTemplate<Char> template <-
        MatchRepeat<Char>$createRange(2,3,MatchRange<Char>$create('w','y'))
    Matcher<Char> matcher <- template.newMatcher()

    MatchState state <- MatchState$matchFail()

    // First character.
    state <- matcher.tryNextMatch('x')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (matcher.matchSatisfied()) {
      fail("match satisfied")
    }

    // Second character.
    state <- matcher.tryNextMatch('q')
    if (!(state `MatchState$equals` MatchState$matchFail())) {
      fail(state)
    }
    if (matcher.matchSatisfied()) {
      fail("match satisfied")
    }

    // Should keep failing to match.
    state <- matcher.tryNextMatch('x')
    if (!(state `MatchState$equals` MatchState$matchFail())) {
      fail(state)
    }
  }
}


testcase "MatchRepeat optional suffix" {
  success Test$execute()
}

concrete Test {
  @type execute () -> ()
}

define Test {
  execute () {
    // Pattern: "(ab*)*"
    MatcherTemplate<Char> template <-
        MatchRepeat<Char>$createZeroPlus(
            MatchBranches<Char>$create(
                BranchSequence<Char>$create(
                    LinkedNode<MatcherTemplate<Char>>$create(MatchSingle<Char>$create('a'),
                        LinkedNode<MatcherTemplate<Char>>$create(
                            MatchRepeat<Char>$createZeroPlus(MatchSingle<Char>$create('b')),empty)))))
    Matcher<Char> matcher <- template.newMatcher()

    if (!matcher.matchSatisfied()) {
      fail("match not satisfied")
    }

    MatchState state <- MatchState$matchFail()

    // First character.
    state <- matcher.tryNextMatch('a')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (!matcher.matchSatisfied()) {
      fail("match not satisfied")
    }

    // Second character.
    state <- matcher.tryNextMatch('b')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (!matcher.matchSatisfied()) {
      fail("match not satisfied")
    }

    // Third character.
    state <- matcher.tryNextMatch('a')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (!matcher.matchSatisfied()) {
      fail("match not satisfied")
    }
  }
}


testcase "MatchChoices match" {
  success Test$execute()
}

concrete Test {
  @type execute () -> ()
}

define Test {
  execute () {
    // Pattern: "[w-y]|a*"
    MatcherTemplate<Char> template <-
        MatchChoices<Char>$create(
            LinkedNode<MatcherTemplate<Char>>$create(MatchRange<Char>$create('w','y'),
                LinkedNode<MatcherTemplate<Char>>$create(
                    MatchBranches<Char>$create(
                        BranchRepeat<Char>$createZeroPlus(MatchSingle<Char>$create('a'))),empty)))
    Matcher<Char> matcher <- template.newMatcher()

    MatchState state <- MatchState$matchFail()

    if (!template.matchesEmpty()) {
      fail("doesn't match empty")
    }
    if (!matcher.matchSatisfied()) {
      fail("match not satisfied")
    }

    // First character.
    state <- matcher.tryNextMatch('a')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }

    // Second character.
    state <- matcher.tryNextMatch('a')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }

    // Third character.
    state <- matcher.tryNextMatch('x')
    if (!(state `MatchState$equals` MatchState$matchFail())) {
      fail(state)
    }

    // Reset to reuse the matcher.
    matcher <- template.newMatcher()

    // First character.
    state <- matcher.tryNextMatch('x')
    if (!(state `MatchState$equals` MatchState$matchComplete())) {
      fail(state)
    }
  }
}


testcase "MatchChoices non-match" {
  success Test$execute()
}

concrete Test {
  @type execute () -> ()
}

define Test {
  execute () {
    // Pattern: "[w-y]|a*"
    MatcherTemplate<Char> template <-
        MatchChoices<Char>$create(
            LinkedNode<MatcherTemplate<Char>>$create(MatchRange<Char>$create('w','y'),
                LinkedNode<MatcherTemplate<Char>>$create(
                    MatchBranches<Char>$create(
                        BranchRepeat<Char>$createZeroPlus(MatchSingle<Char>$create('a'))),empty)))
    Matcher<Char> matcher <- template.newMatcher()

    if (!template.matchesEmpty()) {
      fail("doesn't match empty")
    }
    if (!matcher.matchSatisfied()) {
      fail("match not satisfied")
    }

    MatchState state <- MatchState$matchFail()

    // First character.
    state <- matcher.tryNextMatch('a')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }

    // Should keep failing to match.
    state <- matcher.tryNextMatch('x')
    if (!(state `MatchState$equals` MatchState$matchFail())) {
      fail(state)
    }
  }
}


testcase "MatchChoices empty choice" {
  success Test$execute()
}

concrete Test {
  @type execute () -> ()
}

define Test {
  execute () {
    // Pattern: "[w-y]|a{2,2}|"
    MatcherTemplate<Char> template <-
        MatchChoices<Char>$create(
            LinkedNode<MatcherTemplate<Char>>$create(MatchRange<Char>$create('w','y'),
                LinkedNode<MatcherTemplate<Char>>$create(
                    MatchBranches<Char>$create(
                        BranchRepeat<Char>$createRange(2,2,MatchSingle<Char>$create('a'))),
                    LinkedNode<MatcherTemplate<Char>>$create(
                        MatchEmpty$create(),empty))))
    Matcher<Char> matcher <- template.newMatcher()

    if (!template.matchesEmpty()) {
      fail("doesn't match empty")
    }
    if (!matcher.matchSatisfied()) {
      fail("match not satisfied")
    }

    MatchState state <- MatchState$matchFail()

    // First character.
    state <- matcher.tryNextMatch('a')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (matcher.matchSatisfied()) {
      fail("match satisfied")
    }
  }
}


testcase "BranchRepeat match" {
  success Test$execute()
}

concrete Test {
  @type execute () -> ()
}

define Test {
  execute () {
    // Pattern: "[w-y]{2,3}"
    MatchBrancherTemplate<Char> template <-
        BranchRepeat<Char>$createRange(2,3,MatchRange<Char>$create('w','y'))
    MatchBrancher<Char> brancher <- template.newBrancher()

    if (template.matchesEmpty()) {
      fail("matches empty")
    }
    if (brancher.matchSatisfied()) {
      fail("match satisfied")
    }

    MatchState state <- MatchState$matchFail()
    optional ReadSequence<MatchBrancher<Char>> branches <- empty

    // First character.
    { state, branches } <- brancher.tryBranches('x')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (!present(branches)) {
      fail("branch missing")
    }

    brancher <- require(branches).value()
    if (brancher.matchSatisfied()) {
      fail("match satisfied")
    }
    branches <- require(branches).next()
    if (present(branches)) {
      fail("branch present")
    }

    // Second character.
    { state, branches } <- brancher.tryBranches('y')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (!present(branches)) {
      fail("branch missing")
    }
    if (!brancher.matchSatisfied()) {
      fail("match not satisfied")
    }

    brancher <- require(branches).value()
    branches <- require(branches).next()
    if (present(branches)) {
      fail("branch present")
    }

    // Third character.
    { state, branches } <- brancher.tryBranches('x')
    if (!(state `MatchState$equals` MatchState$matchComplete())) {
      fail(state)
    }
    if (present(branches)) {
      fail("branch present")
    }

    // Reset to reuse the brancher.
    brancher <- template.newBrancher()

    // Fourth character.
    { state, branches } <- brancher.tryBranches('w')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (!present(branches)) {
      fail("branch missing")
    }
  }
}


testcase "BranchRepeat nested" {
  success Test$execute()
}

concrete Test {
  @type execute () -> ()
}

define Test {
  execute () {
    // Pattern: "(x*){2,}"
    MatchBrancherTemplate<Char> template <-
        BranchRepeat<Char>$createRange(2,0,
            MatchBranches<Char>$create(
                BranchRepeat<Char>$createZeroPlus(MatchSingle<Char>$create('x'))))
    MatchBrancher<Char> brancher <- template.newBrancher()

    if (!template.matchesEmpty()) {
      fail("doesn't match empty")
    }
    if (!brancher.matchSatisfied()) {
      fail("match not satisfied")
    }

    MatchState state <- MatchState$matchFail()
    optional ReadSequence<MatchBrancher<Char>> branches <- empty

    // First character.
    { state, branches } <- brancher.tryBranches('x')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (!present(branches)) {
      fail("branch missing")
    }

    brancher <- require(branches).value()
    if (!brancher.matchSatisfied()) {
      fail("match not satisfied")
    }
    branches <- require(branches).next()
    if (present(branches)) {
      fail("branch present")
    }

    // Second character.
    { state, branches } <- brancher.tryBranches('x')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (!present(branches)) {
      fail("branch missing")
    }

    brancher <- require(branches).value()
    if (!brancher.matchSatisfied()) {
      fail("match not satisfied")
    }
    // Expect one additional branch to continue "xx*".
    branches <- require(branches).next()
    if (!present(branches)) {
      fail("branch missing")
    }

    // Third character, branch 1.
    { state, _ } <- brancher.tryBranches('x')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }

    brancher <- require(branches).value()
    if (!brancher.matchSatisfied()) {
      fail("match not satisfied")
    }
    // No more branches expected.
    branches <- require(branches).next()
    if (present(branches)) {
      fail("branch present")
    }

    // Third character, branch 2.
    { state, _ } <- brancher.tryBranches('x')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
  }
}


testcase "BranchRepeat non-match" {
  success Test$execute()
}

concrete Test {
  @type execute () -> ()
}

define Test {
  execute () {
    // Pattern: "[w-y]{2,3}"
    MatchBrancherTemplate<Char> template <-
        BranchRepeat<Char>$createRange(2,3,MatchRange<Char>$create('w','y'))
    MatchBrancher<Char> brancher <- template.newBrancher()

    MatchState state <- MatchState$matchFail()
    optional ReadSequence<MatchBrancher<Char>> branches <- empty

    // First character.
    { state, branches } <- brancher.tryBranches('x')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (!present(branches)) {
      fail("branch missing")
    }

    brancher <- require(branches).value()
    if (brancher.matchSatisfied()) {
      fail("match satisfied")
    }
    branches <- require(branches).next()
    if (present(branches)) {
      fail("branch present")
    }

    // Second character.
    { state, branches } <- brancher.tryBranches('q')
    if (!(state `MatchState$equals` MatchState$matchFail())) {
      fail(state)
    }
    if (present(branches)) {
      fail("branch present")
    }
  }
}


testcase "BranchSequence match" {
  success Test$execute()
}

concrete Test {
  @type execute () -> ()
}

define Test {
  execute () {
    // Pattern: "[w-y]a"
    MatchBrancherTemplate<Char> template <-
        BranchSequence<Char>$create(
            LinkedNode<MatcherTemplate<Char>>$create(MatchRange<Char>$create('w','y'),
                LinkedNode<MatcherTemplate<Char>>$create(MatchSingle<Char>$create('a'),empty)))
    MatchBrancher<Char> brancher <- template.newBrancher()

    if (template.matchesEmpty()) {
      fail("matches empty")
    }
    if (brancher.matchSatisfied()) {
      fail("match satisfied")
    }

    MatchState state <- MatchState$matchFail()
    optional ReadSequence<MatchBrancher<Char>> branches <- empty

    // First character.
    { state, branches } <- brancher.tryBranches('x')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (!present(branches)) {
      fail("branch missing")
    }

    brancher <- require(branches).value()
    branches <- require(branches).next()
    if (present(branches)) {
      fail("branch present")
    }

    // Second character.
    { state, branches } <- brancher.tryBranches('a')
    if (!(state `MatchState$equals` MatchState$matchComplete())) {
      fail(state)
    }
    if (!present(branches)) {
      fail("branch missing")
    }

    // The final branch should just be a record of completeness.
    if (!require(branches).value().matchSatisfied()) {
      fail("match not satisfied")
    }
    { state, branches } <- require(branches).value().tryBranches('a')
    if (!(state `MatchState$equals` MatchState$matchFail())) {
      fail(state)
    }

    // Reset to reuse the brancher.
    brancher <- template.newBrancher()

    // Third character.
    { state, branches } <- brancher.tryBranches('y')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (!present(branches)) {
      fail("branch missing")
    }
  }
}


testcase "BranchSequence non-match" {
  success Test$execute()
}

concrete Test {
  @type execute () -> ()
}

define Test {
  execute () {
    // Pattern: "[w-y]a"
    MatchBrancherTemplate<Char> template <-
        BranchSequence<Char>$create(
            LinkedNode<MatcherTemplate<Char>>$create(MatchRange<Char>$create('w','y'),
                LinkedNode<MatcherTemplate<Char>>$create(MatchSingle<Char>$create('a'),empty)))
    MatchBrancher<Char> brancher <- template.newBrancher()

    MatchState state <- MatchState$matchFail()
    optional ReadSequence<MatchBrancher<Char>> branches <- empty

    // First character.
    { state, branches } <- brancher.tryBranches('q')
    if (!(state `MatchState$equals` MatchState$matchFail())) {
      fail(state)
    }
    if (present(branches)) {
      fail("branch present")
    }

    // Should keep failing to match.
    { state, branches } <- brancher.tryBranches('x')
    if (!(state `MatchState$equals` MatchState$matchFail())) {
      fail(state)
    }
  }
}


testcase "BranchSequence skip empty failed" {
  success Test$execute()
}

concrete Test {
  @type execute () -> ()
}

define Test {
  execute () {
    // Pattern: "a*b"
    MatchBrancherTemplate<Char> template <-
        BranchSequence<Char>$create(
            LinkedNode<MatcherTemplate<Char>>$create(
                MatchBranches<Char>$create(
                    BranchRepeat<Char>$createZeroPlus(MatchSingle<Char>$create('a'))),
                LinkedNode<MatcherTemplate<Char>>$create(
                    MatchSingle<Char>$create('b'),empty)))
    MatchBrancher<Char> brancher <- template.newBrancher()

    if (template.matchesEmpty()) {
      fail("matches empty")
    }
    if (brancher.matchSatisfied()) {
      fail("match satisfied")
    }

    MatchState state <- MatchState$matchFail()
    optional ReadSequence<MatchBrancher<Char>> branches <- empty

    // First character.
    { state, branches } <- brancher.tryBranches('b')
    if (!(state `MatchState$equals` MatchState$matchComplete())) {
      fail(state)
    }
    if (!present(branches)) {
      fail("branch missing")
    }
  }
}


testcase "BranchSequence fail non-empty field" {
  success Test$execute()
}

concrete Test {
  @type execute () -> ()
}

define Test {
  execute () {
    // Pattern: "a+b"
    MatchBrancherTemplate<Char> template <-
        BranchSequence<Char>$create(
            LinkedNode<MatcherTemplate<Char>>$create(
                MatchBranches<Char>$create(
                    BranchRepeat<Char>$createOnePlus(MatchSingle<Char>$create('a'))),
                LinkedNode<MatcherTemplate<Char>>$create(
                    MatchSingle<Char>$create('b'),empty)))
    MatchBrancher<Char> brancher <- template.newBrancher()

    if (template.matchesEmpty()) {
      fail("matches empty")
    }
    if (brancher.matchSatisfied()) {
      fail("match satisfied")
    }

    MatchState state <- MatchState$matchFail()
    optional ReadSequence<MatchBrancher<Char>> branches <- empty

    // First character.
    { state, branches } <- brancher.tryBranches('b')
    if (!(state `MatchState$equals` MatchState$matchFail())) {
      fail(state)
    }
    if (present(branches)) {
      fail("branch present")
    }
  }
}


testcase "BranchSequence branch sequence multi-match" {
  success Test$execute()
}

concrete Test {
  @type execute () -> ()
}

define Test {
  execute () {
    // Pattern: "a*a{0,2}"
    MatchBrancherTemplate<Char> template <-
        BranchSequence<Char>$create(
            LinkedNode<MatcherTemplate<Char>>$create(
                MatchBranches<Char>$create(
                    BranchRepeat<Char>$createZeroPlus(MatchSingle<Char>$create('a'))),
                LinkedNode<MatcherTemplate<Char>>$create(
                    MatchBranches<Char>$create(
                        BranchRepeat<Char>$createRange(0,2,MatchSingle<Char>$create('a'))),empty)))
    MatchBrancher<Char> brancher <- template.newBrancher()

    if (!template.matchesEmpty()) {
      fail("doesn't match empty")
    }
    if (!brancher.matchSatisfied()) {
      fail("match not satisfied")
    }

    MatchState state <- MatchState$matchFail()
    optional ReadSequence<MatchBrancher<Char>> branches <- empty

    // First character.
    { state, branches } <- brancher.tryBranches('a')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (!present(branches)) {
      fail("branch missing")
    }

    brancher <- require(branches).value()
    branches <- require(branches).next()
    if (!present(branches)) {
      fail("branch missing")
    }

    // TODO: This assumes that the branches are ordered from longest to shortest
    // remaining sequence.

    // Second character, branch 1.
    { state, _ } <- brancher.tryBranches('a')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }

    brancher <- require(branches).value()
    branches <- require(branches).next()
    if (present(branches)) {
      fail("branch present")
    }

    // Second character, branch 2.
    { state, _ } <- brancher.tryBranches('a')
    if (!(state `MatchState$equals` MatchState$matchComplete())) {
      fail(state)
    }
  }
}


testcase "MatchBranches match" {
  success Test$execute()
}

concrete Test {
  @type execute () -> ()
}

define Test {
  execute () {
    // Pattern: "[w-y]a"
    MatcherTemplate<Char> template <-
        MatchBranches<Char>$create(
            BranchSequence<Char>$create(
                LinkedNode<MatcherTemplate<Char>>$create(MatchRange<Char>$create('w','y'),
                    LinkedNode<MatcherTemplate<Char>>$create(MatchSingle<Char>$create('a'),empty))))
    Matcher<Char> matcher <- template.newMatcher()

    if (template.matchesEmpty()) {
      fail("matches empty")
    }
    if (matcher.matchSatisfied()) {
      fail("match satisfied")
    }

    MatchState state <- MatchState$matchFail()

    // First character.
    state <- matcher.tryNextMatch('x')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (matcher.matchSatisfied()) {
      fail("match satisfied")
    }

    // Second character.
    state <- matcher.tryNextMatch('a')
    if (!(state `MatchState$equals` MatchState$matchComplete())) {
      fail(state)
    }
    if (!matcher.matchSatisfied()) {
      fail("match not satisfied")
    }

    // Reset to reuse the matcher.
    matcher <- template.newMatcher()

    // Third character.
    state <- matcher.tryNextMatch('y')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
  }
}


testcase "MatchBranches non-match" {
  success Test$execute()
}

concrete Test {
  @type execute () -> ()
}

define Test {
  execute () {
    // Pattern: "[w-y]a"
    MatcherTemplate<Char> template <-
        MatchBranches<Char>$create(
            BranchSequence<Char>$create(
                LinkedNode<MatcherTemplate<Char>>$create(MatchRange<Char>$create('w','y'),
                    LinkedNode<MatcherTemplate<Char>>$create(MatchSingle<Char>$create('a'),empty))))
    Matcher<Char> matcher <- template.newMatcher()

    if (template.matchesEmpty()) {
      fail("matches empty")
    }
    if (matcher.matchSatisfied()) {
      fail("match satisfied")
    }

    MatchState state <- MatchState$matchFail()

    // First character.
    state <- matcher.tryNextMatch('x')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (matcher.matchSatisfied()) {
      fail("match satisfied")
    }

    // Second character.
    state <- matcher.tryNextMatch('q')
    if (!(state `MatchState$equals` MatchState$matchFail())) {
      fail(state)
    }
    if (matcher.matchSatisfied()) {
      fail("match satisfied")
    }

    // Should keep failing to match.
    state <- matcher.tryNextMatch('y')
    if (!(state `MatchState$equals` MatchState$matchFail())) {
      fail(state)
    }
  }
}


testcase "MatchBranches branched match" {
  success Test$execute()
}

concrete Test {
  @type execute () -> ()
}

define Test {
  execute () {
    // Pattern: "ab"
    MatcherTemplate<Char> templateAB <-
        MatchBranches<Char>$create(
            BranchSequence<Char>$create(
                LinkedNode<MatcherTemplate<Char>>$create(MatchSingle<Char>$create('a'),
                    LinkedNode<MatcherTemplate<Char>>$create(MatchSingle<Char>$create('b'),empty))))
    // Pattern: "ac"
    MatcherTemplate<Char> templateAC <-
        MatchBranches<Char>$create(
            BranchSequence<Char>$create(
                LinkedNode<MatcherTemplate<Char>>$create(MatchSingle<Char>$create('a'),
                    LinkedNode<MatcherTemplate<Char>>$create(MatchSingle<Char>$create('c'),empty))))
    // Pattern: "(ab)*ac"
    MatcherTemplate<Char> template <-
        MatchBranches<Char>$create(
            BranchSequence<Char>$create(
                LinkedNode<MatcherTemplate<Char>>$create(
                    MatchBranches<Char>$create(
                        BranchRepeat<Char>$createZeroPlus(templateAB)),
                    LinkedNode<MatcherTemplate<Char>>$create(templateAC,empty))))
    Matcher<Char> matcher <- template.newMatcher()

    MatchState state <- MatchState$matchFail()

    // First character.
    state <- matcher.tryNextMatch('a')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (matcher.matchSatisfied()) {
      fail("match satisfied")
    }

    // Second character.
    state <- matcher.tryNextMatch('c')
    if (!(state `MatchState$equals` MatchState$matchComplete())) {
      fail(state)
    }
    if (!matcher.matchSatisfied()) {
      fail("match not satisfied")
    }

    // Reset to reuse the matcher.
    matcher <- template.newMatcher()

    // First character.
    state <- matcher.tryNextMatch('a')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (matcher.matchSatisfied()) {
      fail("match satisfied")
    }

    // Second character.
    state <- matcher.tryNextMatch('b')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (matcher.matchSatisfied()) {
      fail("match satisfied")
    }
  }
}


testcase "MatchBranches partial repeat" {
  success Test$execute()
}

concrete Test {
  @type execute () -> ()
}

define Test {
  execute () {
    // Pattern: "(ab)*"
    MatcherTemplate<Char> template <-
        MatchBranches<Char>$create(
            BranchRepeat<Char>$createZeroPlus(
                MatchBranches<Char>$create(
                    BranchSequence<Char>$create(
                        LinkedNode<MatcherTemplate<Char>>$create(MatchSingle<Char>$create('a'),
                            LinkedNode<MatcherTemplate<Char>>$create(MatchSingle<Char>$create('b'),empty))))))
    Matcher<Char> matcher <- template.newMatcher()

    if (!matcher.matchSatisfied()) {
      fail("match not satisfied")
    }

    MatchState state <- MatchState$matchFail()

    // First character.
    state <- matcher.tryNextMatch('a')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (matcher.matchSatisfied()) {
      fail("match satisfied")
    }

    // Second character.
    state <- matcher.tryNextMatch('b')
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      fail(state)
    }
    if (!matcher.matchSatisfied()) {
      fail("match not satisfied")
    }
  }
}