r3wp [groups: 83 posts: 189283]
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

World: r3wp

[Parse] Discussion of PARSE dialect

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!
Ladislav
18-Sep-2010
[5214x2]
Pekr, knowing that you were interested in the subject as well, I 
sincerely hope, that you read the wikibook subsection, run the examples, 
and let me know what you are missing in the doc and in the functionality.
thanks, Janko
Claude
20-Sep-2010
[5216]
hi, i would you to parse a string like this {number: 123456 name: 
abcd message: i like rebol}