Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.forth > #30394 > unrolled thread
| Started by | Hannu Vuolasaho <vuokkosetae@gmail.com> |
|---|---|
| First post | 2014-05-14 22:43 -0700 |
| Last post | 2014-05-19 13:03 +0000 |
| Articles | 10 — 8 participants |
Back to article view | Back to comp.lang.forth
Time parse step for gforth? Hannu Vuolasaho <vuokkosetae@gmail.com> - 2014-05-14 22:43 -0700
Re: Time parse step for gforth? humptydumpty <ouatubi@gmail.com> - 2014-05-15 23:46 -0700
Re: Time parse step for gforth? Mark Wills <markwills1970@gmail.com> - 2014-05-16 01:41 -0700
Re: Time parse step for gforth? anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2014-05-16 17:02 +0000
Re: Time parse step for gforth? Bernd Paysan <bernd.paysan@gmx.de> - 2014-05-17 01:11 +0200
Re: Time parse step for gforth? Hannu Vuolasaho <vuokkosetae@gmail.com> - 2014-05-18 03:45 -0700
Re: Time parse step for gforth? humptydumpty <ouatubi@gmail.com> - 2014-05-19 02:31 -0700
Re: Time parse step for gforth? m.a.m.hendrix@tue.nl - 2014-05-19 04:58 -0700
Re: Time parse step for gforth? mhx@iae.nl - 2014-05-19 10:51 -0700
Re: Time parse step for gforth? albert@spenarnc.xs4all.nl (Albert van der Horst) - 2014-05-19 13:03 +0000
| From | Hannu Vuolasaho <vuokkosetae@gmail.com> |
|---|---|
| Date | 2014-05-14 22:43 -0700 |
| Subject | Time parse step for gforth? |
| Message-ID | <2d332084-ec90-42db-9558-a9bbdbc55eec@googlegroups.com> |
Hi! This is propably easy, but I couldn't figure out how to make it right. I'm working on gforth and I have variable resolution. Usually it is 24,25,30 or 1000 and I'm trying to write parse step which could understand hh:mm:ss.fragment format. So that I get milliseconds out of that. .12 is 500 in 24 frame format 1.12 is 1500 in 24 frame format 1. is 1000 2:0 is 120000 1:1.12, 01:01.12 1:01.12 and 01:1.12 all produce 61500 in 24 frame format. and same thing with hours. 1.999 is valid for 1000 resolution, but not in other resolutions. Also it would be nice if that parse step was able throw on too big numbers. 1:60 doesn't exist but 1 min 59 sec is 1:59 and that is valid and should give 119000 I know I lose double input recognizer part I don't mind that. Has anyone done this before and can this be done easily? Best regards, Hannu Vuolasaho
[toc] | [next] | [standalone]
| From | humptydumpty <ouatubi@gmail.com> |
|---|---|
| Date | 2014-05-15 23:46 -0700 |
| Message-ID | <5e0d9b59-84cf-4b12-b6d9-d432d4f9b1f3@googlegroups.com> |
| In reply to | #30394 |
On Thursday, May 15, 2014 8:43:49 AM UTC+3, Hannu Vuolasaho wrote: > Hi! > > > > This is propably easy, but I couldn't figure out how to make it right. > > > > I'm working on gforth and I have variable resolution. > > Usually it is 24,25,30 or 1000 and I'm trying to write parse step > > which could understand > > > > hh:mm:ss.fragment > > > > format. So that I get milliseconds out of that. > > > > .12 is 500 in 24 frame format > > 1.12 is 1500 in 24 frame format > > 1. is 1000 > > 2:0 is 120000 > > 1:1.12, 01:01.12 1:01.12 and 01:1.12 all produce 61500 in 24 frame format. > > and same thing with hours. > > > > 1.999 is valid for 1000 resolution, but not in other resolutions. > > > > Also it would be nice if that parse step was able throw on too big numbers. > > > > 1:60 doesn't exist but 1 min 59 sec is 1:59 and that is valid and should give > > 119000 > > > > I know I lose double input recognizer part I don't mind that. > > > > Has anyone done this before and can this be done easily? > > > > Best regards, > > Hannu Vuolasaho Hi! Hint: use words '>number' '/string' for parsing, '*/' for scaling. Try and post your version here. A word should do just one thing, have a proper name and stack comment. Have a nice day, humptydumpty
[toc] | [prev] | [next] | [standalone]
| From | Mark Wills <markwills1970@gmail.com> |
|---|---|
| Date | 2014-05-16 01:41 -0700 |
| Message-ID | <aa879d14-8919-46ef-92d0-1f5c39835fa5@googlegroups.com> |
| In reply to | #30394 |
On Thursday, 15 May 2014 06:43:49 UTC+1, Hannu Vuolasaho wrote: > Hi! > > > > This is propably easy, but I couldn't figure out how to make it right. > > > > I'm working on gforth and I have variable resolution. > > Usually it is 24,25,30 or 1000 and I'm trying to write parse step > > which could understand > > > > hh:mm:ss.fragment > > > > format. So that I get milliseconds out of that. > > > > .12 is 500 in 24 frame format > > 1.12 is 1500 in 24 frame format > > 1. is 1000 > > 2:0 is 120000 > > 1:1.12, 01:01.12 1:01.12 and 01:1.12 all produce 61500 in 24 frame format. > > and same thing with hours. > > > > 1.999 is valid for 1000 resolution, but not in other resolutions. > > > > Also it would be nice if that parse step was able throw on too big numbers. > > > > 1:60 doesn't exist but 1 min 59 sec is 1:59 and that is valid and should give > > 119000 > > > > I know I lose double input recognizer part I don't mind that. > > > > Has anyone done this before and can this be done easily? > > > > Best regards, > > Hannu Vuolasaho Have a look at SEARCH in the ANS standard. 17.6.1.2191
[toc] | [prev] | [next] | [standalone]
| From | anton@mips.complang.tuwien.ac.at (Anton Ertl) |
|---|---|
| Date | 2014-05-16 17:02 +0000 |
| Message-ID | <2014May16.190233@mips.complang.tuwien.ac.at> |
| In reply to | #30394 |
Hannu Vuolasaho <vuokkosetae@gmail.com> writes:
>I'm trying to write parse step
>which could understand
>
>hh:mm:ss.fragment
>
>format.
...
>I know I lose double input recognizer part I don't mind that.
>
>Has anyone done this before and can this be done easily?
It's not particularly easy, and I have not done so before. You do not
necessarily lose the double number recognizer (there are no conflicts
in the syntax of your number). There have been changes in this area
between 0.7.0 and the current development version; I expected Bernd,
who implemented recognizers in the development version to speak up,
but he has not done so yet.
One thing that you need in either case is a word that takes such a
string, recognizes it, and converts it into a number. I would write a
word that does this on the input stream with PARSE and >NUMBER and
some arithmetic, and then wrap it in EXECUTE-PARSING so that you get a
word that takes a string and produces a (double?) number. When you
have that, take a look in float.fs how the recognizer for floats is
added there (or better ask here).
- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: http://www.forth200x.org/forth200x.html
EuroForth 2014: http://www.euroforth.org/ef14/
[toc] | [prev] | [next] | [standalone]
| From | Bernd Paysan <bernd.paysan@gmx.de> |
|---|---|
| Date | 2014-05-17 01:11 +0200 |
| Message-ID | <ll65vd$34k$1@online.de> |
| In reply to | #30429 |
Anton Ertl wrote: > Hannu Vuolasaho <vuokkosetae@gmail.com> writes: >>I'm trying to write parse step >>which could understand >> >>hh:mm:ss.fragment >> >>format. > ... >>I know I lose double input recognizer part I don't mind that. >> >>Has anyone done this before and can this be done easily? > > It's not particularly easy, and I have not done so before. You do not > necessarily lose the double number recognizer (there are no conflicts > in the syntax of your number). There have been changes in this area > between 0.7.0 and the current development version; I expected Bernd, > who implemented recognizers in the development version to speak up, > but he has not done so yet. Yes, in the git head version of Gforth, you could do that with a recognizer. Writing a recognizer is fairly trivial, it's two components, one of which here already exists (that's the r:float table that knows how to deal with a floating point number). The other takes a string, and tries to convert it if it is recognized, and then returns r:float, otherwise r:fail. -- Bernd Paysan "If you want it done right, you have to do it yourself" http://bernd-paysan.de/
[toc] | [prev] | [next] | [standalone]
| From | Hannu Vuolasaho <vuokkosetae@gmail.com> |
|---|---|
| Date | 2014-05-18 03:45 -0700 |
| Message-ID | <482cf93e-251c-43f8-9e23-5905bca3e851@googlegroups.com> |
| In reply to | #30429 |
On Friday, May 16, 2014 8:02:33 PM UTC+3, Anton Ertl wrote:
> >I know I lose double input recognizer part I don't mind that.
>
> >
>
> >Has anyone done this before and can this be done easily?
>
>
>
> It's not particularly easy, and I have not done so before.
I noticed. I haven't had this much debugging and retrying since I
tried PHP :) I belive there is reason why I hate strings.
>
> One thing that you need in either case is a word that takes such a
> string, recognizes it, and converts it into a number. I would write a
> word that does this on the input stream with PARSE and >NUMBER and
Pretty much like what my word does.
>
> some arithmetic, and then wrap it in EXECUTE-PARSING so that you get a
> word that takes a string and produces a (double?) number. When you
> have that, take a look in float.fs how the recognizer for floats is
> added there (or better ask here).
If I understood float.fs it is just tw words to get in the interpret loop.
However as the Windows version available is only 0.7.0 and my Linux box
has 0.7.2 I'll better stick to it.
My word has some issues. It parses even normal numers and consumes the
input first when it checks for negative time as in -12 test case.
Anyway here is my ugly big honking time parser which likes addr u input
and gives ms out. It should wrapped in to some other word so it
works right. And how to add in 0.7.2 to interpret loop.
I'm open to suggestions and good refactoring examples. :)
Beware this ended ugly.
Hannu Vuolasaho
\ this is just for debugging purposes
: print-time ( msec -- )
dup 0< if ." -" -1 * then
1000 /mod
60 /mod
60 /mod
." (" . ." h) (" . ." min) (" . ." s) (" . ." ms)" cr
;
\ Real processing
variable fps
24 fps !
: number-before ( c-addr1 u1 c-aadr u2 -- c-addr3 u3 n f )
2swap { addr len } addr len 2swap
search
if
{ del rest }
0 0 addr len >number
rest = swap del = and
if
\ ok.
d>s true del char+ -rot rest char- -rot
else
d>s false addr -rot len -rot
then
else
0 false
then
;
: check-time-bounds ( number max -- number )
/mod if s" Too big value for time unit" exception throw then
;
: f>ms ( frames -- ms ) 1000 fps @ */ ;
: parse-time { addr u -- msec }
0 0 0 1 { h m s sign }
addr u s" -" string-prefix?
if
-1 to sign
addr u 1 /string to u to addr
then
addr u s" :" number-before
if
to m
s" :" number-before
if
m to h
to m
s" ." number-before
if
to s
else
drop 0 -rot 0 -rot >number
2>r d>s to s 2r>
then
else
drop
s" ." number-before
if
to s
else
drop 0 -rot 0 -rot >number
2>r d>s to s 2r>
then
then
0 -rot 0 -rot >number
dup if s" Bad time format" exception throw else 2drop then
d>s
f>ms 1000 check-time-bounds
else
drop
s" ." number-before
if
to s
0 -rot 0 -rot >number
dup if s" Bad time format" exception throw else 2drop then
d>s
f>ms 1000 check-time-bounds
else
drop
\ This is normal input. It should bail out and let normal
\ number input take care of it.
0 -rot 0 -rot >number
dup if s" Bad time format" exception throw else 2drop then
d>s
then
then
m 60 check-time-bounds s 60 check-time-bounds 2drop
h 3600 * m 60 * + s + 1000 * + sign *
;
: rounding-error-test 25 0 do i f>ms . loop ;
.( I have rounding errors from frames to ms) cr
rounding-error-test cr
.( These should work) cr
s" 12:34:56.23" parse-time print-time
s" 12:34.23" parse-time print-time
s" 12.3" parse-time print-time
s" 12" parse-time print-time
s" 12:34" parse-time print-time
s" 12:34:56" parse-time print-time
s" :12:34.23" parse-time print-time
s" :12.23" parse-time print-time
s" .12" parse-time print-time
.( Negative times) cr
s" -12" parse-time print-time
s" -12.3" parse-time print-time
s" -12:34" parse-time print-time
s" -12:34.23" parse-time print-time
s" -12:34:56.23" parse-time print-time
s" -:12:34.23" parse-time print-time
s" -:12.23" parse-time print-time
s" -.12" parse-time print-time
.( Not work) cr
: parse-time-test ( xt -- )
['] parse-time catch if ." OK." 2drop else ." Fail: " print-time then cr
;
\ bad punctuation
s" 12.34:56:23" parse-time-test
s" 12:34.23:23" parse-time-test
s" 12:34:56:23" parse-time-test
s" 12.34.23:23" parse-time-test
s" 12:34.23.23" parse-time-test
s" 12.23:56" parse-time-test
s" 12.13.14.23" parse-time-test
\ bad sign
s" -12.-3" parse-time-test
s" 12.-3" parse-time-test
s" -12:-34" parse-time-test
s" 12:-34" parse-time-test
s" -12:-34.-23" parse-time-test
s" -12:-34.23" parse-time-test
s" -12:34.-23" parse-time-test
s" 12:-34.-23" parse-time-test
s" 12:-34.23" parse-time-test
s" 12:34.-23" parse-time-test
s" -12:-34:-56" parse-time-test
s" -12:-34:56" parse-time-test
s" -12:34:-56" parse-time-test
s" 12:-34:-56" parse-time-test
s" 12:-34:56" parse-time-test
s" 12:34:-56" parse-time-test
s" 12:-34:56.23" parse-time-test
s" -12:-34:56.23" parse-time-test
s" 12:34:-56.23" parse-time-test
s" -12:34:-56.23" parse-time-test
s" 12:-34:-56.23" parse-time-test
s" -12:-34:-56.23" parse-time-test
s" 12:34:56.-23" parse-time-test
s" -12:34:56.-23" parse-time-test
s" 12:-34:56.-23" parse-time-test
s" -12:-34:56.-23" parse-time-test
s" 12:34:-56.-23" parse-time-test
s" -12:34:-56.-23" parse-time-test
s" 12:-34:-56.-23" parse-time-test
s" -12:-34:-56.-23" parse-time-test
[toc] | [prev] | [next] | [standalone]
| From | humptydumpty <ouatubi@gmail.com> |
|---|---|
| Date | 2014-05-19 02:31 -0700 |
| Message-ID | <e4b82476-ec91-4976-aac5-d84daee10d2c@googlegroups.com> |
| In reply to | #30448 |
On Sunday, May 18, 2014 1:45:43 PM UTC+3, Hannu Vuolasaho wrote:
> On Friday, May 16, 2014 8:02:33 PM UTC+3, Anton Ertl wrote:
>
>
>
> > >I know I lose double input recognizer part I don't mind that.
>
> >
>
> > >
>
> >
>
> > >Has anyone done this before and can this be done easily?
>
> >
>
> >
>
> >
>
> > It's not particularly easy, and I have not done so before.
>
>
>
> I noticed. I haven't had this much debugging and retrying since I
>
> tried PHP :) I belive there is reason why I hate strings.
>
>
>
> >
>
> > One thing that you need in either case is a word that takes such a
>
> > string, recognizes it, and converts it into a number. I would write a
>
> > word that does this on the input stream with PARSE and >NUMBER and
>
>
>
> Pretty much like what my word does.
>
> >
>
> > some arithmetic, and then wrap it in EXECUTE-PARSING so that you get a
>
> > word that takes a string and produces a (double?) number. When you
>
> > have that, take a look in float.fs how the recognizer for floats is
>
> > added there (or better ask here).
>
>
>
> If I understood float.fs it is just tw words to get in the interpret loop.
>
> However as the Windows version available is only 0.7.0 and my Linux box
>
> has 0.7.2 I'll better stick to it.
>
>
>
> My word has some issues. It parses even normal numers and consumes the
>
> input first when it checks for negative time as in -12 test case.
>
>
>
> Anyway here is my ugly big honking time parser which likes addr u input
>
> and gives ms out. It should wrapped in to some other word so it
>
> works right. And how to add in 0.7.2 to interpret loop.
>
>
>
> I'm open to suggestions and good refactoring examples. :)
>
>
>
> Beware this ended ugly.
>
>
>
> Hannu Vuolasaho
>
>
>
> \ this is just for debugging purposes
>
> : print-time ( msec -- )
>
> dup 0< if ." -" -1 * then
>
> 1000 /mod
>
> 60 /mod
>
> 60 /mod
>
> ." (" . ." h) (" . ." min) (" . ." s) (" . ." ms)" cr
>
> ;
>
> \ Real processing
>
> variable fps
>
> 24 fps !
>
>
>
> : number-before ( c-addr1 u1 c-aadr u2 -- c-addr3 u3 n f )
>
> 2swap { addr len } addr len 2swap
>
> search
>
> if
>
> { del rest }
>
> 0 0 addr len >number
>
> rest = swap del = and
>
> if
>
> \ ok.
>
> d>s true del char+ -rot rest char- -rot
>
> else
>
> d>s false addr -rot len -rot
>
> then
>
> else
>
> 0 false
>
> then
>
> ;
>
> : check-time-bounds ( number max -- number )
>
> /mod if s" Too big value for time unit" exception throw then
>
> ;
>
> : f>ms ( frames -- ms ) 1000 fps @ */ ;
>
> : parse-time { addr u -- msec }
>
> 0 0 0 1 { h m s sign }
>
> addr u s" -" string-prefix?
>
> if
>
> -1 to sign
>
> addr u 1 /string to u to addr
>
> then
>
> addr u s" :" number-before
>
> if
>
> to m
>
> s" :" number-before
>
> if
>
> m to h
>
> to m
>
> s" ." number-before
>
> if
>
> to s
>
> else
>
> drop 0 -rot 0 -rot >number
>
> 2>r d>s to s 2r>
>
> then
>
> else
>
> drop
>
> s" ." number-before
>
> if
>
> to s
>
> else
>
> drop 0 -rot 0 -rot >number
>
> 2>r d>s to s 2r>
>
> then
>
> then
>
> 0 -rot 0 -rot >number
>
> dup if s" Bad time format" exception throw else 2drop then
>
> d>s
>
> f>ms 1000 check-time-bounds
>
> else
>
> drop
>
> s" ." number-before
>
> if
>
> to s
>
> 0 -rot 0 -rot >number
>
> dup if s" Bad time format" exception throw else 2drop then
>
> d>s
>
> f>ms 1000 check-time-bounds
>
> else
>
> drop
>
> \ This is normal input. It should bail out and let normal
>
> \ number input take care of it.
>
> 0 -rot 0 -rot >number
>
> dup if s" Bad time format" exception throw else 2drop then
>
> d>s
>
> then
>
> then
>
> m 60 check-time-bounds s 60 check-time-bounds 2drop
>
> h 3600 * m 60 * + s + 1000 * + sign *
>
> ;
>
>
>
> : rounding-error-test 25 0 do i f>ms . loop ;
>
> .( I have rounding errors from frames to ms) cr
>
> rounding-error-test cr
>
>
>
> .( These should work) cr
>
> s" 12:34:56.23" parse-time print-time
>
> s" 12:34.23" parse-time print-time
>
> s" 12.3" parse-time print-time
>
> s" 12" parse-time print-time
>
> s" 12:34" parse-time print-time
>
> s" 12:34:56" parse-time print-time
>
>
>
> s" :12:34.23" parse-time print-time
>
> s" :12.23" parse-time print-time
>
> s" .12" parse-time print-time
>
>
>
> .( Negative times) cr
>
>
>
> s" -12" parse-time print-time
>
> s" -12.3" parse-time print-time
>
> s" -12:34" parse-time print-time
>
> s" -12:34.23" parse-time print-time
>
> s" -12:34:56.23" parse-time print-time
>
>
>
> s" -:12:34.23" parse-time print-time
>
> s" -:12.23" parse-time print-time
>
> s" -.12" parse-time print-time
>
>
>
> .( Not work) cr
>
> : parse-time-test ( xt -- )
>
> ['] parse-time catch if ." OK." 2drop else ." Fail: " print-time then cr
>
> ;
>
>
>
> \ bad punctuation
>
> s" 12.34:56:23" parse-time-test
>
> s" 12:34.23:23" parse-time-test
>
> s" 12:34:56:23" parse-time-test
>
> s" 12.34.23:23" parse-time-test
>
> s" 12:34.23.23" parse-time-test
>
> s" 12.23:56" parse-time-test
>
> s" 12.13.14.23" parse-time-test
>
>
>
> \ bad sign
>
> s" -12.-3" parse-time-test
>
> s" 12.-3" parse-time-test
>
>
>
> s" -12:-34" parse-time-test
>
> s" 12:-34" parse-time-test
>
>
>
> s" -12:-34.-23" parse-time-test
>
> s" -12:-34.23" parse-time-test
>
> s" -12:34.-23" parse-time-test
>
> s" 12:-34.-23" parse-time-test
>
> s" 12:-34.23" parse-time-test
>
> s" 12:34.-23" parse-time-test
>
>
>
>
>
> s" -12:-34:-56" parse-time-test
>
> s" -12:-34:56" parse-time-test
>
> s" -12:34:-56" parse-time-test
>
> s" 12:-34:-56" parse-time-test
>
> s" 12:-34:56" parse-time-test
>
> s" 12:34:-56" parse-time-test
>
>
>
> s" 12:-34:56.23" parse-time-test
>
> s" -12:-34:56.23" parse-time-test
>
> s" 12:34:-56.23" parse-time-test
>
> s" -12:34:-56.23" parse-time-test
>
> s" 12:-34:-56.23" parse-time-test
>
> s" -12:-34:-56.23" parse-time-test
>
> s" 12:34:56.-23" parse-time-test
>
> s" -12:34:56.-23" parse-time-test
>
> s" 12:-34:56.-23" parse-time-test
>
> s" -12:-34:56.-23" parse-time-test
>
> s" 12:34:-56.-23" parse-time-test
>
> s" -12:34:-56.-23" parse-time-test
>
> s" 12:-34:-56.-23" parse-time-test
>
> s" -12:-34:-56.-23" parse-time-test
Hi!
A way to do it:
: th ( a i -- a+i*cells )
CELLS +
;
:noname ( c -- f ) drop 0 ; \ false
:noname ( c -- f ) [char] . <> ; \ seconds
:noname ( c -- f ) [char] : <> ; DUP \ hours,minutes
CREATE -Separator? , , , , \ Tests for separators
CREATE Lims 24 , 60 , 60 , 24 ,
Lims 3 th CONSTANT FRACT
CREATE Buff 4 CELLS ALLOT
: $time>buff ( ca u -- f ; )
4 0
DO
0 S>D 2SWAP >NUMBER ( d . ca u )
OVER C@ -Separator? I th @ EXECUTE ( d . ca u f )
IF 2DROP 2DROP -1 UNLOOP EXIT THEN
1 /STRING
2SWAP D>S Buff I th !
LOOP
2DROP
0
;
: valid? ( -- f ; )
-1
4 0
DO
Buff I th @ 0 Lims I th @ WITHIN AND
LOOP
;
: parse-time ( ca u -- n ; return -1 for invalid time-string )
$time>buff valid? 0= OR
IF -1 EXIT THEN
Buff 0 th @ 3600000 *
Buff 1 th @ 60000 *
Buff 2 th @ 1000 *
Buff 3 th @ 1000 FRACT @ */
+ + +
;
Have a nice time,
humptydumpty
[toc] | [prev] | [next] | [standalone]
| From | m.a.m.hendrix@tue.nl |
|---|---|
| Date | 2014-05-19 04:58 -0700 |
| Message-ID | <0105b903-681e-4f1b-bd56-967c4e70b072@googlegroups.com> |
| In reply to | #30448 |
On Sunday, May 18, 2014 12:45:43 PM UTC+2, Hannu Vuolasaho wrote:
> On Friday, May 16, 2014 8:02:33 PM UTC+3, Anton Ertl wrote:
[ heaps of it ]
> > >I know I lose double input recognizer part I don't mind that.
Maybe like this?
: step2 ( c-addr u -- d1 c-addr2 u2 ) 1 /string 0. 2swap >number ;
: step1 ( sum1 c-addr u dscale -- sum2 c-addr u )
>S >S step2 2>R 2swap S> S> M*/ D+ 2R> ;
: h:m:s.x ( c-addr u -- d )
BASE @ >R DECIMAL
0. 2swap >number
BEGIN over c@ ':' = WHILE #60 1 step1 REPEAT
over c@ '.' = IF 2swap #1000 1 M*/ 2swap
step2
2>R #1000 #24 M*/ d+ 2R>
ENDIF
2drop
R> BASE ! ;
-marcel
[toc] | [prev] | [next] | [standalone]
| From | mhx@iae.nl |
|---|---|
| Date | 2014-05-19 10:51 -0700 |
| Message-ID | <3d32e210-426f-417c-b6a7-ba5ec7ba1816@googlegroups.com> |
| In reply to | #30458 |
On Monday, May 19, 2014 1:58:45 PM UTC+2, m.a.m....@tue.nl wrote: > On Sunday, May 18, 2014 12:45:43 PM UTC+2, Hannu Vuolasaho wrote: [..] 0. DVALUE $in : get# ( -- d1 ) 0. $in 1 /string >number TO $in ; : step ( sum1 dsc d2 -- dsc*sum1+d2 ) 2>R m*/ get# 2R> m*/ d+ ; : in=? ( char -- bool ) $in drop c@ = ; : h:m:s.x ( c-addr u -- d ) TO $in BASE @ >R DECIMAL 0. $in >number TO $in BEGIN ':' in=? WHILE #60 1 1 1 step REPEAT '.' in=? IF #1000 1 #1000 #24 step ENDIF R> BASE ! ; Add salt and pepper to taste. -marcel
[toc] | [prev] | [next] | [standalone]
| From | albert@spenarnc.xs4all.nl (Albert van der Horst) |
|---|---|
| Date | 2014-05-19 13:03 +0000 |
| Message-ID | <537a010a$0$27154$e4fe514c@dreader35.news.xs4all.nl> |
| In reply to | #30394 |
In article <2d332084-ec90-42db-9558-a9bbdbc55eec@googlegroups.com>,
Hannu Vuolasaho <vuokkosetae@gmail.com> wrote:
>Hi!
>
>This is propably easy, but I couldn't figure out how to make it right.
>
>I'm working on gforth and I have variable resolution.
>Usually it is 24,25,30 or 1000 and I'm trying to write parse step
>which could understand
>
>hh:mm:ss.fragment
>
>format. So that I get milliseconds out of that.
>
>.12 is 500 in 24 frame format
>1.12 is 1500 in 24 frame format
>1. is 1000
>2:0 is 120000
>1:1.12, 01:01.12 1:01.12 and 01:1.12 all produce 61500 in 24 frame format.
>and same thing with hours.
>
>1.999 is valid for 1000 resolution, but not in other resolutions.
>
>Also it would be nice if that parse step was able throw on too big numbers.
>
>1:60 doesn't exist but 1 min 59 sec is 1:59 and that is valid and should give
>119000
>
>I know I lose double input recognizer part I don't mind that.
>
>Has anyone done this before and can this be done easily?
The reason this is a bit tricky is because the string may or may
not contain a &. or &: character. The second reason is that you may
well on your way parsing and still don't know whether you have a single
a double, or a time string. This sits only well with a "catch an error
from a number interpreter, then retry a different format approach"
(a la gForth).
(Replace &. by CHAR . or [CHAR] . as appropriate. )
I'd use my $^ ("string-index") and $/ ("string-slash") on a
string that is fetched in a separate phase (i.e. where converting to
a number fails). I would prefer using a separate recognizer for times T:
: T: PARSE-NAME $-time ; PREFIX IMMEDIATE
$/ has the stack effect ( string delimiter -- after-string before-string )
\ Convert a STRING to a TIME in milliseconds.
: $-time &. $/ seconds >R milliseconds R> 1000 * + ;
Now both words, seconds and milliseconds, should work gracefully on
null-strings and empty strings.
A null-string you'd get for the milliseconds if &. doesn't
occur in the string. An empty string you get whenever there is
an empty string after the &. . Such as "T:18:14:00.".
\ For STRING : "it IS degenerate"
: degenerate 0= ( null-string) SWAP 0= ( empty-string) OR ;
\ Convert a STRING to MILLISECONDS.
: milliseconds 2DUP degenerate IF 2DROP 0 ELSE EVALUATE THEN ;
\ Convert a STRING to SECONDS. 18:42:00 is different from 18:42 !
\ OTOH 18:42:00 is the same as 18:42:
\ So a null-string is handled differently than an empty string!
: seconds 0 >R BEGIN &: $/ OVER ( null-string) WHILE
DUP ( empty string) if 2DROP 0 ELSE EVALUATE THEN >R 60 * + >R THEN
2DROP R> ;
Disclaimer:
The above code has not been tested. It serves to illustrate a possible
factoring, and to highlight the problems.
Groetjes Albert
>
>Best regards,
>Hannu Vuolasaho
--
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- being exponential -- ultimately falters.
albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.forth
csiph-web