]> gitweb.factorcode.org Git - factor.git/blob - basis/regexp/compiler/compiler.factor
Merge branch 'master' of git://factorcode.org/git/factor into clean-linux-x86-32
[factor.git] / basis / regexp / compiler / compiler.factor
1 ! Copyright (C) 2009 Daniel Ehrenberg.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: regexp.classes kernel sequences regexp.negation
4 quotations assocs fry math locals combinators
5 accessors words compiler.units kernel.private strings
6 sequences.private arrays call namespaces unicode.breaks
7 regexp.transition-tables combinators.short-circuit ;
8 IN: regexp.compiler
9
10 GENERIC: question>quot ( question -- quot )
11
12 SYMBOL: shortest?
13 SYMBOL: backwards?
14
15 <PRIVATE
16
17 M: t question>quot drop [ 2drop t ] ;
18 M: f question>quot drop [ 2drop f ] ;
19
20 M: not-class question>quot
21     class>> question>quot [ not ] compose ;
22
23 M: beginning-of-input question>quot
24     drop [ drop zero? ] ;
25
26 M: end-of-input question>quot
27     drop [ length = ] ;
28
29 M: end-of-file question>quot
30     drop [
31         {
32             [ length swap - 2 <= ]
33             [ swap tail { "\n" "\r\n" "\r" "" } member? ]
34         } 2&&
35     ] ;
36
37 M: $ question>quot
38     drop [ { [ length = ] [ ?nth "\r\n" member? ] } 2|| ] ;
39
40 M: ^ question>quot
41     drop [ { [ drop zero? ] [ [ 1- ] dip ?nth "\r\n" member? ] } 2|| ] ;
42
43 M: word-break question>quot
44     drop [ word-break-at? ] ;
45
46 : (execution-quot) ( next-state -- quot )
47     ! The conditions here are for lookaround and anchors, etc
48     dup condition? [
49         [ question>> question>quot ] [ yes>> ] [ no>> ] tri
50         [ (execution-quot) ] bi@
51         '[ 2dup @ _ _ if ]
52     ] [ '[ _ execute ] ] if ;
53
54 : execution-quot ( next-state -- quot )
55     dup sequence? [ first ] when
56     (execution-quot) ;
57
58 TUPLE: box contents ;
59 C: <box> box
60
61 : condition>quot ( condition -- quot )
62     ! Conditions here are for different classes
63     dup condition? [
64         [ question>> ] [ yes>> ] [ no>> ] tri
65         [ condition>quot ] bi@
66         '[ dup _ class-member? _ _ if ]
67     ] [
68         contents>>
69         [ [ 3drop ] ] [ execution-quot '[ drop @ ] ] if-empty
70     ] if ;
71
72 : non-literals>dispatch ( literals non-literals  -- quot )
73     [ swap ] assoc-map ! we want state => predicate, and get the opposite as input
74     swap keys f assoc-answers
75     table>condition [ <box> ] condition-map condition>quot ;
76
77 : literals>cases ( literal-transitions -- case-body )
78     [ execution-quot ] assoc-map ;
79
80 : split-literals ( transitions -- case default )
81     { } assoc-like [ first integer? ] partition
82     [ [ literals>cases ] keep ] dip non-literals>dispatch ;
83
84 :: step ( last-match index str quot final? direction -- last-index/f )
85     final? index last-match ?
86     index str bounds-check? [
87         index direction + str
88         index str nth-unsafe
89         quot call
90     ] when ; inline
91
92 : direction ( -- n )
93     backwards? get -1 1 ? ;
94
95 : transitions>quot ( transitions final-state? -- quot )
96     dup shortest? get and [ 2drop [ drop nip ] ] [
97         [ split-literals swap case>quot ] dip direction
98         '[ { array-capacity string } declare _ _ _ step ]
99     ] if ;
100
101 : word>quot ( word dfa -- quot )
102     [ transitions>> at ]
103     [ final-states>> key? ] 2bi
104     transitions>quot ;
105
106 : states>code ( words dfa -- )
107     [ ! with-compilation-unit doesn't compile, so we need call( -- )
108         [
109             '[
110                 dup _ word>quot
111                 (( last-match index string -- ? ))
112                 define-declared
113             ] each
114         ] with-compilation-unit
115     ] call( words dfa -- ) ;
116
117 : states>words ( dfa -- words dfa )
118     dup transitions>> keys [ gensym ] H{ } map>assoc
119     [ transitions-at ]
120     [ values ]
121     bi swap ; 
122
123 : dfa>main-word ( dfa -- word )
124     states>words [ states>code ] keep start-state>> ;
125
126 PRIVATE>
127
128 : simple-define-temp ( quot effect -- word )
129     [ [ define-temp ] with-compilation-unit ] call( quot effect -- word ) ;
130
131 : dfa>word ( dfa -- quot )
132     dfa>main-word execution-quot '[ drop [ f ] 2dip @ ]
133     (( start-index string regexp -- i/f )) simple-define-temp ;
134
135 : dfa>shortest-word ( dfa -- word )
136     t shortest? [ dfa>word ] with-variable ;
137
138 : dfa>reverse-word ( dfa -- word )
139     t backwards? [ dfa>word ] with-variable ;
140
141 : dfa>reverse-shortest-word ( dfa -- word )
142     t backwards? [ dfa>shortest-word ] with-variable ;