refactor: reorganize functions for skipping/dropping prefixes/suffixes of strings (#12988)
This PR introduces the functions `String.Slice.skipPrefix?`, `String.Slice.Pos.skip?`, `String.Slice.skipPrefixWhile`, `String.Slice.Pos.skipWhile` and redefines `String.Slice.takeWhile` and `String.Slice.dropWhile` to use these new functions.
This commit is contained in:
parent
5cc6585c9b
commit
0f730662de
9 changed files with 295 additions and 221 deletions
|
|
@ -136,42 +136,36 @@ theorem dropPrefix?_char_eq_dropPrefix?_beq {c : Char} {s : Slice} :
|
|||
theorem dropPrefix_char_eq_dropPrefix_beq {c : Char} {s : Slice} :
|
||||
s.dropPrefix c = s.dropPrefix (· == c) := (rfl)
|
||||
|
||||
theorem skipPrefix?_char_eq_skipPrefix?_beq {c : Char} {s : Slice} :
|
||||
s.skipPrefix? c = s.skipPrefix? (· == c) := (rfl)
|
||||
|
||||
theorem Pattern.ForwardPattern.skipPrefix?_char_eq_skipPrefix?_beq {c : Char} {s : Slice} :
|
||||
skipPrefix? c s = skipPrefix? (· == c) s := (rfl)
|
||||
|
||||
private theorem dropWhileGo_eq {c : Char} {s : Slice} (curr : s.Pos) :
|
||||
dropWhile.go s c curr = dropWhile.go s (· == c) curr := by
|
||||
fun_induction dropWhile.go s c curr with
|
||||
theorem Pos.skipWhile_char_eq_skipWhile_beq {c : Char} {s : Slice} (curr : s.Pos) :
|
||||
Pos.skipWhile curr c = Pos.skipWhile curr (· == c) := by
|
||||
fun_induction Pos.skipWhile curr c with
|
||||
| case1 pos nextCurr h₁ h₂ ih =>
|
||||
conv => rhs; rw [dropWhile.go]
|
||||
conv => rhs; rw [Pos.skipWhile]
|
||||
simp [← Pattern.ForwardPattern.skipPrefix?_char_eq_skipPrefix?_beq, h₁, h₂, ih]
|
||||
| case2 pos nextCurr h ih =>
|
||||
conv => rhs; rw [dropWhile.go]
|
||||
conv => rhs; rw [Pos.skipWhile]
|
||||
simp [← Pattern.ForwardPattern.skipPrefix?_char_eq_skipPrefix?_beq, h, ih]
|
||||
| case3 pos h =>
|
||||
conv => rhs; rw [dropWhile.go]
|
||||
conv => rhs; rw [Pos.skipWhile]
|
||||
simp [← Pattern.ForwardPattern.skipPrefix?_char_eq_skipPrefix?_beq]
|
||||
|
||||
theorem skipPrefixWhile_char_eq_skipPrefixWhile_beq {c : Char} {s : Slice} :
|
||||
s.skipPrefixWhile c = s.skipPrefixWhile (· == c) :=
|
||||
Pos.skipWhile_char_eq_skipWhile_beq s.startPos
|
||||
|
||||
theorem dropWhile_char_eq_dropWhile_beq {c : Char} {s : Slice} :
|
||||
s.dropWhile c = s.dropWhile (· == c) := by
|
||||
simpa only [dropWhile] using dropWhileGo_eq s.startPos
|
||||
|
||||
private theorem takeWhileGo_eq {c : Char} {s : Slice} (curr : s.Pos) :
|
||||
takeWhile.go s c curr = takeWhile.go s (· == c) curr := by
|
||||
fun_induction takeWhile.go s c curr with
|
||||
| case1 pos nextCurr h₁ h₂ ih =>
|
||||
conv => rhs; rw [takeWhile.go]
|
||||
simp [← Pattern.ForwardPattern.skipPrefix?_char_eq_skipPrefix?_beq, h₁, h₂, ih]
|
||||
| case2 pos nextCurr h ih =>
|
||||
conv => rhs; rw [takeWhile.go]
|
||||
simp [← Pattern.ForwardPattern.skipPrefix?_char_eq_skipPrefix?_beq, h, ih]
|
||||
| case3 pos h =>
|
||||
conv => rhs; rw [takeWhile.go]
|
||||
simp [← Pattern.ForwardPattern.skipPrefix?_char_eq_skipPrefix?_beq]
|
||||
simp only [dropWhile]; exact congrArg _ skipPrefixWhile_char_eq_skipPrefixWhile_beq
|
||||
|
||||
theorem takeWhile_char_eq_takeWhile_beq {c : Char} {s : Slice} :
|
||||
s.takeWhile c = s.takeWhile (· == c) := by
|
||||
simp only [takeWhile]; exact takeWhileGo_eq s.startPos
|
||||
simp only [takeWhile]; exact congrArg _ skipPrefixWhile_char_eq_skipPrefixWhile_beq
|
||||
|
||||
theorem all_char_eq_all_beq {c : Char} {s : Slice} :
|
||||
s.all c = s.all (· == c) := by
|
||||
|
|
@ -192,47 +186,41 @@ theorem contains_char_eq_contains_beq {c : Char} {s : Slice} :
|
|||
theorem endsWith_char_eq_endsWith_beq {c : Char} {s : Slice} :
|
||||
s.endsWith c = s.endsWith (· == c) := (rfl)
|
||||
|
||||
theorem skipSuffix?_char_eq_skipSuffix?_beq {c : Char} {s : Slice} :
|
||||
s.skipSuffix? c = s.skipSuffix? (· == c) := (rfl)
|
||||
|
||||
theorem dropSuffix?_char_eq_dropSuffix?_beq {c : Char} {s : Slice} :
|
||||
s.dropSuffix? c = s.dropSuffix? (· == c) := (rfl)
|
||||
|
||||
theorem dropSuffix_char_eq_dropSuffix_beq {c : Char} {s : Slice} :
|
||||
s.dropSuffix c = s.dropSuffix (· == c) := (rfl)
|
||||
|
||||
theorem Pattern.BackwardPattern.dropSuffix?_char_eq_dropSuffix?_beq {c : Char} {s : Slice} :
|
||||
dropSuffix? c s = dropSuffix? (· == c) s := (rfl)
|
||||
theorem Pattern.BackwardPattern.skipSuffix?_char_eq_skipSuffix?_beq {c : Char} {s : Slice} :
|
||||
skipSuffix? c s = skipSuffix? (· == c) s := (rfl)
|
||||
|
||||
private theorem dropEndWhileGo_eq {c : Char} {s : Slice} (curr : s.Pos) :
|
||||
dropEndWhile.go s c curr = dropEndWhile.go s (· == c) curr := by
|
||||
fun_induction dropEndWhile.go s c curr with
|
||||
theorem Pos.revSkipWhile_char_eq_revSkipWhile_beq {c : Char} {s : Slice} (curr : s.Pos) :
|
||||
Pos.revSkipWhile curr c = Pos.revSkipWhile curr (· == c) := by
|
||||
fun_induction Pos.revSkipWhile curr c with
|
||||
| case1 pos nextCurr h₁ h₂ ih =>
|
||||
conv => rhs; rw [dropEndWhile.go]
|
||||
simp [← Pattern.BackwardPattern.dropSuffix?_char_eq_dropSuffix?_beq, h₁, h₂, ih]
|
||||
conv => rhs; rw [Pos.revSkipWhile]
|
||||
simp [← Pattern.BackwardPattern.skipSuffix?_char_eq_skipSuffix?_beq, h₁, h₂, ih]
|
||||
| case2 pos nextCurr h ih =>
|
||||
conv => rhs; rw [dropEndWhile.go]
|
||||
simp [← Pattern.BackwardPattern.dropSuffix?_char_eq_dropSuffix?_beq, h, ih]
|
||||
conv => rhs; rw [Pos.revSkipWhile]
|
||||
simp [← Pattern.BackwardPattern.skipSuffix?_char_eq_skipSuffix?_beq, h, ih]
|
||||
| case3 pos h =>
|
||||
conv => rhs; rw [dropEndWhile.go]
|
||||
simp [← Pattern.BackwardPattern.dropSuffix?_char_eq_dropSuffix?_beq]
|
||||
conv => rhs; rw [Pos.revSkipWhile]
|
||||
simp [← Pattern.BackwardPattern.skipSuffix?_char_eq_skipSuffix?_beq]
|
||||
|
||||
theorem skipSuffixWhile_char_eq_skipSuffixWhile_beq {c : Char} {s : Slice} :
|
||||
s.skipSuffixWhile c = s.skipSuffixWhile (· == c) :=
|
||||
Pos.revSkipWhile_char_eq_revSkipWhile_beq s.endPos
|
||||
|
||||
theorem dropEndWhile_char_eq_dropEndWhile_beq {c : Char} {s : Slice} :
|
||||
s.dropEndWhile c = s.dropEndWhile (· == c) := by
|
||||
simpa only [dropEndWhile] using dropEndWhileGo_eq s.endPos
|
||||
|
||||
private theorem takeEndWhileGo_eq {c : Char} {s : Slice} (curr : s.Pos) :
|
||||
takeEndWhile.go s c curr = takeEndWhile.go s (· == c) curr := by
|
||||
fun_induction takeEndWhile.go s c curr with
|
||||
| case1 pos nextCurr h₁ h₂ ih =>
|
||||
conv => rhs; rw [takeEndWhile.go]
|
||||
simp [← Pattern.BackwardPattern.dropSuffix?_char_eq_dropSuffix?_beq, h₁, h₂, ih]
|
||||
| case2 pos nextCurr h ih =>
|
||||
conv => rhs; rw [takeEndWhile.go]
|
||||
simp [← Pattern.BackwardPattern.dropSuffix?_char_eq_dropSuffix?_beq, h, ih]
|
||||
| case3 pos h =>
|
||||
conv => rhs; rw [takeEndWhile.go]
|
||||
simp [← Pattern.BackwardPattern.dropSuffix?_char_eq_dropSuffix?_beq]
|
||||
simp only [dropEndWhile]; exact congrArg _ skipSuffixWhile_char_eq_skipSuffixWhile_beq
|
||||
|
||||
theorem takeEndWhile_char_eq_takeEndWhile_beq {c : Char} {s : Slice} :
|
||||
s.takeEndWhile c = s.takeEndWhile (· == c) := by
|
||||
simpa only [takeEndWhile] using takeEndWhileGo_eq s.endPos
|
||||
simp only [takeEndWhile]; exact congrArg _ skipSuffixWhile_char_eq_skipSuffixWhile_beq
|
||||
|
||||
end String.Slice
|
||||
|
|
|
|||
|
|
@ -181,43 +181,39 @@ theorem dropPrefix?_prop_eq_dropPrefix?_decide {p : Char → Prop} [DecidablePre
|
|||
theorem dropPrefix_prop_eq_dropPrefix_decide {p : Char → Prop} [DecidablePred p] {s : Slice} :
|
||||
s.dropPrefix p = s.dropPrefix (decide <| p ·) := (rfl)
|
||||
|
||||
theorem skipPrefix?_prop_eq_skipPrefix?_decide {p : Char → Prop} [DecidablePred p] {s : Slice} :
|
||||
s.skipPrefix? p = s.skipPrefix? (decide <| p ·) := (rfl)
|
||||
|
||||
theorem Pattern.ForwardPattern.skipPrefix?_prop_eq_skipPrefix?_decide
|
||||
{p : Char → Prop} [DecidablePred p] {s : Slice} :
|
||||
skipPrefix? p s = skipPrefix? (decide <| p ·) s := (rfl)
|
||||
|
||||
private theorem dropWhileGo_eq {p : Char → Prop} [DecidablePred p] {s : Slice} (curr : s.Pos) :
|
||||
dropWhile.go s p curr = dropWhile.go s (decide <| p ·) curr := by
|
||||
fun_induction dropWhile.go s p curr with
|
||||
theorem Pos.skipWhile_prop_eq_skipWhile_decide {p : Char → Prop} [DecidablePred p] {s : Slice}
|
||||
(curr : s.Pos) :
|
||||
Pos.skipWhile curr p = Pos.skipWhile curr (decide <| p ·) := by
|
||||
fun_induction Pos.skipWhile curr p with
|
||||
| case1 pos nextCurr h₁ h₂ ih =>
|
||||
conv => rhs; rw [dropWhile.go]
|
||||
conv => rhs; rw [Pos.skipWhile]
|
||||
simp [← Pattern.ForwardPattern.skipPrefix?_prop_eq_skipPrefix?_decide, h₁, h₂, ih]
|
||||
| case2 pos nextCurr h ih =>
|
||||
conv => rhs; rw [dropWhile.go]
|
||||
conv => rhs; rw [Pos.skipWhile]
|
||||
simp [← Pattern.ForwardPattern.skipPrefix?_prop_eq_skipPrefix?_decide, h, ih]
|
||||
| case3 pos h =>
|
||||
conv => rhs; rw [dropWhile.go]
|
||||
conv => rhs; rw [Pos.skipWhile]
|
||||
simp [← Pattern.ForwardPattern.skipPrefix?_prop_eq_skipPrefix?_decide]
|
||||
|
||||
theorem skipPrefixWhile_prop_eq_skipPrefixWhile_decide {p : Char → Prop} [DecidablePred p]
|
||||
{s : Slice} :
|
||||
s.skipPrefixWhile p = s.skipPrefixWhile (decide <| p ·) :=
|
||||
Pos.skipWhile_prop_eq_skipWhile_decide s.startPos
|
||||
|
||||
theorem dropWhile_prop_eq_dropWhile_decide {p : Char → Prop} [DecidablePred p] {s : Slice} :
|
||||
s.dropWhile p = s.dropWhile (decide <| p ·) := by
|
||||
simpa only [dropWhile] using dropWhileGo_eq s.startPos
|
||||
|
||||
private theorem takeWhileGo_eq {p : Char → Prop} [DecidablePred p] {s : Slice} (curr : s.Pos) :
|
||||
takeWhile.go s p curr = takeWhile.go s (decide <| p ·) curr := by
|
||||
fun_induction takeWhile.go s p curr with
|
||||
| case1 pos nextCurr h₁ h₂ ih =>
|
||||
conv => rhs; rw [takeWhile.go]
|
||||
simp [← Pattern.ForwardPattern.skipPrefix?_prop_eq_skipPrefix?_decide, h₁, h₂, ih]
|
||||
| case2 pos nextCurr h ih =>
|
||||
conv => rhs; rw [takeWhile.go]
|
||||
simp [← Pattern.ForwardPattern.skipPrefix?_prop_eq_skipPrefix?_decide, h, ih]
|
||||
| case3 pos h =>
|
||||
conv => rhs; rw [takeWhile.go]
|
||||
simp [← Pattern.ForwardPattern.skipPrefix?_prop_eq_skipPrefix?_decide]
|
||||
simp only [dropWhile]; exact congrArg _ skipPrefixWhile_prop_eq_skipPrefixWhile_decide
|
||||
|
||||
theorem takeWhile_prop_eq_takeWhile_decide {p : Char → Prop} [DecidablePred p] {s : Slice} :
|
||||
s.takeWhile p = s.takeWhile (decide <| p ·) := by
|
||||
simp only [takeWhile]; exact takeWhileGo_eq s.startPos
|
||||
simp only [takeWhile]; exact congrArg _ skipPrefixWhile_prop_eq_skipPrefixWhile_decide
|
||||
|
||||
theorem all_prop_eq_all_decide {p : Char → Prop} [DecidablePred p] {s : Slice} :
|
||||
s.all p = s.all (decide <| p ·) := by
|
||||
|
|
@ -239,52 +235,46 @@ theorem contains_prop_eq_contains_decide {p : Char → Prop} [DecidablePred p] {
|
|||
theorem endsWith_prop_eq_endsWith_decide {p : Char → Prop} [DecidablePred p] {s : Slice} :
|
||||
s.endsWith p = s.endsWith (decide <| p ·) := (rfl)
|
||||
|
||||
theorem skipSuffix?_prop_eq_skipSuffix?_decide {p : Char → Prop} [DecidablePred p] {s : Slice} :
|
||||
s.skipSuffix? p = s.skipSuffix? (decide <| p ·) := (rfl)
|
||||
|
||||
theorem dropSuffix?_prop_eq_dropSuffix?_decide {p : Char → Prop} [DecidablePred p] {s : Slice} :
|
||||
s.dropSuffix? p = s.dropSuffix? (decide <| p ·) := (rfl)
|
||||
|
||||
theorem dropSuffix_prop_eq_dropSuffix_decide {p : Char → Prop} [DecidablePred p] {s : Slice} :
|
||||
s.dropSuffix p = s.dropSuffix (decide <| p ·) := (rfl)
|
||||
|
||||
theorem Pattern.BackwardPattern.dropSuffix?_prop_eq_dropSuffix?_decide
|
||||
theorem Pattern.BackwardPattern.skipSuffix?_prop_eq_skipSuffix?_decide
|
||||
{p : Char → Prop} [DecidablePred p] {s : Slice} :
|
||||
dropSuffix? p s = dropSuffix? (decide <| p ·) s := (rfl)
|
||||
skipSuffix? p s = skipSuffix? (decide <| p ·) s := (rfl)
|
||||
|
||||
private theorem dropEndWhileGo_eq {p : Char → Prop} [DecidablePred p] {s : Slice}
|
||||
(curr : s.Pos) :
|
||||
dropEndWhile.go s p curr = dropEndWhile.go s (decide <| p ·) curr := by
|
||||
fun_induction dropEndWhile.go s p curr with
|
||||
theorem Pos.revSkipWhile_prop_eq_revSkipWhile_decide {p : Char → Prop} [DecidablePred p]
|
||||
{s : Slice} (curr : s.Pos) :
|
||||
Pos.revSkipWhile curr p = Pos.revSkipWhile curr (decide <| p ·) := by
|
||||
fun_induction Pos.revSkipWhile curr p with
|
||||
| case1 pos nextCurr h₁ h₂ ih =>
|
||||
conv => rhs; rw [dropEndWhile.go]
|
||||
simp [← Pattern.BackwardPattern.dropSuffix?_prop_eq_dropSuffix?_decide, h₁, h₂, ih]
|
||||
conv => rhs; rw [Pos.revSkipWhile]
|
||||
simp [← Pattern.BackwardPattern.skipSuffix?_prop_eq_skipSuffix?_decide, h₁, h₂, ih]
|
||||
| case2 pos nextCurr h ih =>
|
||||
conv => rhs; rw [dropEndWhile.go]
|
||||
simp [← Pattern.BackwardPattern.dropSuffix?_prop_eq_dropSuffix?_decide, h, ih]
|
||||
conv => rhs; rw [Pos.revSkipWhile]
|
||||
simp [← Pattern.BackwardPattern.skipSuffix?_prop_eq_skipSuffix?_decide, h, ih]
|
||||
| case3 pos h =>
|
||||
conv => rhs; rw [dropEndWhile.go]
|
||||
simp [← Pattern.BackwardPattern.dropSuffix?_prop_eq_dropSuffix?_decide]
|
||||
conv => rhs; rw [Pos.revSkipWhile]
|
||||
simp [← Pattern.BackwardPattern.skipSuffix?_prop_eq_skipSuffix?_decide]
|
||||
|
||||
theorem skipSuffixWhile_prop_eq_skipSuffixWhile_decide {p : Char → Prop} [DecidablePred p]
|
||||
{s : Slice} :
|
||||
s.skipSuffixWhile p = s.skipSuffixWhile (decide <| p ·) :=
|
||||
Pos.revSkipWhile_prop_eq_revSkipWhile_decide s.endPos
|
||||
|
||||
theorem dropEndWhile_prop_eq_dropEndWhile_decide {p : Char → Prop} [DecidablePred p]
|
||||
{s : Slice} :
|
||||
s.dropEndWhile p = s.dropEndWhile (decide <| p ·) := by
|
||||
simpa only [dropEndWhile] using dropEndWhileGo_eq s.endPos
|
||||
|
||||
private theorem takeEndWhileGo_eq {p : Char → Prop} [DecidablePred p] {s : Slice}
|
||||
(curr : s.Pos) :
|
||||
takeEndWhile.go s p curr = takeEndWhile.go s (decide <| p ·) curr := by
|
||||
fun_induction takeEndWhile.go s p curr with
|
||||
| case1 pos nextCurr h₁ h₂ ih =>
|
||||
conv => rhs; rw [takeEndWhile.go]
|
||||
simp [← Pattern.BackwardPattern.dropSuffix?_prop_eq_dropSuffix?_decide, h₁, h₂, ih]
|
||||
| case2 pos nextCurr h ih =>
|
||||
conv => rhs; rw [takeEndWhile.go]
|
||||
simp [← Pattern.BackwardPattern.dropSuffix?_prop_eq_dropSuffix?_decide, h, ih]
|
||||
| case3 pos h =>
|
||||
conv => rhs; rw [takeEndWhile.go]
|
||||
simp [← Pattern.BackwardPattern.dropSuffix?_prop_eq_dropSuffix?_decide]
|
||||
simp only [dropEndWhile]; exact congrArg _ skipSuffixWhile_prop_eq_skipSuffixWhile_decide
|
||||
|
||||
theorem takeEndWhile_prop_eq_takeEndWhile_decide {p : Char → Prop} [DecidablePred p]
|
||||
{s : Slice} :
|
||||
s.takeEndWhile p = s.takeEndWhile (decide <| p ·) := by
|
||||
simpa only [takeEndWhile] using takeEndWhileGo_eq s.endPos
|
||||
simp only [takeEndWhile]; exact congrArg _ skipSuffixWhile_prop_eq_skipSuffixWhile_decide
|
||||
|
||||
end String.Slice
|
||||
|
|
|
|||
|
|
@ -100,43 +100,38 @@ public theorem dropPrefix?_string_eq_dropPrefix?_toSlice {pat : String} {s : Sli
|
|||
public theorem dropPrefix_string_eq_dropPrefix_toSlice {pat : String} {s : Slice} :
|
||||
s.dropPrefix pat = s.dropPrefix pat.toSlice := (rfl)
|
||||
|
||||
public theorem skipPrefix?_string_eq_skipPrefix?_toSlice {pat : String} {s : Slice} :
|
||||
s.skipPrefix? pat = s.skipPrefix? pat.toSlice := (rfl)
|
||||
|
||||
public theorem Pattern.ForwardPattern.skipPrefix?_string_eq_skipPrefix?_toSlice
|
||||
{pat : String} {s : Slice} :
|
||||
skipPrefix? pat s = skipPrefix? pat.toSlice s := (rfl)
|
||||
|
||||
private theorem dropWhileGo_string_eq {pat : String} {s : Slice} (curr : s.Pos) :
|
||||
dropWhile.go s pat curr = dropWhile.go s pat.toSlice curr := by
|
||||
fun_induction dropWhile.go s pat curr with
|
||||
public theorem Pos.skipWhile_string_eq_skipWhile_toSlice {pat : String} {s : Slice}
|
||||
(curr : s.Pos) :
|
||||
Pos.skipWhile curr pat = Pos.skipWhile curr pat.toSlice := by
|
||||
fun_induction Pos.skipWhile curr pat with
|
||||
| case1 pos nextCurr h₁ h₂ ih =>
|
||||
conv => rhs; rw [dropWhile.go]
|
||||
conv => rhs; rw [Pos.skipWhile]
|
||||
simp [← Pattern.ForwardPattern.skipPrefix?_string_eq_skipPrefix?_toSlice, h₁, h₂, ih]
|
||||
| case2 pos nextCurr h ih =>
|
||||
conv => rhs; rw [dropWhile.go]
|
||||
conv => rhs; rw [Pos.skipWhile]
|
||||
simp [← Pattern.ForwardPattern.skipPrefix?_string_eq_skipPrefix?_toSlice, h, ih]
|
||||
| case3 pos h =>
|
||||
conv => rhs; rw [dropWhile.go]
|
||||
conv => rhs; rw [Pos.skipWhile]
|
||||
simp [← Pattern.ForwardPattern.skipPrefix?_string_eq_skipPrefix?_toSlice]
|
||||
|
||||
public theorem skipPrefixWhile_string_eq_skipPrefixWhile_toSlice {pat : String} {s : Slice} :
|
||||
s.skipPrefixWhile pat = s.skipPrefixWhile pat.toSlice :=
|
||||
Pos.skipWhile_string_eq_skipWhile_toSlice s.startPos
|
||||
|
||||
public theorem dropWhile_string_eq_dropWhile_toSlice {pat : String} {s : Slice} :
|
||||
s.dropWhile pat = s.dropWhile pat.toSlice := by
|
||||
simpa only [dropWhile] using dropWhileGo_string_eq s.startPos
|
||||
|
||||
private theorem takeWhileGo_string_eq {pat : String} {s : Slice} (curr : s.Pos) :
|
||||
takeWhile.go s pat curr = takeWhile.go s pat.toSlice curr := by
|
||||
fun_induction takeWhile.go s pat curr with
|
||||
| case1 pos nextCurr h₁ h₂ ih =>
|
||||
conv => rhs; rw [takeWhile.go]
|
||||
simp [← Pattern.ForwardPattern.skipPrefix?_string_eq_skipPrefix?_toSlice, h₁, h₂, ih]
|
||||
| case2 pos nextCurr h ih =>
|
||||
conv => rhs; rw [takeWhile.go]
|
||||
simp [← Pattern.ForwardPattern.skipPrefix?_string_eq_skipPrefix?_toSlice, h, ih]
|
||||
| case3 pos h =>
|
||||
conv => rhs; rw [takeWhile.go]
|
||||
simp [← Pattern.ForwardPattern.skipPrefix?_string_eq_skipPrefix?_toSlice]
|
||||
simp only [dropWhile]; exact congrArg _ skipPrefixWhile_string_eq_skipPrefixWhile_toSlice
|
||||
|
||||
public theorem takeWhile_string_eq_takeWhile_toSlice {pat : String} {s : Slice} :
|
||||
s.takeWhile pat = s.takeWhile pat.toSlice := by
|
||||
simp only [takeWhile]; exact takeWhileGo_string_eq s.startPos
|
||||
simp only [takeWhile]; exact congrArg _ skipPrefixWhile_string_eq_skipPrefixWhile_toSlice
|
||||
|
||||
public theorem all_string_eq_all_toSlice {pat : String} {s : Slice} :
|
||||
s.all pat = s.all pat.toSlice := by
|
||||
|
|
@ -145,48 +140,43 @@ public theorem all_string_eq_all_toSlice {pat : String} {s : Slice} :
|
|||
public theorem endsWith_string_eq_endsWith_toSlice {pat : String} {s : Slice} :
|
||||
s.endsWith pat = s.endsWith pat.toSlice := (rfl)
|
||||
|
||||
public theorem skipSuffix?_string_eq_skipSuffix?_toSlice {pat : String} {s : Slice} :
|
||||
s.skipSuffix? pat = s.skipSuffix? pat.toSlice := (rfl)
|
||||
|
||||
public theorem dropSuffix?_string_eq_dropSuffix?_toSlice {pat : String} {s : Slice} :
|
||||
s.dropSuffix? pat = s.dropSuffix? pat.toSlice := (rfl)
|
||||
|
||||
public theorem dropSuffix_string_eq_dropSuffix_toSlice {pat : String} {s : Slice} :
|
||||
s.dropSuffix pat = s.dropSuffix pat.toSlice := (rfl)
|
||||
|
||||
public theorem Pattern.BackwardPattern.dropSuffix?_string_eq_dropSuffix?_toSlice
|
||||
public theorem Pattern.BackwardPattern.skipSuffix?_string_eq_skipSuffix?_toSlice
|
||||
{pat : String} {s : Slice} :
|
||||
dropSuffix? pat s = dropSuffix? pat.toSlice s := (rfl)
|
||||
skipSuffix? pat s = skipSuffix? pat.toSlice s := (rfl)
|
||||
|
||||
private theorem dropEndWhileGo_string_eq {pat : String} {s : Slice} (curr : s.Pos) :
|
||||
dropEndWhile.go s pat curr = dropEndWhile.go s pat.toSlice curr := by
|
||||
fun_induction dropEndWhile.go s pat curr with
|
||||
public theorem Pos.revSkipWhile_string_eq_revSkipWhile_toSlice {pat : String} {s : Slice}
|
||||
(curr : s.Pos) :
|
||||
Pos.revSkipWhile curr pat = Pos.revSkipWhile curr pat.toSlice := by
|
||||
fun_induction Pos.revSkipWhile curr pat with
|
||||
| case1 pos nextCurr h₁ h₂ ih =>
|
||||
conv => rhs; rw [dropEndWhile.go]
|
||||
simp [← Pattern.BackwardPattern.dropSuffix?_string_eq_dropSuffix?_toSlice, h₁, h₂, ih]
|
||||
conv => rhs; rw [Pos.revSkipWhile]
|
||||
simp [← Pattern.BackwardPattern.skipSuffix?_string_eq_skipSuffix?_toSlice, h₁, h₂, ih]
|
||||
| case2 pos nextCurr h ih =>
|
||||
conv => rhs; rw [dropEndWhile.go]
|
||||
simp [← Pattern.BackwardPattern.dropSuffix?_string_eq_dropSuffix?_toSlice, h, ih]
|
||||
conv => rhs; rw [Pos.revSkipWhile]
|
||||
simp [← Pattern.BackwardPattern.skipSuffix?_string_eq_skipSuffix?_toSlice, h, ih]
|
||||
| case3 pos h =>
|
||||
conv => rhs; rw [dropEndWhile.go]
|
||||
simp [← Pattern.BackwardPattern.dropSuffix?_string_eq_dropSuffix?_toSlice]
|
||||
conv => rhs; rw [Pos.revSkipWhile]
|
||||
simp [← Pattern.BackwardPattern.skipSuffix?_string_eq_skipSuffix?_toSlice]
|
||||
|
||||
public theorem skipSuffixWhile_string_eq_skipSuffixWhile_toSlice {pat : String} {s : Slice} :
|
||||
s.skipSuffixWhile pat = s.skipSuffixWhile pat.toSlice :=
|
||||
Pos.revSkipWhile_string_eq_revSkipWhile_toSlice s.endPos
|
||||
|
||||
public theorem dropEndWhile_string_eq_dropEndWhile_toSlice {pat : String} {s : Slice} :
|
||||
s.dropEndWhile pat = s.dropEndWhile pat.toSlice := by
|
||||
simpa only [dropEndWhile] using dropEndWhileGo_string_eq s.endPos
|
||||
|
||||
private theorem takeEndWhileGo_string_eq {pat : String} {s : Slice} (curr : s.Pos) :
|
||||
takeEndWhile.go s pat curr = takeEndWhile.go s pat.toSlice curr := by
|
||||
fun_induction takeEndWhile.go s pat curr with
|
||||
| case1 pos nextCurr h₁ h₂ ih =>
|
||||
conv => rhs; rw [takeEndWhile.go]
|
||||
simp [← Pattern.BackwardPattern.dropSuffix?_string_eq_dropSuffix?_toSlice, h₁, h₂, ih]
|
||||
| case2 pos nextCurr h ih =>
|
||||
conv => rhs; rw [takeEndWhile.go]
|
||||
simp [← Pattern.BackwardPattern.dropSuffix?_string_eq_dropSuffix?_toSlice, h, ih]
|
||||
| case3 pos h =>
|
||||
conv => rhs; rw [takeEndWhile.go]
|
||||
simp [← Pattern.BackwardPattern.dropSuffix?_string_eq_dropSuffix?_toSlice]
|
||||
simp only [dropEndWhile]; exact congrArg _ skipSuffixWhile_string_eq_skipSuffixWhile_toSlice
|
||||
|
||||
public theorem takeEndWhile_string_eq_takeEndWhile_toSlice {pat : String} {s : Slice} :
|
||||
s.takeEndWhile pat = s.takeEndWhile pat.toSlice := by
|
||||
simpa only [takeEndWhile] using takeEndWhileGo_string_eq s.endPos
|
||||
simp only [takeEndWhile]; exact congrArg _ skipSuffixWhile_string_eq_skipSuffixWhile_toSlice
|
||||
|
||||
end String.Slice
|
||||
|
|
|
|||
|
|
@ -316,20 +316,20 @@ class BackwardPattern {ρ : Type} (pat : ρ) where
|
|||
Checks whether the slice ends with the pattern. If it does, the slice is returned with the
|
||||
suffix removed; otherwise the result is {name}`none`.
|
||||
-/
|
||||
dropSuffix? : (s : Slice) → Option s.Pos
|
||||
skipSuffix? : (s : Slice) → Option s.Pos
|
||||
/--
|
||||
Checks whether the slice ends with the pattern. If it does, the slice is returned with the
|
||||
suffix removed; otherwise the result is {name}`none`.
|
||||
-/
|
||||
dropSuffixOfNonempty? : (s : Slice) → (h : s.isEmpty = false) → Option s.Pos := fun s _ => dropSuffix? s
|
||||
skipSuffixOfNonempty? : (s : Slice) → (h : s.isEmpty = false) → Option s.Pos := fun s _ => skipSuffix? s
|
||||
/--
|
||||
Checks whether the slice ends with the pattern.
|
||||
-/
|
||||
endsWith : Slice → Bool := fun s => (dropSuffix? s).isSome
|
||||
endsWith : Slice → Bool := fun s => (skipSuffix? s).isSome
|
||||
|
||||
/--
|
||||
A lawful backward pattern is one where the three functions {name}`BackwardPattern.dropSuffix?`,
|
||||
{name}`BackwardPattern.dropSuffixOfNonempty?` and {name}`BackwardPattern.endsWith` agree for any
|
||||
A lawful backward pattern is one where the three functions {name}`BackwardPattern.skipSuffix?`,
|
||||
{name}`BackwardPattern.skipSuffixOfNonempty?` and {name}`BackwardPattern.endsWith` agree for any
|
||||
given input slice.
|
||||
|
||||
Note that this is a relatively weak condition. It is non-uniform in the sense that the functions
|
||||
|
|
@ -337,14 +337,14 @@ can still return completely different results on different slices, even if they
|
|||
string.
|
||||
|
||||
There is a stronger lawfulness typeclass {lit}`LawfulBackwardPatternModel` that asserts that the
|
||||
{name}`BackwardPattern.dropSuffix?` function behaves like a function that drops the longest prefix
|
||||
{name}`BackwardPattern.skipSuffix?` function behaves like a function that skips the longest prefix
|
||||
according to some notion of matching.
|
||||
-/
|
||||
class LawfulBackwardPattern {ρ : Type} (pat : ρ) [BackwardPattern pat] : Prop where
|
||||
dropSuffixOfNonempty?_eq {s : Slice} (h) :
|
||||
BackwardPattern.dropSuffixOfNonempty? pat s h = BackwardPattern.dropSuffix? pat s
|
||||
skipSuffixOfNonempty?_eq {s : Slice} (h) :
|
||||
BackwardPattern.skipSuffixOfNonempty? pat s h = BackwardPattern.skipSuffix? pat s
|
||||
endsWith_eq (s : Slice) :
|
||||
BackwardPattern.endsWith pat s = (BackwardPattern.dropSuffix? pat s).isSome
|
||||
BackwardPattern.endsWith pat s = (BackwardPattern.skipSuffix? pat s).isSome
|
||||
|
||||
/--
|
||||
A strict backward pattern is one which never drops an empty suffix.
|
||||
|
|
@ -354,7 +354,7 @@ iterator.
|
|||
-/
|
||||
class StrictBackwardPattern {ρ : Type} (pat : ρ) [BackwardPattern pat] : Prop where
|
||||
ne_endPos {s : Slice} (h) (q) :
|
||||
BackwardPattern.dropSuffixOfNonempty? pat s h = some q → q ≠ s.endPos
|
||||
BackwardPattern.skipSuffixOfNonempty? pat s h = some q → q ≠ s.endPos
|
||||
|
||||
/--
|
||||
Provides a conversion from a pattern to an iterator of {name}`SearchStep` searching for matches of
|
||||
|
|
@ -398,11 +398,11 @@ instance (s : Slice) [BackwardPattern pat] :
|
|||
Std.Iterator (DefaultBackwardSearcher pat s) Id (SearchStep s) where
|
||||
IsPlausibleStep it
|
||||
| .yield it' (.rejected p₁ p₂) => ∃ (h : it.internalState.currPos ≠ s.startPos),
|
||||
BackwardPattern.dropSuffixOfNonempty? pat (s.sliceTo it.internalState.currPos) (by simpa) = none ∧
|
||||
BackwardPattern.skipSuffixOfNonempty? pat (s.sliceTo it.internalState.currPos) (by simpa) = none ∧
|
||||
p₁ = it.internalState.currPos.prev h ∧ p₂ = it.internalState.currPos ∧
|
||||
it'.internalState.currPos = it.internalState.currPos.prev h
|
||||
| .yield it' (.matched p₁ p₂) => ∃ (h : it.internalState.currPos ≠ s.startPos), ∃ pos,
|
||||
BackwardPattern.dropSuffixOfNonempty? pat (s.sliceTo it.internalState.currPos) (by simpa) = some pos ∧
|
||||
BackwardPattern.skipSuffixOfNonempty? pat (s.sliceTo it.internalState.currPos) (by simpa) = some pos ∧
|
||||
p₁ = Slice.Pos.ofSliceTo pos ∧ p₂ = it.internalState.currPos ∧
|
||||
it'.internalState.currPos = Slice.Pos.ofSliceTo pos
|
||||
| .done => it.internalState.currPos = s.startPos
|
||||
|
|
@ -411,7 +411,7 @@ instance (s : Slice) [BackwardPattern pat] :
|
|||
if h : it.internalState.currPos = s.startPos then
|
||||
pure (.deflate ⟨.done, by simp [h]⟩)
|
||||
else
|
||||
match h' : BackwardPattern.dropSuffixOfNonempty? pat (s.sliceTo it.internalState.currPos) (by simpa) with
|
||||
match h' : BackwardPattern.skipSuffixOfNonempty? pat (s.sliceTo it.internalState.currPos) (by simpa) with
|
||||
| some pos =>
|
||||
pure (.deflate ⟨.yield ⟨⟨Slice.Pos.ofSliceTo pos⟩⟩
|
||||
(.matched (Slice.Pos.ofSliceTo pos) it.internalState.currPos), by simp [h, h']⟩)
|
||||
|
|
|
|||
|
|
@ -36,15 +36,15 @@ instance {c : Char} : ToForwardSearcher c (ToForwardSearcher.DefaultForwardSearc
|
|||
toSearcher s := ToForwardSearcher.toSearcher (· == c) s
|
||||
|
||||
instance {c : Char} : BackwardPattern c where
|
||||
dropSuffixOfNonempty? s h := BackwardPattern.dropSuffixOfNonempty? (· == c) s h
|
||||
dropSuffix? s := BackwardPattern.dropSuffix? (· == c) s
|
||||
skipSuffixOfNonempty? s h := BackwardPattern.skipSuffixOfNonempty? (· == c) s h
|
||||
skipSuffix? s := BackwardPattern.skipSuffix? (· == c) s
|
||||
endsWith s := BackwardPattern.endsWith (· == c) s
|
||||
|
||||
instance {c : Char} : StrictBackwardPattern c where
|
||||
ne_endPos h q := StrictBackwardPattern.ne_endPos (pat := (· == c)) h q
|
||||
|
||||
instance {c : Char} : LawfulBackwardPattern c where
|
||||
dropSuffixOfNonempty?_eq h := LawfulBackwardPattern.dropSuffixOfNonempty?_eq (pat := (· == c)) h
|
||||
skipSuffixOfNonempty?_eq h := LawfulBackwardPattern.skipSuffixOfNonempty?_eq (pat := (· == c)) h
|
||||
endsWith_eq s := LawfulBackwardPattern.endsWith_eq (pat := (· == c)) s
|
||||
|
||||
instance {c : Char} : ToBackwardSearcher c (ToBackwardSearcher.DefaultBackwardSearcher c) :=
|
||||
|
|
|
|||
|
|
@ -88,12 +88,12 @@ end Decidable
|
|||
|
||||
@[default_instance]
|
||||
instance {p : Char → Bool} : BackwardPattern p where
|
||||
dropSuffixOfNonempty? s h :=
|
||||
skipSuffixOfNonempty? s h :=
|
||||
if p ((s.endPos.prev (Ne.symm (by exact Slice.startPos_ne_endPos h))).get (by simp)) then
|
||||
some (s.endPos.prev (Ne.symm (by exact Slice.startPos_ne_endPos h)))
|
||||
else
|
||||
none
|
||||
dropSuffix? s :=
|
||||
skipSuffix? s :=
|
||||
if h : s.endPos = s.startPos then
|
||||
none
|
||||
else if p ((s.endPos.prev h).get (by simp)) then
|
||||
|
|
@ -108,17 +108,17 @@ instance {p : Char → Bool} : BackwardPattern p where
|
|||
|
||||
instance {p : Char → Bool} : StrictBackwardPattern p where
|
||||
ne_endPos {s h q} := by
|
||||
simp only [BackwardPattern.dropSuffixOfNonempty?, Option.ite_none_right_eq_some,
|
||||
simp only [BackwardPattern.skipSuffixOfNonempty?, Option.ite_none_right_eq_some,
|
||||
Option.some.injEq, ne_eq, and_imp]
|
||||
rintro _ rfl
|
||||
simp
|
||||
|
||||
instance {p : Char → Bool} : LawfulBackwardPattern p where
|
||||
dropSuffixOfNonempty?_eq {s h} := by
|
||||
simp [BackwardPattern.dropSuffixOfNonempty?, BackwardPattern.dropSuffix?,
|
||||
skipSuffixOfNonempty?_eq {s h} := by
|
||||
simp [BackwardPattern.skipSuffixOfNonempty?, BackwardPattern.skipSuffix?,
|
||||
Eq.comm (a := s.endPos), Slice.startPos_eq_endPos_iff, h]
|
||||
endsWith_eq {s} := by
|
||||
simp only [BackwardPattern.endsWith, BackwardPattern.dropSuffix?]
|
||||
simp only [BackwardPattern.endsWith, BackwardPattern.skipSuffix?]
|
||||
split <;> (try split) <;> simp_all
|
||||
|
||||
@[default_instance]
|
||||
|
|
@ -128,15 +128,15 @@ instance {p : Char → Bool} : ToBackwardSearcher p (ToBackwardSearcher.DefaultB
|
|||
namespace Decidable
|
||||
|
||||
instance {p : Char → Prop} [DecidablePred p] : BackwardPattern p where
|
||||
dropSuffixOfNonempty? s h := BackwardPattern.dropSuffixOfNonempty? (decide <| p ·) s h
|
||||
dropSuffix? s := BackwardPattern.dropSuffix? (decide <| p ·) s
|
||||
skipSuffixOfNonempty? s h := BackwardPattern.skipSuffixOfNonempty? (decide <| p ·) s h
|
||||
skipSuffix? s := BackwardPattern.skipSuffix? (decide <| p ·) s
|
||||
endsWith s := BackwardPattern.endsWith (decide <| p ·) s
|
||||
|
||||
instance {p : Char → Prop} [DecidablePred p] : StrictBackwardPattern p where
|
||||
ne_endPos h q := StrictBackwardPattern.ne_endPos (pat := (decide <| p ·)) h q
|
||||
|
||||
instance {p : Char → Prop} [DecidablePred p] : LawfulBackwardPattern p where
|
||||
dropSuffixOfNonempty?_eq h := LawfulBackwardPattern.dropSuffixOfNonempty?_eq (pat := (decide <| p ·)) h
|
||||
skipSuffixOfNonempty?_eq h := LawfulBackwardPattern.skipSuffixOfNonempty?_eq (pat := (decide <| p ·)) h
|
||||
endsWith_eq s := LawfulBackwardPattern.endsWith_eq (pat := (decide <| p ·)) s
|
||||
|
||||
instance {p : Char → Prop} [DecidablePred p] : ToBackwardSearcher p (ToBackwardSearcher.DefaultBackwardSearcher p) :=
|
||||
|
|
|
|||
|
|
@ -316,7 +316,7 @@ def endsWith (pat : Slice) (s : Slice) : Bool :=
|
|||
false
|
||||
|
||||
@[inline]
|
||||
def dropSuffix? (pat : Slice) (s : Slice) : Option s.Pos :=
|
||||
def skipSuffix? (pat : Slice) (s : Slice) : Option s.Pos :=
|
||||
if endsWith pat s then
|
||||
some <| s.pos! <| s.endPos.offset.unoffsetBy pat.rawEndPos
|
||||
else
|
||||
|
|
@ -324,11 +324,11 @@ def dropSuffix? (pat : Slice) (s : Slice) : Option s.Pos :=
|
|||
|
||||
instance {pat : Slice} : BackwardPattern pat where
|
||||
endsWith := endsWith pat
|
||||
dropSuffix? := dropSuffix? pat
|
||||
skipSuffix? := skipSuffix? pat
|
||||
|
||||
instance {pat : String} : BackwardPattern pat where
|
||||
endsWith := endsWith pat.toSlice
|
||||
dropSuffix? := dropSuffix? pat.toSlice
|
||||
skipSuffix? := skipSuffix? pat.toSlice
|
||||
|
||||
end BackwardSliceSearcher
|
||||
|
||||
|
|
|
|||
|
|
@ -328,6 +328,26 @@ def splitInclusive (s : Slice) (pat : ρ) [ToForwardSearcher pat σ] :
|
|||
Std.Iter (α := SplitInclusiveIterator pat s) Slice :=
|
||||
{ internalState := .operating s.startPos (ToForwardSearcher.toSearcher pat s) }
|
||||
|
||||
/--
|
||||
If {name}`pat` matches a prefix of {name}`s`, returns the position at the start of the remainder.
|
||||
Returns {name}`none` otherwise.
|
||||
|
||||
This function is generic over all currently supported patterns.
|
||||
-/
|
||||
@[inline]
|
||||
def skipPrefix? (s : Slice) (pat : ρ) [ForwardPattern pat] : Option s.Pos :=
|
||||
ForwardPattern.skipPrefix? pat s
|
||||
|
||||
/--
|
||||
If {name}`pat` matches a prefix at {name}`pos`, returns the position after the end of the match.
|
||||
Returns {name}`none` otherwise.
|
||||
|
||||
This function is generic over all currently supported patterns.
|
||||
-/
|
||||
@[inline]
|
||||
def Pos.skip? {s : Slice} (pos : s.Pos) (pat : ρ) [ForwardPattern pat] : Option s.Pos :=
|
||||
((s.sliceFrom pos).skipPrefix? pat).map Pos.ofSliceFrom
|
||||
|
||||
/--
|
||||
If {name}`pat` matches a prefix of {name}`s`, returns the remainder. Returns {name}`none` otherwise.
|
||||
|
||||
|
|
@ -344,7 +364,7 @@ Examples:
|
|||
-/
|
||||
@[inline]
|
||||
def dropPrefix? (s : Slice) (pat : ρ) [ForwardPattern pat] : Option Slice :=
|
||||
(ForwardPattern.skipPrefix? pat s).map s.sliceFrom
|
||||
(s.skipPrefix? pat).map s.sliceFrom
|
||||
|
||||
/--
|
||||
If {name}`pat` matches a prefix of {name}`s`, returns the remainder. Returns {name}`s` unmodified
|
||||
|
|
@ -400,6 +420,28 @@ Examples:
|
|||
def drop (s : Slice) (n : Nat) : Slice :=
|
||||
s.sliceFrom (s.startPos.nextn n)
|
||||
|
||||
/--
|
||||
Advances {name}`pos` as long as {name}`pat` matches.
|
||||
-/
|
||||
@[specialize pat]
|
||||
def Pos.skipWhile {s : Slice} (pos : s.Pos) (pat : ρ) [ForwardPattern pat] : s.Pos :=
|
||||
if let some nextCurr := ForwardPattern.skipPrefix? pat (s.sliceFrom pos) then
|
||||
if pos < Pos.ofSliceFrom nextCurr then
|
||||
skipWhile (Pos.ofSliceFrom nextCurr) pat
|
||||
else
|
||||
pos
|
||||
else
|
||||
pos
|
||||
termination_by pos
|
||||
|
||||
/--
|
||||
Returns the position after the longest prefix of {name}`s` for which {name}`pat` matches
|
||||
(potentially repeatedly).
|
||||
-/
|
||||
@[inline]
|
||||
def skipPrefixWhile (s : Slice) (pat : ρ) [ForwardPattern pat] : s.Pos :=
|
||||
s.startPos.skipWhile pat
|
||||
|
||||
/--
|
||||
Creates a new slice that contains the longest prefix of {name}`s` for which {name}`pat` matched
|
||||
(potentially repeatedly).
|
||||
|
|
@ -412,18 +454,7 @@ Examples:
|
|||
-/
|
||||
@[inline]
|
||||
def dropWhile (s : Slice) (pat : ρ) [ForwardPattern pat] : Slice :=
|
||||
go s.startPos
|
||||
where
|
||||
@[specialize pat]
|
||||
go (curr : s.Pos) : Slice :=
|
||||
if let some nextCurr := ForwardPattern.skipPrefix? pat (s.sliceFrom curr) then
|
||||
if curr < Pos.ofSliceFrom nextCurr then
|
||||
go (Pos.ofSliceFrom nextCurr)
|
||||
else
|
||||
s.sliceFrom curr
|
||||
else
|
||||
s.sliceFrom curr
|
||||
termination_by curr
|
||||
s.sliceFrom (s.skipPrefixWhile pat)
|
||||
|
||||
/--
|
||||
Removes leading whitespace from a slice by moving its start position to the first non-whitespace
|
||||
|
|
@ -472,18 +503,7 @@ Examples:
|
|||
-/
|
||||
@[inline]
|
||||
def takeWhile (s : Slice) (pat : ρ) [ForwardPattern pat] : Slice :=
|
||||
go s.startPos
|
||||
where
|
||||
@[specialize pat]
|
||||
go (curr : s.Pos) : Slice :=
|
||||
if let some nextCurr := ForwardPattern.skipPrefix? pat (s.sliceFrom curr) then
|
||||
if curr < Pos.ofSliceFrom nextCurr then
|
||||
go (Pos.ofSliceFrom nextCurr)
|
||||
else
|
||||
s.sliceTo curr
|
||||
else
|
||||
s.sliceTo curr
|
||||
termination_by curr
|
||||
s.sliceTo (s.skipPrefixWhile pat)
|
||||
|
||||
/--
|
||||
Finds the position of the first match of the pattern {name}`pat` in a slice {name}`s`. If there
|
||||
|
|
@ -668,6 +688,26 @@ def revSplit (s : Slice) (pat : ρ) [ToBackwardSearcher pat σ] :
|
|||
Std.Iter (α := RevSplitIterator pat s) Slice :=
|
||||
{ internalState := .operating s.endPos (ToBackwardSearcher.toSearcher pat s) }
|
||||
|
||||
/--
|
||||
If {name}`pat` matches a suffix of {name}`s`, returns the position at the beginning of the suffix.
|
||||
Returns {name}`none` otherwise.
|
||||
|
||||
This function is generic over all currently supported patterns.
|
||||
-/
|
||||
@[inline]
|
||||
def skipSuffix? (s : Slice) (pat : ρ) [BackwardPattern pat] : Option s.Pos :=
|
||||
BackwardPattern.skipSuffix? pat s
|
||||
|
||||
/--
|
||||
If {name}`pat` matches a suffix at {name}`pos`, returns the position at the beginning of the match.
|
||||
Returns {name}`none` otherwise.
|
||||
|
||||
This function is generic over all currently supported patterns.
|
||||
-/
|
||||
@[inline]
|
||||
def Pos.revSkip? {s : Slice} (pos : s.Pos) (pat : ρ) [ForwardPattern pat] : Option s.Pos :=
|
||||
((s.sliceFrom pos).skipPrefix? pat).map Pos.ofSliceFrom
|
||||
|
||||
/--
|
||||
If {name}`pat` matches a suffix of {name}`s`, returns the remainder. Returns {name}`none` otherwise.
|
||||
|
||||
|
|
@ -684,7 +724,7 @@ Examples:
|
|||
-/
|
||||
@[inline]
|
||||
def dropSuffix? (s : Slice) (pat : ρ) [BackwardPattern pat] : Option Slice :=
|
||||
(BackwardPattern.dropSuffix? pat s).map s.sliceTo
|
||||
(s.skipSuffix? pat).map s.sliceTo
|
||||
|
||||
/--
|
||||
If {name}`pat` matches a suffix of {name}`s`, returns the remainder. Returns {name}`s` unmodified
|
||||
|
|
@ -719,6 +759,28 @@ Examples:
|
|||
def dropEnd (s : Slice) (n : Nat) : Slice :=
|
||||
s.sliceTo (s.endPos.prevn n)
|
||||
|
||||
/--
|
||||
Rewinds {name}`pos` as long as {name}`pat` matches.
|
||||
-/
|
||||
@[specialize pat]
|
||||
def Pos.revSkipWhile {s : Slice} (pos : s.Pos) (pat : ρ) [BackwardPattern pat] : s.Pos :=
|
||||
if let some nextCurr := BackwardPattern.skipSuffix? pat (s.sliceTo pos) then
|
||||
if Pos.ofSliceTo nextCurr < pos then
|
||||
revSkipWhile (Pos.ofSliceTo nextCurr) pat
|
||||
else
|
||||
pos
|
||||
else
|
||||
pos
|
||||
termination_by pos.down
|
||||
|
||||
/--
|
||||
Returns the position a the start of the longest suffix of {name}`s` for which {name}`pat` matches
|
||||
(potentially repeatedly).
|
||||
-/
|
||||
@[inline]
|
||||
def skipSuffixWhile (s : Slice) (pat : ρ) [BackwardPattern pat] : s.Pos :=
|
||||
s.endPos.revSkipWhile pat
|
||||
|
||||
/--
|
||||
Creates a new slice that contains the longest suffix of {name}`s` for which {name}`pat` matched
|
||||
(potentially repeatedly).
|
||||
|
|
@ -730,18 +792,7 @@ Examples:
|
|||
-/
|
||||
@[inline]
|
||||
def dropEndWhile (s : Slice) (pat : ρ) [BackwardPattern pat] : Slice :=
|
||||
go s.endPos
|
||||
where
|
||||
@[specialize pat]
|
||||
go (curr : s.Pos) : Slice :=
|
||||
if let some nextCurr := BackwardPattern.dropSuffix? pat (s.sliceTo curr) then
|
||||
if Pos.ofSliceTo nextCurr < curr then
|
||||
go (Pos.ofSliceTo nextCurr)
|
||||
else
|
||||
s.sliceTo curr
|
||||
else
|
||||
s.sliceTo curr
|
||||
termination_by curr.down
|
||||
s.sliceTo (s.skipSuffixWhile pat)
|
||||
|
||||
/--
|
||||
Removes trailing whitespace from a slice by moving its end position to the last non-whitespace
|
||||
|
|
@ -789,18 +840,7 @@ Examples:
|
|||
-/
|
||||
@[inline]
|
||||
def takeEndWhile (s : Slice) (pat : ρ) [BackwardPattern pat] : Slice :=
|
||||
go s.endPos
|
||||
where
|
||||
@[specialize pat]
|
||||
go (curr : s.Pos) : Slice :=
|
||||
if let some nextCurr := BackwardPattern.dropSuffix? pat (s.sliceTo curr) then
|
||||
if Pos.ofSliceTo nextCurr < curr then
|
||||
go (Pos.ofSliceTo nextCurr)
|
||||
else
|
||||
s.sliceFrom curr
|
||||
else
|
||||
s.sliceFrom curr
|
||||
termination_by curr.down
|
||||
s.sliceFrom (s.skipSuffixWhile pat)
|
||||
|
||||
/--
|
||||
Finds the position of the first match of the pattern {name}`pat` in a slice, starting
|
||||
|
|
|
|||
|
|
@ -208,6 +208,39 @@ def dropRightWhile (s : String) (p : Char → Bool) : String :=
|
|||
def Slice.dropRightWhile (s : Slice) (p : Char → Bool) : Slice :=
|
||||
s.dropEndWhile p
|
||||
|
||||
/--
|
||||
If {name}`pat` matches a prefix of {name}`s`, returns the position at the start of the remainder.
|
||||
Returns {name}`none` otherwise.
|
||||
|
||||
This function is generic over all currently supported patterns.
|
||||
-/
|
||||
@[inline] def skipPrefix? (s : String) (pat : ρ) [ForwardPattern pat] : Option s.Pos :=
|
||||
(s.toSlice.skipPrefix? pat).map Pos.ofToSlice
|
||||
|
||||
/--
|
||||
Returns the position after the longest prefix of {name}`s` for which {name}`pat` matches
|
||||
(potentially repeatedly).
|
||||
-/
|
||||
@[inline] def skipPrefixWhile (s : String) (pat : ρ) [ForwardPattern pat] : s.Pos :=
|
||||
Pos.ofToSlice (s.toSlice.skipPrefixWhile pat)
|
||||
|
||||
/--
|
||||
If {name}`pat` matches at {name}`pos`, returns the position after the end of the match.
|
||||
Returns {name}`none` otherwise.
|
||||
|
||||
This function is generic over all currently supported patterns.
|
||||
-/
|
||||
@[inline]
|
||||
def Pos.skip? {s : String} (pos : s.Pos) (pat : ρ) [ForwardPattern pat] : Option s.Pos :=
|
||||
(pos.toSlice.skip? pat).map Pos.ofToSlice
|
||||
|
||||
/--
|
||||
Advances {name}`pos` as long as {name}`pat` matches.
|
||||
-/
|
||||
@[inline]
|
||||
def Pos.skipWhile {s : String} (pos : s.Pos) (pat : ρ) [ForwardPattern pat] : s.Pos :=
|
||||
Pos.ofToSlice (pos.toSlice.skipWhile pat)
|
||||
|
||||
/--
|
||||
Checks whether the first string ({name}`s`) begins with the pattern ({name}`pat`).
|
||||
|
||||
|
|
@ -258,6 +291,39 @@ Examples:
|
|||
@[inline] def endsWith (s : String) (pat : ρ) [BackwardPattern pat] : Bool :=
|
||||
s.toSlice.endsWith pat
|
||||
|
||||
/--
|
||||
If {name}`pat` matches a suffix of {name}`s`, returns the position at the beginning of the suffix.
|
||||
Returns {name}`none` otherwise.
|
||||
|
||||
This function is generic over all currently supported patterns.
|
||||
-/
|
||||
@[inline] def skipSuffix? (s : String) (pat : ρ) [BackwardPattern pat] : Option s.Pos :=
|
||||
(s.toSlice.skipSuffix? pat).map Pos.ofToSlice
|
||||
|
||||
/--
|
||||
Returns the position at the start of the longest suffix of {name}`s` for which {name}`pat` matches
|
||||
(potentially repeatedly).
|
||||
-/
|
||||
@[inline] def skipSuffixWhile (s : String) (pat : ρ) [BackwardPattern pat] : s.Pos :=
|
||||
Pos.ofToSlice (s.toSlice.skipSuffixWhile pat)
|
||||
|
||||
/--
|
||||
If {name}`pat` matches at {name}`pos`, returns the position after the end of the match.
|
||||
Returns {name}`none` otherwise.
|
||||
|
||||
This function is generic over all currently supported patterns.
|
||||
-/
|
||||
@[inline]
|
||||
def Pos.revSkip? {s : String} (pos : s.Pos) (pat : ρ) [ForwardPattern pat] : Option s.Pos :=
|
||||
(pos.toSlice.revSkip? pat).map Pos.ofToSlice
|
||||
|
||||
/--
|
||||
Rewinds {name}`pos` as long as {name}`pat` matches.
|
||||
-/
|
||||
@[inline]
|
||||
def Pos.revSkipWhile {s : String} (pos : s.Pos) (pat : ρ) [BackwardPattern pat] : s.Pos :=
|
||||
Pos.ofToSlice (pos.toSlice.revSkipWhile pat)
|
||||
|
||||
/--
|
||||
Removes trailing whitespace from a string by returning a slice whose end position is the last
|
||||
non-whitespace character, or the start position if there is no non-whitespace character.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue