(import scheme) (import (chicken base)) (import (chicken irregex)) (import (chicken pretty-print)) (import comparse) ;; key = "[A-Z0-9_]+" ;; char = "[^\r\n ]" ;; string-arg = "[^\r\n]+" ;; number = "[0-9]+" ;; newline = ("\r\n" | "\n") ;; whitespace = "[\t\v ]+" ;; comment = "REM" whitespace string-arg ;; default_delay = ("DEFAULTDELAY" | "DEFAULT_DELAY") whitespace number ;; delay = "DELAY" whitespace number ;; string = "STRING" whitespace string-arg ;; mod = ("WINDOWS" | "GUI" | "MENU" | "APP" | "SHIFT" | "ALT" | "CONTROL" | "CTRL") ;; modifiers = (mod whitespace)* ;; shortcut = modifiers? (char | key) ;; repeat = "REPEAT" whitespace number ;; command = (comment | default_delay | delay | string | repeat | shortcut) (define (parse-duckyscript input) (define (as-number parser) (bind (as-string parser) (lambda (s) (result (string->number s))))) (define (prefixed-argument prefix-parser arg-parser type) (sequence* ((_ prefix-parser) (_ whitespace) (arg arg-parser)) (result (list type arg)))) (define key (char-seq-match "[A-Z0-9_]+")) (define char (char-seq-match "[^\t\v ]")) (define string-arg (char-seq-match ".+")) (define digits (char-seq-match "[0-9]+")) (define whitespace (char-seq-match "[\t\v ]+")) (define comment (prefixed-argument (char-seq "REM") string-arg 'comment)) (define default-delay (prefixed-argument (any-of (char-seq "DEFAULTDELAY") (char-seq "DEFAULT_DELAY")) (as-number digits) 'default-delay)) (define delay (prefixed-argument (char-seq "DELAY") (as-number digits) 'delay)) (define string (prefixed-argument (char-seq "STRING") string-arg 'string)) (define repeat (prefixed-argument (char-seq "REPEAT") (as-number digits) 'repeat)) (define modifier (any-of (char-seq "WINDOWS") (char-seq "GUI") (char-seq "MENU") (char-seq "APP") (char-seq "SHIFT") (char-seq "ALT") (char-seq "CONTROL") (char-seq "CTRL"))) (define modifiers (zero-or-more (sequence* ((mod modifier) (_ whitespace)) (result mod)))) (define shortcut (sequence* ((mods modifiers) (key (any-of key char))) (result (list 'shortcut mods key)))) (define command (any-of comment default-delay delay string repeat shortcut)) (map (lambda (line) (parse (followed-by command end-of-input) line)) (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"))