2017-02-10 1 views
1

J'essaie d'analyser une région "récapitulative" d'un ensemble de rapports d'ordinateur, où les noms de rapports et leurs variables associées changent de fichier en fichier. Je donne un composé exemple suivant le format ci-dessous:TXR: Analyse des rapports récapitulatifs contenant unicode avec une syntaxe plus compliquée à l'aide des fonctions

Summary Report 


     Bath Tub 

    Temperature: 30 °C  

    Water ready     
     volume: 200000 cm³ 


    Bath Room 

    Floor Area: 40 ft²  

    Door Height: 9 ± 0.1 ft 



Full Report Set 

Il est difficile de voir de ce qui précède que l'espace blanc ressemble, alors voici une capture d'écran de mon éditeur de texte avec un espace blanc visible.

dummy report summary file screenshot

la région d'intérêt commence par Summary Report et se termine par Full Report Set. Les propriétés peuvent potentiellement s'étendre sur deux lignes. Les noms de propriété sont alignés de telle sorte que les deux-points : restent à la même position de caractère dans chaque sous-rapport. A partir de la sortie de diagnostic, il semble que ma tentative d'exploiter ce fait ne fonctionne pas.

TXR: (src/generic-Micromeritics-report.txr: 36) non-concordance chr (position 11 par rapport à k) TXR: (src/generic-Micromeritics-report.txr: 36) de liaison non-concordance variable k (13 vs. 12) txr: (src/generic-micrometrics-report.txr: 36) incompatibilité chr (position 12 vs k) txr: (src/generic-micrometrics-report.txr: 36) chaîne appariée, position 13-18 (data/dummy-generic-report.txt: 6) txr: (src/generic-micrometrics-report.txr: 36) Température: 30 ° C
txr: (src/generic-micrometrics-report .txr: 36)^^ txr: (src/generic-micrometrics-report.txr: 23) spec épuisé de données txr: (emplacement source n/a) fonction (capture (néant (k. 13) (rapport "Baignoire"))) a échoué

J'ai inclus le code ci-dessous. Pouvez-vous expliquer pourquoi ce code ne fonctionne pas? Est-ce que je fais ce que je pense faire avec la fonction colon_position? Si oui, pourquoi échoue-t-il? Comment écririez-vous la fonction capture? Est-ce l'approche générale que vous adopteriez? Y a-t-il un meilleur moyen? Merci beaucoup pour votre aide et vos conseils.

@; This output format always starts with or ends with atleast 2 blank spaces. 
@; Fully blank spaced lines follow each property value pair line. 
@(define blank_spaces) 
    @/[ ]+/@(eol) 
@(end) 
@; All colons align at the same column position within the body of a report. 
@; If that doesn't happen, that means there is nothing to capture, 
@; which shouldn't happen. 
@; This function should bind the appropriate position without updating 
@; the line position. 
@; Reports end when there is an empty line, so don't look past that. 
@(define colon_position (column)) 
@(trailer) 
@(gather :vars (column)) 
@(skip)@(chr column):@(skip) 
@(until) 

@(end) 
@(end) 
@; Capture values for a property. Values are always given on a single line. 
@; If there is error information, it will be indicated by a ± character.#\x00B1 
@(define capture (value error units)) 
@(cases)@[email protected]\ ±@\ @[email protected]\ @[email protected]/[ ]+/@(eol)@\ 
@(or)@[email protected]\ @[email protected]/[ ]+/@(eol)@(bind error "")@\ 
@(end) 
@(end) 
Summary Report 

@(collect :vars (report property value error units)) 

@report 

@(forget k) 
@(colon_position k) 
@(cases) 
@[email protected](chr k): @(capture value error units)@(blank_spaces) 
@(ord) 
@; Properties can span two lines. I have not seen any that span more. 
@[email protected](chr k)  @(blank_spaces) 
@[email protected](chr k): @(capture value error units)@(blank_spaces) 
@(merge property property_head property_tail) 
@(cat property " ") 
@(end) 
@(blank_spaces) 
@(end) 


Full Report Set 
@(output) 
report,property,value,error,units 
@(repeat) 
@report,@property,@value,@error,@units 
@(end) 
@(end) 

Répondre

1

Après avoir fait quelques changements ici et là, je reçois maintenant cette sortie:

report,property,value,error,units 
Bath Tub,Temperature,30,,°C 
Bath Tub,Water ready volume,200000,,cm³ 
Bath Room,Floor Area,40,,ft² 
Bath Room,Door Height,9,0.1,ft 

code:

@; This output format always starts with or ends with atleast 2 blank spaces. 
@; Fully blank spaced lines follow each property value pair line. 
@(define blank_spaces)@\ 
@/[ ]*/@(eol)@\ 
@(end) 
@; All colons align at the same column position within the body of a report. 
@; If that doesn't happen, that means there is nothing to capture, 
@; which shouldn't happen. 
@; This function should bind the appropriate position without updating 
@; the line position. 
@; Reports end when there is an empty line, so don't look past that. 
@(define colon_position (column)) 
@ (trailer) 
@ (gather :vars (column)) 
@ (skip)@(chr column):@(skip) 
@(until) 

@(end) 
@(end) 
@; Capture values for a property. Values are always given on a single line. 
@; If there is error information, it will be indicated by a ± character.#\x00B1 
@(define capture (value error units))@\ 
    @(cases)@[email protected]\ ±@\ @[email protected]\ @units @(eol)@\ 
    @(or)@[email protected]\ @[email protected]/[ ]+/@(eol)@(bind error "")@\ 
    @(end)@\ 
@(end) 
Summary Report 

@(collect :vars (report property value error units)) 

@report 

@ (colon_position k) 
@ (collect) 
@ (cases) 
@[email protected](chr k): @(capture value error units)@(blank_spaces) 
@ (or) 
@; Properties can span two lines. I have not seen any that span more. 
@[email protected](chr k)  @(blank_spaces) 
@[email protected](chr k): @(capture value error units)@(blank_spaces) 
@  (merge property property_head property_tail) 
@  (cat property " ") 
@ (end) 
@ (until) 


@ (end) 
@(until) 
Full Report Set 
@(end) 
@(output) 
report,property,value,error,units 
@ (repeat) 
@ (repeat) 
@report,@property,@value,@error,@units 
@ (end) 
@ (end) 
@(end) 

Le truc avec le côlon fonctionne réellement (belle application de trailer et chr). Où le code est déclenché est divers petits détails. Faute d'orthographe @(or) comme @(orf), les fonctions de modèle qui devraient être horizontales ne pas utiliser les suites correctes @\ de ligne, et l'inexactitude dans le @(blank_spaces) l'obligeant à consommer des espaces inconditionnellement, les espaces parasites avant @(merge) et tels.

En outre, le problème principal est que les données sont doublement imbriquées, nous avons donc besoin d'une collecte au sein d'une collecte. Nous avons également besoin de modèles de terminaison @(until) appropriés. Pour la collecte interne, j'ai choisi deux lignes vides; cela semble être ce qui met fin aux sections (cela fonctionne pour l'échantillon de données). La collecte externe est terminée sur le Full Report Set, mais ce n'est pas strictement nécessaire.Pour aller avec la collection imbriquée, nous utilisons une répétition imbriquée dans la sortie.

J'ai appliqué une indentation. Les fonctions horizontales peuvent utiliser l'indentation des espaces car les espaces blancs après les suites de ligne sont ignorés. Le @(forget k) est parti; il n'y a pas k dans la portée là. Chaque itération de la collecte environnante liera à nouveau k dans un environnement dépourvu de k.


Addendum: voici un diff par rapport au code pour le rendre plus robuste contre les données inattendues. Comme c'est le cas, le @(collect) interne ignorera silencieusement les éléments non concordants, ce qui signifie que si le fichier contient des éléments qui ne sont pas conformes aux cas prévus, ils seront ignorés. Ce comportement est déjà utilisé: c'est la raison pour laquelle les lignes vides entre les éléments de données sont ignorées. Nous pouvons resserrer cela avec :gap 0 (les régions collectées doivent être consécutives) et manipuler les lignes vides comme un cas. Un scénario de secours peut alors diagnostiquer une ligne d'entrée comme non reconnue:

diff --git a/extract.txr b/extract.txr 
index 8c93d89..3d1fac6 100644 
--- a/extract.txr 
+++ b/extract.txr 
@@ -24,6 +24,7 @@ 
    @(or)@[email protected]\ @[email protected]/[ ]+/@(eol)@(bind error "")@\ 
    @(end)@\ 
@(end) 
[email protected](name file) 
    Summary Report 

@(collect :vars (report property value error units)) 
@@ -31,7 +32,7 @@ 
    @report 

@ (colon_position k) 
[email protected] (collect) 
[email protected] (collect :gap 0) 
@ (cases) 
    @[email protected](chr k): @(capture value error units)@(blank_spaces) 
@ (or) 
@@ -40,6 +41,12 @@ 
    @[email protected](chr k): @(capture value error units)@(blank_spaces) 
@  (merge property property_head property_tail) 
@  (cat property " ") 
[email protected] (or) 
+ 
[email protected] (or) 
[email protected]  (line ln) 
[email protected]  badline 
[email protected]  (throw error `@file:@ln unrecognized syntax: @badline`) 
@ (end) 
@ (until) 
+0

Comment rendre les fonctions horizontales plus robustes? Y at-il un moyen de lancer des exceptions avec eux? – wdkrnls

+0

@wdkrnls Oups, quelqu'un a-t-il oublié une version horizontale de '@ (throw)'? Cela peut être fait avec une expression '@ (do (throw' sym args ...)) 'Lisp comme une solution de contournement plus verbeuse. De plus '@ (assert ...)' peut être utilisé à la place de 'throw' dans certaines situations. – Kaz

+1

Je l'ai corrigé maintenant, mais il manque encore des choses dans le domaine horizontal, comme try/catch et blocks. – Kaz