AltME groups: search
Help · search scripts · search articles · search mailing listresults summary
world | hits |
r4wp | 0 |
r3wp | 97 |
total: | 97 |
results window for this page: [start: 1 end: 97]
world-name: r3wp
Group: All ... except covered in other channels [web-public] | ||
Gabriele: 2-May-2006 | rewrite: func [block rules /local rules* rule flag mk1 mk2 prod] [ if empty? rules [return block] rules*: make block! 16 foreach [pattern production] rules [ insert insert/only insert/only tail rules* pattern make paren! compose/only [ prod: compose/deep (production) ] '| ] remove back tail rules* until [ ;probe block ask "" not match block [mk1: rules* mk2: (mk2: change/part mk1 prod mk2) :mk2] ] block ] | |
BrianH: 4-May-2006 | Here are some minimum additonal parse operations, and some workarounds that could be used to replace them until they are implemented. fail ==> [end skip] check (code) ==> (tmp1: unless (code) [fail]) tmp1 remove rule ==> tmp1: rule tmp2: :tmp1 (remove/part :tmp1 :tmp2) replace rule (code) ==> tmp1: rule tmp2: :tmp1 (tmp1: change/part :tmp1 (code) :tmp2) :tmp1 replace-only rule (code) ==> tmp1: rule tmp2: :tmp1 (tmp1: change/part/only :tmp1 (code) :tmp2) :tmp1 into-string rule ==> set tmp1 string! (tmp1: unless parse tmp1 rule [fail]) tmp1 Note that if parse operations are changed to take refinements or if these are being done as rewrite rules, replace-only and into-string could be expressed as remove/only and into/string. This would be slower in a native implementation, but about the same in rewrite rules. It would look more REBOL-like if that matters to you. A rewrite engine for these workarounds will need temporaries for their implementation. The caller would need to provide a block of their own temporaries, and would not be able to reuse them in their code. The rewriter will need to count temporaries and complain if the caller doesn't provide enough. As with all parse rules, these temporaries will not be recursion-safe. Directly nested rules should be fine as long as there are enough temporaries provided. | |
BrianH: 17-May-2006 | Looks good to me. BTW, the mk2: in not match data [mk1: rules* mk2: (mk2: change/part mk1 prod mk2) :mk1] isn't used by your code. Did you mean mk1: instead? | |
Group: Core ... Discuss core issues [web-public] | ||
Romano: 3-Mar-2005 | Didec, i should do: parse b [any [h: set x skip (h: change/part h x 1) :h]] | |
Chris: 30-Mar-2005 | I was thinking (name pending) -- one-word: func [blk][head while [not tail? blk][blk: change/part blk get blk/1 1]] | |
Anton: 18-Apr-2007 | >> a: copy b == [[1 2] [3 4]] >> while [not tail? a][a: change/part a a/1 1] a: head a == [1 2 3 4] | |
Oldes: 19-Apr-2007 | tm: func [p act [block!] /local t][t: now/time/precise loop p :act print now/time/precise - t] flat-while: func[b][a: copy b while [not tail? a][a: change/part a a/1 1] a: head a] flat-repeat: func[b][a: copy [] repeat i length? b [insert tail a pick b i] a] flat-parse: func [b][a: copy [] parse b r: [any [ p: block! :p into r | skip (insert/only tail a first p)]]a] flat-load: func[b][load form b] b1: [[1 2 3 4 5][6 7 8 9 0]] tm 10000 [flat-while b1] ;== 0:00:00.062 tm 10000 [flat-repeat b1] ;== 0:00:00.063 tm 10000 [flat-parse b1] ;== 0:00:00.172 tm 10000 [flat-load b1] ;== 0:00:00.046 b2: head insert/dup copy [] [a b c d] 300 b3: head insert/dup copy [] b2 100 tm 1000 [flat-while b3] ;== 0:03:03.985 tm 1000 [flat-repeat b3] ;== 0:02:11.125 tm 1000 [flat-parse b3] ;== 0:02:43.704 tm 1000 [flat-load b3] ;== 0:00:52.344 | |
Chris: 22-May-2007 | flatten: func [block [any-block!]][ parse block [ any [block: any-block! (change/part block first block 1) :block | skip] ] head block ] | |
Oldes: 12-Jun-2007 | hm.. parse t: "a//bb/c" [any [to "/" p1: some "/" p2: (p1: change/part p1 "/" p2) :p1] to end] t | |
Steeve: 25-Oct-2007 | REBOL [] parse-async: func [ file rules /local port buffer offset getf seek meta & && result ][ port: open/seek/binary file buffer: clear #{} offset: 1 getf: func [len][ offset: offset - length? buffer clear buffer append buffer copy/part at port offset len offset: offset + len ] seek: [(offset: offset + 1)] ..: func [blk] [change/part & compose/deep blk && ] parse rules meta: [ some [ &: binary! &&: (.. [buffer: (to-paren reduce ['getf length? &/1]) (&/1)]) :& 3 skip | &: 'skip &&: (.. [seek]) :& skip | &: 'get word! integer! &&: (.. [buffer: (to-paren compose/deep [getf (&/3) set [(&/2)] to integer! as-binary cp buffer]) to end]) :& 4 skip | &: string! &&: (.. [(as-binary &/1)]) :& | 'end 'skip | into meta | skip ] ] result: parse/all buffer rules close port result ] if parse-async %15.jpg [ #{FFD8} ; jpeg Header [ #{FFE0} ;JFIF header get len 2 ;get data length for the current header (2 bytes) "JFIF" ;yeah it's a JFIF (confirmation) (len: len - 6) len skip ;skip data (len) times some [ #{FFC0} ;good ! i found the length properties 2 skip ; skip length of this header skip ; filler ??? always = #{08} get height 2 get width 2 break ; finished | #{FF} skip ;skip this header get len 2 (len: len - 2) len skip | [end skip] ;error format ] | #{FFE1} ;EXIF header get len 2 ;get length of a header ;... to do [end skip] ] to end ][ ?? height ?? width ] halt | |
Anton: 23-Feb-2008 | Paul, you can avoid copy blk/1 by using change/part. And perhaps better to continue processing the data when blk/1 is not a block. | |
Anton: 23-Feb-2008 | semi-flat: func [blk][ while [not tail? blk][ blk: either block? blk/1 [ change/part blk blk/1 1 ][ next blk ] ] head blk ] semi-flat [[1 ["one"]] [2 ["two"]] "other data"] | |
Anton: 23-Feb-2008 | You can also use until instead of while: semi-flat: func [blk][ until [ tail? blk: either block? blk/1 [ change/part blk blk/1 1 ][ next blk ] ] head blk ] | |
BrianH: 7-Mar-2008 | Here's a version which modifies in place: flatten: func [blk [block!] /local rule a b] [ parse blk [some [a: set b block! (change/part a b 1) :a | skip]] blk ] | |
Anton: 16-Oct-2008 | s2: copy s parse/all s2 [some [p: "^/" (change/part p "^^/" 1) skip | "^-" (change/part p "^^-" 1) skip | skip]] | |
amacleod: 16-Oct-2008 | s2: copy a parse/all s2 [some [p: "^/" (change/part p "^^/" 1) skip | "^-" (chang e/part p "^^-" 1) skip | skip]] == true >> s2 == {a^^/^^-b^^/^^-c} >> print s2 a^/^-b^/^-c Anton, It looks like what I want but if aI print it the newlines are not reconized??? | |
Anton: 16-Oct-2008 | >> s: "a^/^-b^/^-^-c" == {a ^-b ^-^-c} >> s2: copy s parse/all s2 [some [p: "^/" (change/part p "^^/" 1) skip | "^-" (change/part p "^^-" 1) skip | skip]] == true >> s3: load rejoin ["{" s "}"] == {a ^-b ^-^-c} >> s = s3 == true | |
BrianH: 13-Feb-2009 | while [not empty? blk] [ blk: change/part blk copy/part blk span ] | |
BrianH: 13-Feb-2009 | Sorry, change/part -> change/part/only | |
Steeve: 13-Feb-2009 | unless [empty? blk: change/part blk copy/part blk span span] (unless is a litlle faster than while) | |
Ammon: 10-Apr-2009 | Yeah, you need to be escaping a lot more than just those characters to really do it right. I can't help you with building the table of escapes, but this version should be a lot faster if you're escaping large quantities of text... encode-html: func [ "Make HTML tags into HTML viewable escapes (for posting code)" text ][ parse/all text [ any [ h: #"&" (h: change/part h "&" 1) :h | h: #"<" (h: change/part h "<" 1) :h | h: #">" (h: change/part h ">" 1) :h | h: #""" (h: change/part h """ 1) :h | h: #"'" (h: change/part h "'" 1) :h | h: #"€" (h: change/part h "€" 1) :h | skip ] ] text ] | |
Geomol: 18-Nov-2009 | Maybe better: forall blk [change/part blk blk/1 1] | |
Izkata: 18-Nov-2009 | Slight differences - no internal blocks are preserved in Geomol's: >> blk: [1 [2] [3 [4]] [5 6]] == [1 [2] [3 [4]] [5 6]] >> forall blk [change/part blk blk/1 1] == [] >> blk == [1 2 3 4 5 6] My version (gives the same result as kcollins, but is in-place like Geomol's) only flattens one level: >> blk: [1 [2] [3 [4]] [5 6]] == [1 [2] [3 [4]] [5 6]] >> forall blk [blk: back insert blk also blk/1 remove blk] == [6] >> blk == [1 2 3 [4] 5 6] | |
Chris: 3-Apr-2010 | I use a variant of this: sanitize: use [chars encode][ chars: complement charset {&<>"} encode: func [txt chr][change/part txt chr 1] func [text [any-string!]][ parse/all copy text [ copy text any [ text: some chars | #"&" (text: encode text "&") :text | #"<" (text: encode text "<") :text | #">" (text: encode text ">") :text | #"^"" (text: encode text """) :text ] ] any [text ""] ] ] Provides a bit of scope for expansion... | |
Ashley: 4-Apr-2010 | A non-parse solution (for the replace problem) based on the existing replace mezz: replace-each: make function! [ target [series!] "Series that is being modified" values [block!] "Block of search/replace strings" /local len pos ][ foreach [search replace] values [ len: length? search while [pos: find target search] [ target: change/part pos replace len ] ] ] | |
BrianH: 1-Oct-2010 | Sounds interesting. I know that CHANGE/part is the real fundamental operation, but that needs an additional parameter and would require renaming the option - /into isn't an appropriate name for that operation. But I don't think it would have been implemented in that case, and having it be a direct CHANGE would definitely not have been accepted because /into is mostly used to replace chained INSERT and APPEND operations. | |
Group: View ... discuss view related issues [web-public] | ||
Geomol: 22-Aug-2005 | Is there a way to copy a part of an image from a certain position to another image at a certain position? Something like: change/part at image1 5x5 at image2 10x10 20x20 That should take 20x20 pixels from image2 at position 10x10 and put them in image1 at position 5x5, but it takes from the start of image2, so it doesn't work as intended. | |
BrianH: 2-Jul-2008 | For a binary float value in the variable binfloat, try this: a: make struct! [x [float]] none change/part third a binfloat a/x The third a accessor returns a reference to the binary data of the struct. Modifications to the value returned affect the struct. Be sure to keep the length of the returned binary the same. | |
BrianH: 2-Jul-2008 | Whoops, the change line is: change/part third a binfloat 4 | |
Group: I'm new ... Ask any question, and a helpful person will try to answer. [web-public] | ||
btiffin: 18-Jul-2007 | dt: now/precise t: dt/time t: find form t/second "." rejoin [form-date dt "%C%y-%m-%d-%H:%M:%S" head change/part ".000000" t length? t] I think I'll bug Chris to add %P for precise padded seconds. :) | |
btiffin: 18-Jul-2007 | and of course head change/part COPY ".000000" ... if you reuse the sequence...It'd be nice to be able to just use form-date now/precise "%C%y-%m-%d-%H:%M:%P" | |
Gregg: 11-May-2009 | REBOL [] do %include.r include %file-list.r flash-wnd: flash "Finding test files..." if file: request-file/only [ files: read first split-path file ] if none? file [halt] items: collect/only item [ foreach file files [item: reduce [file none]] ] unview/only flash-wnd ;------------------------------------------------------------------------------- ;-- Generic functions call*: func [cmd] [ either find first :call /show [call/show cmd] [call cmd] ] change-each: func [ [throw] "Change each value in the series by applying a function to it" 'word [word!] "Word or block of words to set each time (will be local)" series [series!] "The series to traverse" body [block!] "Block to evaluate. Return value to change current item to." /local do-body ][ do-body: func reduce [[throw] word] body forall series [change/only series do-body series/1] ; The newer FORALL doesn't return the series at the tail like the old one ; did, but it will return the result of the block, which is CHANGE's result, ; so we need to explicitly return the series here. series ] collect: func [ "Collects block evaluations." [throw] 'word block [block!] "Block to evaluate." /into dest [block!] "Where to append results" /only "Insert series results as series" /local fn code marker at-marker? marker* mark replace-marker rules ][ block: copy/deep block dest: any [dest make block! []] fn: func [val] compose [(pick [insert insert/only] not only) tail dest get/any 'val get/any 'val ] code: 'fn marker: to set-word! word at-marker?: does [mark/1 = marker] replace-marker: does [change/part mark code 1] marker*: [mark: set-word! (if at-marker? [replace-marker])] parse block rules: [any [marker* | into rules | skip]] do block head :dest ] edit-file: func [file] [ ;print mold file call* join "notepad.exe " to-local-file file ;join test-file-dir file ] flatten: func [block [any-block!]][ parse block [ any [block: any-block! (change/part block first block 1) :block | skip] ] head block ] logic-to-words: func [block] [ change-each val block [either logic? val [to word! form val] [:val]] ] standardize: func [ "Make sure a block contains standard key-value pairs, using a template block" block [block!] "Block to standardize" template [block!] "Key value template pairs" ][ foreach [key val] template [ if not found? find/skip block key 2 [ repend block [key val] ] ] ] tally: func [ "Counts values in the series; returns a block of [value count] sub-blocks." series [series!] /local result blk ][ result: make block! length? unique series foreach value unique series [repend result [value reduce [value 0]]] foreach value series [ blk: first next find/skip result value 2 blk/2: blk/2 + 1 ] extract next result 2 ] ;------------------------------------------------------------------------------- counts: none refresh: has [i] [ reset-counts i: 0 foreach item items [ i: i + 1 set-status reform ["Testing" mold item/1] item/2: random/only reduce [true false] show main-lst set-face f-prog i / length? items wait .25 ] update-counts set-status mold counts ] reset-counts: does [counts: copy [total 0 passed 0 failed 0]] set-status: func [value] [set-face status form value] update-counts: has [pass-fail] [ counts/total: length? items pass-fail: logic-to-words flatten tally collect res [foreach item items [res: item/2]] ;result (e.g.): [true 2012 false 232] standardize pass-fail [true 0 false 0] counts/passed: pass-fail/true counts/failed: pass-fail/false ] ;--------------------------------------------------------------- main-lst: sld: ; The list and slider faces c-1: ; A face we use for some sizing calculations none ml-cnt: ; Used to track the result list slider value. visible-rows: ; How many result items are visible at one time. 0 lay: layout [ origin 5x5 space 1x0 across style col-hdr text 100 center black mint - 20 text 600 navy bold { This is a sample using file-list and updating progress as files are processed. } return pad 0x10 col-hdr "Result" col-hdr 400 "File" col-hdr 100 return pad -2x0 ; The first block for a LIST specifies the sub-layout of a "row", ; which can be any valid layout, not just a simple "line" of data. ; The SUPPLY block for a list is the code that gets called to display ; data, in this case as the list is scrolled. Here COUNT tells us ; which ~visible~ row data is being requested for. We add that to the ; offset (ML-CNT) set as the slider is moved. INDEX tells us which ; ~face~ in the sub-layout the data is going to. ; COUNT is defined in the list style itself, as a local variable in ; the 'pane function. main-lst: list 607x300 [ across space 1x0 origin 0x0 style cell text 100x20 black mint + 25 center middle c-1: cell cell 400 left cell [edit-file item/1] ] supply [ count: count + ml-cnt item: pick items count face/text: either item [ switch index [ 1 [ face/color: switch item/2 reduce [none [gray] false [red] true [green]] item/2 ] 2 [mold item/1] 3 ["Edit"] ] ] [none] ] sld: scroller 16x298 [ ; use SLIDER for older versions of View if ml-cnt <> (val: to-integer value * subtract length? items visible-rows) [ ml-cnt: val show main-lst ] ] return pad 0x20 f-prog: progress 600x16 return status: text 500 return button 200 "Run" [refresh show lay] pad 200 button "Quit" #"^q" [quit] ] visible-rows: to integer! (main-lst/size/y / c-1/size/y) either visible-rows >= length? items [ sld/step: 0 sld/redrag 1 ][ sld/step: 1 / ((length? items) - visible-rows) sld/redrag (max 1 visible-rows) / length? items ] view lay | |
Group: Parse ... Discussion of PARSE dialect [web-public] | ||
Gregg: 30-Apr-2005 | Something like this? (it's not parse based though) flatten: func [block] [ head forall block [ if block? block/1 [change/part block block/1 1] ] ] | |
Volker: 13-Aug-2005 | s: "Hello cè World" es: charset[#"e" #"è"#"è"#"ê"#"i"#"î" #"y"] parse/all s [ to "c" p: skip es p2: ( p: change/part p "s" p2 ) :p ] ? s | |
Volker: 13-Aug-2005 | questions: -long string? then better copy instead of change/part -more patterns in same path, then not 'to. | |
BrianH: 22-Aug-2005 | parse/all data [any [to "*" a: skip b: to "*" c: skip d: :a (change/part a rejoin ["<strong>" copy/part b c "</strong>"] d)] to end] | |
BrianH: 22-Aug-2005 | markup-chars: charset "*~" non-markup: complement markup-chars tag1: ["*" "<strong>" "~" "<i>"] tag2: ["*" "</strong>" "~" "</i>"] parse/all data [ any non-markup any [ ["*" a: skip b: to "*" c: skip d: | "~" a: skip b: to "~" c: skip d: ] :a ( change/part a rejoin [ select tag1 copy/part a b copy/part b c select tag2 copy/part c d ] d ) any non-markup ] to end ] | |
Tomc: 22-Aug-2005 | w: complement charset "*" rule: [ to "*" here: "*" opt[ copy item some w "*" there: (change/part :here join "" [<strong> item </strong>] :there) ] ] parse/all str [some rule] | |
BrianH: 22-Aug-2005 | OK, I tried this: parse "abc" [to "bc" a: "bc" (change/part a "b" 2)] It returns true on View 1.3 and Core 2.6, but false on View 1.2 and Core 2.5.0. | |
BrianH: 22-Aug-2005 | Here's a simplified version of my example that can handle multiple instances of multiple markup types and be adapted to different end tags (thanks Tomc for the idea!): markup-chars: charset "*~" non-markup: complement markup-chars tag1: ["*" "<strong>" "~" "<i>"] tag2: ["*" "</strong>" "~" "</i>"] parse/all data [ any non-markup any [ ; This next block can be generated if you have many markup types... [a: copy b "*" copy c to "*" copy d "*" e: | a: copy b "~" copy c to "~" copy d "~" e: ] :a (change/part a rejoin [tag1/:b c tag2/:d] e) any non-markup ] to end ] | |
BrianW: 22-Aug-2005 | Here's what I have right now: markup-chars: charset "*_@" non-markup: complement markup-chars inline-tags: [ "*" "strong" "_" "em" "@" "code" ] markup-rule: [ any non-markup any [ [ a: "*" b: to "*" c: skip d: | a: "_" b: to "_" c: skip d: | a: "@" b: to "@" c: skip d: ] :a ( change/part a rejoin [ "<" select inline-tags copy/part a b ">" copy/part b c "</" select inline-tags copy/part a b ">" ] d ) any non-markup ] to end ] parse text markup-rule | |
BrianW: 22-Aug-2005 | okay, here's a slightly tweaked version that uses a multichar markup tag: markup-chars: charset "[*_-:---]" non-markup: complement markup-chars inline-tags: [ "*" "strong" "_" "em" "@" "code" "--" "small" ] markup-rule: [ any non-markup any [ [ a: "*" b: to "*" c: skip d: | a: "_" b: to "_" c: skip d: | a: "@" b: to "@" c: skip d: | a: "--" b: to "--" c: skip skip d: ] :a ( change/part a rejoin [ "<" select inline-tags copy/part a b ">" copy/part b c "</" select inline-tags copy/part a b ">" ] d ) any non-markup | skip ] to end ] parse/all text markup-rule | |
BrianH: 27-Jun-2006 | capitals: charset ["#"A" - #"Z"] alpha: charset ["#"A" - #"Z" #"a" - #"z"] non-alpha: complement alpha parse/all/case [any non-alpha any [ a: 5 capitals any capitals b: non-alpha ( b: change/part a rejoin ["<strong>" copy/part a b "</strong>"] b ) :b | some alpha any non-alpha ] to end] | |
BrianH: 27-Jun-2006 | ; A few fixes capitals: charset ["#"A" - #"Z"] alpha: charset ["#"A" - #"Z" #"a" - #"z"] non-alpha: complement alpha parse/all/case [any non-alpha any [ a: 5 capitals any capitals b: [non-alpha | end] ( b: change/part a rejoin ["<strong>" copy/part a b "</strong>"] b ) :b | some alpha any non-alpha ] to end] | |
BrianH: 27-Jun-2006 | ; Sorry, more fixes capitals: charset ["#"A" - #"Z"] alpha: charset ["#"A" - #"Z" #"a" - #"z"] non-alpha: complement alpha parse/all/case [any [ any non-alpha a: 5 capitals any capitals b: [non-alpha | end] ( b: change/part a rejoin ["<strong>" copy/part a b "</strong>"] b ) :b | some alpha ] to end] | |
BrianH: 27-Jun-2006 | ; Sorry, more fixes capitals: charset [#"A" - #"Z"] alpha: charset [#"A" - #"Z" #"a" - #"z"] non-alpha: complement alpha parse/all/case [any [to alpha [ a: 5 capitals any capitals b: [non-alpha | end] ( b: change/part a rejoin ["<strong>" copy/part a b "</strong>"] b ) :b | some alpha ]] to end] | |
Graham: 1-Jul-2006 | Trying to do some macro expansion in text ... This is not working :( expand-macros: func [tmp [string!] macros [block!] /local white-rule rule len lexp ] [ white-rule: charset [#" " #"^/"] foreach [macro expansion] macros [ len: length? macro lexp: length? expansion rule: compose/deep copy [ [ to here: white-rule (macro) white-rule ( change/part here expansion len ?? macro) lexp skip ] to end ] parse/all tmp [some [rule]] ] tmp ] | |
BrianH: 1-Jul-2006 | expand-macros: func [data [string!] macros [block!] /local whitespace macro-rule macro here there ] compose [ whitespace: (charset " ^/") macro-rule: make block! length? macros foreach [macro expansion] macros [ macro-rule: insert insert macro-rule macro '| ] macro-rule: head remove back macro-rule parse/all data [some [ here: copy macro macro-rule there: [whitespace | end] ( there: change/part here select/skip macros macro 2 there ) :there | skip ]] macro-rule: none data ] | |
BrianH: 1-Jul-2006 | expand-macros: func [data [string!] macros [block!] /local whitespace macro-rule macro here there ] compose [ whitespace: (charset " ^/") macro-rule: make block! length? macros foreach [macro expansion] macros [ macro-rule: insert insert macro-rule macro '| ] macro-rule: head remove back macro-rule parse/all data [some [ here: copy macro macro-rule there: [whitespace | end] ( there: change/part here select/skip macros macro 2 there ) :there | skip ]] macro-rule: none data ] | |
BrianH: 1-Jul-2006 | expand-macros: func [data [string!] macros [block!] /local whitespace macro-rule macro expansion here there ] compose [ whitespace: (charset " ^/") macro-rule: make block! 2.5 * length? macros foreach [macro expansion] macros [ macro-rule: insert macro-rule compose [here: (macro) there: [whitespace | end] '|] ] macro-rule: head remove back macro-rule parse/all data [some [ macro-rule ( macro: copy/part here there there: change/part here select/skip macros macro 2 there ) :there | skip ]] macro-rule: none data ] | |
BrianH: 1-Jul-2006 | expand-macros: func [data [string!] macros [block!] /local whitespace macro-rule macro expansion here there ] compose [ whitespace: (charset " ^/") macro-rule: make block! 2.5 * length? macros foreach [macro expansion] macros [ macro-rule: insert macro-rule compose [here: (macro) there: [whitespace | end] |] ] macro-rule: head remove back macro-rule parse/all data [some [ macro-rule ( macro: copy/part here there there: change/part here select/skip macros macro 2 there ) :there | skip ]] macro-rule: none data ] | |
BrianH: 1-Jul-2006 | expand-macros: func [data [string!] macros [block!] /local whitespace macro-rule macro expansion here there ] compose [ whitespace: (charset " ^/") macro-rule: make block! 2.5 * length? macros foreach [macro expansion] macros [ macro-rule: insert macro-rule compose [here: (macro) there: [whitespace | end] |] ] macro-rule: head remove back macro-rule parse/all data [some [ macro-rule ( macro: copy/part here there there: change/part here select/skip macros macro 2 there ) :there | thru whitespace ] to end] macro-rule: none data ] | |
BrianH: 1-Jul-2006 | ; Now whitespace is dealt with expand-macros: func [data [string!] macros [block!] /local whitespace macro-rule macro expansion here there ] compose [ whitespace: (charset " ^/") macro-rule: make block! 2.5 * length? macros foreach [macro expansion] macros [ macro-rule: insert macro-rule compose [here: (macro) there: [whitespace | end] |] ] macro-rule: head remove back macro-rule parse/all data [some [any whitespace [ macro-rule ( macro: copy/part here there there: change/part here select/skip macros macro 2 there ) :there | to whitespace ]] to end] macro-rule: none data ] | |
BrianH: 1-Jul-2006 | expand-macros: func [data [string!] macros [block!] /local ws non-ws macro-rule macro expansion here there ] compose [ ws: (charset " ^/") non-ws: (complement charset " ^/") macro-rule: make block! 2.5 * length? macros foreach [macro expansion] macros [ macro-rule: insert macro-rule compose [here: (macro) there: [ws | end] |] ] macro-rule: head remove back macro-rule parse/all data [some [any ws [ macro-rule ( macro: copy/part here there there: change/part here select/skip macros macro 2 there ) :there | some non-ws ]] to end] macro-rule: none data ] | |
Anton: 4-Oct-2006 | string: "<good tag><bad tag><other tag><good tag>" entity: "<ENTITY>" parse/all string [ any [ to "<" start: skip to ">" end: skip (if not find copy/part start end "good tag" [ change/part start entity 1 ; fix up END (for when your entity is other than a 1-character long string) end: skip end (length? entity) - 1 change/part end entity 1 ; fix up END again end: skip end (length? entity) - 1 ]) :end skip ] to end ] string ;== {<good tag><ENTITY>bad tag<ENTITY><ENTITY>other tag<ENTITY><good tag>} | |
Anton: 4-Oct-2006 | string: "<good tag><bad tag> 3 > 5 <other tag><good tag with something inside>" string: " > >> < <<good tag><bad tag> 3 > 5 <other tag><good tag etc> >> > " ; (1) search for end tags >, they are erroneous so replace them ; (2) search for start tags <, if there is more than one, replace all except the last one ; (3) search for end tag >, check tag body and replace if necessary entity: "&entity;" ntag: complement charset "<>" ; non tag parse/all result: copy string [ any [ ; (1) any [ any ntag start: ">" end: ( change/part start entity 1 end: skip start length? entity ;print [1 index? start] ) :end ] ; (2) (start: none stop?: none) any [ any ntag start: "<" end: ;(print [2 mold start]) any ntag "<" ( ;print "found a second start tag" change/part start entity 1 end: skip start length? entity ;(print [2.1 mold copy/part start end]) start: none ) :end ] (if none? start [stop?: 'break]) stop? ; ok, we found at least one start tag ;(print ["OK we found at least one start tag" mold start]) :start skip ; (3) any ntag end: ">" ;(print [3 mold copy/part start end]) (if not find copy/part start end "good tag" [ ;print ["found a bad tag" mold copy/part start end] change/part start entity 1 ; fix up END (for when your entity is other than a 1-character long string) end: skip end (length? entity) - 1 change/part end entity 1 ; fix up END again end: skip end (length? entity) - 1 ]) :end skip ] to end ] result | |
Maxim: 24-Dec-2008 | but, in R2, I'm not using it for some reason I don't remember... I actually use the change/part within a paren and manually set the series using the :here trick. | |
Oldes: 31-Jan-2009 | convert-input: func[input [string!] /local stops rest opened-tags b e][ probe input space: charset " ^-" stops: charset "-+^/" rest: complement stops opened-li?: false parse/all input [ some [ () ;<-- to be able escape from the parse loop if there is any infinite loop b: #"^/" e: ( if opened-li? [ e: change/part b "</li>^/" 1 opened-li?: false ] ) :e b: [ #"-" any space e: ( e: change/part b {<li class="minus">} e opened-li?: true ) | #"+" any space e: ( e: change/part b {<li class="plus">} e opened-li?: true ) ] :e | to #"^/" | end ] ] if opened-li? [ append input "</li>" ] input ] probe convert-input { - line 1 + line 2 + line 3 - line 4 + line 5} | |
Steeve: 16-May-2009 | Assuming SRC: contains the source text, it seems to work too: header-char: complement charset "^/:" EOL2: rejoin [newline newline] parse/all src [ some [ some [pos: #" " (change pos #"-") | header-char] #":" pos: newline (change/part pos " {" 1) [to EOL2 | to end] pos: (change pos "} ") skip skip ] ] probe construct to block! src | |
Steeve: 17-May-2009 | Right, i added skiping of useless newline. parse/all src [ some [ any newline some [pos: #" " (change pos #"-") | header-char] #":" pos: newline (change/part pos " {" 1) [to EOL2 | to end] pos: (change pos "} ") skip skip ] ] Could you figure it ? | |
Steeve: 2-Oct-2009 | it's a change/part which is performed | |
Pekr: 2-Oct-2009 | But change/part just tells you, how many chars you replace, no? mmnt | |
Pekr: 2-Oct-2009 | >> change/part s: "(1)" "(2222222)" 4 s == "(2222222)" | |
Steeve: 2-Oct-2009 | it's not behaving the same way, if it was the same, we would not have this difference: >> parse s: "(1)." [change "(1)" "(11)"] ?? s s: "(11)." >> head change "(1)." "(11)" == "(11)" In parse it's a change/part that is performed | |
Pekr: 2-Oct-2009 | >> head change/part "(1)." "(11)" 3 == "(11)." | |
Steeve: 2-Oct-2009 | yep a change/part not a simple change | |
Pekr: 2-Oct-2009 | You are right, it is most probably a bug: >> head change/part "(1)" "()" 3 == "()" >> parse s: "(1)" [change "(1)" "()"] s == "())" | |
BrianH: 2-Oct-2009 | Actually, Steeve, the behavior of parse's change does have to do with the behavior of change in normal code. That would be an error if the CHANGE/part function had that same behavior. It's a bug. | |
Geomol: 25-Oct-2009 | Another: >> out: parse "this-is-a-string" "-" >> forall out [change/part out rejoin [out/1 "-" out/2] 2] >> out == ["this-is" "a-string"] | |
Steeve: 13-Apr-2010 | Classical... ending: (ending: change/part start "mystring" ending) :ending | |
Ladislav: 13-Apr-2010 | Now, I can make a bold statement: for any method distinct from the one using PARSE and CHANGE/PART combo holds, that it is faster than the above method, until it's not :-p | |
Maxim: 13-Apr-2010 | its not a single change/part which is the issue, its managing the stack, allocating all those blocks over and over... the sheer speed of the parse loop, blows away all the other looped/recursive algorythms in my usage so far. | |
BudzinskiC: 14-Apr-2010 | And here I thought yesterday, wow I finally understood Parse and gosh it's awesome. And now I read change/part, which I used, is not the way to do things unless it is. I am confused! Generally, but also now specifically. | |
Pekr: 15-Apr-2010 | I think change/part is as fast as Rebol's change/part native, and hence usable, unless Ladislav proves such pov being somehow fundamentally wrong :-) | |
ChristianE: 16-Apr-2010 | Of course that has other semantics than >> head change/part "abc" take/part "123" 2 1 == "12bc" and may lead to new confusion. | |
Steeve: 17-Apr-2010 | it's true, 'change/part does not behave correctly by default. insert/part et append/part do the right thing we want now for change | |
ChristianE: 17-Apr-2010 | That's said too much; I think it's more that CHANGE/PART behaves as advertised and the /PART refinement just happens to have a different meaning for INSERT or APPEND. Neither one of /WITH, /TO, /SPAN and /RANGE communicate very well that they refer to the second argument though, and /TAKE has the drawback of suggesting that it's taking away from the second argument like TAKE instead of leaving the second argument untouched. CHANGE/FROM, however, seems to work: >> head change/from #abcdef #123456 3 == #123def >> head change/part/from #abcdef #12345 1 3 == #123bcdef All that under the assumption that for compatibility, /PART in it's current meaning will stay as it is. | |
BrianH: 17-Apr-2010 | It's funny, I always thought INSERT/part was the weird one, and CHANGE/part the normal one. Didn't stop me from adding /part to APPEND though, in the INSERT style. | |
Steeve: 19-Apr-2010 | Gregg, I used to use append/part to avoid the memory overhead of copy/part in many case. Instead of doing like in the Ladislav's example. >> change/part something copy/part something-else range part. I used to do. >> change/part something append/part clear #{} something-else range part. It's not faster, but saves memory. So, I don't know if it's a good idea to discard this use case from append and insert. | |
Group: !RebGUI ... A lightweight alternative to VID [web-public] | ||
Volker: 5-Jun-2005 | prebol: func [code "changes code" /local p f] [ parse code rule: [ any [ p: #include set f file! ( p: change/part p load f 2 ) :p | into rule | skip ] ] code ] ; changes code, use copy/deep if needed t1: now/precise save %test.r [The embedded stuff] p: prebol [Hello [World #include %test.r here] we are ] print[difference now/precise t1] | |
Volker: 5-Jun-2005 | prebol: func [code /local p f rule] [ if file? code [code: load code] parse code rule: [ any [ p: #include set f file! ( p: change/part p prebol load f 2 ) :p | into rule | skip ] ] code ] ; changes code, use copy/deep if needed t1: now/precise save %test.r [The embedded and #include %test2.r stuff] save %test2.r [Subembedded] p: prebol probe [Hello [World #include %test.r here] we are] print [difference now/precise t1 newline mold p] | |
Group: Rebol School ... Rebol School [web-public] | ||
Volker: 26-Jun-2007 | make the string without numbers, put the numbers in. with 'at, 'change/part ruler num length? num. | |
Maxim: 15-Apr-2010 | this prevents the copy... change/part s at s 5 2 | |
Ladislav: 19-Apr-2010 | Change/part for the n-th time. Did anybody expect this? >> tgt: "123456789" == "123456789" >> src: at tgt 5 == "56789" >> change/part tgt src 1 == "23456789" >> tgt == "5678923456789" | |
Group: rebcode ... Rebcode discussion [web-public] | ||
BrianH: 22-Oct-2005 | Change/part can be fast, especially if you what you are changing to is the same length. | |
BrianH: 28-Oct-2005 | First impression: - Yay! setw/getw, rotl/rotr, bswap, change = change/part, brab - I hadn't thought of those, but cool: ext8/ext16, break now breakt/breakf, making rebcode* now a field in system/internal - Questions: Haven't done the grand renaming yet? Rewrite getting rewritten? Does brab work yet (it crashed for me)? | |
Group: SQLite ... C library embeddable DB [web-public]. | ||
Ashley: 25-Mar-2006 | Replace the column-text block in the SQL function with: [( either direct [ [*column-text (sid) idx] ][ [ s: v: *column-text (sid) idx while [s: find s {""}] [change/part s "" 2] load v ] ] )] I've added this to the next build. | |
Group: !REBOL3-OLD1 ... [web-public] | ||
Geomol: 17-Aug-2007 | A little update from Alpha testing. Since last time, this happened: - POWER can now handle negative number and exponent - Some bugs fixed regarding: money!, path, VID crash, change/part, read, function and closure recursion crash, compose/deep - New dictionary! datatype (replacing hash!) - A lot is going on in the graphics, VID and DRAW groups - Ongoing work to get the test methods to perfection We're now on Alpha 49. | |
Steeve: 12-Mar-2009 | i make a proposal: Most of the times, we use the same rules several times on different data. reword should be able to not reconstruct the rules if so. I used the similiar tricks in some scripts, for example: map-chars: func [ {replace/all pair chars in a string} data [string!] values [block!] /local chars pos ][ ;** if the first value in values is a bitset, do not reconstruct the bitset unless bitset? chars: first values [ chars: make bitset! 256 forskip array 2 [append chars array/1] insert values chars ] pos: data values: next values while [pos: find pos chars][pos: change/part pos select/skip values first pos 2 1] data ] data: "Hello You" map-chars copy data values: [#"s" "SS" #"t" #"T"] ;** the second call is faster map-chars copy data values | |
BrianH: 3-Apr-2009 | load: func [ {Loads a file, URL, or string.} source [file! url! string! binary! block!] {Source or block of sources} /header {Includes REBOL header object if present. Preempts /all.} /next {Load the next value only. Return block with value and new position.} ; /library {Force file to be a dynamic library. (Command version)} ; /markup {Convert HTML and XML to a block of tags and strings.} /all {Load all values. Does not evaluate REBOL header.} /unbound {Do not bind the block.} /local data content val rst tmp ][ ; Note: Avoid use of ALL and NEXT funcs, because of /all and /next options content: val: rst: tmp: none ; In case people call LOAD/local ; Retrieve the script data data: case [ block? source [ ; Load all in block return map x source [apply :load [:x header next all unbound]] ] string? source [source] ; Will convert to binary! later binary? source [source] ; Otherwise source is file or url 'else [ ; See if a codec exists for this file type tmp: find find system/catalog/file-types suffix? source word! ; Get the data, script required if /header content: read source ; Must be a value, not unset case [ binary? :content [content] ; Assumed script or decodable string? :content [content] ; Assumed script or decodable header [cause-error 'syntax 'no-header source] block? :content [content] 'else [content: reduce [:content]] ] ; Don't LOAD/header non-script data from urls and files. ] ; content is data if content doesn't need copying, or none if it does ] ;print [1 "data type?" type? :data 'content true? :content] if string? :data [data: to-binary data] ; REBOL script is UTF-8 assert/type [data [binary! block!] content [binary! string! block! none!]] assert [any [binary? :data not header]] if tmp [ ; Use a codec if found earlier set/any 'data decode first tmp :data ; See if we can shortcut return the value, or fake a script if we can't case [ block? :data [if header [insert data val: make system/standard/script []]] header [data: reduce [val: make system/standard/script [] :data]] (to logic! unbound) and not next [return :data] ; Shortcut return any [next any-block? :data any-word? :data] [data: reduce [:data]] 'else [return :data] ; No binding needed, shortcut return ] assert/type [data block!] ; If we get this far ] ;print [2 'data mold to-string :data] if binary? :data [ ; It's a script unless find [0 8] tmp: utf? data [ ; Not UTF-8 cause-error 'script 'no-decode ajoin ["UTF-" abs tmp] ] ; Process the header if necessary either any [header not all] [ if tmp: script? data [data: tmp] ; Load script data ; Check for a REBOL header set/any [val rst] transcode/only data unless case [ :val = [rebol] [ ; Possible script-in-a-block set/any [val rst] transcode/next/error rst if block? :val [ ; Is script-in-a-block data: first transcode/next data rst: skip data 2 ] ; If true, val is header spec ] :val = 'rebol [ ; Possible REBOL header set/any [val rst] transcode/next/error rst block? :val ; If true, val is header spec ] ] [ ; No REBOL header, use default val: [] rst: data ] ; val is the header spec block, rst the position afterwards assert/type [val block! rst [binary! block!] data [binary! block!]] assert [same? head data head rst] ; Make the header object either val: attempt [construct/with :val system/standard/script] [ if (select val 'content) = true [ val/content: any [:content copy source] ] ] [cause-error 'syntax 'no-header data] ; val is correct header object! here, or you don't get here ; Convert the rest of the data if necessary and not /next unless any [next block? data] [data: rst: to block! rst] if block? data [ ; Script-in-a-block or not /next case [ header [change/part data val rst] ; Replace the header with the object not all [remove/part data rst] ; Remove the header from the data ] rst: none ; Determined later ] ] [rst: data] ; /all and not /header ] ; val is the header object or none, rst is the binary position after or none assert/type [val [object! none!] rst [binary! none!] data [binary! block!]] assert [any [none? rst same? head data head rst] any [val not header]] ;print [3 'val mold/all :val 'data mold/all :data "type?" type? :data] ; LOAD/next or convert data to block - block either way assert [block? data: case [ not next [ ; Not /next unless any [block? data not binary? rst] [data: to block! rst] data ] ; Otherwise /next block? data [reduce pick [[data] [first+ data data]] empty? data] header [reduce [val rst]] ; Already transcoded above binary? rst [transcode/next rst] ]] ; Bind to current global context if not a module unless any [ ; Note: NOT ANY instead of ALL because of /all unbound (select val 'type) = 'module ][ bind/new data system/contexts/current ] ;print [6 'data mold/all :data 'tmp mold/all :tmp] ; If appropriate and possible, return singular data value unless any [ all header next ; /all /header /next empty? data 1 < length? data ][set/any 'data first data] ;print [7 'data mold/all :data] :data ] | |
Ammon: 10-Apr-2009 | While I have your attention and I'm thinking about sorting I just thought I'd mention that I'm using the following work-around for the lack of /compare in sort: ; R3 /compare bug work around sort-compare: func [ blk ][ ; disorder the rows forskip blk 2 [change/part blk reduce [blk/2 blk/1] 2] ; sort em sort/skip/reverse blk 2 ; reorder the rows forskip blk 2 [change/part blk reduce [blk/2 blk/1] 2] blk ] | |
Steeve: 27-Sep-2009 | I came with something existing, and said: Now, how can i do this more rebolish... parse/case opcode [ any [ start: | "nn" end: (change/part start get-byte end) | "+d" end: (change/part start get-d end) | "e" end: (change/part start get-e end) | skip ] ] | |
Group: !REBOL3 ... [web-public] | ||
Geomol: 18-Feb-2010 | Yet another version, that works with nested blocks: flatten: func [block] [ forall block [ if block! = type? block/1 [ change/part block block/1 1 ] ] block ] >> flatten [1 [2 [hmm] 42 3] 4] == [1 2 hmm 42 3 4] | |
Gregg: 18-Feb-2010 | flatten: func [block [any-block!]] [ parse block [ any [block: any-block! (change/part block first block 1) :block | skip] ] head block ] | |
BrianH: 28-Feb-2010 | As parse rules go, it wouldn't be difficult. Try this: >> hex: charset [#"0" - #"9" #"a" - #"f" #"A" - #"F"] == make bitset! #{000000000000FFC07E0000007E} >> parse a: "paul%40tretbase.com" [any [to "%" [b: skip copy x 2 hex (b: change/part b to-char first debase/base x 16 3) :b | skip]]] a == "[paul-:-tretbase-:-com]" Now that is a modifying method, but it should be easy to adapt that to a copying method. | |
Group: Core ... Discuss core issues [web-public] | ||
BrianH: 28-Oct-2011 | It's a little better if you do this, but still not quite right: >> a: [[1] 2 [[3] [4]] [[5]]] forall a [change/part a first a 1] a == [1 2 [3] 4 [5]] ; should be [1 2 [3] [4] [5]] | |
BrianH: 28-Oct-2011 | The WHILE trick above needs the same CHANGE/part (whoops): >> b: [[1] 2 [[3] [4]] [[5]]] while [not tail? b] [either block? first b [b: change/part b first b 1] [++ b]] b: head b == [1 2 [3] [4] [5]] >> b: [[1] 2 [[3] [4]] [[5]]] while [not tail? b] [either block? first b [change/part b first b 1] [++ b]] b: head b == [1 2 3 4 5] |