Category talk:Factor-numspec

From Rosetta Code

Source code

<lang factor>USING: ascii assocs kernel lexer lists lists.lazy math math.functions math.parser namespaces pair-rocket parser sequences words.constant ; IN: numspec

SYMBOL: digits

H{

   CHAR: E => L{ 0 2 4 6 8 }
   CHAR: e => L{ 2 4 6 8 }
   CHAR: f => L{ 2 4 6 }
   CHAR: o => L{ 1 3 5 7 9 }
   CHAR: s => L{ 1 2 3 4 5 6 7 8 9 }
   CHAR: p => L{ 2 3 5 7 }
   CHAR: q => L{ 1 3 7 9 }
   CHAR: r => L{ 3 5 7 }
   CHAR: _ => L{ 0 1 2 3 4 5 6 7 8 9 }

}

digits set-global

<PRIVATE

digits>number ( {5,2,4} -- 524 )
   <reversed> 0 [ 10^ * + ] reduce-index ;
parse-digit ( n -- list )
   dup digit? [ digit> 1list ] [ digits get at ] if ;
(parse-digits-spec) ( str -- list-of-lists )
   [ parse-digit ] { } map-as >list ;
parse-digits-spec ( str -- list-of-lists )
   dup length 1 = [ CHAR: 0 prefix ] when (parse-digits-spec) ;
(parse-numspec) ( seq -- list-of-lists-of-lists )
   [ parse-digits-spec ] map >list ;
extrapolate ( list -- list' )
   uncons uncons dupd cons cons cons ;
>infinite ( list -- list' ) [ extrapolate ] lfrom-by ;
infinitize ( seq -- list )
   but-last unclip-last [ (parse-numspec) ]
   [ parse-digits-spec >infinite ] bi* lappend-lazy ;
parse-numspec ( seq -- list-of-lists-of-lists )
   dup last "..." = [ infinitize ] [ (parse-numspec) ] if ;

PRIVATE>

numspec ( seq -- list )
   parse-numspec [ lcartesian-product* ] lmap-lazy lconcat
   [ digits>number ] lmap-lazy ;

SYNTAX: NUMSPEC:

   scan-new-word ";" parse-tokens numspec define-constant ;

SYNTAX: DIGIT:

   scan-token scan-token
   [ first ] [ [ digit> ] { } map-as >list ] bi*
   swap digits get set-at ;</lang>