开发者

I thought this parsing would be simple

开发者 https://www.devze.com 2022-12-23 10:06 出处:网络
... 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 ) ):

... 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.

0

精彩评论

暂无评论...
验证码 换一张
取 消