(===> from)
(===> from to)
(==> from)
(==> from to)
(=> from)
(=> from to)
(=>:from => default)
(=>:to => default)
(=>:type => default)
(def-derived name parent-dialect & decls)
Create a new dialect based on another one by defining terminals or forms that should be added or removed.
This works essentially the same as [[define-dialect]] but adds a parent-dialect argument and makes it possible to prevent inheritance of terminals, forms or expressions within forms from the parent dialect by prefixing each one with either + or -.
(def-derived D2 NS
(terminals + (symbol s)
- (nsname nsn)
- (typename tn))
- NsForm
(Expr [e]
+ (let [(?:* ?s:binding* ?e:bound*)] ??e:body)))
In the above example, 1 new terminal is added, and 2 are removed, the entire NsForm form is removed, and a new Expr form is added, adding a let binding. It is also possible to remove a pattern expression from a form by replacing the + with a -. Forms that are newly added may also omit all of the + symbols as well, but within a form all expressions must either be marked with +/- or not marked at all.
Create a new dialect based on another one by defining terminals or forms that should be added or removed. This works essentially the same as [[define-dialect]] but adds a parent-dialect argument and makes it possible to prevent inheritance of terminals, forms or expressions within forms from the parent dialect by prefixing each one with either + or -. (def-derived D2 NS (terminals + (symbol s) - (nsname nsn) - (typename tn)) - NsForm (Expr [e] + (let [(?:* ?s:binding* ?e:bound*)] ??e:body))) In the above example, 1 new terminal is added, and 2 are removed, the entire NsForm form is removed, and a new Expr form is added, adding a let binding. It is also possible to remove a pattern expression from a form by replacing the + with a -. Forms that are newly added may also omit all of the + symbols as well, but within a form all expressions must either be marked with +/- or not marked at all.
(def-dialect name & decls)
Create a new dialect.
Both terminals and forms may be defined. The following example creates a language with 2 terminals (nsn and tn) and two forms (nsform and ns):
(def-dialect NS (terminals [nsn nsname?] [tn typename?]) (NsForm [nsform] (:require (?:* (| ?nsn:req-symbol [?nsn:req-symbol ??opts]))) (:import (?:* (| ?nsn:fq-name (?nsn:ns-name ??tn:typenames))))) (Namespace [ns :enforce] ((?:literal ns) ?nsn:name ??nsform)) (entry Namespace))
The last form is the entry form for conformance unless a formis specifically designated by using (entry FormName).
By default, only terminals are predicated in matchers. If you want a form to be enforced, mark it with :enforce.
This is a somewhat sophisticated macro and as such has a bit of syntax you need to understand.
There are 2 top-level syntax types: terminals declarations and form declarations. Terminals are matched objects that do not require any further matching, ie. they are leaves of the syntax tree for the dialect. Forms are groups of patterns. In order for an IR instance to be valid, every form as it is recursively traversed must match one of the patterns and be tagged with the form type (ie. NsForm or Namespace in the above example).
Create a new dialect. Both terminals and forms may be defined. The following example creates a language with 2 terminals (nsn and tn) and two forms (nsform and ns): (def-dialect NS (terminals [nsn nsname?] [tn typename?]) (NsForm [nsform] (:require (?:* (| ?nsn:req-symbol [?nsn:req-symbol ??opts]))) (:import (?:* (| ?nsn:fq-name (?nsn:ns-name ??tn:typenames))))) (Namespace [ns :enforce] ((?:literal ns) ?nsn:name ??nsform)) (entry Namespace)) The last form is the entry form for conformance unless a formis specifically designated by using (entry FormName). By default, only terminals are predicated in matchers. If you want a form to be enforced, mark it with :enforce. This is a somewhat sophisticated macro and as such has a bit of syntax you need to understand. There are 2 top-level syntax types: terminals declarations and form declarations. Terminals are matched objects that do not require any further matching, ie. they are leaves of the syntax tree for the dialect. Forms are groups of patterns. In order for an IR instance to be valid, every form as it is recursively traversed must match one of the patterns and be tagged with the form type (ie. NsForm or Namespace in the above example).
(descend-into dialect)
(descend-into dialect forms)
(descend-into dialect forms descend-abbrs)
Creates a rule-list based on the valid expressions in the given dialect. The rules do not make any change to the expressions they match, but they enable correct descent through those expressions.
Each form
in the dialect has a list of expressions. You can either specify
a list of forms to include, or specify :all
.
Descent through the forms is based on the abbr
of the expression. If a
form's abbreviation is included in the list of descend-abbrs
, then for each
included expression, the vars that have that abbr will be descended through.
If no descend-abbr is provided, the abbr of each selected form will be used.
Note that terminals are never included in the list by default, but sometimes
it may be useful to include them in the descend-abbrs
list.
Example dialect
(def-dialect D1
(Exp [e] (if ?e:cond ?e:then ?e:else) (prg ?p ??e*))
(Program [p] (program ?e))
Example usages
(descend-into D1)
;; => rule list with 3 rules, descending into e and p abbrs.
(descend-into D1 '[Program])
;; => rule list just matching (program ?e), but only descending into p
;; abbrs, so really does nothing.
(descend-into D1 '[Exp] '[p])
;; => rule list matching the 2 forms in Exp, but only descending into
;; p abbrs. Equivalent to:
(rule-list
(rule '(if ?e0 ?e1 ?e2)) ;; does nothing but prevents other rules from matching
(rule '(prg ?->p ??e*))) ;; descends into ?->p but otherwise makes no change
Creates a rule-list based on the valid expressions in the given dialect. The rules do not make any change to the expressions they match, but they enable correct descent through those expressions. Each `form` in the dialect has a list of expressions. You can either specify a list of forms to include, or specify `:all`. Descent through the forms is based on the `abbr` of the expression. If a form's abbreviation is included in the list of `descend-abbrs`, then for each included expression, the vars that have that abbr will be descended through. If no descend-abbr is provided, the abbr of each selected form will be used. Note that terminals are never included in the list by default, but sometimes it may be useful to include them in the `descend-abbrs` list. Example dialect (def-dialect D1 (Exp [e] (if ?e:cond ?e:then ?e:else) (prg ?p ??e*)) (Program [p] (program ?e)) Example usages (descend-into D1) ;; => rule list with 3 rules, descending into e and p abbrs. (descend-into D1 '[Program]) ;; => rule list just matching (program ?e), but only descending into p ;; abbrs, so really does nothing. (descend-into D1 '[Exp] '[p]) ;; => rule list matching the 2 forms in Exp, but only descending into ;; p abbrs. Equivalent to: (rule-list (rule '(if ?e0 ?e1 ?e2)) ;; does nothing but prevents other rules from matching (rule '(prg ?->p ??e*))) ;; descends into ?->p but otherwise makes no change
(dialect d)
Look up a dialect if d is a symbol, otherwise return d.
Look up a dialect if d is a symbol, otherwise return d.
(dialects =>dialects & body)
Wrap a given rule combinator definition to specify that those rules transform between the given pair of dialects.
The rules will also make use of all abbr predicates defined within the rule (either terminals or expressions that are marked with :enforce).
Wrap a given rule combinator definition to specify that those rules transform between the given pair of dialects. The rules will also make use of all abbr predicates defined within the rule (either terminals or expressions that are marked with :enforce).
(from-dialect dialect & body)
Wrap a given rule combinator with the dialect. See dialects
Wrap a given rule combinator with the dialect. See `dialects`
(from-dialect* dialect f)
(show-dialect dialect & {:keys [full-names]})
Show the given dialect with all additions and removals of terminals, forms and expressions resolved. This is a useful tool for debugging, especially for dialects that go through many layers of derivation.
Show the given dialect with all additions and removals of terminals, forms and expressions resolved. This is a useful tool for debugging, especially for dialects that go through many layers of derivation.
(show-parse dialect expr)
Show a detailed view of how the dialect parses a given input, even if it parses it successfully.
Show a detailed view of how the dialect parses a given input, even if it parses it successfully.
(to-dialect dialect & body)
Wrap a given rule combinator with the dialect. See dialects
Wrap a given rule combinator with the dialect. See `dialects`
(to-dialect* dialect f)
(valid? dialect expr)
Returns true if the expr is valid in the given dialect
Returns true if the expr is valid in the given dialect
(validate dialect expr)
Validates an expression in the given dialect and either returns ok
or a
detailed parse showing all parse errors.
Validates an expression in the given dialect and either returns `ok` or a detailed parse showing all parse errors.
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close