parse-api.ss
(module parse-api mzscheme

  (require
   (lib "pretty.ss")
   (planet "ssax.ss" ("lizorkin" "ssax.plt" 1))
   (only (planet "sxml.ss" ("lizorkin" "sxml.plt" 1)) sxpath)
   (planet "xml.ss" ("jim" "webit.plt" 1 5)))

  (provide
   (all-defined))
  
  (define api
    (with-input-from-file "selenium-api.xml"
      (lambda () (ssax:xml->sxml (current-input-port) '()))))

  (define functions
    ((sxpath '(// function)) api))
  
  ;; struct function : string symbol (listof symbol)
  (define-struct function (name return-type params))

  (define (camelCase->scheme-case string)
    (regexp-replace* #rx"[A-Z]"
                     string
                     (lambda (str)
                       (string-append
                        "-"
                        (string-downcase str)))))

  (define (selenium-name->scheme-name str)
    (string->symbol (camelCase->scheme-case str)))
  
  (define (create-function name return-type params)
    (make-function name
                   (string->symbol return-type)
                   (map selenium-name->scheme-name params)))

  (define (return-type->converter return-type)
    (case return-type
      [(string) 'identity]
      [(boolean) 'boolean]
      [(|string[]|) 'string-array]
      [(number) 'string->number]
      [else (error (format "Unknown return type ~a" return-type))]))
     
  
  (define (function->scheme fn)
    `(define ,(selenium-name->scheme-name (function-name fn))
       (lambda (,@(function-params fn))
         ,(if (eq? 'void (function-return-type fn))
              `(send-command ,(function-name fn)
                             ,@(function-params fn))
              `(read-response
                (send-command ,(function-name fn)
                              ,@(function-params fn))
                ,(return-type->converter (function-return-type fn)))))))
  
  (define (parse-function fn)
    (xml-match fn
      [(function name: ,name
                 (return type: ,return-type ,ret-desc ...)
                 (param name: ,param-name ,desc ...) ...
                 (comment ,_ ...))
       (create-function name
                        return-type
                        (list param-name ...))]
      [(function name: ,name
                 (param name: ,param-name ,desc ...) ...
                 (comment ,_ ...))
       (create-function name "void" (list param-name ...))]))
  
  ;; parse-functions : sxml -> (listof function)
  (define (parse-functions functions)
    (map
     parse-function
     functions))

  (with-output-to-file "commands.scm"
    (lambda ()
      (map pretty-print
           (map function->scheme (parse-functions functions))))
    'replace)

  ;; This is for the provides line
  (with-output-to-file "command-names.txt"
    (lambda ()
      (map (lambda (name) (printf "   ~a~n" name))
           (map selenium-name->scheme-name
                (map function-name
                     (parse-functions functions)))))
    'replace)
  
  )