Last active
August 30, 2017 18:18
-
-
Save pataprogramming/fcbd9260ee173a7813ad639d9c1e285b to your computer and use it in GitHub Desktop.
PhillyDev Slack #daily_programmer 2017-08-30 - Reverse Polish Notation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns daily.rpn | |
;; Needs [instaparse "1.4.7"] in project deps | |
(:require [instaparse.core :as insta] | |
[instaparse.failure :as failure] | |
[clojure.string :as string] | |
[clojure.edn :as edn])) | |
(def whitespace | |
(insta/parser | |
"whitespace = #'\\s*'")) | |
(def grammar | |
"expression = term | expression (plus | minus) term | |
term = factor | expression (times | div) factor | |
<factor> = number | ( <'('> expression <')'> ) | |
plus = '+' | |
minus = '-' | '−' | |
times = '*' | '×' | 'x' | |
div = '/' | '÷' | |
number = #'\\d+' | |
") | |
(def parse | |
(insta/parser grammar :auto-whitespace whitespace)) | |
(defn process [parse-tree] | |
(->> parse-tree | |
(insta/transform | |
{:expression (fn [a & [op b]] (if op [a b op] a)) | |
:term (fn [a & [op b]] (if op [a b op] a)) | |
:plus (constantly '+) | |
:minus (constantly '-) | |
:times (constantly '*) | |
:div (constantly '/) | |
:number edn/read-string}))) | |
(defn infix->rpn [expr] | |
(let [parse-tree (parse expr)] | |
(if (insta/failure? parse-tree) | |
(failure/print-reason parse-tree) | |
(->> parse-tree process flatten (map str) (string/join " "))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment