• Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

AltME groups: search

Help · search scripts · search articles · search mailing list

results summary

worldhits
r4wp190
r3wp3717
total:3907

results window for this page: [start: 1 end: 100]

world-name: r4wp

Group: #Red ... Red language group [web-public]
Pekr:
14-Mar-2012
that's what Doc replied on his blog:


@Thomas: for the very first Red alpha, only memory management, basic 
datatypes and a few natives/actions. Ports and I/O will probably 
be added in following alpha versions, as PARSE. If we don't hit any 
walls, we should have it a few weeks, probably a month.
BrianH:
15-Jun-2012
You can make a port work a lot like a series, and you mostly did 
with the virtual block scheme. FOREACH and PARSE not working on ports 
can be a bit annoying, but they would only work on a subset of the 
port types that either work like series or (theoretically) like files 
(like open/direct file ports in R2).
BrianH:
15-Jun-2012
If Red adopts R3's port model, I would definitely like to try to 
implement that port PARSE idea I was thinking of for R3.
Pekr:
27-Jun-2012
Well, as for dialects, I still can see PARSE as a secret weapon. 
Hopefully Red gets to R3 or Topaz level, as far as parsing goes. 
We could create some dialects for niches, I think ppl would see the 
advantage ...
Kaj:
18-Aug-2012
Yes, except that Red/System is designed to fit Red, and Red will 
pass code to Red/System efficiently in loaded block form, instead 
of text form that the C compilers had to parse again
Pekr:
25-Aug-2012
What I still think is, that we need strong parse. It is very cool 
technology. Yes, I dare to call it a technology. We need r3 level 
parse. Then we can create dialects, and show other guys, that dialecting 
is a cool concept. Pity we were not able to capitalise on it more, 
mainly due to closed nature of R2 possibilities to bind to other 
environments .... you imo :-)
Kaj:
25-Aug-2012
Petr, I think we need Topaz level PARSE :-)
Pekr:
25-Aug-2012
Topaz has even better parse than R3?
BrianH:
4-Oct-2012
R2 and R3 use their own stacks, though recursive PARSE may use the 
C stack. The stack frames of R2 and R3 are different, but I wouldn't 
be able to tell you how.
DocKimbel:
18-Oct-2012
Think PARSE usable from any other language as example. ;-)
Arnold:
30-Nov-2012
Great explanations Nenad! My apologies if sometimes I seem to ask 
for the known things.. 


For the documentation we need a Red marker pen and mark the REBOL 
documentation where appropriate for Red.

I took a little time (just 5 minutes LoL) to see if I could find 
a starting point for the documentation extraction script from the 
suggested makedoc2.r script but 'parse is not my best REBOL skill.


Besides graphics and a killer application as Pekr described, having 
CGI support for Red can bring a lot of attention to Red too imho. 
(And this could bring financing Red up too when Red programmers are 
making money making websites using Red.)
DocKimbel:
9-Dec-2012
The source code should be easily parse-able, so the list of functions, 
native, actions, ops could be extracted and pretty-printed as a web 
page. IIRC, someone tried to make such script but I didn't see any 
result yet.
Arnold:
9-Dec-2012
Yes I wanted to give it a try for the doc scripts. But parse is not 
my expertise, and at the moment I am short in time as I can make 
extra hours at work. So everybody step in please and publish your 
baby-doc-scripts so we can all contribute little bits.
Pekr:
11-Dec-2012
Jerry: yes, it is. I just hope, that some I/O and later parse comes 
in next 2 months, to be really usefull in real life :-)
Kaj:
8-Jan-2013
With my proposal, you can parse numbers in issue notation, detect 
it's an integer and convert it to integer storage, without polluting 
the symbol table
Group: Ann-Reply ... Reply to Announce group [web-public]
MaxV:
18-Jul-2012
There a a lot of function undocumented. For example about VID a lot 
of documentation is missing, but VID is one the most important feature 
of Rebol. Similar for parse... and so on. Do you know that you can 
use "of" for radio buttons?
BrianH:
18-Jul-2012
Others can chime in about the VID, but there are some pretty good 
tutorials about the parse dialect. Plus, you might look into the 
parse enhancement project page, which ended up with a lot of discussion 
of the semantic model, and in many cases the behavior of existing 
operations.
BrianH:
18-Jul-2012
Someone else will have to provide the tutorial links. The parse project 
is here: http://www.rebol.net/wiki/Parse_Projec
BrianH:
18-Jul-2012
Sorry, http://www.rebol.net/wiki/Parse_Project
Kaj:
25-Sep-2012
PARSE level should be compatible, except for bug fixes
BrianH:
25-Sep-2012
MaxV, REBOL isn't really an interpreter. DO is an interpreter, as 
is PARSE. The rest are library functions. If your code calls any 
of these functions, you need to provide the source to your code, 
even if it's encapped.
BrianH:
25-Sep-2012
Oh, weirdly enough, DELECT and DO-COMMANDS are also interpreters. 
There is an additional gotcha though.


Though DO, PARSE, DELECT and DO-COMMANDS are interpreters, they are 
implemented as library functions. This means that the code that you 
pass to these functions can be closed-source, but the code that *calls* 
these functions needs to be GPL-compatible. If you make a REBOL-in-REBOL 
interpreter or compiler that treats the code it runs as data, and 
the code it runs doesn't call any REBOL functions at all, even indirectly, 
then the code it runs can be closed source. This is basically what 
Red is, so Red would be legal.
Ladislav:
26-Sep-2012
Re: 'Maybe you interpret "these functions" as DO, etc' - I have to 
because the citation actually is:


Though DO, PARSE, DELECT and DO-COMMANDS are interpreters, they are 
implemented as library functions. This means that the code that you 
pass to these functions can be closed-source, but the code that *calls* 
these functions needs to be GPL-compatible
BrianH:
26-Sep-2012
Here is the FSF FAQ entry relating to interpreters and their libraries: 
http://www.gnu.org/licenses/gpl-faq.html#IfInterpreterIsGPL

Pretty much the whole entry is applicable. The first paragraph would 
apply to data passed to DO, PARSE, DELECT, DO-COMMANDS, or other 
dialect processors.


The second paragraph would definitely apply to extensions, and could 
apply to built-in functions unless we get an exception like GCC's; 
or we could get a FAQ entry declaring that the functions built into 
R3 are "part of the interpreter" rather than "library code", despite 
R3's actual system model. Note that PARSE's built-in operations are 
more unambiguously "part of the interpreter", and the same could 
be said for other similar dialects.


The last two paragraphs apply to mezzanine code and embedded modules. 
If they are GPL'd and your code uses them, it would be affected.
Ladislav:
27-Sep-2012
The first paragraph would apply to data passed to DO, PARSE, DELECT, 
DO-COMMANDS, or other dialect processors.

 - actually, there is absolutely no need to not apply it also to the 
 r3.exe+r3lib.dll
Ladislav:
27-Sep-2012
So, readers may see different opinions. From "there are libraries 
different than r3lib.dll in the r3.exe+r3lib.dll interpreter" to 
even more extreme: every one of DO, PARSE, etc. is a separate program 
(obviously false) to which the GPL has to be applied on a separate 
basis".
Ladislav:
27-Sep-2012
Also a wrong interpretation. There are no "libraries coming with 
the interpreter" and your interpretation is overly extensive, like 
the interpretation that DO, PARSE, etc. are "separate programs".
Andreas:
27-Sep-2012
I don't follow the DO, PARSE, etc interpretation.
Ladislav:
27-Sep-2012
'or we could get a FAQ entry declaring that the functions built into 
R3 are "part of the interpreter" rather than "library code"' - that 
is where I do agree with you, except for the fact that we do have 
such an indication:


1) the functions *are physically/* part of the interpreter, they 
are "linked into it" (I would say "statically", since the interpreter 
does not need to look for them "elsewhere in the system", they are 
"inside")

2) the functions are a part of the interpreter, the interpreter documentation 
specifically mentions the functionality of the interpreter (the documentation 
mentions that the "ordinary version" of the interpreter "understands" 
FUNC, DO, PARSE, whatnot...)
Group: Rebol School ... REBOL School [web-public]
Gregg:
24-Apr-2012
He's one of us now Endo. Next thing, he'll b3 wondering why every 
other programming language has only 6 or 8 datatypes and why they 
don't have a PARSE function. :-)
GrahamC:
24-Apr-2012
has anyone written parse rules for phone numbers?   I need to setup 
a set of rules for international numbers, local numbers, cell numbers, 
1800 etc for use in asterisk and prevent users from making toll calls 
unless authorise
Gregg:
24-Apr-2012
set 'parse-phone-num func [
        num [string!]
        /local  digit digits sep _ext_  ch nums pin ext
    ] [
        digit:  charset "0123456798"
        digits: [some digit]
        sep:    charset "()-._"
        _ext_:  ["ext" opt "." | "x"]

        nums: copy ""
        rules: [
            any [
                some [sep | copy ch digit (append nums ch)]
                | _ext_ copy ext digits
                | "pin" copy pin digits
            ]
            end
        ]
        either parse trim num rules 
            [reduce ['num nums 'ext ext 'pin pin]]
            [none]
    ]

    set 'well-formed-phone-number? func [num /local data] [
        either none? data: parse-phone-num num [false] [
            any [
                found? find [7 10] length? data/num
                all [11 = length? data/num  data/num/1 = #"1"]
            ]
        ]
    ]
Gregg:
24-Apr-2012
set 'format-phone-number func [
        num [string! object!] "String or object with /text value"
        /def-area-code area-code [string! integer!]
        /local left right mid obj res
    ] [
        left:  func [s len][copy/part s len]
        right: func [s len] [copy skip tail s negate len]
        mid:   func [s start len][copy/part at s start len]

        if object? num [obj: num  num: obj/text]

        res: either data: parse-phone-num num [
            ; discard leader if it's there.
            if all [11 = length? data/num  data/num/1 = #"1"] [
                data/num: right data/num 10
            ]
            rejoin [
                rejoin switch/default length? data/num [
                    7  [ compose [

                        (either area-code [rejoin ["(" area-code ") "]][])
                        left data/num 3 "-" right data/num 4
                    ]]
                    10 [[
                        "(" left data/num 3 ") "
                        mid data/num 4 3 "-" right data/num 4
                    ]]
                ][[data/num]]

                reduce either data/ext [[" ext" trim data/ext]] [""]

                reduce either data/pin [[" pin" trim data/pin]] [""]
            ]
        ][num]

        if obj [
            obj/text: res
            attempt [if 'face = obj/type [show obj]]
        ]
        res
    ]
GrahamC:
24-Apr-2012
I guess users are going to have to make their own parse rules then
Gregg:
24-Apr-2012
parse-int-values: func [

    "Parses and returns integer values, each <n> chars long in a string."
    input [any-string!]

    spec [block!] "Dialected block of commands: <n>, skip <n>, done, 
    char, or string"
    /local
        gen'd-rules ; generated rules
        result      ; what we return to the caller

        emit emit-data-rule emit-skip-rule emit-literal-rule emit-data
        digit= n= literal=
        int-rule= skip-rule= literal-rule= done= build-rule=
        data-rule skip-rule
][

    ; This is where we put the rules we build; our gernated parse rules.
    gen'd-rules: copy []
    ; This is where we put the integer results
    result: copy []

    ; helper functions

    emit: func [rule n] [append gen'd-rules replace copy rule 'n n]
    emit-data-rule: func [n] [emit data-rule n]
    emit-skip-rule: func [n] [emit skip-rule n]
    emit-literal-rule: func [value] [append gen'd-rules value]
    emit-data: does [append result to integer! =chars]

    ; Rule templates; used to generate rules

    ;data-rule: [copy =chars n digit= (append result to integer! =chars)]
    data-rule: [copy =chars n digit= (emit-data)]
    skip-rule: [n skip]

    ; helper parse rules
	digit=: charset [#"0" - #"9"]
    n=: [set n integer!]
    literal=: [set lit-val [char! | any-string!]]

    ; Rule generation helper parse rules
    int-rule=: [n= (emit-data-rule n)]
    skip-rule=: ['skip n= (emit-skip-rule n)]
    literal-rule=: [literal= (emit-literal-rule lit-val)]
    done=: ['done (append gen'd-rules [to end])]

    ; This generates the parse rules used against the input

    build-rule=: [some [skip-rule= | int-rule= | literal-rule=] opt done=]


    ; We parse the spec they give us, and use that to generate the

    ; parse rules used against the actual input. If the spec parse

    ; fails, we return none (maybe we should throw an error though);

    ; if the data parse fails, we return false; otherwise they get
    ; back a block of integers. Have to decide what to do if they
    ; give us negative numbers as well.
    either parse spec build-rule= [
        either parse input gen'd-rules [result] [false]
    ] [none]
]
Gregg:
24-Apr-2012
Example: parse-int-values "1234567890" [2 4 skip 2 2]
Gregg:
24-Apr-2012
parse-int-values "(123) 456-7890" [#"(" 3 ") " 3 #"-" 4]
Sunanda:
28-Apr-2012
REBOL is structured more like LISP or Haskell (but without being 
a pure functional language).


So, yes, it does not have direct access to the machine instructions 
or low-level op sys APIs in the way that assembler or assembler-wrapper 
languages (like C) does.


What REBOL does have is easy integrated access to very high level 
APIs: parse. bind, map, etc.
ChristianE:
14-May-2012
indent: funct [string [string!]] [
    whitespace: charset "^- "
    indention: line-start: content: none
    parse/all string [
        copy indention any whitespace 

        any [thru "^/" line-start: any whitespace content: (insert remove/part 
        line-start content indention) :content]
    ]
    string
]
Endo:
14-May-2012
hah! I wrote something similar:

indent: func [s /local x] [parse/all s [x: (insert x "^-") any [thru 
newline x: (insert x "^-")]] s]
GiuseppeC:
18-Jun-2012
I have a problem with Parse
The following string does not work
parse line [any [to mystring copy link to {<br />}]]
mystring is a variable
This works
parse line [any [to "http://mysite.com"copy link to {<br />}]]
Can't variables be used after TO ?
sqlab:
19-Jun-2012
it works with global variables.
maybe your variable is not visible to parse

>> mys: "ac"
== "ac"
>> parse " abacbac  ba" [any [to mys copy s to "b" (probe s)]]
ac
ac  
== false
GiuseppeC:
19-Jun-2012
How do I parse the same data with different ending ?
I could have
http://myfile.txt</BR>
http://myfile.txt</DIV>
I need something like 
PARSE mystring [copy link to [</ BR>|</ DIV>]
Endo:
19-Jun-2012
to
 doesn't accept block, so put "to" inside the block:

s1: {http://myfile.txt</br>}
s2: {http://myfile.txt</div>}
parse s1 [copy link [to </br> | to </div>] (print link)] ;works

parse s2 [copy link [to </br> | to </div>] (print link)] ;works too
GiuseppeC:
19-Jun-2012
I need something like the following
parse s1 [any [to "http://"copy link [to </br>|to </div>]]
Is it possible ?
Ladislav:
19-Jun-2012
Of course it is possible, if I understand if well what you want, 
is:

s1: "a http://xxx</div>b http://yyy</br>"

parse/all s1 [any [to "http://"copy link any [</br> break | </div> 
break | skip] (print link)]]
Ladislav:
19-Jun-2012
If you do want to leave out the </br> and </div> substrings, the 
simplest way probably is:

s1: "a http://xxx</div>b http://yyy</br>"

parse/all s1 [any [to "http://"start: any [end: </br> break | </div> 
break | skip] (print copy/part start end)]]
Endo:
20-Jun-2012
There is no documentaion about BREAK in PARSE (for R2), so it is 
always difficult to remember for me. Thanks Ladislav.
Endo:
20-Jun-2012
Guiseppe: if you didn't read this before, here is a very good article:
http://www.codeconscious.com/rebol/parse-tutorial.html
other articles are also great, take a look at them all.
GiuseppeC:
20-Jun-2012
Also:

parse/all s1 [any [to "http://"copy link any [</br> break | </div> 
break | skip] (print link)]]
Could it be written as:

parse/all s1 [any [to "http://"copy link TO any [</br> break | </div> 
break | skip] (print link)]]
Or

parse/all s1 [any [to "http://"copy link any [TO </br> break |TO 
 </div> break | skip] (print link)]]

Finally, which is the purpose of the SKIP keywork in this context 
?
Endo:
20-Jun-2012
Guiseppe: "I am not ablie to understand the use of Break. Why it 
is useful ?"
I'll try to explain:

>> parse/all "http://a.txthttp://b.dat"[any [to "http://"copy 
x any [".txt" | ".dat" | skip] (print x)]]

http://a.txthttp://b.dat;it prints just one line, from the first 
http:// to the last .dat


>> parse/all "http://a.txthttp://b.dat"[any [to "http://"copy 
x any [".txt" break | ".dat" break | skip] (print x)]]

http://a.txt;now it works as expected, from http:// to .txt 
and breaks
http://b.dat;and from the next http:// to .dat
Endo:
20-Jun-2012
But still there is a problem in your example. Here I'll try to explain:


>> parse/all "http://a.txthttp://b.dat"[any [to "http://"copy 
x any [thru ".txt" (print 1) break | thru ".dat" (print 2) break 
| skip (print 3)] (print x)]]
1
http://a.txt
2
http://b.dat


it looks correct. but actually it depends on which one is first (.txt 
or .dat)

here is the problem:

>> parse/all "http://a.txthttp://b.dat"[any [to "http://"copy 
x [thru ".dat" (print 1) | thru ".txt" (print 2) | skip (print 3)] 
(print x)]]
1
http://a.txthttp://b.dat
BrianH:
20-Jun-2012
Petr, R3 can't decode any 8bit encodings with its built-in code, 
just ASCII (which is 7bit) and UTF-8. However, its binary handling 
is better so it should be easy to write your own converters. For 
R2, I would suggest looking at Gabriele's PowerMezz package; it has 
some great text converters. Of course you lose out on R3's PARSE 
if you use R2.
Ladislav:
21-Jun-2012
'Could it be written as:

parse/all s1 [any [to "http://"copy link TO any [</br> break | </div> 
break | skip] (print link)]]' - no, since:

- TO ANY is not supported

- if it were supported it would not do what you want (you want to 
find the first terminator whatever it is, while TO ANY would find 
the </div> if it were in the input text even when a "closer" </br> 
would be "closer"
Ladislav:
21-Jun-2012
Or
parse/all s1 [any [to 

http://"copy link any [TO </br> break |TO  </div> break | skip] 
(print link)]]" - this *is* supported, but it does not do what you 
want; it finds the </br> even if </div> occurs "sooner"
Sunanda:
30-Jul-2012
Anyone want to have a try at this little puzzle? I have a working 
solution, but I am sure there is way more REBOLish way.


I have two objects that each contain simple REBOL values (ie imagine 
they've just been created from some serialised data, so no recursive 
blocks or anything tricky):
    obj1: make object! [aaa: 1 bbb: "xx"]
    obj2: make object! [bbb: "XX" aaa: 1]


All I want to do is confirm that they contain identical words and 
values under normal REBOL comparison rules -- so obj1 and obj2 should 
be treated as identical, while the next few are not identical to 
obj1 or obj2:
    obj3: make object! [bbb: "xx"]    ;; no 'aaa word
    obj4: make object! [bbb: "XX" aaa: 1 ccc: 3]  ;; extra word

    obj5: make object! [bbb: "XX" aaa: -1]  ;; different 'aaa word value


I am sure there is a simple one-line 'parse solution .... Isn't there 
always!? Thanks!
DocKimbel:
8-Aug-2012
Endo: I think a much faster version could be coded using PARSE.
Endo:
8-Aug-2012
And I'm not that good using PARSE, my PARSE expriments usually stuck 
with infinite loops :(
BrianH:
8-Aug-2012
Here's a version for R3 parse, with some optimizations:

rle2: funct ["Run length encode" b [series!]] [
	output: copy [] x: none

 r: either any-block? :b [qr: copy [quote 1] [(qr/2: :x) any qr]] 
 [[any x]]
	parse :b [any [pos1: set x skip r pos2: (
		reduce/into [subtract index? :pos2 index? :pos1 :x] tail output
	)]]
	output
]
BrianH:
8-Aug-2012
rle2: funct ["Run length encode" b [series!]] [
	output: copy [] x: none

 r: either any-block? :b [qr: copy [quote 1] [(qr/2: :x) any qr]] 
 [[any x]]
	parse/case :b [any [pos1: set x skip r pos2: (
		reduce/into [subtract index? :pos2 index? :pos1 :x] tail output
	)]]
	output
]

>> rle2 [a a A b b c d D d d d]
== [2 a 1 A 2 b 1 c 1 d 1 D 3 d]
BrianH:
8-Aug-2012
I tried to come up with a more optimal R3 version without using parse, 
but I got blocked by case-sensitivity, without considering binding. 
I suppose I could just consider binding too, or unbind the results. 
It also doesn't do structural comparison of functions, either in 
the parse or procedural version.
BrianH:
8-Aug-2012
Can someone come up with an equivalent R2 parse version? Of course 
words aren't case-preserving in R2, nor can they be compared case-sensitively.
DocKimbel:
8-Aug-2012
Here's a R2 solution with same rules for string! and block! series:

rle: func [s [series!] /local out c i][
    out: make block! 1

    parse/case/all s [
        any [
            [end | c: (
                c: either word? c/1 [to-lit-word c/1][c/1]
                i: 1
            )]
           skip
           some [
               c (i: i + 1)
               | (repend out [i c]) break
           ]
       ]
    ]
    out
]

>> rle "aaabbcx"
== [3 #"a" 2 #"b" 1 #"c" 1 #"x"]

>> rle [a a a a a]
== [5 a]

>> rle [a a a a a b b]
== [5 a 2 b]

>> rle [a a A b b c d D d d d]
== [3 a 2 b 1 c 5 d]
DocKimbel:
8-Aug-2012
Another version of 'rle for R2 that uses two pointers (like your 
R3 version) instead of a counter:

rle: func [s [series!] /local out c pos1 pos2][
    out: make block! 1

    parse/case/all s [
        any [
            [end | c: (
                c: either word? c/1 [to-lit-word c/1][c/1]
            )]
           pos1: skip

           some [c | pos2: (repend out [offset? pos1 pos2 c]) break]
       ]
    ]
    out
]
BrianH:
8-Aug-2012
Ah, yeah, I overspecced the R3 version by using QUOTE. Although there's 
a standatd workaround for integers (precede it with 1 1), for any-blocks 
and functions it might be best to do the comparison using REBOL code. 
The R2 equivalent of the IF operation in R3 parse would help here: 
http://www.rebol.net/wiki/Parse_Project#IF_.28condition.29
BrianH:
8-Aug-2012
Here's a version of Doc's with all datatypes handled, even unset. 
It even avoids accidentally converting lit-words to words and lit-paths 
to paths:

rle: func [s [series!] /local out pos1 pos2 cont][
	out: make block! 1
	parse/all s [
		any [
			pos1: skip some [
				pos2: skip (cont: if any [
					not-equal? unset? :pos1/1 unset? :pos2/1
					strict-not-equal? :pos1/1 :pos2/1
				] [[end skip]]) cont |
				pos2: (repend out [offset? :pos1 :pos2 :pos1/1]) break
			]
		]
	]
	out
]
BrianH:
8-Aug-2012
There was no point in using parse/case since the comparisons were 
being done by strict-not-equal?, not parse.
BrianH:
8-Aug-2012
This version handles unsets too:

rle: func [s [series!] /local out emit pos1 pos2 cont][
	out: make block! 1
	emit: [(repend out [offset? :pos1 :pos2 :pos1/1])]
	parse/all s [
		any [
			pos1: unset! some [pos2: unset! | pos2: emit break] |
			pos1: skip some [
				pos2: unset! :pos2 emit break |
				pos2: skip (
					cont: if strict-not-equal? :pos1/1 :pos2/1 [[end skip]]
				) cont |
				pos2: emit break
			]
		]
	]
	out
]
BrianH:
8-Aug-2012
Slight improvement:

rle: func [s [series!] /local out emit pos1 pos2 cont][
	out: make block! 1
	emit: [(repend out [offset? :pos1 :pos2 :pos1/1])]
	parse/all s [any [
		pos1: unset! any unset! pos2: emit |
		pos1: skip some [
			pos2: unset! :pos2 emit break |
			pos2: skip (
				cont: if strict-not-equal? :pos1/1 :pos2/1 [[end skip]]
			) cont |
			pos2: emit break
		]
	]]
	out
]
DocKimbel:
9-Aug-2012
Endo: you should rather bench on one long series rather than 1M times 
on a small one in order to avoid function calls overhead and get 
a more fair comparison. When I try with a 1M size string with random 
a,b,c chars, my parse solution is twice faster than the mezz one 
(Brian's one is crashing so can't test it). I was expecting a greater 
difference though.
BrianH:
9-Aug-2012
Weird, I found the bug in R2 parse that causes the crash:
>> parse "" [integer!]
== false
>> parse "" [unset!]
== true  ; should be false
BrianH:
9-Aug-2012
Two rules it is then. This doesn't crash, and is optimized for strings 
while we're at it. It's probably slower when doing blocks than Doc's, 
but it handles all datatypes:

rle: func [s [series!] /local out emit pos1 pos2 cont][
	out: make block! 1
	emit: [(repend out [offset? :pos1 :pos2 first :pos1])]
	parse/case/all :s pick [[
		any [pos1: skip (cont: first :pos1) any cont pos2: emit]
	] [
		any [
			pos1: unset! any unset! pos2: emit |
			pos1: skip some [
				end pos2: emit break |
				pos2: unset! :pos2 emit break |
				pos2: skip (

     cont: unless strict-equal? first :pos1 first :pos2 [[end skip]]
				) cont |
				pos2: emit break
			]
		]
	]] any-string? :s
	out
]


It also works around the strict-not-equal? bug in pre-2.7.7 R2, and 
using FIRST instead of path access is another speedup in R2 (path 
access is faster in R3).
BrianH:
9-Aug-2012
Change the repend to chained inserts and it gets noticably faster, 
due to less mezzanine overhead:

rle: func [s [series!] /local out emit pos1 pos2 cont][
	out: make block! 2

 emit: [(out: insert/only insert out offset? :pos1 :pos2 first :pos1)]
	parse/case/all :s pick [[
		any [pos1: skip (cont: first :pos1) any cont pos2: emit]
	] [
		any [
			pos1: unset! any unset! pos2: emit |
			pos1: skip some [
				end pos2: emit break |
				pos2: unset! :pos2 emit break |
				pos2: skip (

     cont: unless strict-equal? first :pos1 first :pos2 [[end skip]]
				) cont |
				pos2: emit break
			]
		]
	]] any-string? :s
	head out
]
BrianH:
9-Aug-2012
You can get rid of this line too for a slight speedup:
				end pos2: emit break |

It's a leftover when I was trying to work around the bug in PARSE.
BrianH:
9-Aug-2012
If you follow the /into option standard you can do chained calls 
to RLE too:


rle: func [s [series!] /into out [any-block!] /local emit pos1 pos2 
cont][
	unless into [out: make block! 2]

 emit: [(out: insert/only insert :out offset? :pos1 :pos2 first :pos1)]
	parse/case/all :s pick [[
		any [pos1: skip (cont: first :pos1) any cont pos2: emit]
	] [
		any [
			pos1: unset! any unset! pos2: emit |
			pos1: skip some [
				pos2: unset! :pos2 emit break |
				pos2: skip (

     cont: unless strict-equal? first :pos1 first :pos2 [[end skip]]
				) cont |
				pos2: emit break
			]
		]
	]] any-string? :s
	either into [:out] [head :out]
]
BrianH:
9-Aug-2012
R3 version, same /into option:


rle: funct ["Run length encode" s [series!] /into output [any-block!]] 
[
	unless into [output: make block! 2] x: none

 r: either any-block? :s [qr: copy [quote 1] [(qr/2: :x) any qr]] 
 [[any x]]
	parse/case :s [any [pos1: set x skip r pos2: (

  output: reduce/into [subtract index? :pos2 index? :pos1 :x] :output
	)]]
	either into [:output] [head :output]
]
BrianH:
9-Aug-2012
Sorry, same unset problems, have to use POKE:


rle: funct ["Run length encode" s [series!] /into output [any-block!]] 
[
	unless into [output: make block! 2] x: none

 r: either any-block? :s [qr: copy [quote 1] [(poke qr 2 :x) any qr]] 
 [[any x]]
	parse/case :s [any [pos1: set x skip r pos2: (

  output: reduce/into [subtract index? :pos2 index? :pos1 :x] :output
	)]]
	either into [:output] [head :output]
]
Steeve:
10-Aug-2012
An alternative for R3 (strings and blocks)
rle: func [s /local p e o][
	o: copy []
	parse/case s [
		any [

   p: skip any [e: if (p/1 == e/1) skip] (repend o [offset? p e p/1])
		]
	]
	o
]
BrianH:
11-Aug-2012
Steeve, that's basically the same as my R2 RLE's block rule, but 
with the IF workaround replaced with IF. It has a few gotchas:
- Executes function values in block data
- Doesn't handle unset! or error! values

- Converts lit-paths to paths and lit-words to words before comparison 
and again before putting in the output.
- Lots of intermediate block creation overhead

- Considers bindings of words when comparing them, not just case-sensitive 
spelling


The first 3 can be handled by using :p/1 and :e/1 instead of p/1 
and e/1, and the fourth by using REDUCE/into instead of REPEND. The 
last one can't be handled by any built-in function or operator in 
R3 (see http://issue.cc/r3/1834for details) but you could do a combination 
of functions and operators to get case-sensitive comparison without 
considering bindings. PARSE/case's QUOTE operation is the fastest 
method for doing that at the moment.


Nice job on neatly bypassing the relaxed bounds checking of R3 blocks. 
Though the if (p/1 == e/1) would succeed if p/1 is none and e is 
at the end of the block, the skip would still fail. That trick saves 
one e: operation.
BrianH:
11-Aug-2012
The advantages of == or =? comparison over PARSE QUOTE would be lost 
if you serialize the data and save it to a file or send it over a 
network. REBOL syntax doesn't keep track of those distinctions.
BrianH:
11-Aug-2012
The PARSE IF method does let you add a /compare function option though, 
so you can be as specific as you want. Instead of if (:p/1 == :e/1) 
you would do if (apply :f [:p/1 :e/1]) then pass :== or :strict-equal? 
as a parameter..
BrianH:
11-Aug-2012
Here's a version of my last one above, but with Steeve's trick adapted 
to make a /compare option. It defaults to its old case-sensitive 
behavior.

rle: func [
	"Run length encode to series of [length value]"
	s [series!] "The series to encode"

 /into {Insert into a buffer instead (returns position after insert)}
	output [any-block!] "The output buffer (modified)"
	/compare "Comparator function for equvilance"
	comparator [any-function!]
	/local x r qr b e
] [
	unless into [output: make block! 2] x: none
	r: case [
		compare [[any [e: if (apply :comparator [:x :e/1]) skip]]]
		any-string? :s [[any x]]
		'else [qr: copy [quote 1] [(poke qr 2 :x) any qr]
	]
	parse/case :s [any [b: set x skip r e: (
		output: reduce/into [offset? :b :e :x] :output
	)]]
	either into [:output] [head :output]
]
BrianH:
11-Aug-2012
Whoops, forgot a bracket:

rle: func [
	"Run length encode to series of [length value]"
	s [series!] "The series to encode"

 /into {Insert into a buffer instead (returns position after insert)}
	output [any-block!] "The output buffer (modified)"
	/compare "Comparator function for equvilance"
	comparator [any-function!]
	/local x r qr b e
] [
	unless into [output: make block! 2] x: none
	r: case [
		compare [[any [e: if (apply :comparator [:x :e/1]) skip]]]
		any-string? :s [[any x]]
		'else [qr: copy [quote 1] [(poke qr 2 :x) any qr]]
	]
	parse/case :s [any [b: set x skip r e: (
		output: reduce/into [offset? :b :e :x] :output
	)]]
	either into [:output] [head :output]
]
Steeve:
11-Aug-2012
I don't think it would be hard to code with parse
Steeve:
11-Aug-2012
But I didn't use parse at that time
BrianH:
14-Aug-2012
Yes. It uses the IF and QUOTE operations, SET working on string parsing, 
PARSE default /all, :x meaning GET/any 'x, REDUCE/into, and equality 
finctions handling unset! values.
BrianH:
14-Aug-2012
If you are doing anything in PARSE, or generating blocks, or a wide 
variety of other things, it almost always pays off to do it in R3 
if you can, rather than R2 or any of the other REBOL-alikes except 
maybe Topaz. Topaz has a few PARSE enhancements that R3 could use, 
but the rest don't even come close; there are so many bugs in R2 
that need to be worked around that code for it can be quite different. 
Unfortunately, other factors can prevent people from using R3. Hopefully 
when Red itself is developed, not just Red/System, it will adopt 
the changes that we made for R3.
BrianH:
14-Aug-2012
I'd love to see the Topaz PARSE enhancements in Red too :)
BrianH:
14-Aug-2012
Gabriele has done a great job of reimplementing many of R3's PARSE 
enhancements in R2 using rule generators. If you're stuck on R2 or 
REBOL-alikes with R2-like behavior, that's a good place to start. 
It also helps to look at the parse project page, since there are 
a lot of code equivalent examples in the proposals there. That way 
you can translate your rules manually, and in some cases get faster 
rules as a result. Be careful with unset! vlaues though since there 
are a lot of bugs and limitations to R2's unset value handling, as 
demonstrated in the R2 RLE code above.
james_nak:
14-Aug-2012
Brian, it's so nice to have a Parse expert here. Thanks for your 
advice.
james_nak:
14-Aug-2012
Really though, you are probably one of the few who really know Parse.
Marco:
14-Aug-2012
Speaking of Parse. I think it could be useful to compile some kind 
of FAQ or even better a tips&tricks doc.
MagnussonC:
18-Sep-2012
I read a file, line by line and want parts of each line in certain 
variables. First is an integer then a space and then a 3-4 character 
word then a space and then the rest of the line in a string. I guess 
there is no way like in Perl to match those variabels at once and 
put the value in numbered variables. I suppose I need to parse that 
line with something like (thru "a" copy b to "c") once for each variable 
(or perhaps first char with line/1)!?
MaxV:
18-Sep-2012
Read this http://rebol2.blogspot.it/2012/05/text-extraction-with-parse.html
   ;-)
Maxim:
18-Sep-2012
does this help?
--------------------------

a: {123 abcd bla blca bla
534 hged bla blca bla
947 ahg psogie rpgioseg seo[rgieh rpgiu}

digits: charset "0123456789"
letters: charset [#"A" - #"Z" #"a" - #"z"]
space: charset " "
data: complement charset "^/"
ctx: copy [ ]
parse/all a [
	some [
		copy id some digits
		space 
		copy var 3 4 letters
		space
		copy line-data some data
		; we have a match for all data, add it in our container

  ( append ctx copy reduce [  to-set-word rejoin [var "-" id]   line-data] 
  )
		"^/"
	]	
]

ctx: context ctx

probe ctx
Maxim:
18-Sep-2012
I added a bit of processing to show how to use parse in order to 
actually do things beyond just match patterns.


note that the paren is at the end, once we have all data we want 
to match.  An error people often do is to start processing too soon.
MagnussonC:
18-Sep-2012
Thank you both! Now I have something to work with. Didn't realize 
you could do parse complex like that.
Gregg:
19-Sep-2012
Magnusson, have you looked at the REBOL manual that explains the 
parse grammar?
Ladislav:
19-Sep-2012
See also


http://en.wikibooks.org/wiki/REBOL_Programming/Language_Features/Parse/Parse_expressions
Group: Databases ... group to discuss various database issues and drivers [web-public]
BrianH:
17-Mar-2012
ChristianE implements an R2-like API in an R3 port model, and it 
just feels alien, though it does allow me to have more portable code 
between R2 and R3. This helps when i have to have a script extract 
data in R2 because it needs to get text or numeric type data, but 
then close and call itself in R3 to parse that data. My %rebol.r 
is R2 and R3 compatible.
1 / 3907[1] 2345...3637383940