Skip to content

Commit

Permalink
Rough implementation of extract
Browse files Browse the repository at this point in the history
  • Loading branch information
propensive committed Jan 9, 2025
1 parent 7930e99 commit d55c9a1
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 6 deletions.
15 changes: 12 additions & 3 deletions src/core/kaleidoscope.Kaleidoscope.scala
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,20 @@ object Kaleidoscope:
class NoExtraction(pattern: String):
inline def apply(): Regex = Regex.make(List(pattern))(using Unsafe)

def unapply(scrutinee: Text): Boolean =
Regex.make(List(pattern))(using Unsafe).matches(scrutinee)
def unapply(scrutinee: Text)(using matching: Matching): Boolean =
matching.nextStart match
case Unset =>
Regex.make(List(pattern))(using Unsafe).matches(scrutinee)

case index: Int =>
val regex = Regex.make(List(pattern))(using Unsafe)
val matcher = regex.javaPattern.matcher(scrutinee.s).nn
val found = matcher.find(index)
if found then matching.nextStart = matcher.start
found

class RExtractor[ResultType](parts: Seq[String]):
def unapply(scrutinee: Text): ResultType =
def unapply(scrutinee: Text)(using matching: Matching): ResultType =
val result = Regex.make(parts)(using Unsafe).matchGroups(scrutinee)
val result2 = result.asInstanceOf[Option[IArray[List[Text] | Optional[Text]]]]

Expand Down
7 changes: 7 additions & 0 deletions src/core/kaleidoscope.Matching.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package kaleidoscope

import vacuous.*

object Matching:
given (using DummyImplicit) => Matching as default = Matching(Unset)
class Matching(var nextStart: Optional[Int] = Unset)
24 changes: 21 additions & 3 deletions src/core/kaleidoscope.Regex.scala
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ case class Regex(pattern: Text, groups: List[Regex.Group]):
val matcher: jur.Matcher = javaPattern.matcher(input.s).nn
if matcher.find(start.n0) then Interval.zerary(matcher.start, matcher.end) else Unset


def search(input: Text, start: Ordinal = Prim, overlap: Boolean = false): LazyList[Interval] =
val matcher: jur.Matcher = javaPattern.matcher(input.s).nn

Expand All @@ -251,9 +252,10 @@ case class Regex(pattern: Text, groups: List[Regex.Group]):

recur(start.n0)

def matches(text: Text): Boolean = !matchGroups(text).isEmpty
def matches(text: Text)(using Matching): Boolean = !matchGroups(text).isEmpty

def matchGroups(text: Text)(using matching: Matching): Option[IArray[List[Text] | Optional[Text]]] =

def matchGroups(text: Text): Option[IArray[List[Text] | Optional[Text]]] =
val matcher: jur.Matcher = javaPattern.matcher(text.s).nn

def recur(todo: List[Regex.Group], matches: List[Optional[Text] | List[Text]], index: Int)
Expand Down Expand Up @@ -284,4 +286,20 @@ case class Regex(pattern: Text, groups: List[Regex.Group]):

recur(tail, matches2, index + 1)

if matcher.matches then Some(IArray.from(recur(captureGroups, Nil, 0).reverse)) else None
matching.nextStart match
case Unset =>
if !matcher.matches then None else Some(IArray.from(recur(captureGroups, Nil, 0).reverse))

case index: Int =>
if !matcher.find(index) then None else
matching.nextStart = matcher.start + 1
Some(IArray.from(recur(captureGroups, Nil, 0).reverse))

def extract[ValueType](input: Text, start: Ordinal = Prim)
(lambda: Matching ?=> PartialFunction[Text, ValueType]): LazyList[ValueType] =
if start.n0 < input.s.length then
val matching = Matching(start.n0)
lambda(using matching).lift(input) match
case Some(head) => head #:: extract(input, Ordinal.zerary(matching.nextStart.or(0)))(lambda)
case _ => LazyList()
else LazyList()

0 comments on commit d55c9a1

Please sign in to comment.