World: r3wp
[Parse] Discussion of PARSE dialect
older newer | first last |
Gregg 13-Sep-2010 [5164] | And 'inner-inner-body. :-) |
Ladislav 13-Sep-2010 [5165x2] | yes, I wanted to have a FNII variable referring to a function having access to the CONTEXT-FNs context without being influenced directly by the context |
...and yet influencing what the CONTEXT-FN is actually doing | |
Gregg 13-Sep-2010 [5167] | It's another great example of bending REBOL to your will with a great deal of control. |
Ladislav 13-Sep-2010 [5168x2] | If I wanted to do it just in R2, it could have been simpler, but R3 is more picky about what it allows |
(in R2 you can directly modify the CONTEXT-FN, which is protected in R3) | |
Gregg 13-Sep-2010 [5170x2] | Does it look like I understand it, based on these comments? |
set 'use-rule func [ "Create a recursion and thread-safe parse rule with local variables. R2/R3 compatible." words [block!] "Local word(s) to the parse rule" rule [block!] "Parse rule" ] [ make object! [ ; Create a new function context. 'Inner-body refers to a function ; with access to CONTEXT-FN's context without being influenced ; directly by the context. spec: copy [/local] append spec words inner-body: func ['word] [inner-inner-body word] context-fn: func spec reduce [:inner-body first words] ; Bind the rule the caller gave us to the new context we just created. inner-inner-body: func [word] [bind/copy rule word] bound-rule: context-fn ; Now define the use rule. Because this is an "active" rule, ; with state we need to include some state variables used ; by the internal PARSE call ('pos and 'success). pos: none success: none inner-inner-body: func [word] [ ; If the parse of the rule succeeds, we set the parse position ; to the where the rule match ended, otherwise we don't change ; the parse position and use [end skip] to return a false ; result (for R2 compatibility). success: either parse pos [bound-rule pos: to end] [ [:pos] ] [ [end skip] ] ] set 'rule copy/deep [pos: (context-fn) success] ] rule ] | |
Ladislav 13-Sep-2010 [5172] | Quite precise, except for the fact, that SUCCESS and POS are mainly used to "transfer" the inner parse state to the "outer parse" |
Gregg 13-Sep-2010 [5173] | Thanks. I'll note that. I usually have to analyze your code bit by bit to understand it. :-) |
Ladislav 13-Sep-2010 [5174] | I am glad you added your notes. I hope you do not mind me using your comments to make the code more understandable for others? |
Gregg 13-Sep-2010 [5175x4] | I don't mind at all. :-) |
set 'use-rule func [ "Create a recursion and thread-safe parse rule with local variables. R2/R3 compatible." words [block!] "Local word(s) to the parse rule" rule [block!] "Parse rule" ] [ make object! [ ; Create a new function context. 'Inner-body refers to a function ; with access to CONTEXT-FN's context without being influenced ; directly by the context. spec: copy [/local] append spec words inner-body: func ['word] [inner-inner-body word] context-fn: func spec reduce [:inner-body first words] ; Bind the rule the caller gave us to the new context we just created. inner-inner-body: func [word] [bind/copy rule word] bound-rule: context-fn ; Now define the use rule. Because this is an "active" rule, ; with state we need to include some state variables used ; by the internal PARSE call ('pos and 'success). They are used to ; "transfer" the inner parse state to the "outer parse". pos: none success: none inner-inner-body: func [word] [ ; If the parse of the rule succeeds, we set the parse position ; to the where the rule match ended, otherwise we don't change ; the parse position and use [end skip] to return a false ; result (for R2 compatibility). success: either parse pos [bound-rule pos: to end] [ [:pos] ] [ [end skip] ] ] set 'rule copy/deep [pos: (context-fn) success] ] rule ] | |
Typos in comments. Just a minute. | |
set 'use-rule func [ "Create a recursion and thread-safe parse rule with local variables. R2/R3 compatible." words [block!] "Local word(s) to the parse rule" rule [block!] "Parse rule" ] [ make object! [ ; Create a new function context. 'Inner-body refers to a function ; with access to CONTEXT-FN's context without being influenced ; directly by the context. spec: copy [/local] append spec words inner-body: func ['word] [inner-inner-body word] context-fn: func spec reduce [:inner-body first words] ; Bind the rule the caller gave us to the new context we just created. inner-inner-body: func [word] [bind/copy rule word] bound-rule: context-fn ; Now define the use rule. Because this is an "active" rule, ; with state, we need to include some state variables used ; by the internal PARSE call ('pos and 'success). They are used to ; "transfer" the inner parse state to the "outer parse". pos: none success: none inner-inner-body: func [word] [ ; If the parse of the rule succeeds, we set the parse position ; to the point where the rule match ended, otherwise we don't ; change the parse position and use [end skip] to return a false ; result (for R2 compatibility). success: either parse pos [bound-rule pos: to end] [ [:pos] ] [ [end skip] ] ] set 'rule copy/deep [pos: (context-fn) success] ] rule ] | |
Ladislav 14-Sep-2010 [5179x3] | fine, I used your text, and added some more |
Brian, do you think, that a more "seamless" way how to do the above in parse shall be considered, or that this approach is good enough as it stands now? | |
Reposting the link: http://www.rebol.org/view-script.r?script=use-rule.r | |
Graham 14-Sep-2010 [5182x2] | Very useful ... |
( that was a pun :) ) | |
Pekr 15-Sep-2010 [5184x2] | hmm, I thought that in R3, parse variables are safe for recursion rules? |
ah, there was USE 1 (BrianH) and USE 2 proposal (Peta). USE 1 was assigned for implementation, but deferred along with LIMIT, OF, REVERSE and some other proposals ... | |
Ladislav 15-Sep-2010 [5186] | Pekr, there are no "parse variables", as far as I know. My above code was inspired by BrianH and USE2 |
Pekr 15-Sep-2010 [5187] | I know, but I reacted upon Carl's recent blog, and if Carl dares to use the incorrect terminology, then I can too, no? :-) This function is useful because PARSE rules often store data in variables which, depending on how you handle them, can be overwritten by rule recursion. (Which is done often in parsing.) |
Ladislav 15-Sep-2010 [5188] | parse rules often store data in variables is fine, but that does not mean, that there are "parse variables", those are just variables |
Pekr 15-Sep-2010 [5189] | ok, as for terminology, how do I refer to following: start: copy user to "</user>" :end (temp: find blk user) while the code is not real, I can see three different "variable types": - start: :end markers - user parse level variable? - temp: rebol level word? Thanks :-) |
Ladislav 15-Sep-2010 [5190x5] | Sorry if you find it nitpicking, but I wanted to point out, that an assumption that "parse variables are safe for recursion rules" should be wrong exactly because there are only variables in REBOL, which the interpreter does not have any reason to make "recursion safe" unless you specifically do something about it. |
Regarding the above "three different variable types" - as far as the interpreter is concerned, there is no difference between the 'start 'end and 'copy variables. You used them in a specific way, but, later, you can very well use another expression, where you write: user: copy start to "whatever" etc. So, you can easily see, that neither the 'start nor the 'user variable has any "variable type" you could infer based upon their usage in one specific expression. | |
err, I meant the 'start 'end and 'user variables | |
if you call 'temp a "rebol level variable" in the above example expression, how would you call it in the expression below? (temp: either 1 > 0 [none] [[end skip]]) temp | |
So, generally speaking, it may be useful for you to use some some variables only as "markers", but that "variable type" is something you impose just to make the things easy for you to handle. The interpreter does not (and should not) make such distinctions. | |
Pekr 15-Sep-2010 [5195] | temp is "rebol level variable", whose value is bound to parse dialect :-) |
Ladislav 15-Sep-2010 [5196x2] | Hmm, what does the "bound" word mean? |
As I said, you can use some variables for specific purposes only, but that is your decision, and is not supported by any interpreter property, and certainly is not useful for all purposes. I may want to use some variables in more "roles" than you want to. | |
Pekr 15-Sep-2010 [5198x2] | hmm, then maybe not. Temp following the paren simply refers to the rule, resulting from previous paren expression evaluation .... |
and hence is probably a regular rebol level word, just used inside the parse dialect? | |
Ladislav 15-Sep-2010 [5200] | In my opinion, all of the above 'start 'end 'user and 'temp words are "regular" REBOL words, while e.g. the 'copy word above is actually a parse dialect keyword |
Pekr 15-Sep-2010 [5201x2] | corret ... |
and - it was not nitpicking on your part - using the correct terminology where possible is important, as it helps to correctly interpret the way in which the language works. It is just lack of knowledge on my part, that I confuse the terms ... exactly because I often don't understand the internals ... | |
Izkata 15-Sep-2010 [5203] | start: :end and temp: would just be called set-words and get-words, either within the Parse dialect or the Do dialect (Do dialect being "rebol level") |
Anton 15-Sep-2010 [5204] | To be even more precise; The 'copy word above is also a "regular" rebol word (it just happens, additionally, to be interpreted by PARSE as a keyword in the PARSE dialect). |
Ladislav 15-Sep-2010 [5205] | Re start: and :start e.g. - they are values of different datatypes, but can be seen as just one variable. |
Ladislav 16-Sep-2010 [5206] | http://www.rebol.org/view-script.r?script=use-rule.rupdated. Changes: now it implements both USE-RULE variants as described in http://www.rebol.net/wiki/Parse_Project . |
Ladislav 18-Sep-2010 [5207x6] | Hi, I rewrote http://www.fm.tul.cz/~ladislav/rebol/evaluate.rto contain slightly more comments and to use the USE-RULE function, so that it now became a more complex example of its usage. |
I hope everyone struggling with local variables in PARSE to find this a much more comfortable way. | |
On the other hand, I expect the %evaluate.r to have a value of its own, since it shows how to handle expressions using PARSE, while being able to respect different priority/associativity rules sets. | |
The funny thing about it is, that just one local variable per parse rule was quite sufficient in this case, although the example isn't trivial in my opinion. | |
http://en.wikibooks.org/wiki/REBOL_Programming/Language_Features/Parse#Local_variables_in_parse_rules , a new subsection in the REBOL Programming wikibook. | |
http://en.wikibooks.org/wiki/REBOL_Programming/Language_Features/Parse#Local_variables_in_parse_rules a new section in the REBOL Programming wikibook | |
Janko 18-Sep-2010 [5213] | wowo, most awesome Ladislav! |
older newer | first last |