diff --git a/grammar/php.janet b/grammar/php.janet new file mode 100644 index 0000000..874c6ae --- /dev/null +++ b/grammar/php.janet @@ -0,0 +1,91 @@ +#!/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 "" (htmlspecialchars value) "") + [:multi-line-comment value] (string "" (htmlspecialchars value) "") + [:string value] (string "" (htmlspecialchars value) "") + [:variable value] (string "" (htmlspecialchars value) "") + [:return-type value] (string "" (htmlspecialchars value) "") + [:keyword value] (string "" (htmlspecialchars value) "") + [: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 "
" (ast-to-html (peg/match php-to-ast (read-from-file "sample.php"))) "")))
diff --git a/sample.php b/sample.php
new file mode 100644
index 0000000..6c6b9dd
--- /dev/null
+++ b/sample.php
@@ -0,0 +1,28 @@
+ "yolo";
+$🎈 = "balooooon";
+$u_a = 2;
+