aboutsummaryrefslogtreecommitdiff
path: root/libs/regex.neb
blob: 8de476f973a89223cefc40e99aa68f0edb4c47a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
; regex
; for doing regex matches

(func match? :bool (pattern :string text :string)
    (if (eq? 0 (length pattern))
        #true
        (.search pattern text)))

(func .match-one :bool (left right)
    (in? left (list "" "." right)))

(func .match-? :bool (pattern text)
    (or
        (and 
            (.match-one (first pattern) (first text))
            (.match-inner (rest (rest pattern)) (rest text)))
        (.match-inner (rest (rest pattern)) text)))

(func .match-* (pattern text)
    (or
        (and
            (.match-one (first pattern) (first text))
            (.match-inner pattern (rest text)))
        (.match-inner (rest (rest pattern)) text)))

(func .read-inner (pattern end)
    (.read-inner pattern end ""))

(func .read-inner (pattern end progress)
    (if (eq? end (first pattern))
        (list (rest pattern) progress)
        (.read-inner (rest pattern) end (concat progress (first pattern)))))

(func .match-bracket (pattern text)
    (def processed (.read-inner (rest pattern) "]"))
    (not (empty? (drop-while (split (last processed))
        (not (.match-inner (concat _item_ (first processed)) text))))))

(func .match-inner (pattern text)
    (branch
        ((eq? "" pattern) #true)
        ((and (eq? "$" pattern) (eq? "" text)) #true)
        ((eq? "" text) #false)
        ((eq? "[" (first pattern))
            (.match-bracket pattern text))
        ((and (>= (length pattern) 2) (eq? "?" (first (rest pattern))))
            (.match-? pattern text))
        ((and (>= (length pattern) 2) (eq? "*" (first (rest pattern))))
            (.match-* pattern text))
        (#true
            (and
                (.match-one (first pattern) (first text))
                (.match-inner (rest pattern) (rest text))))))

(func .search (pattern text)
    (if (eq? "^" (first pattern))
        (.match-inner (rest pattern) text)
        ;(.match-inner (concat ".*" pattern) text)))  ; this is elegant but requires going through the entire string
        (block
            (def seed (list))
            (for-count (length text)
                (redef seed (append seed _idx_)))

            (not (empty? (drop-while seed
                (not (.match-inner pattern (join (slice (split text) _item_) "")))))))))