]> gitweb.factorcode.org Git - factor.git/blob - basis/regexp/nfa/nfa.factor
Various regexp changes, including the addition of regexp combinators
[factor.git] / basis / regexp / nfa / nfa.factor
1 ! Copyright (C) 2008, 2009 Doug Coleman, Daniel Ehrenberg.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors arrays assocs grouping kernel
4 locals math namespaces sequences fry quotations
5 math.order math.ranges vectors unicode.categories
6 regexp.transition-tables words sets hashtables combinators.short-circuit
7 unicode.case.private regexp.ast regexp.classes ;
8 IN: regexp.nfa
9
10 ! This uses unicode.case.private for ch>upper and ch>lower
11 ! but case-insensitive matching should be done by case-folding everything
12 ! before processing starts
13
14 GENERIC: remove-lookahead ( syntax-tree -- syntax-tree' )
15 ! This is unfinished and does nothing right now!
16
17 M: object remove-lookahead ;
18
19 M: with-options remove-lookahead
20     [ tree>> remove-lookahead ] [ options>> ] bi <with-options> ;
21
22 M: alternation remove-lookahead
23     [ first>> ] [ second>> ] bi [ remove-lookahead ] bi@ alternation boa ;
24
25 M: concatenation remove-lookahead ;
26
27 SYMBOL: option-stack
28
29 SYMBOL: state
30
31 : next-state ( -- state )
32     state [ get ] [ inc ] bi ;
33
34 SYMBOL: nfa-table
35
36 : set-each ( keys value hashtable -- )
37     '[ _ swap _ set-at ] each ;
38
39 : options>hash ( options -- hashtable )
40     H{ } clone [
41         [ [ on>> t ] dip set-each ]
42         [ [ off>> f ] dip set-each ] 2bi
43     ] keep ;
44
45 : using-options ( options quot -- )
46     [ options>hash option-stack [ ?push ] change ] dip
47     call option-stack get pop* ; inline
48
49 : option? ( obj -- ? )
50     option-stack get assoc-stack ;
51
52 GENERIC: nfa-node ( node -- start-state end-state )
53
54 : add-simple-entry ( obj class -- start-state end-state )
55     [ next-state next-state 2dup ] 2dip
56     make-transition nfa-table get add-transition ;
57
58 : epsilon-transition ( source target -- )
59     epsilon <literal-transition> nfa-table get add-transition ;
60
61 M:: star nfa-node ( node -- start end )
62     node term>> nfa-node :> s1 :> s0
63     next-state :> s2
64     next-state :> s3
65     s1 s0 epsilon-transition
66     s2 s0 epsilon-transition
67     s2 s3 epsilon-transition
68     s1 s3 epsilon-transition
69     s2 s3 ;
70
71 M: tagged-epsilon nfa-node
72     literal-transition add-simple-entry ;
73
74 M: concatenation nfa-node ( node -- start end )
75     [ first>> ] [ second>> ] bi
76     reversed-regexp option? [ swap ] when
77     [ nfa-node ] bi@
78     [ epsilon-transition ] dip ;
79
80 :: alternate-nodes ( s0 s1 s2 s3 -- start end )
81     next-state :> s4
82     next-state :> s5
83     s4 s0 epsilon-transition
84     s4 s2 epsilon-transition
85     s1 s5 epsilon-transition
86     s3 s5 epsilon-transition
87     s4 s5 ;
88
89 M: alternation nfa-node ( node -- start end )
90     [ first>> ] [ second>> ] bi
91     [ nfa-node ] bi@
92     alternate-nodes ;
93
94 GENERIC: modify-class ( char-class -- char-class' )
95
96 M: object modify-class ;
97
98 M: integer modify-class
99     case-insensitive option? [
100         dup Letter? [
101             [ ch>lower ] [ ch>upper ] bi 2array <or-class>
102         ] when
103     ] when ;
104
105 M: integer nfa-node ( node -- start end )
106     modify-class dup class?
107     class-transition literal-transition ?
108     add-simple-entry ;
109
110 M: primitive-class modify-class
111     class>> modify-class <primitive-class> ;
112
113 M: or-class modify-class
114     seq>> [ modify-class ] map <or-class> ;
115
116 M: not-class modify-class
117     class>> modify-class <not-class> ;
118
119 M: any-char modify-class
120     drop dotall option? t any-char-no-nl ? ;
121
122 : modify-letter-class ( class -- newclass )
123     case-insensitive option? [ drop Letter-class ] when ;
124 M: letter-class modify-class modify-letter-class ;
125 M: LETTER-class modify-class modify-letter-class ;
126
127 : cased-range? ( range -- ? )
128     [ from>> ] [ to>> ] bi {
129         [ [ letter? ] bi@ and ]
130         [ [ LETTER? ] bi@ and ]
131     } 2|| ;
132
133 M: range modify-class
134     case-insensitive option? [
135         dup cased-range? [
136             [ from>> ] [ to>> ] bi
137             [ [ ch>lower ] bi@ <range> ]
138             [ [ ch>upper ] bi@ <range> ] 2bi 
139             2array <or-class>
140         ] when
141     ] when ;
142
143 M: class nfa-node
144     modify-class class-transition add-simple-entry ;
145
146 M: with-options nfa-node ( node -- start end )
147     dup options>> [ tree>> nfa-node ] using-options ;
148
149 : construct-nfa ( ast -- nfa-table )
150     [
151         0 state set
152         <transition-table> nfa-table set
153         remove-lookahead nfa-node
154         nfa-table get
155             swap dup associate >>final-states
156             swap >>start-state
157     ] with-scope ;