Advertisement
Average-user

logic expressions parser

Aug 14th, 2018
1,276
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. (ns lec.parser
  2.   (:require [clojure.string :as cs]))
  3.  
  4. (def valid-chars (set "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"))
  5. (def operators (set "&|>=+"))
  6. (def char->operator {\& :and, \| :or, \> :implies, \= :iff, \+ :xor})
  7.  
  8. (defn- section
  9.   "Must be used with a string that starts with '(', and will return
  10.   a vector of what is inside of that clause, and whats after.
  11.    (section '(a & (b | c)) > d' ) => ['a & (b | c)', ' > d']"
  12.   [xs]
  13.   (-> (fn [[n acc xs]]
  14.         (case (first xs)
  15.           \( [(inc n) (conj acc (first xs)) (rest xs)]
  16.           \) (if (= n 1) [(dec n) acc (rest xs)]
  17.                          [(dec n) (conj acc (first xs)) (rest xs)])
  18.           [n (conj acc (first xs)) (rest xs)]))
  19.       (iterate [1 [] (rest xs)])
  20.       (->> (drop-while (comp not zero? first))
  21.            (first)
  22.            (rest))))
  23.                
  24. (defn parse
  25.   "For parsing logic formulas like: !(a & b) > ((c + b) | (a = d))
  26.   (Input mus not have spaces) to something like:
  27.   [[:not ['a' :and 'b']] :implies [['c' :xor 'b'] :or ['a' :iff 'd']]]"
  28.   [xs]
  29.   (cond
  30.     (not (some operators xs)) ; Just a literal
  31.     (if (= \! (first xs))
  32.       [:not (apply str (rest xs))]
  33.       (apply str xs))
  34.  
  35.     (= (take 2 xs) '(\! \()) ; negation of a nested expression
  36.     (let [[a b] (section (rest xs))]
  37.       (if (empty? (filter (partial not= \)) b))
  38.         [:not (parse a)]
  39.         [[:not (parse a)] (char->operator (first b)) (parse (rest b))]))
  40.    
  41.     (= \( (first xs)) ; nested expression
  42.     (let [[a b] (section xs)]
  43.       (if (empty? (filter (partial not= \)) b))
  44.         (parse a)
  45.         [(parse a) (char->operator (first b)) (parse (rest b))]))
  46.  
  47.     :else
  48.     (let [[a b] (split-with (comp not operators) xs)]
  49.       [(parse a) (char->operator (first b)) (parse (rest b))])))
Advertisement
RAW Paste Data Copied
Advertisement