/
specification.yml
430 lines (409 loc) · 18 KB
/
specification.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
---
title: WLang
version: 0.9.3
sections:
- identifier: about
name: About
file: about.rdoc
- identifier: overview
name: Overview
file: overview.rdoc
- identifier: rulesets
name: Rulesets
file: rulesets.wtpl
links: 'spec["rulesets"].reverse'
- identifier: dialects
name: Dialects
file: dialects.wtpl
- identifier: hosting
name: Hosting language
file: hosting.rdoc
- identifier: glossary
name: Glossary
file: glossary.wtpl
- identifier: symbols
name: Tag symbols
file: symbols.wtpl
glossary:
- term: template
definition: |-
Source code respecting the wlang grammar, and attached to a given <em>wlang
dialect</em>.
example: |-
<tt>Hello ${name}</tt>
- term: dialect
definition: |-
Basically, <em>dialect</em> is used as a synonym for (programming) <em>language</em>.
However _wlang_ uses a tree of dialects, allowing specializations: <tt>sql/sybase</tt>
for example is the qualified name of a sub-dialect 'sybase' of the 'sql' dialect.
Dialects come with associated _encoders_.
example: |-
<tt>sql/sybase</tt>
- term: wlang dialect
definition: |-
When we talk about a <em>wlang dialect</em>, we are actually refering to some
specialization of the wlang tag-based grammar: <tt>wlang/xhtml</tt> for example
is the templating language _wlang_ proposes to generate xhtml pages. An
example of source code in that dialect has been shown before.
In addition to its encoders a <em>wlang dialect</em> comes with its sets of _tags_
and associated _rules_.
example: |-
<tt>wlang/xhtml</tt>
- term: encoder
definition: |-
Text transformation (algorithm) applying some encoding conventions of a portion
of a the target language generated by a dialect. HTML entities-encoding, SQL's back-quoting
are examples of encoders. Encoders are accessible through their qualified name (dialect/encoder).
example: |-
<tt>xhtml/entities-encoding</tt><br/><tt>sql/single-quoting</tt>
- term: ruleset
definition: |-
Reusable set of <em>tags</em> associated to <em>rule</em>s.
example: |-
<tt>Imperative ruleset</tt><br/><tt>Encoding rulset</tt>
- term: wlang tag
definition: |-
Special tags in the template, starting with wlang symbols and a number of wlang
blocks. A tag is associated with a wlang rule.
example: |-
<tt>${...}</tt><br/><tt>?{...}{...}{...}</tt>
- term: rule
definition: |-
Transformation semantics of a given <em>tag</em>. When wlang instantiates a
template it simply replaces <em>wlang tags</em> by some <em>replacement value</em>
(which is always a string). This value is computed by the rule attached to
the tag. Rule definition (see Rulesets tab on top of the page)
explicitly describes the number of blocks it expects, in which dialect they
are parsed and instantiated and the way the replacement value is computed.
example: |-
<tt>^{wlang/active-string}{...}</tt><br/>
Instantiates #1, looking for an encoder qualified name. Instantiates #2 in
the current dialect. Encode #2's instantiation using encoder found in (#1)
and return the result as replacement value.
- term: context
definition: |-
Some rules allow code to be executed in the <em>hosting language</em> (the
definition explicitly announce it by putting <tt>wlang/hosted</tt> in the corresponding
block). When doing so, this code is in fact executed in a given context that
provides the execution semantics.
- term: hosting language
definition: |-
language (or framework) that executes wlang. More precisely, the hosting language
is the one that rules what is considered as an executable expression in tags that
relies on some execution semantics (like !{...} for example). See the 'Hosting language'
section to learn more.
example: |-
ruby
rulesets:
- name: Basic
description: |-
The Basic ruleset is commonly installed on any dialect and provides access to _wlang_
foundations inside your template: requesting the hosting language to execute some expression,
changing the current dialect and encoding text.
examples:
- ["wlang/active-string", "Hello !{name}", "Hello O'Neil"]
- ["wlang/active-string", "Hello %{wlang/dummy}{!{name}}", "Hello !{name}"]
- ["wlang/dummy", "Hello %{wlang/dummy}{!{name}}", "Hello %{wlang/dummy}{!{name}}"]
- ["wlang/active-string", "Hello ^{plain-text/upcase}{${name}}", "Hello O'NEIL"]
rules:
# !{wlang/hosted}
- name: "execution"
symbol: "!"
signature: "!{wlang/hosted}"
definition: |-
Instantiates #1, looking for an expression of the hosting language. Evaluates it,
looking for any object. Converts it to a string (using to_s for example if Ruby is
the hosting language) and returns the result as replacement value.
# %{wlang/active-string}{...}
- name: "modulation"
symbol: "%"
signature: "%{wlang/active-string}{...}"
definition: |-
Instantiates #1, looking for a dialect qualified name. Instantiates #2
according to the rules defined by that dialect and returns the #2's
instantiation as replacement value.
# ^{wlang/active-string}{...}
- name: "encoding"
symbol: "^"
signature: "^{wlang/active-string}{...}"
definition: |-
Instantiates #1, looking for an encoder qualified name. Instantiates #2 in
the current dialect. Encode #2's instantiation using encoder found in (#1) and
returns encoding as replacement value.
# %!{wlang/active-string using ... with ...}{...}
- name: "recursive-application"
symbol: "%!"
signature: "%!{wlang/active-string <using>? <with>?}{...}"
definition: |-
Instantiates #1, looking for a dialect qualified name. Instantiates #2
in the current dialect. Instantiates #2's instantiation in the dialect found
in #1, using context installed by 'using ...' and 'with ...'. Returns this
instantiation as replacement value (this really advanced rule allows
metaprogramming).
# ${wlang/hosted}
- name: "injection"
symbol: "$"
signature: "${wlang/hosted}"
definition: Same semantics as execution (intended to be overrided).
# +{wlang/hosted}
- name: "inclusion"
symbol: "+"
signature: "+{wlang/hosted}"
definition: Same semantics as execution (intended to be overrided).
- name: Encoding
description: |-
Almost all languages require escaping/encoding in specific situations: quoted string literals
always come with an escaping mechanism (unfortunately different from one language to another),
html requires entities-encoding, etc. The Encoding ruleset proposes shortcut tags for encoding.
Note that these shortcuts are written in such a way that they don't depend on the effective
dialect. _wlang_ hides language and vendors differences!
examples:
- ["wlang/xhtml", "Hello &{name}", "Hello name"]
- ["wlang/xhtml", "Hello &{<script>}", "Hello <script>"]
- ["wlang/xhtml", "Hello &;{<script>}", "Hello <script>"]
- ["wlang/ruby", "puts 'Hello &'{name}'", "puts 'Hello name'"]
- ["wlang/ruby", "puts 'Hello &'{!{name}}'", "puts 'Hello O\'Neil'"]
- ["wlang/ruby", "puts 'Hello ' << '{name}'", "puts 'Hello ' << 'O\'Neil'"]
- ["wlang/sql", "... WHERE name='{name}'", "... WHERE name='O\'Neil'"]
- ["wlang/sql/sybase", "... WHERE name='{name}'", "... WHERE name='O''Neil'"]
rules:
# &{...}
- name: "main-encoding"
symbol: "&"
signature: "&{...}"
definition: "<tt>^{+{@parser.current_dialect}/main-encoding}{#1}</tt>"
# &;{...}
- name: "entities-encoding"
symbol: "&;"
signature: "&;{...}"
definition: "<tt>^{+{@parser.current_dialect}/entities-encoding}{#1}</tt>"
# &'{...}
- name: "single-quoting"
symbol: "&'"
signature: "&'{...}"
definition: "<tt>^{+{@parser.current_dialect}/single-quoting}{#1}</tt>"
# &;{...}
- name: "double-quoting"
symbol: '&"'
signature: '&"{...}'
definition: "<tt>^{+{@parser.current_dialect}/double-quoting}{#1}</tt>"
# ${wlang/hosted}
- name: "injection"
symbol: "$"
signature: "${wlang/hosted}"
definition: "<tt>&{+{#1}}</tt>"
# '{wlang/hosted}
- name: "single-quoted"
symbol: "'"
signature: "'{wlang/hosted}"
definition: |-
<tt>'&'{+{#1}}</tt> (first single quote is kept in the result)
# "{wlang/hosted}
- name: "double-quoted"
symbol: '"'
signature: '"{wlang/hosted}'
definition: |-
<tt>"&"{+{#1}}</tt> (first double quote is kept in the result)
- name: Imperative
description: |-
Instantiating conditionally and iterating collection elements are common code generation tasks.
The Imperative dialect provides these features.
examples:
- ["wlang/*", '?{true}{then}{else}', 'then']
- ["wlang/*", '?{/th/ =~ "not tat"}{then}{else}', 'else']
- ["wlang/*", '?{authors.include? "blambeau"}{yes}{no}', 'yes']
- ["wlang/*", '[*{authors as a}{"{a}"}{, }]', '["blambeau", "llambeau", "ancailliau"]']
rules:
# ?{wlang/hosted}{...}{...}
- name: "conditional<br/>(third block is optional)"
symbol: "?"
signature: "?{wlang/hosted}{...}{...}"
definition: |-
Instantiates #1, looking for an expression in the hosting language.
Evaluates it, looking for a boolean value (according to boolean semantics
of the hosting language). If true, instantiates #2, otherwise instantiates
#3 if present, returning instantiation as replacement value.
# *{wlang/hosted as x}{...}{...}
- name: "enumeration<br/>(third block is optional)"
symbol: "*"
signature: "*{wlang/hosted <as x>?}{...}{...}"
definition: |-
Instantiates #1, looking for an expression in the hosting language. Evaluates
it, looking for an enumerable. Iterates all its elements, instantiating #2 for
each of them (the iterated value is set under name x in the scope). If #3 is
present, it is instantiated between elements. Replacement is the concatenation
of all these instantiations.
- name: Context
description: |-
Complex templates come with specific needs. The ability to manipulate the context and the current
scope is provided by the Context ruleset. All are variants of 'saving previous instantiations' in
scope variables...
examples:
- ["wlang/*", '={name as n}{Hello !{n}}', "Hello O'Neil"]
- ["wlang/*", '={name as n}Hello !{n}', "Hello O'Neil"]
- ["wlang/*", '#={name}{blambeau}{Hello !{name}} and !{name}', "Hello blambeau and O'Neil"]
- ["wlang/*", '#={name}{blambeau}Hello !{name} and !{name}', "Hello blambeau and blambeau"]
- ["wlang/*", '={author as name}{Hello !{name}} and !{name}', "Hello blambeau and O'Neil"]
- ["wlang/*", '={author as name}Hello !{name} and !{name}', "Hello blambeau and blambeau"]
- ["wlang/*", '%={wlang/dummy as hello}{Hello !{name}}{!{hello}}', "Hello !{name}"]
- ["wlang/*", '^={plain-text/upcase as name}{!{author}}{Hello !{name}} and !{name}', "Hello BLAMBEAU and O'Neil"]
- ["wlang/*", '^={plain-text/upcase as name}{!{author}}Hello !{name} and !{name}', "Hello BLAMBEAU and BLAMBEAU"]
rules:
# ={wlang/hosted as x}{...}
- name: "assignment<br/>(second block is optional)"
symbol: "="
signature: "={wlang/hosted <as x>}{...}"
definition: |-
Instantiates #1, looking for an expression in the hosting language. Evaluates
it, looking for any object. Without second block, expands the current scope with
'x' being bound to evaluation result. Otherwise, branches the current scope for
the second block instantiation only and bind 'x' the same way (i.e. x will not be
available outside the second block). Returns an empty string as replacement value.
# %={wlang/active-string as x}{...}{...}
- name: "modulo-assignment<br/>(third block is optional)"
symbol: "%="
signature: "%={wlang/active-string <as x>}{...}{...}"
definition: |-
Instantiates #1, looking for a dialect qualified name. Instantiates #2 according
to the rules defined by that dialect. Without third block, expands the current
scope with 'x' being bound to #2's instantiation. Otherwise, branches the current
scope for the third block instantiation only and binds 'x' the same way (i.e. x will
not be available outside the third block). Returns an empty string as replacement
value.
# #={wlang/active-string}{...}{...}
- name: "block-assignment<br/>(third block is optional)"
symbol: "="
signature: "#={wlang/active-string}{...}{...}"
definition: |-
<tt>%={+{@parser.current_dialect} as #1}{#2}{#3}</tt>
# ^={wlang/active-string as x}{...}{...}
- name: "encoding-assignment<br/>(third block is optional)"
symbol: "^="
signature: "^={wlang/active-string <as x>}{...}{...}"
definition: |-
<tt>%={+{@parser.current_dialect} as x}{^{#1}{#2}}{#3}</tt>
- name: Buffering
description: |-
The Buffering ruleset is probably one of the more useful. It allows you to load text and data files,
to change the current output buffer (for generating multiple files for example) and even to start
the instantiation on other templates.
rules:
# <<{wlang/uri}
- name: "input"
symbol: "<<"
signature: "<<{wlang/uri}"
definition: |-
Instantiates #1, looking for an uri. Returns the text content of the found
uri (#1) as replacement value.
# >>{wlang/uri}
- name: "output"
symbol: ">>"
signature: ">>{wlang/uri}{...}"
definition: |-
Instantiates #1, looking for an uri. Instantiates #2 in the current dialect,
using the file found in #1 as output buffer. Returns an empty string as replacement
value.
# <<={wlang/uri as x}{...}
- name: "data-assignment"
symbol: "<<="
signature: "<<={wlang/uri <as x>}{...}"
definition: |-
Instantiates #1, looking for an uri. Loads data provided by this uri, based on the
file extension (typically .yml or .rb). Without second block, expands the current scope
with 'x' being bound to the data. Otherwise, branches the current scope for the second
block instantiation only and binds 'x' the same way (i.e. x will not be available outside
the second block). Returns an empty string as replacement value.
# <<+{wlang/uri with ...}
- name: "input-inclusion"
symbol: "<<+"
signature: "<<+{wlang/uri <using>? <with>?}"
definition: |-
Instantiates #1, looking for an uri. Instantiates the _wlang_ template at this location
(the dialect is infered from the file extension) in a fresh new scope built from the _with_
expression. Returns this instantiation as replacement value.
symbols:
- name: exclamation mark
symbol: '!'
meaning: execution
remark: should never be overrided as single
- name: 'caret/circumflex'
symbol: '^'
meaning: explicit encoding
remark: should never be overrided as single
- name: percent
symbol: '%'
meaning: modulation
remark: should never be overrided as single
- name: double quote
symbol: '"'
meaning: double-quoting
- name: dollar
symbol: '$'
meaning: 'main-encoding'
- name: ampersand
symbol: '&'
meaning: encoding
- name: single quote
symbol: "'"
meaning: single-quoting
- name: asterisk
symbol: '*'
meaning: iteration
- name: plus
symbol: '+'
meaning: inclusion
- name: question mark
symbol: '?'
meaning: condition
- name: at symbol
symbol: '@'
meaning: linking
- name: tilde
symbol: '~'
meaning: matching
- name: number sign
symbol: '#'
- name: comma
symbol: ','
- name: minus (dash)
symbol: '-'
- name: dot
symbol: '.'
- name: forward slash
symbol: '/'
- name: colon
symbol: ':'
- name: 'semi-colon'
symbol: ';'
- name: equal sign
symbol: '='
- name: less than
symbol: '<'
- name: greater than
symbol: '>'
- name: vertical bar
symbol: '|'
- name: underscore
symbol: '_'
remark: cannot be used as tag symbol; reserved for escaping in future versions
- name: back slash
symbol: \
remark: cannot be used as tag symbol; reserved for escaping in current version
- name: left parenthesis
symbol: '('
remark: cannot be used as tag symbol; reserved for block delimiter
- name: right parenthesis
symbol: ')'
remark: cannot be used as tag symbol; reserved for block delimiter
- name: left bracket
symbol: '['
remark: cannot be used as tag symbol; reserved for block delimiter
- name: right bracket
symbol: ']'
remark: cannot be used as tag symbol; reserved for block delimiter
- name: left brace
symbol: '{'
remark: cannot be used as tag symbol; reserved for block delimiter
- name: right brace
symbol: '}'
remark: cannot be used as tag symbol; reserved for block delimiter