2010-03-17 6 views
1

... et je frappe le mur, je ne comprends pas pourquoi cela ne fonctionne pas (je dois être en mesure d'analyser soit la version single tag (terminé avec />) ou les 2 versions d'étiquette (se terminant par)):Je pensais que cette analyse serait simple

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 

Répondre

5

Dans ce cas, le problème n'est pas votre règle - c'est que votre « insérer après chaque changement d'étiquette modifie la position au point que vous faites l'insert .

À titre d'illustration:

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

L'insert est correct, mais après l'insertion, la règle d'analyse syntaxique est toujours en position 2, et avant où il y avait juste « d », il est maintenant « cd » et la règle échoue. Trois stratégies:

1) Intégrer le nouveau contenu:

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

2) Calculer la longueur du nouveau contenu et sauter:

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

3) Changer la position après la manipulation:

Numéro 2) serait le plus rapide dans votre cas, car vous savez que la longueur de votre chaîne est de 16:
>> probe parse str: "abd" ["ab" mark: (mark: insert mark "c") :mark "d"] probe str 
true 
"abcd" 
== "abcd" 
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: c'est la même règle que la vôtre avec juste [16 skip] ajouté.

+0

Merci beaucoup Chris pour ces réponses détaillées Je suis en train de progresser vraiment sur l'analyse :) –

+0

Mais évidemment, ne pas coder les longueurs de corde comme ça! Puisque le comportement par défaut d'un mot est de l'évaluer, vous pouvez faire * replacement: {Visible = "false"} * et ensuite * replacement-length: length? remplacement*. Utilisez le remplacement et la longueur de remplacement dans votre règle. Bien sûr, tout est basé sur l'hypothèse que l'utilisation d'un analyseur orienté non-DOM pour XML/HTML est une bonne idée, que je réitère, ce n'est pas ... :) – HostileFork

+0

+ 1 pour l'idée même de personnes faisant Rebol Q & A en dehors de AltME et R3 chat. Si d'autres personnes dans la communauté peuvent être invitées à se joindre au reste de la civilisation, cela ne ressemblera peut-être pas à une telle langue morte ... apportons-en d'autres sur SO. – HostileFork

Questions connexes