I thought this parsing would be simple
... 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="hel开发者_JAVA百科lo"/>
<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
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.
精彩评论