Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.forth > #30394 > unrolled thread

Time parse step for gforth?

Started byHannu Vuolasaho <vuokkosetae@gmail.com>
First post2014-05-14 22:43 -0700
Last post2014-05-19 13:03 +0000
Articles 10 — 8 participants

Back to article view | Back to comp.lang.forth


Contents

  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

#30394 — Time parse step for gforth?

FromHannu Vuolasaho <vuokkosetae@gmail.com>
Date2014-05-14 22:43 -0700
SubjectTime 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]


#30411

Fromhumptydumpty <ouatubi@gmail.com>
Date2014-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]


#30414

FromMark Wills <markwills1970@gmail.com>
Date2014-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]


#30429

Fromanton@mips.complang.tuwien.ac.at (Anton Ertl)
Date2014-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]


#30433

FromBernd Paysan <bernd.paysan@gmx.de>
Date2014-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]


#30448

FromHannu Vuolasaho <vuokkosetae@gmail.com>
Date2014-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]


#30457

Fromhumptydumpty <ouatubi@gmail.com>
Date2014-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]


#30458

Fromm.a.m.hendrix@tue.nl
Date2014-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]


#30461

Frommhx@iae.nl
Date2014-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]


#30459

Fromalbert@spenarnc.xs4all.nl (Albert van der Horst)
Date2014-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