92 lines
4.0 KiB
Plaintext
92 lines
4.0 KiB
Plaintext
#!/usr/bin/env janet
|
|
|
|
# need to get comment, link, doctag, string literal/regexp, other literal, keyword identifier?
|
|
# based on https://github.com/php/php-langspec/blob/ca697b43031efd70b5306d29b74e1190e7eacac8/spec/19-grammar.md
|
|
|
|
(defn read-from-file [file-path]
|
|
"Read a file from string filepath"
|
|
(let [f (file/open file-path :r)
|
|
content (file/read f :all)]
|
|
(file/close f)
|
|
content))
|
|
|
|
(defn write-to-file [file-path content]
|
|
"Append to file from string filepath"
|
|
(let [f (file/open file-path :w)]
|
|
(file/write f content)
|
|
(file/flush f)
|
|
(file/close f)
|
|
content))
|
|
|
|
|
|
(defn pp-ast
|
|
"Pretty prints the PHP AST (as provided by (peg/match php-to-ast))"
|
|
[ast]
|
|
(if ast
|
|
(do
|
|
(print "[")
|
|
(map |(printf "\t%q" $0) ast)
|
|
(print "]"))))
|
|
|
|
(defn htmlspecialchars
|
|
"Convert html special chars from a string"
|
|
[value]
|
|
(string/replace-all "\"" """
|
|
(string/replace-all "'" "'"
|
|
(string/replace-all "<" "<"
|
|
(string/replace-all ">" ">"
|
|
(string/replace-all "&" "&" value))))))
|
|
|
|
(def php-to-ast
|
|
"A custom markdown flavored grammar"
|
|
~{
|
|
:end-of-line (* (? "\r") "\n")
|
|
|
|
:single-line-comment (cmt (<- (* (+ "//" "#") (some (if-not :end-of-line 1)))),|[:single-line-comment (string/join $&)])
|
|
:multi-line-comment (cmt (<- (* "/*" (some (if-not "*/" 1)) "*/")),|[:multi-line-comment (string/join $&)])
|
|
:comment (+ :single-line-comment :multi-line-comment)
|
|
|
|
:string (cmt (<- (* "\"" (some (if-not "\"" 1)) "\"")),|[:string (string/join $&)])
|
|
|
|
:name-non-digit (+ :a "_")
|
|
:name (some (+ :name-non-digit (range "\x80\xFF")))
|
|
:variable (cmt (<- (* "$" :name)),|[:variable (string/join $&)])
|
|
|
|
:scalar-type (+ "bool" "float" "int" "string")
|
|
:base-type (+ "array" "callable" "iterable" :scalar-type)
|
|
:return-type (cmt (<- (+ :base-type "void")),|[:return-type $0])
|
|
|
|
:keyword (cmt (<- (+ "abstract" "and" "array" "as" "break" "callable" "case" "catch" "class" "clone"
|
|
"const" "continue" "declare" "default" "die" "do" "echo" "else" "elseif" "empty"
|
|
"enddeclare" "endfor" "endforeach" "endif" "endswitch" "endwhile" "eval" "exit"
|
|
"extends" "final" "finally" "for" "foreach" "function" "fn" "global"
|
|
"goto" "if" "implements" "include" "include_once" "instanceof"
|
|
"insteadof" "interface" "isset" "list" "namespace" "new" "or" "print" "private"
|
|
"protected" "public" "require" "require_once" "return" "static" "switch"
|
|
"throw" "trait" "try" "unset" "use" "var" "while" "xor" "yield" "yield from")),|[:keyword $0])
|
|
|
|
:other (cmt (<- (if-not :comment 1)),|[:other (string/join $&)])
|
|
|
|
:main (some (+ :comment :string :variable :return-type :keyword :other))})
|
|
|
|
(defn ast-to-html
|
|
[ast]
|
|
(string/join
|
|
(map
|
|
|(match $0
|
|
[:single-line-comment value] (string "<span style=\"color:#a0a1a7;font-style:italic\">" (htmlspecialchars value) "</span>")
|
|
[:multi-line-comment value] (string "<span style=\"color:#a0a1a7;font-style:italic\">" (htmlspecialchars value) "</span>")
|
|
[:string value] (string "<span style=\"color:#50a14f\">" (htmlspecialchars value) "</span>")
|
|
[:variable value] (string "<span style=\"color:#986801\">" (htmlspecialchars value) "</span>")
|
|
[:return-type value] (string "<span style=\"color:#216ce7\">" (htmlspecialchars value) "</span>")
|
|
[:keyword value] (string "<span style=\"color:#a626a4\">" (htmlspecialchars value) "</span>")
|
|
[:other value] (htmlspecialchars value)
|
|
_ (error (string "Invalid symbol: " (get $0 0))))
|
|
ast)
|
|
""))
|
|
|
|
|
|
(defn main [bin & args]
|
|
# (pp-ast (peg/match php-to-ast (read-from-file "sample.php"))))
|
|
(write-to-file "php.html" (string "<pre><code>" (ast-to-html (peg/match php-to-ast (read-from-file "sample.php"))) "</code></pre>")))
|