blog/grammar/code/janet.janet

42 lines
1.6 KiB
Plaintext

#!/usr/bin/env janet
(def to-ast
~{
:ws (set " \t\r\f\n\0\v")
:readermac (set "';~,|")
:symchars (+ (range "09" "AZ" "az" "\x80\xFF") (set "!$%&*+-./:<?=>@^_"))
:token (some :symchars)
:hex (range "09" "af" "AF")
:escape (* "\\" (+ (set `"'0?\abefnrtvz`)
(* "x" :hex :hex)
(* "u" [4 :hex])
(* "U" [6 :hex])
(error (constant "bad escape"))))
:comment (* "#" (any (if-not (+ "\n" -1) 1)))
:symbol :token
:keyword (* ":" (any :symchars))
:constant (* (+ "true" "false" "nil") (not :symchars))
:bytes (* "\"" (any (+ :escape (if-not "\"" 1))) "\"")
:string :bytes
:buffer (* "@" :bytes)
:long-bytes {:delim (some "`")
:open (capture :delim :n)
:close (cmt (* (not (> -1 "`")) (-> :n) '(backmatch :n)) ,=)
:main (drop (* :open (any (if-not :close 1)) :close))}
:long-string :long-bytes
:long-buffer (* "@" :long-bytes)
:number (cmt (<- :token) ,scan-number)
:raw-value (+ :comment :constant :number :keyword
:string :buffer :long-string :long-buffer
:parray :barray :ptuple :btuple :struct :dict :symbol)
:value (* (any (+ :ws :readermac)) :raw-value (any :ws))
:root (any :value)
:root2 (any (* :value :value))
:ptuple (* "(" :root (+ ")" (error "")))
:btuple (* "[" :root (+ "]" (error "")))
:struct (* "{" :root2 (+ "}" (error "")))
:parray (* "@" :ptuple)
:barray (* "@" :btuple)
:dict (* "@" :struct)
:main :root})