factor/core/math/parser/parser.factor

163 lines
3.6 KiB
Factor
Raw Normal View History

2008-02-01 00:00:08 -05:00
! Copyright (C) 2004, 2008 Slava Pestov.
2007-09-20 18:09:08 -04:00
! See http://factorcode.org/license.txt for BSD license.
2008-09-27 18:54:44 -04:00
USING: kernel math.private namespaces sequences strings
arrays combinators splitting math assocs make ;
2007-09-20 18:09:08 -04:00
IN: math.parser
: digit> ( ch -- n )
2008-02-01 00:00:08 -05:00
H{
{ CHAR: 0 0 }
{ CHAR: 1 1 }
{ CHAR: 2 2 }
{ CHAR: 3 3 }
{ CHAR: 4 4 }
{ CHAR: 5 5 }
{ CHAR: 6 6 }
{ CHAR: 7 7 }
{ CHAR: 8 8 }
{ CHAR: 9 9 }
{ CHAR: A 10 }
{ CHAR: B 11 }
{ CHAR: C 12 }
{ CHAR: D 13 }
{ CHAR: E 14 }
{ CHAR: F 15 }
{ CHAR: a 10 }
{ CHAR: b 11 }
{ CHAR: c 12 }
{ CHAR: d 13 }
{ CHAR: e 14 }
{ CHAR: f 15 }
} at ;
2007-09-20 18:09:08 -04:00
2008-02-06 21:05:03 -05:00
: string>digits ( str -- digits )
[ digit> ] { } map-as ;
2008-02-06 22:15:47 -05:00
: digits>integer ( seq radix -- n )
0 swap [ swapd * + ] curry reduce ;
2008-02-06 21:05:03 -05:00
DEFER: base>
<PRIVATE
SYMBOL: radix
2008-02-10 02:40:17 -05:00
SYMBOL: negative?
2008-06-08 16:32:55 -04:00
: sign ( -- str ) negative? get "-" "+" ? ;
2008-02-06 21:05:03 -05:00
: with-radix ( radix quot -- )
radix swap with-variable ; inline
: (base>) ( str -- n ) radix get base> ;
: whole-part ( str -- m n )
sign split1 [ (base>) ] dip
2008-02-06 21:05:03 -05:00
dup [ (base>) ] [ drop 0 swap ] if ;
2007-09-20 18:09:08 -04:00
2008-02-06 21:05:03 -05:00
: string>ratio ( str -- a/b )
2008-07-20 05:05:09 -04:00
"-" ?head dup negative? set swap
"/" split1 (base>) [ whole-part ] dip
2008-07-20 05:05:09 -04:00
3dup and and [ / + swap [ neg ] when ] [ 2drop 2drop f ] if ;
2008-02-06 21:05:03 -05:00
: valid-digits? ( seq -- ? )
2007-09-20 18:09:08 -04:00
{
2008-02-06 21:05:03 -05:00
{ [ dup empty? ] [ drop f ] }
{ [ f over memq? ] [ drop f ] }
2008-04-11 13:53:22 -04:00
[ radix get [ < ] curry all? ]
2007-09-20 18:09:08 -04:00
} cond ;
2008-02-06 21:05:03 -05:00
: string>integer ( str -- n/f )
2008-07-20 05:05:09 -04:00
"-" ?head swap
2008-02-06 21:05:03 -05:00
string>digits dup valid-digits?
2008-07-20 05:05:09 -04:00
[ radix get digits>integer swap [ neg ] when ] [ 2drop f ] if ;
2007-09-20 18:09:08 -04:00
2008-02-06 21:05:03 -05:00
PRIVATE>
2007-09-20 18:09:08 -04:00
: base> ( str radix -- n/f )
2008-02-06 21:05:03 -05:00
[
2008-07-20 05:05:09 -04:00
CHAR: / over member? [
string>ratio
2008-07-20 01:56:25 -04:00
] [
2008-07-20 05:05:09 -04:00
CHAR: . over member? [
string>float
] [
string>integer
] if
2008-07-20 01:56:25 -04:00
] if
2008-02-06 21:05:03 -05:00
] with-radix ;
2007-09-20 18:09:08 -04:00
: string>number ( str -- n/f ) 10 base> ;
: bin> ( str -- n/f ) 2 base> ;
: oct> ( str -- n/f ) 8 base> ;
: hex> ( str -- n/f ) 16 base> ;
: >digit ( n -- ch )
dup 10 < [ CHAR: 0 + ] [ 10 - CHAR: a + ] if ;
2008-09-27 18:54:44 -04:00
: positive>base ( num radix -- str )
2007-09-20 18:09:08 -04:00
dup 1 <= [ "Invalid radix" throw ] when
2008-09-27 18:54:44 -04:00
[ dup 0 > ] swap [ /mod >digit ] curry [ ] "" produce-as nip
dup reverse-here ; inline
2007-09-20 18:09:08 -04:00
2008-02-06 21:05:03 -05:00
PRIVATE>
2007-09-20 18:09:08 -04:00
GENERIC# >base 1 ( n radix -- str )
2008-02-06 21:05:03 -05:00
<PRIVATE
2008-09-30 19:28:11 -04:00
: (>base) ( n -- str ) radix get positive>base ;
2008-02-06 21:05:03 -05:00
PRIVATE>
2007-09-20 18:09:08 -04:00
M: integer >base
2008-09-27 18:54:44 -04:00
over 0 = [
2drop "0"
] [
over 0 > [
positive>base
2007-09-20 18:09:08 -04:00
] [
2008-09-27 18:54:44 -04:00
[ neg ] dip positive>base CHAR: - prefix
2007-09-20 18:09:08 -04:00
] if
2008-09-27 18:54:44 -04:00
] if ;
2007-09-20 18:09:08 -04:00
M: ratio >base
[
2008-09-27 18:54:44 -04:00
dup 0 < negative? set
2008-09-30 19:28:11 -04:00
abs 1 /mod
2008-09-27 18:54:44 -04:00
[ dup zero? [ drop "" ] [ (>base) sign append ] if ]
2008-02-06 21:05:03 -05:00
[
2008-09-27 18:54:44 -04:00
[ numerator (>base) ]
[ denominator (>base) ] bi
"/" swap 3append
] bi* append
negative? get [ CHAR: - prefix ] when
2008-02-06 21:05:03 -05:00
] with-radix ;
2007-09-20 18:09:08 -04:00
: fix-float ( str -- newstr )
{
{
[ CHAR: e over member? ]
[ "e" split1 [ fix-float "e" ] dip 3append ]
2007-09-20 18:09:08 -04:00
} {
[ CHAR: . over member? ]
[ ]
}
2008-04-11 13:53:22 -04:00
[ ".0" append ]
2007-09-20 18:09:08 -04:00
} cond ;
M: float >base
drop {
2008-05-05 19:09:44 -04:00
{ [ dup fp-nan? ] [ drop "0.0/0.0" ] }
2007-09-20 18:09:08 -04:00
{ [ dup 1.0/0.0 = ] [ drop "1.0/0.0" ] }
{ [ dup -1.0/0.0 = ] [ drop "-1.0/0.0" ] }
2008-08-22 01:32:37 -04:00
{ [ dup double>bits HEX: 8000000000000000 = ] [ drop "-0.0" ] }
2008-04-11 13:53:22 -04:00
[ float>string fix-float ]
2007-09-20 18:09:08 -04:00
} cond ;
: number>string ( n -- str ) 10 >base ;
: >bin ( n -- str ) 2 >base ;
: >oct ( n -- str ) 8 >base ;
: >hex ( n -- str ) 16 >base ;
: # ( n -- ) number>string % ;