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