tags:

views:

88

answers:

1

... and I'm hitting the wall, I don't understand why this doesn't work (I need to be able to parse either the single tag version (terminated with />) or the 2 tag versions (terminated with ) ):

Rebol[]

content: {<pre:myTag      attr1="helloworld" attr2="hello"/>
<pre:myTag      attr1="helloworld" attr2="hello">
</pre:myTag>
<pre:myTag      attr3="helloworld" attr4="hello"/>
}

spacer: charset reduce [#" " newline]
letter: charset reduce ["ABCDEFGHIJKLMNOPQRSTUabcdefghijklmnopqrstuvwxyz1234567890="]

rule: [

any [
{<pre:myTag} 
any [any letter {"} any letter {"}] mark: 
(print {clipboard... after any letter {"} any letter {"}} write clipboard:// mark input)
any spacer mark: (print "clipboard..." write clipboard:// mark input) ["/>" | ">" 
any spacer </pre:myTag>
]
any spacer
(insert mark { Visible="false"}) 
]
to end

]

parse content rule
write clipboard:// content
print "The end"
input
+2  A: 

In this case, the problem isn't your rule - it's that your 'insert after each tag changes alters the position at the point you do the insert.

To illustrate:

>> probe parse str: "abd" ["ab" mark: (insert mark "c") "d"] probe str
false
"abcd"
== "abcd"

The insert is correct, but after the insert, the parse rule is still at position 2, and before where there was just "d", there is now "cd" and the rule fails. Three strategies:

1) Incorporate the new content:

>> probe parse str: "abd" ["ab" mark: (insert mark "c") "cd"] probe str
true
"abcd"
== "abcd"

2) Calculate the length of the new content and skip:

>> probe parse str: "abd" ["ab" mark: (insert mark "c") 1 skip "d"] probe str
true
"abcd"
== "abcd"

3) Change the position after the manipulation:

>> probe parse str: "abd" ["ab" mark: (mark: insert mark "c") :mark "d"] probe str 
true
"abcd"
== "abcd"

Number 2) would be the quickest in your case as you know your string length is 16:

rule: [
    any [
        {<pre:myTag} ; opens tag

        any [ ; eats through all attributes
            any letter {"} any letter {"}
        ]

        mark: ( ; mark after the last attribute, pause (input)
            print {clipboard... after any letter {"} any letter {"}}
            write clipboard:// mark
            input
        )

        any spacer mark: ; space, mark, print, pause
        (print "clipboard..." write clipboard:// mark input)

        [ ; close tag
            "/>"
            |
            ">" any spacer </pre:myTag>
        ]

        any spacer ; redundant without /all

        (insert mark { Visible="false"})
        16 skip ; adjust position based on the new content
    ]

    to end
]

Note: this is the same rule as yours with just [16 skip] added.

rgchris
Great Many Thanks Chris for these detailed answers I'm now really progressing on parse :)
Rebol Tutorial
But obviously, do not hardcode string lengths like that! Since parse's default behavior for a word is to evaluate it, you can make *replacement: { Visible="false"}* and then *replacement-length: length? replacement*. Use replacement and replacement-length in your rule. Of course that's all on the assumption that using a non-DOM oriented parser for XML/HTML is a good idea, which I will reiterate it is not... :)
Hostile Fork
Hostile Fork
HFork: there is also the mailing list populated by much the same people.
rgchris