(define (parse-duckyscript input) (define blank '(+ ("\t\v "))) (define number '(+ numeric)) (define string '(+ nonl)) (define comment-cmd `(: (=> cmd "REM") ,blank (=> comment ,string))) (define default-delay '((=> cmd "DEFAULT") (? "_") "DELAY")) (define default-delay-cmd `(: ,@default-delay ,blank (=> default-delay ,number))) (define delay-cmd `(: (=> cmd "DELAY") ,blank (=> delay ,number))) (define string-cmd `(: (=> cmd "STRING") ,blank (=> string ,string))) (define repeat-cmd `(: (=> cmd "REPEAT") ,blank (=> repetitions ,number))) (define mod '(or "WINDOWS" "GUI" "MENU" "APP" "SHIFT" "ALT" "CONTROL" "CTRL")) (define key '(+ (or upper numeric #\_))) (define char '(~ #\space)) (define shortcut-cmd `(: (=> modifiers (* (: ,mod (? ,blank)))) (=> key-or-char (? (or ,key ,char))))) (define command-rx `(: (or ,comment-cmd ,default-delay-cmd ,delay-cmd ,string-cmd ,repeat-cmd ,shortcut-cmd))) (define (to-lower s) (list->string (map char-downcase (string->list s)))) (define (non-blank-string s) (if (zero? (string-length s)) #f s)) (define (parse line) (define $ irregex-match-substring) (let ((m (irregex-match command-rx line))) (if m (let ((command ($ m 'cmd))) (case (and command (string->symbol (to-lower command))) ((rem) `(comment ,($ m 'comment))) ((default) `(default-delay ,(string->number ($ m 'default-delay)))) ((delay) `(delay ,(string->number ($ m 'delay)))) ((string) `(string ,($ m 'string))) ((repeat) `(repeat ,(string->number ($ m 'repetitions)))) (else `(shortcut ,(irregex-split blank ($ m 'modifiers)) ,(or (non-blank-string ($ m 'key-or-char)) (error "Missing key or character" line)))))) (error "Unrecognized line" line)))) (map parse (irregex-split "\r\n|\n" input))) (pp (parse-duckyscript "REM Hello Rick! DEFAULTDELAY 30 DELAY 3000 GUI r DELAY 200 STRING https://www.youtube.com/watch?v=dQw4w9WgXcQ ENTER DELAY 3000 STRING f REPEAT 3 CTRL ALT DELETE")) ;; ((comment "Hello Rick!") ;; (default-delay 30) ;; (delay 3000) ;; (shortcut ("GUI") "r") ;; (delay 200) ;; (string "https://www.youtube.com/watch?v=dQw4w9WgXcQ") ;; (shortcut () "ENTER") ;; (delay 3000) ;; (string "f") ;; (repeat 3) ;; (shortcut ("CTRL" "ALT") "DELETE"))