packages feed

zeolite-lang-0.3.0.0: example/regex/regex.0rx

define MatchState {
  @value Int enum
  @value String name
  @category MatchState matchFailVal     <- MatchState{ 0, "matchFail" }
  @category MatchState matchCompleteVal <- MatchState{ 1, "matchComplete" }
  @category MatchState matchContinueVal <- MatchState{ 2, "matchContinue" }

  formatted () {
    return "MatchState$" + name + "()"
  }

  equals (x,y) {
    return x.getEnum() == y.getEnum()
  }

  lessThan (x,y) {
    return x.getEnum() < y.getEnum()
  }

  matchFail () {
    return matchFailVal
  }

  matchComplete () {
    return matchCompleteVal
  }

  matchContinue () {
    return matchContinueVal
  }

  @value getEnum () -> (Int)
  getEnum () {
    return enum
  }
}

define MatchSingle {
  @value #c match

  create (match) {
    return MatchSingle<#c>{ match }
  }

  matchesEmpty () {
    return false
  }

  newMatcher () {
    return MatchSingleMatcher<#c>$create(match)
  }
}

concrete MatchSingleMatcher<#c> {
  #c defines Equals<#c>

  refines Matcher<#c>

  @type create (#c) -> (MatchSingleMatcher<#c>)
}

define MatchSingleMatcher {
  @value #c match
  @value MatchState state

  create (match) {
    return MatchSingleMatcher<#c>{ match, MatchState$matchContinue() }
  }

  matchSatisfied () {
    return state `MatchState$equals` MatchState$matchComplete()
  }

  tryNextMatch (data) {
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      return (state <- MatchState$matchFail())
    }
    if (data `#c$equals` match) {
      return (state <- MatchState$matchComplete())
    } else {
      return (state <- MatchState$matchFail())
    }
  }
}

define MatchRange {
  @value #c minMatch
  @value #c maxMatch

  create (minMatch,maxMatch) {
    return MatchRange<#c>{ minMatch, maxMatch }
  }

  matchesEmpty () {
    return false
  }

  newMatcher () {
    return MatchRangeMatcher<#c>$create(minMatch,maxMatch)
  }
}

concrete MatchRangeMatcher<#c> {
  #c defines LessThan<#c>

  refines Matcher<#c>

  @type create (#c,#c) -> (MatchRangeMatcher<#c>)
}

define MatchRangeMatcher {
  @value #c minMatch
  @value #c maxMatch
  @value MatchState state

  create (minMatch,maxMatch) {
    return MatchRangeMatcher<#c>{ minMatch, maxMatch, MatchState$matchContinue() }
  }

  matchSatisfied () {
    return state `MatchState$equals` MatchState$matchComplete()
  }

  tryNextMatch (data) {
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      return (state <- MatchState$matchFail())
    }
    if (!(data `#c$lessThan` minMatch) && !(maxMatch `#c$lessThan` data)) {
      return (state <- MatchState$matchComplete())
    } else {
      return (state <- MatchState$matchFail())
    }
  }
}

define MatchAny {
  create () {
    return MatchAny{ }
  }

  matchesEmpty () {
    return false
  }

  newMatcher () {
    return MatchAnyMatcher$create()
  }
}

concrete MatchAnyMatcher {
  refines Matcher<any>

  @type create () -> (MatchAnyMatcher)
}

define MatchAnyMatcher {
  @value MatchState state

  create () {
    return MatchAnyMatcher{ MatchState$matchContinue() }
  }

  matchSatisfied () {
    return state `MatchState$equals` MatchState$matchComplete()
  }

  tryNextMatch (data) {
    if (!(state `MatchState$equals` MatchState$matchContinue())) {
      return (state <- MatchState$matchFail())
    }
    return (state <- MatchState$matchComplete())
  }
}

define MatchEmpty {
  create () {
    return MatchEmpty{ }
  }

  matchesEmpty () {
    return true
  }

  newMatcher () {
    return MatchEmptyMatcher$create()
  }
}

concrete MatchEmptyMatcher {
  refines Matcher<any>

  @type create () -> (MatchEmptyMatcher)
}

define MatchEmptyMatcher {
  @value Bool failed

  create () {
    return MatchEmptyMatcher{ false }
  }

  matchSatisfied () {
    return !failed
  }

  tryNextMatch (data) {
    failed <- true
    return MatchState$matchFail()
  }
}

define MatchRepeat {
  @value MatcherTemplate<#c> template
  @value Int minCount
  @value Int maxCount

  createZeroPlus (template) {
    return createRange(0,0,template)
  }

  createOnePlus (template) {
    return createRange(1,0,template)
  }

  createRange (minCount,maxCount,template) {
    return MatchRepeat<#c>{ template, minCount, maxCount }
  }

  matchesEmpty () {
    return minCount <= 0 || template.matchesEmpty()
  }

  newMatcher () {
    return MatchRepeatMatcher<#c>$create(minCount,maxCount,template)
  }
}

concrete MatchRepeatMatcher<#c> {
  refines Matcher<#c>

  @type create (Int,Int,MatcherTemplate<#c>) -> (MatchRepeatMatcher<#c>)
}

define MatchRepeatMatcher {
  @value MatcherTemplate<#c> template
  @value Matcher<#c> matcher
  @value Int minCount
  @value Int maxCount // 0 means unlimited.
  @value Int repetitionCount
  @value MatchState lastState

  create (minCount,maxCount,template) {
    return MatchRepeatMatcher<#c>{ template, template.newMatcher(), minCount,
                                   maxCount, 0, MatchState$matchComplete() }
  }

  matchSatisfied () {
    if (lastState `MatchState$equals` MatchState$matchFail()) {
      return false
    }
    if (lastState `MatchState$equals` MatchState$matchContinue() &&
        (repetitionCount+1 >= minCount || template.matchesEmpty()) &&
        matcher.matchSatisfied()) {
      // The rest of the current repetition can be ignored.
      return true
    }
    if (lastState `MatchState$equals` MatchState$matchComplete() &&
        (repetitionCount >= minCount || template.matchesEmpty())) {
      return true
    }
    return false
  }

  tryNextMatch (data) (state) {
    if (atMax() || lastState `MatchState$equals` MatchState$matchFail()) {
      return MatchState$matchFail()
    }
    Bool canSkip <- matcher.matchSatisfied()
    state <- matcher.tryNextMatch(data)
    if (state `MatchState$equals` MatchState$matchFail() &&
        lastState `MatchState$equals` MatchState$matchContinue() && canSkip) {
      // Handle the case where an optional end to the pattern can be skipped.
      \ incrementMatch()
      \ startRepeat()
      state <- matcher.tryNextMatch(data)
    }
    lastState <- state
    if (state `MatchState$equals` MatchState$matchComplete()) {
      \ incrementMatch()
      \ startRepeat()
      if (atMax()) {
        state <- MatchState$matchComplete()
      } else {
        state <- MatchState$matchContinue()
      }
    }
  }

  @value incrementMatch () -> ()
  incrementMatch () {
    repetitionCount <- repetitionCount+1
  }

  @value atMax () -> (Bool)
  atMax () {
    return maxCount > 0 && repetitionCount >= maxCount
  }

  @value startRepeat () -> ()
  startRepeat () {
    matcher <- template.newMatcher()
  }
}

define MatchChoices {
  @value optional ReadSequence<MatcherTemplate<#c>> choices

  create (choices) {
    return MatchChoices<#c>{ choices }
  }

  matchesEmpty () {
    scoped {
      optional ReadSequence<MatcherTemplate<#c>> current <- choices
    } in while (present(current)) {
      if (require(current).value().matchesEmpty()) {
        return true
      }
    } update {
      current <- require(current).next()
    }
    return false
  }

  newMatcher () {
    return MatchChoicesMatcher<#c>$create(recursiveNewMatcher(choices))
  }

  @type recursiveNewMatcher (optional ReadSequence<MatcherTemplate<#c>>) ->
                            (optional ReadSequence<Matcher<#c>>)
  recursiveNewMatcher (choices) {
    if (!present(choices)) {
      return empty
    }
    return LinkedNode<Matcher<#c>>$create(require(choices).value().newMatcher(),
                                          recursiveNewMatcher(require(choices).next()))
  }
}

concrete MatchChoicesMatcher<#c> {
  refines Matcher<#c>

  @type create (optional ReadSequence<Matcher<#c>>) -> (MatchChoicesMatcher<#c>)
}

define MatchChoicesMatcher {
  @value optional ReadSequence<Matcher<#c>> choices

  create (choices) {
    return MatchChoicesMatcher<#c>{ choices }
  }

  matchSatisfied () {
    scoped {
      optional ReadSequence<Matcher<#c>> current <- choices
    } in while (present(current)) {
      if (require(current).value().matchSatisfied()) {
        return true
      }
    } update {
      current <- require(current).next()
    }
    return false
  }

  tryNextMatch (data) (state) {
    state <- MatchState$matchFail()
    scoped {
      optional ReadSequence<Matcher<#c>> current <- choices
    } in while (present(current)) {
      // NOTE: Failing matchers are left in for simplicity, under the assumption
      // that they will keep failing.
      MatchState state2 <- require(current).value().tryNextMatch(data)
      if (state `MatchState$lessThan` state2) {
        state <- state2
      }
    } update {
      current <- require(current).next()
    }
  }
}

define MatchBranches {
  @value MatchBrancherTemplate<#c> template

  create (template) {
    return MatchBranches<#c>{ template }
  }

  matchesEmpty () {
    return template.matchesEmpty()
  }

  newMatcher () {
    return MatchBranchesMatcher<#c>$create(template.newBrancher())
  }
}

concrete MatchBranchesMatcher<#c> {
  refines Matcher<#c>

  @type create (MatchBrancher<#c>) -> (MatchBranchesMatcher<#c>)
}

define MatchBranchesMatcher {
  @value optional ReadSequence<MatchBrancher<#c>> branches
  @value Bool complete

  create (brancher) {
    return MatchBranchesMatcher<#c>{ LinkedNode<MatchBrancher<#c>>$create(brancher,empty), false }
  }

  matchSatisfied () {
    if (complete) {
      return true
    }
    scoped {
      optional ReadSequence<MatchBrancher<#c>> current <- branches
    } in while (present(current)) {
      if (require(current).value().matchSatisfied()) {
        return true
      }
    } update {
      current <- require(current).next()
    }
    return false
  }

  tryNextMatch (data) (state) {
    state <- MatchState$matchFail()
    optional ReadSequence<MatchBrancher<#c>> current <- branches
    branches <- empty
    complete <- false
    scoped {
    } in while(present(current)) {
      MatchState state2, optional ReadSequence<MatchBrancher<#c>> branches2 <-
          require(current).value().tryBranches(data)
      if (state2 `MatchState$equals` MatchState$matchComplete()) {
        complete <- true
      }
      if (state `MatchState$lessThan` state2) {
        state <- state2
      }
      branches <- LinkedNode<MatchBrancher<#c>>$concatSequences(branches2,branches)
    } update {
      current <- require(current).next()
    }
  }
}

concrete BranchRepeatMatcher<#c> {
  refines MatchBrancher<#c>

  @type create (Int,Int,MatcherTemplate<#c>) -> (BranchRepeatMatcher<#c>)
  @value tryBranches (#c) -> (MatchState,optional ReadSequence<BranchRepeatMatcher<#c>>)
}

define BranchRepeatMatcher {
  @value MatcherTemplate<#c> template
  @value Matcher<#c> matcher
  @value Int minCount
  @value Int maxCount // 0 means unlimited.
  @value Int repetitionCount
  @value MatchState lastState

  create (minCount,maxCount,template) {
    return BranchRepeatMatcher<#c>{ template, template.newMatcher(), minCount,
                                    maxCount, 0, MatchState$matchComplete() }
  }

  matchSatisfied () {
    if (lastState `MatchState$equals` MatchState$matchFail()) {
      return false
    }
    if (lastState `MatchState$equals` MatchState$matchContinue() &&
        (repetitionCount+1 >= minCount || template.matchesEmpty()) &&
        matcher.matchSatisfied()) {
      // The rest of the current repetition can be ignored.
      return true
    }
    if (lastState `MatchState$equals` MatchState$matchComplete() &&
        (repetitionCount >= minCount || template.matchesEmpty())) {
      return true
    }
    return false
  }

  tryBranches (data) (state,branch) {
    state <- MatchState$matchFail()
    branch <- empty
    if (atMax() || lastState `MatchState$equals` MatchState$matchFail()) {
      return _
    }
    if (lastState `MatchState$equals` MatchState$matchContinue()) {
      // Handle a possible single branch.
      Bool canSkip <- matcher.matchSatisfied()
      state <- matcher.tryNextMatch(data)
      if (canSkip) {
        if (state `MatchState$equals` MatchState$matchContinue()) {
          // Add a branch for the optional suffix.
          branch <- LinkedNode<BranchRepeatMatcher<#c>>$create(
              BranchRepeatMatcher<#c>{ template, matcher, minCount,
                                       maxCount, repetitionCount,
                                       MatchState$matchContinue() },empty)
        }
        // Continue, skipping over the optional suffix.
        \ incrementMatch()
        \ startRepeat()
        if (atMax()) {
          // Skipping the branch puts us at the max.
          return _
        }
        state <- matcher.tryNextMatch(data)
      }
    } else {
      // Branching is not possible.
      state <- matcher.tryNextMatch(data)
    }
    lastState <- state
    if (state `MatchState$equals` MatchState$matchComplete()) {
      \ incrementMatch()
      \ startRepeat()
      if (!atMax()) {
        branch <- LinkedNode<BranchRepeatMatcher<#c>>$create(self,branch)
      }
    } elif (state `MatchState$equals` MatchState$matchContinue()) {
      branch <- LinkedNode<BranchRepeatMatcher<#c>>$create(self,branch)
    }
    if (present(branch)) {
      state <- MatchState$matchContinue()
    }
  }

  @value incrementMatch () -> ()
  incrementMatch () {
    repetitionCount <- repetitionCount+1
  }

  @value atMax () -> (Bool)
  atMax () {
    return maxCount > 0 && repetitionCount >= maxCount
  }

  @value startRepeat () -> ()
  startRepeat () {
    matcher <- template.newMatcher()
  }
}

define BranchSequence {
  @value optional ReadSequence<MatcherTemplate<#c>> sequence

  create (sequence) {
    return BranchSequence<#c>{ sequence }
  }

  matchesEmpty () {
    scoped {
      optional ReadSequence<MatcherTemplate<#c>> current <- sequence
    } in while (present(current)) {
      if (!require(current).value().matchesEmpty()) {
        return false
      }
    } update {
      current <- require(current).next()
    }
    return true
  }

  newBrancher () {
    return BranchSequenceMatcher<#c>$create(sequence)
  }
}

concrete BranchSequenceMatcher<#c> {
  refines MatchBrancher<#c>

  @type create (optional ReadSequence<MatcherTemplate<#c>>) -> (BranchSequenceMatcher<#c>)
  @value tryBranches (#c) -> (MatchState,optional ReadSequence<BranchSequenceMatcher<#c>>)
}

define BranchSequenceMatcher {
  @value optional Matcher<#c> continued
  @value optional ReadSequence<MatcherTemplate<#c>> sequence
  @value Bool consumed

  create (sequence) {
    return BranchSequenceMatcher<#c>{ empty, sequence, false }
  }

  matchSatisfied () {
    if (consumed) {
      return false
    }
    if (present(continued) && !require(continued).matchSatisfied()) {
      return false
    }
    scoped {
      optional ReadSequence<MatcherTemplate<#c>> current <- sequence
    } in while (present(current)) {
      if (!require(current).value().matchesEmpty()) {
        return false
      }
    } update {
      current <- require(current).next()
    }
    return true
  }

  tryBranches (data) {
    if (consumed) {
      return MatchState$matchFail(), empty
    }
    consumed <- true
    return recursiveBranch(data,continued,sequence)
  }

  @type recursiveBranch (#c,optional Matcher<#c>,optional ReadSequence<MatcherTemplate<#c>>) ->
                        (MatchState,optional ReadSequence<BranchSequenceMatcher<#c>>)
  recursiveBranch (data,continued,sequence) (state,branch) {
    state <- MatchState$matchFail()
    branch <- empty
    if (!present(continued) && !present(sequence)) {
      return _
    }
    optional Matcher<#c> continued2 <- continued
    optional ReadSequence<MatcherTemplate<#c>> sequence2 <- sequence
    if (!present(continued2)) {
      continued2 <- require(sequence2).value().newMatcher()
      sequence2 <- require(sequence2).next()
    }
    if (require(continued2).matchSatisfied()) {
      MatchState state2, branch <- recursiveBranch(data,empty,sequence2)
      if (state `MatchState$lessThan` state2) {
        state <- state2
      }
    }
    MatchState state2 <- require(continued2).tryNextMatch(data)
    if (state `MatchState$lessThan` state2) {
      state <- state2
    }
    if (state2 `MatchState$equals` MatchState$matchComplete()) {
      if (present(sequence2)) {
        // Add a branch to continue this sequence.
        branch <- LinkedNode<BranchSequenceMatcher<#c>>$create(
            BranchSequenceMatcher<#c>{ empty, sequence2, false },branch)
        state <- MatchState$matchContinue()
      } else {
        // Add a branch to serve as a record of completeness. It will fail to
        // match anything, but matchSatisfied() will return true.
        branch <- LinkedNode<BranchSequenceMatcher<#c>>$create(
            BranchSequenceMatcher<#c>{ empty, empty, false },branch)
      }
    } elif (state `MatchState$equals` MatchState$matchContinue()) {
        // Add a branch to continue this sequence.
        branch <- LinkedNode<BranchSequenceMatcher<#c>>$create(
            BranchSequenceMatcher<#c>{ continued2, sequence2, false },branch)
    }
  }
}

define BranchRepeat {
  @value MatcherTemplate<#c> template
  @value Int minCount
  @value Int maxCount

  createZeroPlus (template) {
    return createRange(0,0,template)
  }

  createOnePlus (template) {
    return createRange(1,0,template)
  }

  createRange (minCount,maxCount,template) {
    return BranchRepeat<#c>{ template, minCount, maxCount }
  }

  matchesEmpty () {
    return minCount <= 0 || template.matchesEmpty()
  }

  newBrancher () {
    return BranchRepeatMatcher<#c>$create(minCount,maxCount,template)
  }
}

define LinkedNode {
  @value optional ReadSequence<#x> nextNode
  @value #x data

  create (data,nextNode) {
    return LinkedNode<#x>{ nextNode, data }
  }

  concatSequences (head1,head2) {
    if (!present(head2)) {
      return head1
    } elif (present(head1)) {
      return LinkedNode<#x>$create(require(head1).value(),
                                   concatSequences(require(head1).next(),head2))
    } else {
      return head2
    }
  }

  value () {
    return data
  }

  next () {
    return nextNode
  }
}