Skip to content

Instantly share code, notes, and snippets.

@borkdude
Last active August 6, 2023 22:14
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save borkdude/8255eaf3c0301591a639b96125070a91 to your computer and use it in GitHub Desktop.
Save borkdude/8255eaf3c0301591a639b96125070a91 to your computer and use it in GitHub Desktop.
Parse JavaScript in Clojure using the Google Closure Compiler
#!/bin/sh
#_(
"exec" "clojure" "-Sdeps" "{:deps {org.clojure/clojurescript {:mvn/version \"1.10.520\"}}}" "$0" "$@"
)
;; running js_parser.clj "function foo(x) { var y = x + 1; }" will print:
;; [{:type :function, :name "foo", :body [{:variable-statement [{:lvalue "y", :initializer {:type :binary-op, :left "x", :operator "+", :right "1"}}]}], :params ["x"]}]
(import '[com.google.javascript.jscomp.parsing.parser
Parser
Parser$Config
SourceFile
IdentifierToken
LiteralToken
Token])
(import '[com.google.javascript.jscomp.parsing.parser.trees
FunctionDeclarationTree
VariableStatementTree
VariableDeclarationListTree
VariableDeclarationTree
IdentifierExpressionTree
BlockTree
FormalParameterListTree
EmptyStatementTree
LiteralExpressionTree
BinaryOperatorTree])
(require '[clojure.pprint :refer [pprint]])
(require '[clojure.datafy :refer [datafy]])
(defn inspect [x]
(pprint (datafy (.getClass x))))
(defmulti ->clj class)
(defmethod ->clj nil [x] x)
(defmethod ->clj com.google.common.collect.ImmutableList [x]
(mapv ->clj x))
(defmethod ->clj VariableStatementTree [x]
{:variable-statement (->clj (.-declarations x))})
(defmethod ->clj VariableDeclarationListTree [x]
(->clj (.-declarations x)))
(defmethod ->clj VariableDeclarationTree [x]
{:lvalue (->clj (.-lvalue x))
:initializer (->clj (.-initializer x))})
(defmethod ->clj IdentifierExpressionTree [x]
(->clj (.-identifierToken x)))
(defmethod ->clj IdentifierToken [x]
(.-value x))
(defmethod ->clj FunctionDeclarationTree [x]
{:type :function
:name (->clj (.-name x))
:body (->clj (.-functionBody x))
:params (->clj (.-formalParameterList x))})
(defmethod ->clj BlockTree [x]
(->clj (.-statements x)))
(defmethod ->clj FormalParameterListTree [x]
(->clj (.-parameters x)))
(defmethod ->clj EmptyStatementTree [x]
nil)
(defmethod ->clj LiteralExpressionTree [x]
(->clj (.-literalToken x)))
(defmethod ->clj LiteralToken [x]
(.-value x))
(defmethod ->clj BinaryOperatorTree [x]
{:type :binary-op
:left (->clj (.-left x))
:operator (->clj (.-operator x))
:right (->clj (.-right x))})
(defmethod ->clj Token [x]
(str x))
(def input (first *command-line-args*))
(def parsed
(let [prog (.parseProgram (Parser. (Parser$Config.) nil (SourceFile. "" input)))]
(->clj (.-sourceElements prog))))
(prn parsed)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment