(ns cef-parser.core (:require [instaparse.core :as insta])) (def cef-grammar "CEF Grammar" (insta/parser "cef = #'.*?CEF:' version <'|'> device_vendor <'|'> device_product <'|'> device_version <'|'> device_event_class_id <'|'> name <'|'> severity (<'|'> extension)? version = #'\\d+' device_vendor = string device_product = string device_version = string device_event_class_id = string name = string severity = #'(?i)(unknown|low|medium|high|very-high)'| #'[1-9]'|'10' extension = (key <'='> value <' '>?)* = (#'[^\\\\]' | escaped-char)+ escaped-char = (<'\\\\'> ('|' | '\\\\' | 'n' | 'r')) key = (#'[^\\\\ ]' | escaped-char-key)(#'[^\\\\ ]' | escaped-char-key)* escaped-char-key = (<'\\\\'> ('=' | '\\\\' | ' ' | 'n' | 'r' ) ) value = ((#'[^\\\\ ]*' | escaped-char-key) (' '|Epsilon))+ ")) (defn parse-cef [txt] (insta/transform {:string str :escaped-char (fn [& args] (case (first args) "n" "\n" "r" "\r" (apply str args))) :escaped-char-key (fn [& args] (case (first args) "n" "\n" "r" "\r" (apply str args))) :device_vendor str :device_product str :device_version str :device_event_class_id str :name str :severity str :extension hash-map :key str :version str :value str :cef (fn ([_ _ version device-vendor device-product device-event-class-id name severity] (merge {:version version :device-vendor device-vendor :device-product device-product :device_event_class_id device-event-class-id :name name :severity severity})) ([_ _ version device-vendor device-product device-event-class-id name severity extension] (merge {:version version :device-vendor device-vendor :device-product device-product :device_event_class_id device-event-class-id :name name :severity severity :extension extension})))} (cef-grammar txt))) (defn tst [] (parse-cef excef))