0

This works fine:

(sxml-match '(div)
  ((div) #t))

But this fails:

(sxml-match '(div)
  ((,element) #t))

I am wondering how to match any element?


This is a more concrete example. The following is a snippet from the XCB's "xproto.xml" file:

(define xproto '((struct (@ (name "CHAR2B"))
                         (field (@ (type "CARD8") (name "byte1")))
                         (field (@ (type "CARD8") (name "byte2"))))
                 (xidtype (@ (name "WINDOW")))
                 (xidtype (@ (name "PIXMAP")))
                 (xidtype (@ (name "ATOM")))
                 (xidunion (@ (name "DRAWABLE"))
                           (type "WINDOW")
                           (type "PIXMAP"))))

My aim is to extract the names:

(define names '((struct "CHAR2B")
                (xidtype "WINDOW")
                (xidtype "PIXMAP")
                (xidtype "ATOM")
                (xidunion "DRAWABLE")))

So I tried this:

(sxml-match xproto ((,kind (@ (name ,name)) . ,body) ...))

But I get the error:

bad pattern syntax (not an element pattern)

I do not understand what else I should do.

Is sxml-match an insufficient tool for this job?

ceving
  • 21,900
  • 13
  • 104
  • 178

2 Answers2

0

From the Backus-Naur form it follows, doing (,div) is not syntactically correct. This matches only the element-pattern left symbol and is waiting for a tag-symbol in the car position. But it is correct to do (sxml-match '(div) (,element 10)), as this matches the pat-var-or-cata rule for a node. So it is a syntax error to do (,something) then, because ,something matches only pat-var-or-cata rule.

These rules look very similar to the prepossessing syntax made via some kind of unification.

UPDATE for your example:

I added a constant @ respectively ww for the first 2 levels of nesting on the CAR position, otherwise I do not know if it works.

(define xproto '(@
            (ww struct (@ (name "CHAR2B"))
                (field (@ (type "CARD8") (name "byte1")))
                (field (@ (type "CARD8") (name "byte2"))))
            (ww xidtype (@ (name "WINDOW")))
            (ww xidtype (@ (name "PIXMAP")))
            (ww xidtype (@ (name "ATOM")))
            (ww xidunion (@ (name "DRAWABLE"))
                (type "WINDOW")
                (type "PIXMAP"))))

 (sxml-match xproto
             ((@ (ww ,t . ,d) ...) (list "???" t))
             (,otherwise "no match"))

 (sxml-match xproto
             ((@ (ww (@ (name ,t)) . ,d) ...) (list "???" t))
             (,otherwise "no match"))

You can zip the results of these 2 expressions to get it.

alinsoar
  • 15,386
  • 4
  • 57
  • 74
  • I am still not sure, how to work around this problem. Is `sxml-match` the wrong tool for my task? – ceving Dec 18 '22 at 19:22
  • @ceving I updated. This is the best I could write, as I am not expert in syntax rules. For sure you can improve it but I do not think it will be possible to match the CAR of a list using a variable name. – alinsoar Dec 19 '22 at 01:26
0

You have to include the specific element and attribute names to match and extract information from; they have to be hard coded and can't be variable. But since you know the DTD and thus the document's structure, you know what needs to be matched. It's just tedious. A named catamorphism can help keep things structured:

(define (get-names xproto)
  ; match a single struct/xidtype/xidunion element and return
  ; which element and its name attribute
  (define (struct/xid x)
    (sxml-match x
     ((struct (@ (name ,name)) . ,rest) (list 'struct name))
     ((xidtype (@ (name ,name))) (list 'xidtype name))
     ((xidunion (@ (name ,name)) . ,rest) (list 'xidunion name))))
  ; Match a nodeset of 0 or more struct/xidtype/xidunion elements
  (sxml-match xproto
   ((list ,(struct/xid -> element+name) ...)
    `(,element+name ...))))

returns ((struct "CHAR2B") (xidtype "WINDOW") (xidtype "PIXMAP") (xidtype "ATOM") (xidunion "DRAWABLE")) for your example data.


The documentation says the catamorphism function can return multiple values that can be bound to multiple ids, but my attempts to do so kept raising errors (Multiple values/ids and ... don't seem to play well together), so this just returns lists.

Shawn
  • 47,241
  • 3
  • 26
  • 60
  • Yes I had this before, but I tried to get rid of the redundancy. – ceving Dec 20 '22 at 08:40
  • For this to work the OP needs to write an exhaustive list of tags from the CAR position. BTW. On the CAR position one must not have a variable name. This is the same as in Prolog, where the first position needs to contain a fixed operator, in order for the unification to work, but I think there are other logic programming languages where it is possible to unify in the first position some variable. What is the reason they do not allow variable in the CAR position in scheme ? Maybe for the unification to be able to be indexed and optimized ? – alinsoar Dec 20 '22 at 12:10
  • @alinsoar *For this to work the OP needs to write an exhaustive list of tags from the CAR position.* Yes, that's what I said in my first paragraph. Matching specific sxml nodes with given layouts is the whole point of `sxml-match`. It's not a generic list destructure-and-bind macro. – Shawn Dec 20 '22 at 12:19