Supression des lignes commentées

Liste des forums > Forum Core

Anonyme | 19:31 15/02/2006
Bonjour,
Une petite question complétement ouverte :
sur une lecture ligne à ligne d'un script Rebol (lignes: read/line %fichier.r), quel est le moyen le plus efficace de ne prendre en compte QUE les lignes non commentées, sachant qu'une ligne commentée peut prendre un seul ";" en début de ligne, mais qu'on peut avoir aussi les cas avec des espaces, tabulations, en nombre quelconques avant le signe ";" ?
(et extension au cas de ligne commencant par un caractère # comme pour Unix, // pour Js, etc )
===Philippe
reboltof | 09:19 16/02/2006
Le moyen le plus simple, à mon humble avis, est de lire le fichier après en avoir retiré toutes les lignes inutiles... et c'est justement ce que fait le préprocesseur %prerebol.r, dont le code est gracieusement mis à disposition dans le dernier SDK, et utilisable sans clef de licence...
Si tu préfères contràler toi-même l'output, le code est très simple:
foreach line read/lines %monfichier [
    if not find line ";" [print line]
]

Christophe Coussement
A la recherche de doc sur REBOL ? Visitez The REBOL Documentation Project sur http://rebdocproj.net
coccinelle | 10:31 16/02/2006
Sans faire une lecture ligne à ligne, tu peux utiliser load & save pour créer un fichier sans commentaires :
save/header %output.r next script: load/header %input.r first script
Mais ceci t'enlève tous les commentaires, y compris ceux en fin de ligne. Sinon un petit parse peut te donner un meilleur controle:
foreach line read/lines %monfichier [
    if parse line [[";" | "#" | "//"] to end][print line]
]
Il ne faut pas oublier que le parse d'un string sans le refinement /all exclut les espaces et les tabulations.
Marco.
Fugit tempus irreparabile (Virgile)
Philippe | 13:09 16/02/2006
All,
Merci des contributions. C'est toujours interessant de torturer un peu Rebol, et accessoirement nos neurones.
Xtof, ta solution était celle que j'utilisais quand je maîtrise le fichier en input, et comme je mets des commentaires en début de ligne, elle peut fonctionner. Mais le "Find " prend aussi les lignes pour lesquels le commentaire est en fin, par exemple :
ma-variable: none ; ceci est une variable importante
Donc, le find n'est pas assez restrictif.
Marco, j'ai eu exactement le même raisonnement. (Ouf ;-). (mais ce n'est pas super "naturel", et mériterait d'être un chtouille plus développé dans une doc, parce qu'on (j') oublie souvent le fonctionnement par défaut de parse.)
Voilà un fichier de test :
test
  
; test
   ;
	
		; test3
	a: make face []  ; à garder
# ceci est un autre type de commentaire
	 # ceci aussi 

et voilà la fonction qui teste s'il y un commentaire.
comment?: func [
    "Test if text is a code comment, return true or false"
    text 
	/custom var [string!] { for custom comment symbol }
	/local rules
	][
	rules: either custom [ head change [";" to end] :var ] [[";" to end]]
	either parse text rules  [ true ][ false]
]

Merci de cette petite réflexion.
===Philippe
Philippe | 14:37 16/02/2006
Re-salut,
Bon, j'en ai profité pour en faire un script sur la Library, histoire de voir si mon compte marchait encore.
===Philippe
coccinelle | 15:12 16/02/2006
Philippe,
J'avoue ne pas bien comprendre ton [head change [";" to end] :var] ni le either parse ...
Pourquoi ne pas simplifier ton code ainsi :
comment?: func [
    "Test if text is a code comment, return true or false"
    line [string!] {script line}
    /with symbol [string! char!] { for custom comment symbol }
][
    unless with [symbol: #";"]
    parse line [symbol to end]
]
Je préfère l'emploi du refinement /with qui se retrouve dans plusieurs fonctions mais tout cela n'est qu'une question de goût et moi j'avoue rechercher un code le plus simple possible.
Marco.
Fugit tempus irreparabile (Virgile)
Philippe | 16:15 16/02/2006
Marco,
J'oserais à peine dire que je recherche aussi de plus en plus un code concis, mais bon, ouch, j'ai quelques années de progression devant moi ;-)
Je n'avais pas pensé au "unless", c'est carrément plus astucieux comme cela.
Le "either parse.." venait du fait que j'avais fait des tests avec des chaines et des cas qui ne renvoyaient pas nécessairement strictement "true", et je n'ai pas changé après.
J'ai fait les modifs. Merci pour la leçon ;-))
===Philippe
DideC | 18:52 16/02/2006
Perso, je prèfère à la syntaxe Unless quelque chose comme ça.
symbol: any [symbol #";"]

... puisque 'symbol sera à 'none si /with n'est pas spécifié lors de l'appel de la fonction.
Ca à l'avantage, à la lecture du code, de montrer que l'on défini toujours 'symbol, même si c'est avec ça propre valeur.


Une remarque sur l'utilisation de 'find pour trouver les ";" : si il y a une chaine de texte dans la ligne avec un ";" à l'intérieur : ça va merder !!!!
De même, que donne vos diverses méthodes dans le cas suivant :
this is a code
; un commentaire
chaine: {il fait beau.
il fait chaud ; même très chaud.
; c'est un commentaire ou pas ;-)))
Bon au boulàt}

DideC
Anonyme | 09:42 17/02/2006
Salut,
Comme quoi une question anodine ....
Avec unless et any, la ligne 5 de ton exemple est détectée par comment? comme un commentaire , mais Didec, tu élargis le débat, parce que ma question initiale était sur une lecture ligne à ligne d'un fichier.
Et dans ce cas, l'input est la ligne, donc le contexte de blocs ou chaines multi-lignes n'est pas appréhendé, ce qui d'ailleurs n'est pas nécessairement une bonne chose.
Est-ce utopique (sans faire une usine à gaz) d'imaginer une fonction capable de trouver les commentaires en multi-lignes ? Genre :
; chaine: {
blabla
blabla
blabla
; <- piege
blabla
}
Ici "chaine" ne serait pas à évaluer. Cela suppose une lecture globale du fichier, la gestion des accolades, et parenthèses ouvrantes/fermantes et sans doute d'autres trucs auquels je ne pense pas.
===Philippe
johnatemps | 10:00 17/02/2006
la solution: réécrire un morceau d'interpréteur rebol... :-(
C'est pas que cela soit inintéressant, mais... cela a déjà été fait, non ?
prebol.r me semble un bon départ de travail.
---..--- JohnATemps ---..---
coccinelle | 10:23 17/02/2006
Didier, Philippe
J'ai hésité sur la forme any [...], mais j'ai trouvé utile de rappeler l'existence d'unless.
Tout à fait juste l'exemple qui va merder, effectivement, il ne faut plus faire un ligne à ligne, mais parser l'ensemble de la chaîne. Il faut aussi pouvoir traiter des chaines qui imbrique des paires de {} ou de "". Je ne crois pas nécessaire de traiter les pair de () mais peut-être que je me trompe :
this is a code
; un commentaire
chaine: {il fait beau.
il fait chaud ; {même très chaud.}
; c'est un "commentaire" ou pas ;-)))
Bon au boulàt}
Dans ce cas, le parse est à peine plus compliqué, y compris pour les commentaires multi-lignes:
decomment: func [
    "Remove all script line starting with a comment symbol, return the script without comment"
    script [string!] {script}
    /with symbol [string! char!] { for custom comment symbol }
    /local guillemet crochet thru-newline commentaire s e
][
    unless with [symbol: #";"]
    guillement: [
        "{" crochet
    |
        {"}
    |
        skip guillement
    ]
    crochet: [
        {"} guillement
    |
        "{" crochet
    |
        "}"
    |
        skip crochet
    ]
    thru-newline: [
        {"} guillement [thru newline | thru end]
    |
        "{" crochet [thru newline | thru end]
    |
        newline
    |
        end
    |
        skip thru-newline
    
    ]
    commentaire: [
        s: any [#" " | #"^-"] symbol thru-newline e: (remove/part s e) :s
    ]
    parse/all script: copy script [
        commentaire
    |
        any [
            {"} guillement
        |
            "{" crochet
        |
            newline commentaire
        |
            skip
        ]
    ]
    script
]
Exemple :
script: {
this is a code
; un commentaire
chaine: {il fait beau.
il fait chaud ; même "très" chaud.
; c'est un commentaire ou pas ;-)))
Bon au boulàt}
; chaine: { 
blabla
blabla
blabla
; <- piege
blabla 
} aussi supprimé
}
donne
>> decomment script
== {
this is a code

chaine: {il fait beau.
il fait chaud ; même "très" chaud.
Bon au boulàt}

}

Marco.
PS. C'est vrai qu'on réécrit une partie de l'interpréteur, mais c'est aussi amusant.
Fugit tempus irreparabile (Virgile)
coccinelle | 11:24 17/02/2006
Une des choses les plus difficiles avec le parsing, c'est à mon avis lorsque l'on parse un string contenant des structures imbriquées et que l'on veut produire un block contenant aussi une structure imbriquée. Un exemple tout simple :
    parse {... [ ... [ ... ] ... ...] ...} [... rules ...]
doit retourner :
    [... [ ... [ ... ] ... ...] ...] 
C'est un cas que j'ai rencontré avec le parsing du SQL pour sql-protocol.r mais je ne suis pas vraiment satisfait de la solution.
Marco.
Fugit tempus irreparabile (Virgile)
Philippe | 11:58 17/02/2006
re-salut,
Bon, chapeau bas, maître marco.
coccinelle a dit :

PS. C'est vrai qu'on réécrit une partie de l'interpréteur, mais c'est aussi amusant.

Tout à fait d'accord. Parfois (souvent ;-)), je me pose des questions à deux balles, en me disant "tiens, pourquoi cela marche comme cela ?" et à force de creuser la question, soit je retombe sur une évidence oubliée, soit je découvre un truc assez sioux, et là, il y a beaucoup de plaisir. Je ne sais pas comment dire : arriver sur une ligne de code bien ciselée, c'est un peu comme une oeuvre d'art. Il y a un càté "esthétique" en REBOL.
Et ce genre de discussion, je trouve çà super "éducatif".
===Philippe