-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Silly-j parser #12
base: master
Are you sure you want to change the base?
Silly-j parser #12
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
(ns hopen.syntax.silly-j | ||
(:require [hopen.renderer.xf :as rxf] | ||
[instaparse.core :as insta])) | ||
|
||
(declare parse) | ||
|
||
;; TODO test case | ||
(defn render | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would suggest to let the user do his own composition between the renderers and the parsers. If this function is here just for testing, it makes sense to move it to the test namespace. |
||
([template data] | ||
(render template data '())) | ||
([template data other-env] | ||
(let [new-env (update rxf/default-env :bindings assoc other-env) | ||
renderer (rxf/renderer (parse template) new-env)] | ||
(transduce renderer str data)))) | ||
|
||
(def ebnf | ||
(insta/parser " | ||
S = [STR | SILLYSTR]+ | ||
STR = #'[^{}]+' | ||
SILLYSTR = OBK SILLY CBK | ||
OBK = '{' | ||
CBK = '}' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would suggest using non-abbreviated names or less abbreviated names, to ensure that anybody can easily read the source code. OPEN_BLOCK, CLOSE_BLOCK for example. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As a side note: the casing (upper-case / lower-case) does not matter for instaparse. |
||
SILLY = [FCTX | FN] | ||
FCTX = '@' ':' ATTR | ||
ATTR = #'[^}]'+ | ||
FN = FNNAME APPLIES* | ||
APPLIES = SPC | FCTX | APPLY | ||
FNNAME = #'[a-zA-Z0-9\\-]+' | ||
SPC = #'\\ '+ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SPACE |
||
APPLY = #'^[^@\\ ][^}\\ ]+' | ||
" | ||
)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Odie I think that you might want to give instaparse a try. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, I think mustache is sufficiently simple to deal with by hand. (Famous last words?) Instaparse is really fantastic, but my last impression of it was “really magical, but maybe somewhat slow”. It might have been due to an ambiguous grammar that caused it to try going down two separate paths of the grammar tree though. Anyway, since there are no complicated grammatical structures, and mustache is already fully spec’ed out, I’ll try seeing it through the rest of the way. |
||
|
||
(defn parse [msg] | ||
(->> (ebnf msg) | ||
(insta/transform | ||
{:STR str | ||
;; :FCTX 'hopen/ctx | ||
:APPLY str | ||
:FNNAME str | ||
:ATTR str | ||
:FCTX (fn [at comma attr] | ||
(list 'hopen/ctx (keyword attr))) | ||
:SPC identity | ||
:FN (fn [fn & applies] | ||
green-coder marked this conversation as resolved.
Show resolved
Hide resolved
|
||
(cons (symbol fn) | ||
(filter #(not= " " %) applies) | ||
green-coder marked this conversation as resolved.
Show resolved
Hide resolved
|
||
)) | ||
:APPLIES identity | ||
:SILLY identity | ||
:SILLYSTR (fn [obrk silly cbrk] | ||
silly) | ||
:S list | ||
}))) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
(ns hopen.syntax.silly-j-test | ||
(:require #?(:clj [clojure.test :refer [deftest testing is are]] | ||
:cljs [cljs.test :refer [deftest testing is are] | ||
:include-macros true]) | ||
[hopen.syntax.silly-j :refer [parse]])) | ||
|
||
(deftest parse-test | ||
(testing "basic syntax test" | ||
(are [template parsed] | ||
(= (parse template) | ||
parsed) | ||
;; Split string and context | ||
"Hello {@:name}, {@:n} * {@:n} = {square @:n}" ["Hello " | ||
green-coder marked this conversation as resolved.
Show resolved
Hide resolved
|
||
'(hopen/ctx :name) | ||
", " | ||
'(hopen/ctx :n) | ||
" * " | ||
'(hopen/ctx :n) | ||
" = " | ||
'(square (hopen/ctx :n))] | ||
))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be avoided if the render function can be defined after the parser.
Usually, the
declare
is only used when there is a cross recursion between 2 functions defined at the root level.