parse is implemented? Where can one see the implementation on github?{"Hello World"}{Hello World}{Company name "Hello World"}{Company name: "Hello World"}str: {"Hello World"}
parse str [remove {"} to end ]
probe strremove-quotes: function [str][
parse dst: copy str [
p-st: opt dbl-quote
some [not dbl-quote skip]
p-end: dbl-quote end
(if p-st/1 = dbl-quote [remove p-end remove p-st])
]
dst
]>> remove-quotes {"Hello World"}
== "Hello World"
>> remove-quotes {Company name "Hello World"}
== {Company name "Hello World"}
>> remove-quotes {"Hello World" Company name}
== {"Hello World" Company name}parse really not needed there:rem: function [str][if all [#"^"" = first str (index? find next str {"}) = length? str][replace/all str {"} ""] str]
rem {"Hello World"}
;== "Hello World"
rem {"Hello World" company}
;== {"Hello World" company}
rem {Company name "Hello World"}
;== {Company name "Hello World"}>> str: {"hello"} if all [#"^"" = first str #"^"" = last str][remove back tail remove str] str
== "hello"str: {"hello" wrong "world"} if all [#"^"" = first str #"^"" = last str][remove back tail remove str] str
== {hello" wrong "world}[remove back tail remove str] is better, yes.parse is not needed here :)>> parse s: {"hello" wrong "world"} [remove {"} to [{"} end] remove {"}] s
== {hello" wrong "world}
>> parse s: {"hello" wrong "world"} [remove {"} to [remove [{"} end]]] s
== {hello" wrong "world}remove :)Red ["24 Game"]
numbers: copy []
collect/into [loop 4 [keep random 9]] numbers
op: charset "*/+-"
valid-number: charset form numbers
valid-expression: [valid-number op valid-number op valid-number op valid-number]
explode: func [val /local c][
c: copy []
forall val [collect/into [keep val/1] c]
]
; allow spaces or no spaces in the expression with trim/all,
; but since Red throws invalid integer error without spaces, break the string
; back apart with explode, and then form it into a string with spaces.
; load that and feed it to math.
check-expression: does [
either parse trim/all e: ask "Enter expression: " valid-expression [
either 24 = math load form explode e ["You got it!"]["Not quite correct"]
][
"Invalid expression"
]
]
print ["Using the following numbers, enter an expression that equals 24:" numbers]
check-expressionUsing the following numbers, enter an expression that equals 24: 7 2 7 2 Enter expression: 7-2+7*2 == "Not quite correct"
>> 7 - 2 + 7 * 2 == 24
math so follow order of operaations toomasappend [] ... better?collect? it does the copy for you/intoop: charset "*/+-"
valid-expression: [valid-number op valid-number op valid-number op valid-number]
explode: func [val][
extract/into val 1 c: copy []
]
check-expression: does [
if "q" = e: ask "Enter expression: " [halt]
either parse trim/all e valid-expression [
either 24 = math load form explode e [print "You got it!"][print "Not quite correct"]
][
print "Invalid expression"
]
]
main: does [
numbers: collect [loop 4 [keep random 9]]
valid-number: charset form numbers
print [newline "Using the following numbers, enter an expression that equals 24:" numbers]
check-expression
]
forever [main]math obeysnumbers: collect [loop 4 [keep random 9]]
op: charset "*/+-"
n: charset form numbers
num: [keep n]
exp: [num some [op num]]
term: ["(" exp ")" | num]
formula: [collect [term any [op term]]]
explode: func [val][collect [forall val [keep val/1]]]
check-expression: does [
either attempt [(sort numbers) = (sort load form parse trim/all e: ask "Enter expression: " formula)] [
either 24 = do load form explode e ["You got it!"]["Not quite correct"]
][
"Invalid expression"
]
]
print ["Using the following numbers, enter an expression that equals 24:" numbers]
check-expressionUsing the following numbers, enter an expression that equals 24: 8 7 4 6 >> check-expression Enter expression: 8-7*4*6 == "You got it!" >> check-expression Enter expression: (8-7)*4*6 == "You got it!" >> check-expression Enter expression: 4*6 == "Invalid expression" >> check-expression Enter expression: 2*2*2*3 == "Invalid expression"
op: charset "*/+-"
num: [keep n]
exp: [num some [op num]]
term: ["(" exp ")" | num]
formula: [collect [term any [op term]]]
explode: func [val][
extract/into val 1 c: copy []
]
check-expression: does [
if "q" = e: ask "Enter expression: " [halt]
either parse trim/all e formula [
either 24 = math load form explode e [print "You got it!"][print "Not quite correct"]
][
print "Invalid expression"
]
]
main: does [
numbers: collect [loop 4 [keep random 9]]
n: charset form numbers
print [newline "Using the following numbers, enter an expression that equals 24 (pdmas):" numbers]
check-expression
]
forever [main]attempt; and comparison - to ensure each number is used and only those numbers are used.numbers: collect [loop 4 [keep random 9]]
num: charset form numbers
op: charset "*/+-"
expr: [num some [op num] | num]
term: ["(" expr ")" | num]
p1: [term op term op term op term] ; (7)*3+1-2
p2: [term op term op term] ; (7*3)+1-2
p3: [term op term] ; 7*(3+1-2)
p4: [term] ; (7*3+1-2)
valid-expression: [p1 | p2 | p3 | p4]>> numbers == [7 2 7 2] >> parse "7272" valid-expression == false >> parse "7+2+7+2" valid-expression == true >> parse "(7*2)+7+2" valid-expression == true >> parse "7*(2)+7+2" valid-expression == true >> parse "7*(2+7)+2" valid-expression == true >> parse "7*(2+7/2)" valid-expression == true >> parse "hello" valid-expression == false
>> parse "7+2+7+2" valid-expression == true >> parse "7+7+7+2" valid-expression == true >> parse "2+2+2+2" valid-expression == true >> parse "2+2" valid-expression == true >> parse "2" valid-expression == true >> parse "7" valid-expression == true >> parse "(7)" valid-expression == true
Red [
Title: "24 Game"
Note: "Math precedence rules, PMDAS"
]
op: charset "*/+-"
expr: [num some [op num] | num]
term: ["(" expr ")" | num]
; naming? or recursive way?
p1: [term op term op term op term] ; (7)*3+1-2
p2: [term op term op term] ; (7*3)+1-2
p3: [term op term] ; 7*(3+1-2)
p4: [term] ; (7*3+1-2)
valid-expression: [p1 | p2 | p3 | p4]
explode: func [val][
extract/into val 1 c: copy []
]
check-expression: does [
if "q" = e: ask "Enter expression: " [halt]
either parse trim/all e valid-expression [
either 24 = math load form explode e [print "You got it!"][print "Not quite correct"]
][
print "Invalid expression"
]
]
main: does [
numbers: collect [loop 4 [keep random 9]]
num: charset form numbers
print [newline "Using the following numbers, enter an expression that equals 24: (pmdas)" numbers]
check-expression
]
forever [main]; (7)*3+1-2 comments are just examples if the numbers generated were 7 3 1 2op: charset "*/+-"
expr: [num some [op num] | num]
term: [num | "(" expr ")"]
p1: [term op term op term op term]
p2: [term op term op term]
p3: [term op term]
valid-expression: [p1 | p2 | p3]
explode: func [val][
extract/into val 1 c: copy []
]
check-expression: does [
if "q" = e: ask "Enter expression: " [halt]
either parse trim/all e valid-expression [
either 24 = m: math to-block form explode e [
print ["You got it!" m]
][
print ["Not quite correct. That's" m]]
][
print "Invalid expression"
]
]
main: does [
numbers: collect [loop 4 [keep random 9]]
num: charset form numbers
print [newline "Using the following numbers, enter an expression that equals 24: (pmdas)" numbers]
check-expression
]
forever [main]Using the following numbers, enter an expression that equals 24: (pmdas) 8 7 4 6 Enter expression: 4*6 You got it! 24
[num op num op num op num], and "ignore any balanced paren along the way". math will take care of obeying the parens.term: [opt "(" num opt ")"]
valid-expression: [term op term op term op term]check-expressionmain: does [
numbers: collect [loop 4 [keep random 9]]
num: charset form numbers
print [newline "Using the following numbers, enter an expression that equals 24: (pmdas)" numbers]
if none? attempt [check-expression][print "Invalid expression"]
][btn: button]which the parse gives
res: parse [style btn: button "hello" 120x24] [
collect any [
'style
some [
some [ ahead () keep set-word! ] | ;-- needs () to work??
some [ ahead keep word! ]
]
| skip
]
]
? res
RES is a block! value. length: 2 [btn: button]>res: parse [style btn: button "hello" 120x24] [ collect any [ 'style ; some [ keep some set-word! | keep some word! ; ] | skip ] ] ? res
ahead ()blk: [style b1: button "hello" 120x24 b2: button] res: parse blk [collect [some [to set-word! keep thru word!]]]
btn: button if that's what you wanted. skip is needed, otherwise it may never reach style (in general case), or reach next style somewhere later.any and some in this case.SET-IN obj 'word in parse to write values in objects... this would save me lot of code in parens and also using temporary words.SET-IN, it is an important feature when you work initializing objects with parse.0x01 + KEYWORD sequences ending with 0x17. In the middle there is a string I want to change.BINARY-DATA 0X01 "NAME:" "<PRODUCT-NAME>" 0x17 0X01 "BATCH:" "<BATCH STRING NUMBER>" 0x17 0X01 "EXPIRE:" "<EXPIRE STRING DATE >" 0x17 BINARY-DATA
>> binary: to-binary "Hello Giuseppe!"
== #{48656C6C6F20476975736570706521}
>> parse binary reduce [to-binary "Hello" space quote s:] to-string s
== "Giuseppe!"string! or string! and block!parse reduce [integer! string!] [some datatype! end]get them and check for datatype or typeset valueparse file-content [
some [
tag (save-parent tag-name) | ahead chars copy tag-value to "<" ( do-operation-on-tags-tree-with-value tag-value ) | to "<"
]
]
]some iteration and see if there's something suspicious.to backtracks if it fails, which in worst case leads to time complexity ~ file-size^2some iteration and see if there's something suspicious.time-it, but how to wrap some with it?now/precise when you enter some to get the time and subtract the previous result from it.>> t1: now/precise == 18-Apr-2022/20:02:50.7804+03:00 >> >> >> t2: now/precise == 18-Apr-2022/20:02:54.1006+03:00 >> >> t1 - t2 == 0 >> >> t2 - t1 == 0
>> s: now/precise/utc == 18-Apr-2022/17:05:34.037 >> e: now/precise/utc == 18-Apr-2022/17:05:35.7549 >> difference e s == 0:00:01.71785
- just returns number of days, which is handy for calendar stuff onlysome [ (s: now/precise) <my parsing rules> (e: now/precise)]
time-it, and they works fast, but result file is parsing slowly in a block: inside attribute:list: [
{<ns1:foo bar="123" baz="2002-02-26" region="En">}
{<ns1:foo bar="123" baz="2002-02-26" region="En"/>}
{<foo bar="123" baz="2002-02-26" region="En"/>}
{<ns1:foo>}
{<foo x=1>}
{<foo x=2/>}
{<ns1:foo/>}
{<ns1:foo bar="123" baz="2002-02-26" region="En" baz="66:77">}
{<foo bar="123" baz="2002-02-26" region="En" baz="66:77">}
]
foreach tag-name list [
only-tag-name: rejoin parse tag-name [ collect [ keep "<" opt [thru ":"] keep to end ] ]
probe only-tag-name
]foreach tag-name list [
starting?: yes
only-tag-name: rejoin parse tag-name [ collect [keep "<" s: any [sp (starting?: no) :s keep to end | if (starting?) ":" keep to end | skip]]]
probe only-tag-name
]
{<foo bar="123" baz="2002-02-26" region="En">}
{<foo bar="123" baz="2002-02-26" region="En"/>}
{<foo bar="123" baz="2002-02-26" region="En"/>}
"<foo>"
"<foo x=1>"
"<foo x=2/>"
"<foo/>"
{<foo bar="123" baz="2002-02-26" region="En" baz="66:77">}
{<foo bar="123" baz="2002-02-26" region="En" baz="66:77">}parse "a" [any [| #"a"]] return true as it does for parse "a" [any [#"a"]]?parse "a" [ any [ | #"a" | #"b" ] ]
parse "a" [any [| #"a"]] to me that looks like something is missing. I think the other chat might be in red/bugs, but my thought in this moment is that it will lead to rules that are harder to reason about.>> parse [1] [collect any [keep some integer! | skip]] == [1] >> parse [1 1] [collect any [keep any integer! | skip]] == [[1 1]] ;=== why not just [1 1]?
>> parse [1 "a" 2 2 "b" 3] [collect any [keep some integer! | skip]] == [1 [2 2] 3]
pick. Is it supposed to work only with keep? If so, should not be this an error:>> parse [1 1] [any [pick | skip]] == true
pick is mentioned in [docs](https://github.com/red/docs/blob/master/en/parse.adoc#393-collect).>> parse [1 2 3][collect keep integer! collect keep integer! collect keep integer!] == [1 [2] [3]] ;<-- it would be more logical to have it [[1] [2] [3]]
collectcollect creates collection block, then it is only logical for all the rest to fall into this block. If you write it up with explicit block it is very clear:parse [1 2 3][collect [keep integer! collect keep integer! collect keep integer!]]
collect>> parse [1 2 3][collect [collect keep integer! collect keep integer! collect keep integer!]] == [[1] [2] [3]]
>> parse [1 2 3][collect [3 collect keep integer!]] == [[1] [2] [3]]
copy:>> parse [1 2 3][collect [3 keep copy _ integer!]] == [[1] [2] [3]]
>> parse [1 2 3][collect [keep integer! collect [keep integer! collect keep integer!]]] == [1 [2 [3]]]
collect/keep in parse is much more complex than I initially thought and have many edge cases.collect ... collect ... it's most likely one has forgotten to add the outer collect, hence the error would remind.>> parse [1 2 3][collect keep integer! collect [keep integer! collect keep integer!]] == [1 [2 [3]]]
keep pick (mentioned in the doc) should do? Because I don't see any difference:>> parse "ab" [collect [keep ("ab")]]
== ["ab"]
>> parse "ab" [collect [keep pick ("ab")]]
== ["ab"]
>> parse [] [collect [keep ([1])]]
== [[1]]
>> parse [] [collect [keep pick ([1])]]
== [[1]][1].>> parse [1 2][collect [keep 2 integer!]] == [[1 2]] >> parse [1 2][collect [keep pick 2 integer!]] == [1 2]
keep pick .. but there are no unit tests for it.to end is a rule!keep pick is there only to outline that it's a valid combokeep (which is not said there)>> parse [1][collect [keep pick ([x: 1 +]) keep integer!]] == [x: 1 + 1] ;== instead of current: [[x: 1 +] 1]
collect set in the inner collect be excluded from the upper result?>> parse [1 2][collect [collect keep skip]] == [[1]] >> parse [1 2][collect [collect set x keep skip]] == []
>> parse [1 2][collect [collect [set x keep skip]]] == [[1]] >> parse [1 2][collect [collect set x keep skip]] == []
>> parse [1 2][collect [collect set x keep skip]] == [[1]] >> x == [1]
collect [set x keep skip] and collect set x keep skip.x is different) So I expect this:>> parse [1 2][collect [collect set x keep skip]] == [[1]] >> x == [1] >> parse [1 2][collect [collect [set x keep skip]]] == [[1]] >> x == 1
x be different?>> parse [1 2][collect [set x collect keep skip]] == [[1]]
>> parse [1 2][collect [keep integer! collect set x keep skip]] == [1] >> x == [2]
set-rule to collect seems to ignore collect. And setting x seems also weird. Compare these >> parse [1][collect set x keep skip] == true >> x == [1] >> parse [1][collect copy x keep skip] == [1] >> x == [1]
>> parse [1][collect keep set x skip] == [1] >> x == 1 >> parse [1][collect keep copy x skip] == [[1]] >> x == [1]
>> parse [1 2][collect [keep integer! collect keep set x skip]] == [1 [2]] >> parse [1 2][collect [keep integer! collect keep copy x skip]] == [1 [[2]]]
>> a: "" parse to-binary "ah" [collect into a keep 2 skip] a
== "#{6168}"
>> a: "" parse to-binary "šo" [collect into a keep 2 skip] a
== "#{C5A1}">> a: #{} parse "1" [collect into a keep skip]
*** Script Error: PARSE - COLLECT INTO/AFTER expects a series! of compatible datatype>> a: [] parse to-binary "ahhaa!" [collect into a [some keep skip]] a == [97 104 104 97 97 33]
a as block and or string!2 rule <=> 2 2 rule is a special case of N M rule, which we could require to evaluate N times unconditionally, and then depending on advancement(^) in Parse? d: complement charset "\"
a: "+xx+ x\+y +yy+"
parse a [
some [
to [ d #"+" ] skip remove thru #"+" insert ("<s>")
to [ d #"+" ] skip remove thru #"+" insert ("</s>")
]
]
probe a
== "+xx<s> x\+y </s>yy<s>"(^) was in the bitset, it could return: == "xx x\+y yy">> a: "+xx+ x\+y +yy+" >> parse a [any ["\+" | change "+" "<s>" any ["\+" | not "+" skip] change "+" "</s>" | skip]] a == "<s>xx</s> x\+y <s>yy</s>
[... pos: if (head? pos) ...] though. A rule will fail unless pos is at it's head.parse solution is usually faster.parse-ctx: context [ datatypes: [any word!];<<<<--- need [any datatype!] specs: [word! ahead block! into datatypes] ] spec: [x [word!] y [integer!]] probe parse spec bind [ any specs ] parse-ctx
>> type? first [integer!] == word! >> type? first reduce [integer!] == datatype!
get the word at check for it as datatypehelp's source (specifically parse-func-spec), which reduces the type part of the spec (the block).map! and the construction syntax.. we can use something like:swap-map-cons: function[src [string!]][
bl: complement charset "[]"
pb: complement charset "()#"
cr: [#"[" any bl opt cr #"]"]
crn: [ any bl opt cr #"]"]
mr: [#"(" any pb opt tr #")"]
mrn: [ any pb opt tr #")"]
tr: [ any pb [
#"#" s: [
#"[" (s/1: #"(") crn s: (s/-1: #")")
| #"(" (s/1: #"[") mrn s: (s/-1: #"]")
| tr
]
]]
parse src [any tr]
src
]
print swap-map-cons {
#[none] #[f32! [1 3 4]] #[string! "aaa" 2]
#(x: 1 y: #(a: 2 b: #[true]))
#issue #{01}
#[integer!]
}#[..] or #(..) in comments/strings, than it is the most probably commented out code, which also need conversion. I don't think I would find a comment inside my construction value.charset "#(){}" you don't wanna mess things like that.gen-delims: charset ":/?#[]@" from red codebase#[none] in my tests.rule opt [rule reject]?rule not rule?>> rule: ['a integer!] == ['a integer!] >> parse [a 22 x x x x x b ] [rule opt [rule reject | skip]] == false >> parse [a 22 x x x x x a 33] [rule opt [rule reject | skip]] == false >>
b1: [a 1 x x] b2: [a 1 x x a 2] b3: [x a 1 x x b 2 z] b4: [a b x a 1 a c a a 2 x] f: func [b] [parse b [any [check any [check (return false) | skip] | skip]] true]
>> f b1 == true >> f b2 == false >> f b3 == true >> f b4 == false >> b4: [a b x a 1 a c a a 2.5 x] == [a b x a 1 a c a a 2.5 x] >> f b4 == true >> even? length? b4 == false >> even? length? b1 == true
parse returns or how to combine rules then>> rule: [thru ['a integer!]] >> parse [a 22 x x x x x b ] [rule not rule to end] == true >> parse [a 22 x x x x x a 33] [rule not rule to end] == false
thru approach is dangerous for me:[a 2 b c 2] must fail as I want to process values by couples, where the first is always a word and skip by 2.check: ['a integer!] f: func [b] [parse b [any [check any [check (return false) | skip] | skip]] true] >> f [a b] == true
>> f: func [b] [parse b [1 [check any [check (return false) | skip skip] | skip skip]]]
>> f [a 2 b 2] == true f [a x] == false
f [a x b x a 2] == false f [a x a 2 b x] == false
['a integer!] should always be present, on any position? Maybe this:f: function [b] [out: false parse b [some [check (if out [return false] out: true) | 2 skip | (out: false)]] out]
[x a 1 x]? Should it succeed?['a integer! ] it must always be there 1 time and no moref perform?split-words: func [ word [word! object!] /local out-data ] [ out-data: copy [] if object? word [ word: words-of word forall word [append out-data reduce [word/1 get word/1]] ] if word? word [ append out-data reduce [word get word] ] out-data ] check-key: func [ data [word! object! block!] check [block!] ] [ either any [word? data object? data] [ f split-words data check ] [ f data check ] ]
>> data: make object! [x: 22 c: 33 d: [a b c]] >> check-key data ['x integer!] == true >> check-key [a 88 x 22 d 33] ['x integer!] == true
p, below the x button?view [ p: panel 300x150 [ x: button "hello" [append p/pane layout/only [button "world"]] ] ]
x ;). Give it a different offset.flag: false same behavior: flag: false
parse "foo" [
some [
"fo"
(print "test")
if (flag) break
(print "here") ; not printing
]
]some loop or terminate all parsing?return from a function or break from the loop or throw into catch.loop 1 [
parse "foo" [
some [
"fo"
(print "test")
(if flag [break])
(print "here") ; not printing
]
]
]com.caucho.hessian.test.TestObject, corresponding #{636F6D2E63617563686F2E6865737369616E2E746573742E546573744F626A656374} ;4D = 'M'
;74 = 't'
;7A = 'z'
data: #{7201004D740022636F6D2E63617563686F2E6865737369616E2E746573742E546573744F626A6563745300065F76616C756549000000007A7A}
probe collect [
probe parse data [
thru #{720100} thru "M"
opt [
thru "t" [
; copy len skip 4 (keep to integer! len)
]
]
to end
]
]data: #{7201004D740022636F6D2E63617563686F2E6865737369616E2E746573742E546573744F626A6563745300065F76616C756549000000007A7A}
probe parse data [
thru #{720100} thru "M"
opt [
thru "t" [
copy len 2 skip (n: to-integer len) copy class-name n skip (probe to-string class-name)
]
]
]