Я думал, что этот анализ будет простым - PullRequest
1 голос
/ 17 марта 2010

... и я бью стену, я не понимаю, почему это не работает (мне нужно иметь возможность анализировать либо версию с одним тегом (завершается с />), либо версии с 2 тегами ( прекращено с)):

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

1 Ответ

5 голосов
/ 18 марта 2010

В этом случае проблема не в вашем правиле, а в том, что ваша вставка после каждого изменения тега меняет положение в той точке, где вы выполняете вставку.

Для иллюстрации:

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

Вставка верна, но после вставки правило синтаксического анализа все еще находится на позиции 2, а перед тем, где было только "d", теперь есть "cd" и правило не выполняется. Три стратегии:

1) Включить новый контент:

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

2) Рассчитайте длину нового контента и пропустите:

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

3) Измените положение после манипуляции:

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

Номер 2) будет самым быстрым в вашем случае, поскольку вы знаете, что длина вашей строки равна 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
]

Примечание: это то же правило, что и у вас, только с добавленным [16 skip].

...