|
| 1 | +import scala.compiletime.ops.int.{ +, -, Max } |
| 2 | +import scala.compiletime.ops.string.{ Substring, Length, Matches, CharAt } |
| 3 | + |
| 4 | +class Regex[P] private() extends Serializable: |
| 5 | + def unapply(s: CharSequence)(implicit n: Regex.Sanitizer[P]): Option[P] = ??? |
| 6 | + |
| 7 | +object Regex: |
| 8 | + def apply[R <: String & Singleton](regex: R): Regex[Compile[R]] = ??? |
| 9 | + |
| 10 | + abstract class Sanitizer[T] |
| 11 | + object Sanitizer: |
| 12 | + given Sanitizer[EmptyTuple] = ??? |
| 13 | + given stringcase[T <: Tuple: Sanitizer]: Sanitizer[String *: T] = ??? |
| 14 | + given optioncase[T <: Tuple: Sanitizer]: Sanitizer[Option[String] *: T] = ??? |
| 15 | + given Sanitizer[String] = ??? |
| 16 | + given Sanitizer[Option[String]] = ??? |
| 17 | + |
| 18 | + type Compile[R <: String] = Matches["", R] match |
| 19 | + case _ => Reverse[EmptyTuple, Loop[R, 0, Length[R], EmptyTuple, IsPiped[R, 0, Length[R], 0]]] |
| 20 | + |
| 21 | + type Loop[R <: String, Lo <: Int, Hi <: Int, Acc <: Tuple, Opt <: Int] <: Tuple = Lo match |
| 22 | + case Hi => Acc |
| 23 | + case _ => CharAt[R, Lo] match |
| 24 | + case '\\' => CharAt[R, Lo + 1] match |
| 25 | + case 'Q' => Loop[R, ToClosingQE[R, Lo + 2], Hi, Acc, Opt] |
| 26 | + case _ => Loop[R, Lo + 2, Hi, Acc, Opt] |
| 27 | + case '[' => Loop[R, ToClosingBracket[R, Lo + 1, 0], Hi, Acc, Opt] |
| 28 | + case ')' => Loop[R, Lo + 1, Hi, Acc, Max[0, Opt - 1]] |
| 29 | + case '(' => Opt match |
| 30 | + case 0 => IsMarked[R, ToClosingParenthesis[R, Lo + 1, 0], Hi] match |
| 31 | + case true => IsCapturing[R, Lo + 1] match |
| 32 | + case false => Loop[R, Lo + 1, Hi, Acc, 1] |
| 33 | + case true => Loop[R, Lo + 1, Hi, Option[String] *: Acc, 1] |
| 34 | + case false => IsCapturing[R, Lo + 1] match |
| 35 | + case false => Loop[R, Lo + 1, Hi, Acc, IsPiped[R, Lo + 1, Hi, 0]] |
| 36 | + case true => Loop[R, Lo + 1, Hi, String *: Acc, IsPiped[R, Lo + 1, Hi, 0]] |
| 37 | + case _ => IsCapturing[R, Lo + 1] match |
| 38 | + case false => Loop[R, Lo + 1, Hi, Acc, Opt + 1] |
| 39 | + case true => Loop[R, Lo + 1, Hi, Option[String] *: Acc, Opt + 1] |
| 40 | + case _ => Loop[R, Lo + 1, Hi, Acc, Opt] |
| 41 | + |
| 42 | + type IsCapturing[R <: String, At <: Int] <: Boolean = CharAt[R, At] match |
| 43 | + case '?' => CharAt[R, At + 1] match |
| 44 | + case '<' => CharAt[R, At + 2] match |
| 45 | + case '=' | '!' => false |
| 46 | + case _ => true |
| 47 | + case _ => false |
| 48 | + case _ => true |
| 49 | + |
| 50 | + type IsMarked[R <: String, At <: Int, Hi <: Int] <: Boolean = At match |
| 51 | + case Hi => false |
| 52 | + case _ => CharAt[R, At] match |
| 53 | + case '?' | '*' => true |
| 54 | + case '{' => CharAt[R, At + 1] match |
| 55 | + case '0' => true |
| 56 | + case _ => false |
| 57 | + case _ => false |
| 58 | + |
| 59 | + type IsPiped[R <: String, At <: Int, Hi <: Int, Lvl <: Int] <: Int = At match |
| 60 | + case Hi => 0 |
| 61 | + case _ => CharAt[R, At] match |
| 62 | + case '\\' => CharAt[R, At + 1] match |
| 63 | + case 'Q' => IsPiped[R, ToClosingQE[R, At + 2], Hi, Lvl] |
| 64 | + case _ => IsPiped[R, At + 2, Hi, Lvl] |
| 65 | + case '[' => IsPiped[R, ToClosingBracket[R, At + 1, 0], Hi, Lvl] |
| 66 | + case '(' => IsPiped[R, ToClosingParenthesis[R, At + 1, 0], Hi, Lvl + 1] |
| 67 | + case '|' => 1 |
| 68 | + case ')' => 0 |
| 69 | + case _ => IsPiped[R, At + 1, Hi, Lvl] |
| 70 | + |
| 71 | + type ToClosingParenthesis[R <: String, At <: Int, Lvl <: Int] <: Int = CharAt[R, At] match |
| 72 | + case '\\' => CharAt[R, At + 1] match |
| 73 | + case 'Q' => ToClosingParenthesis[R, ToClosingQE[R, At + 2], Lvl] |
| 74 | + case _ => ToClosingParenthesis[R, At + 2, Lvl] |
| 75 | + case '[' => ToClosingParenthesis[R, ToClosingBracket[R, At + 1, 0], Lvl] |
| 76 | + case ')' => Lvl match |
| 77 | + case 0 => At + 1 |
| 78 | + case _ => ToClosingParenthesis[R, At + 1, Lvl - 1] |
| 79 | + case '(' => ToClosingParenthesis[R, At + 1, Lvl + 1] |
| 80 | + case _ => ToClosingParenthesis[R, At + 1, Lvl] |
| 81 | + |
| 82 | + type ToClosingBracket[R <: String, At <: Int, Lvl <: Int] <: Int = CharAt[R, At] match |
| 83 | + case '\\' => CharAt[R, At + 1] match |
| 84 | + case 'Q' => ToClosingBracket[R, ToClosingQE[R, At + 2], Lvl] |
| 85 | + case _ => ToClosingBracket[R, At + 2, Lvl] |
| 86 | + case '[' => ToClosingBracket[R, At + 1, Lvl + 1] |
| 87 | + case ']' => Lvl match |
| 88 | + case 0 => At + 1 |
| 89 | + case _ => ToClosingBracket[R, At + 1, Lvl - 1] |
| 90 | + case _ => ToClosingBracket[R, At + 1, Lvl] |
| 91 | + |
| 92 | + type ToClosingQE[R <: String, At <: Int] <: Int = CharAt[R, At] match |
| 93 | + case '\\' => CharAt[R, At + 1] match |
| 94 | + case 'E' => At + 2 |
| 95 | + case _ => ToClosingQE[R, At + 2] |
| 96 | + case _ => ToClosingQE[R, At + 1] |
| 97 | + |
| 98 | + type Reverse[Acc <: Tuple, X <: Tuple] <: Tuple = X match |
| 99 | + case x *: xs => Reverse[x *: Acc, xs] |
| 100 | + case EmptyTuple => Acc |
| 101 | + |
| 102 | +object Test: |
| 103 | + def main(args: Array[String]): Unit = |
| 104 | + val r75 = Regex("(x|y|z[QW])*(longish|loquatious|excessive|overblown[QW])*") |
| 105 | + "xyzQzWlongishoverblownW" match |
| 106 | + case r75((Some(g0), Some(g1))) => ??? // failure |
0 commit comments