factor/basis/regexp/traversal/traversal.factor

98 lines
2.7 KiB
Factor
Raw Normal View History

! Copyright (C) 2008 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
2008-11-22 18:31:40 -05:00
USING: accessors assocs combinators kernel math
quotations sequences regexp.parser regexp.classes fry arrays
combinators.short-circuit regexp.utils prettyprint regexp.nfa ;
IN: regexp.traversal
TUPLE: dfa-traverser
dfa-table
2009-02-15 15:28:22 -05:00
current-state
text
match-failed?
start-index current-index
matches ;
: <dfa-traverser> ( text regexp -- match )
2009-02-15 15:28:22 -05:00
dfa-table>>
dfa-traverser new
swap [ start-state>> >>current-state ] [ >>dfa-table ] bi
swap >>text
0 >>start-index
0 >>current-index
2009-02-15 15:28:22 -05:00
V{ } clone >>matches ;
: final-state? ( dfa-traverser -- ? )
[ current-state>> ]
[ dfa-table>> final-states>> ] bi key? ;
: beginning-of-text? ( dfa-traverser -- ? )
current-index>> 0 <= ; inline
: end-of-text? ( dfa-traverser -- ? )
[ current-index>> ] [ text>> length ] bi >= ; inline
: text-finished? ( dfa-traverser -- ? )
2008-09-22 15:55:17 -04:00
{
[ current-state>> empty? ]
[ end-of-text? ]
[ match-failed?>> ]
2008-09-22 15:55:17 -04:00
} 1|| ;
: save-final-state ( dfa-straverser -- )
[ current-index>> ] [ matches>> ] bi push ;
: match-done? ( dfa-traverser -- ? )
dup final-state? [
dup save-final-state
] when text-finished? ;
2009-02-15 15:28:22 -05:00
: text-character ( dfa-traverser n -- ch )
[ text>> ] swap '[ current-index>> _ + ] bi nth ;
: previous-text-character ( dfa-traverser -- ch )
2009-02-15 15:28:22 -05:00
-1 text-character ;
: current-text-character ( dfa-traverser -- ch )
2009-02-15 15:28:22 -05:00
0 text-character ;
: next-text-character ( dfa-traverser -- ch )
2009-02-15 15:28:22 -05:00
1 text-character ;
2008-09-19 18:54:34 -04:00
: increment-state ( dfa-traverser state -- dfa-traverser )
2009-02-15 15:28:22 -05:00
[ [ 1 + ] change-current-index ]
[ first ] bi* >>current-state ;
: match-literal ( transition from-state table -- to-state/f )
transitions>> at at ;
: match-class ( transition from-state table -- to-state/f )
transitions>> at* [
2009-02-15 15:28:22 -05:00
'[ drop _ swap class-member? ] assoc-find [ nip ] [ drop ] if
] [ drop ] if ;
: match-default ( transition from-state table -- to-state/f )
[ drop ] 2dip transitions>> at t swap at ;
: match-transition ( obj from-state dfa -- to-state/f )
{ [ match-literal ] [ match-class ] [ match-default ] } 3|| ;
: setup-match ( match -- obj state dfa-table )
[ [ current-index>> ] [ text>> ] bi nth ]
[ current-state>> ]
[ dfa-table>> ] tri ;
: do-match ( dfa-traverser -- dfa-traverser )
dup match-done? [
dup setup-match match-transition
[ increment-state do-match ] when*
] unless ;
: return-match ( dfa-traverser -- slice/f )
dup matches>>
[ drop f ]
[
[ [ text>> ] [ start-index>> ] bi ]
[ peek ] bi* rot <slice>
] if-empty ;