author | Volker Birk <vb@pep-project.org> |
Thu, 08 Apr 2021 15:17:25 +0200 | |
changeset 74 | c3c5a089072a |
parent 44 | 4e5f42d51cc4 |
permissions | -rw-r--r-- |
0 | 1 |
include homepage.en.yhtml2 |
2 |
||
3 |
page "The Features" { |
|
4 |
h2 id=text > Text |
|
5 |
||
6 |
p >> |
|
7 |
To output text nodes (¬http://www.w3.org/TR/2008/REC-xml-20081126/#syntax character data¬), |
|
8 |
write literals. There are integer literals, floating point literals and text literals. |
|
9 |
>> |
|
10 |
||
11 |
p >> |
|
12 |
Literals are written |
|
13 |
¬http://docs.python.org/reference/lexical_analysis.html#id7 like in Python¬, |
|
14 |
that means, text literals are in single or double quotes, or multiline |
|
15 |
in triple double quotes: |
|
16 |
>> |
|
17 |
||
18 |
Code || |
|
19 |
"text" 'also text' """some more text""" |
|
20 |
42 "an integer and" 42.23 "a floating point literal" |
|
21 |
|| |
|
22 |
||
23 |
p >> |
|
24 |
Literals are being output by the ¬#textfunction text function¬. |
|
25 |
>> |
|
26 |
||
27 |
h2 id=functioncalls > Function Calls |
|
28 |
||
29 |
p >> |
|
30 |
The main idea of YML scripts is calling functions which then generate |
|
31 |
XML tags (¬http://www.w3.org/TR/2008/REC-xml-20081126/#syntax Markup¬). |
|
32 |
Functions are generating single tags, lists or trees of tags. |
|
33 |
>> |
|
34 |
||
35 |
p >> |
|
36 |
To call a function, write the name of the function, followed by a comma separated list |
|
37 |
of function parameters (C like syntax) or just «attribute=value» pairs. Unlike C, you don't |
|
38 |
need to insert the parameter list into parentheses. A simple function call can be terminated |
|
39 |
by a semicolon «;» or by a period «.» |
|
40 |
>> |
|
41 |
||
42 |
p >> |
|
43 |
It does not matter, if you're calling your function using parentheses or brackets or without. |
|
44 |
So these statements are equal: |
|
45 |
>> |
|
46 |
||
47 |
Code || |
|
48 |
foo "hello, world"; |
|
49 |
foo "hello, world". |
|
50 |
foo("hello, world"); |
|
51 |
foo["hello, world"]; |
|
52 |
|| |
|
53 |
||
54 |
h3 id=subtree > Subtrees |
|
55 |
||
56 |
p >> |
|
57 |
If you omit the tailing semicolon, you're creating a Subtree; YML Subtrees can also be |
|
58 |
opened and closed with braces: |
|
59 |
>> |
|
60 |
||
61 |
Code || |
|
62 |
foo { |
|
63 |
bar { |
|
64 |
something; |
|
65 |
} |
|
66 |
} |
|
67 |
|| |
|
68 |
||
69 |
p > If a Subtree only consists of one single subelement, then you may omit the braces: |
|
70 |
||
71 |
Code || |
|
72 |
foo |
|
73 |
bar; |
|
74 |
|| |
|
75 |
||
76 |
h3 id=named > Named Parameters |
|
77 |
||
78 |
p >> |
|
79 |
To generate ¬http://www.w3.org/TR/2008/REC-xml-20081126/#attdecls attributes¬ by calling |
|
80 |
a function, you can use Named Parameters. |
|
81 |
>> |
|
82 |
||
83 |
p >> |
|
84 |
For that case, assign literals or symbols to attribute names like the following. |
|
85 |
The name of the parameter then will be used as the name of the generated attribute. |
|
86 |
An example: |
|
87 |
>> |
|
88 |
||
89 |
Code || |
|
90 |
div id=sample { |
|
91 |
"this is a " a href="#sample" "link sample" |
|
92 |
} |
|
93 |
|| |
|
94 |
||
95 |
p > This generates: |
|
96 |
||
97 |
Code | <div id="sample">this is a <a href="#sample">link sample</a></div> |
|
98 |
||
99 |
h3 > Unnamed Parameters |
|
100 |
||
101 |
p >> |
|
102 |
Unnamed Parameters prepare values for predefined attributes. The following example is |
|
103 |
equivalent to the sample above: |
|
104 |
>> |
|
105 |
||
106 |
Code || |
|
107 |
decl a(href); |
|
108 |
decl div(id); |
|
109 |
||
110 |
div "sample" { |
|
111 |
"this is a " a "#sample" "link sample" |
|
112 |
} |
|
113 |
|| |
|
114 |
||
115 |
p > If no predefined attribute can be allocated, the value of the parameter is added to the body. |
|
116 |
||
117 |
h3 > Calling with & |
|
118 |
||
119 |
p >> |
|
120 |
Especially if you have a ¬#defaultbody default body¬ for your function, calling with |
|
121 |
a leading «&» can be sensible: then the tag itself is omitted and only the body is being output: |
|
122 |
>> |
|
123 |
||
124 |
Code || |
|
125 |
decl something { tag1; tag2; }; |
|
126 |
||
127 |
list { |
|
128 |
&something; |
|
129 |
} |
|
130 |
|| |
|
131 |
||
132 |
p > results in: |
|
133 |
||
134 |
Code || |
|
135 |
<list> |
|
136 |
<tag1/> |
|
137 |
<tag2/> |
|
138 |
</list> |
|
139 |
|| |
|
140 |
||
141 |
p >> |
|
142 |
This has the same result as ¬#alias aliasing¬ «something» to «-». |
|
143 |
>> |
|
144 |
||
145 |
h3 id=funclist > Function Lists |
|
146 |
||
147 |
p >> |
|
148 |
Function Lists are a feature of YML to simulate a more C like syntax. Let's have some |
|
149 |
examples. You can have a list of functions whereever you can have a function. Function |
|
150 |
Lists are comma separated: |
|
151 |
>> |
|
152 |
||
153 |
Code || |
|
154 |
x i, j, k |
|
155 |
|| |
|
156 |
||
157 |
p > compiles to: |
|
158 |
||
159 |
Code || |
|
160 |
<x> |
|
161 |
<i/> |
|
162 |
<j/> |
|
163 |
<k/> |
|
164 |
</x> |
|
165 |
|| |
|
166 |
||
167 |
h3 id=paramlists > Parameter Lists |
|
168 |
||
169 |
p >> |
|
170 |
A sample together with ¬#descending Descending Attributes¬: |
|
171 |
>> |
|
172 |
||
173 |
Code || |
|
174 |
decl Interface @name; |
|
175 |
decl attr @type @name; |
|
176 |
decl func @type @name; |
|
177 |
||
178 |
Interface Icecream { |
|
179 |
attr color flavour; |
|
180 |
attr long number; |
|
181 |
func int getPrice(); |
|
182 |
func void addFlavour(in color flavour, in long number); |
|
183 |
} |
|
184 |
|| |
|
185 |
||
186 |
p > compiles to: |
|
187 |
||
188 |
Code || |
|
189 |
<Interface name="Icecream"> |
|
190 |
<attr type="color" name="flavour"/> |
|
191 |
<attr type="long" name="number"/> |
|
192 |
<func type="int" name="getPrice"/> |
|
193 |
<func type="void" name="addFlavour"> |
|
194 |
<parm> |
|
195 |
<in/> |
|
196 |
<color/> |
|
197 |
<flavour/> |
|
198 |
</parm> |
|
199 |
<parm> |
|
200 |
<in/> |
|
201 |
<long/> |
|
202 |
<number/> |
|
203 |
</parm> |
|
204 |
</func> |
|
205 |
</Interface> |
|
206 |
|| |
|
207 |
||
208 |
p >> |
|
209 |
Note the «parm» tags – they're generated by default, if you write a Parameter List |
|
210 |
behind a Function Call. That differs from calling the function with parameters – |
|
211 |
¬#functioncalls calling¬ means using ¬#text text¬ values. |
|
212 |
>> |
|
213 |
||
214 |
p >> |
|
215 |
The «parm» tags are emitted, because the «_parm» function is called each time |
|
216 |
such a parameter will be emitted. |
|
217 |
>> |
|
218 |
||
219 |
p >> |
|
220 |
If you want to have the «_parm» function doing other things, just ¬#decl declare¬ |
|
221 |
it in another way. |
|
222 |
>> |
|
223 |
||
224 |
h3 id=generics > Generic Declarations |
|
225 |
||
226 |
p >> |
|
227 |
Using Generic Declarations is just like using ¬#paramlists Parameter Lists¬ – use angle brackets |
|
228 |
instead of parentheses. For Generic Declarations, the «_generic» function is called each |
|
229 |
time such a Generic Declaration will be emitted, generating «generic» tags as the default: |
|
230 |
>> |
|
231 |
||
232 |
Code | max<int>(x, y) |
|
233 |
||
234 |
p > compiles to: |
|
235 |
||
236 |
Code || |
|
237 |
<max> |
|
238 |
<generic> |
|
239 |
<int/> |
|
240 |
</generic> |
|
241 |
<parm> |
|
242 |
<x/> |
|
243 |
</parm> |
|
244 |
<parm> |
|
245 |
<y/> |
|
246 |
</parm> |
|
247 |
</max> |
|
248 |
|| |
|
249 |
||
250 |
h3 id=contentfc > The «content» function |
|
251 |
||
252 |
p >> |
|
253 |
The «content;» Function Call has a special meaning (only in a ¬#defaultbody default body¬): |
|
254 |
it does not generate a tag, but instead |
|
255 |
the tags of a supplied body in a call will be inserted at each place where the «content;» |
|
256 |
function call is existing in the ¬#defaultbody default body¬. |
|
257 |
>> |
|
258 |
||
259 |
h3 id=textfunction > The «text» function |
|
260 |
||
261 |
p >> |
|
262 |
There is a special YML function named «text». Usually, it's just ¬#alias aliased¬ to «-» (and |
|
263 |
therefore outputting nothing). The «text» function is called each time a text literal will be |
|
264 |
output. |
|
265 |
>> |
|
266 |
||
267 |
p >> |
|
268 |
If you ¬#decl declare¬ the «text» function, you can overload that behaviour. For example, |
|
269 |
¬yslt YSLT¬ is declaring «text» like this: |
|
270 |
>> |
|
271 |
||
272 |
Code || |
|
273 |
decl text alias xsl:text; |
|
274 |
||
275 |
"test" |
|
276 |
|| |
|
277 |
||
278 |
p > generates: |
|
279 |
||
280 |
Code | <xsl:text>test</xsl:text> |
|
281 |
||
282 |
p >> |
|
283 |
The «text» function is not called, if you give text as a value for an attribute: |
|
284 |
>> |
|
285 |
||
286 |
Code || |
|
287 |
decl text alias xsl:text; |
|
288 |
||
289 |
a "test" |
|
290 |
|| |
|
291 |
||
292 |
p > generates: |
|
293 |
||
294 |
Code | <a>test</a> |
|
295 |
||
296 |
p >> |
|
297 |
But it is called using the quoting operators: |
|
298 |
>> |
|
299 |
||
300 |
Code || |
|
301 |
decl text alias xsl:text; |
|
302 |
||
303 |
a > test |
|
304 |
|| |
|
305 |
||
306 |
p > generates: |
|
307 |
||
308 |
Code | <a><xsl:text>test</xsl:text></a> |
|
309 |
||
310 |
h3 id=declfunction > The «decl», «define» and «operator» functions |
|
311 |
||
312 |
p >> |
|
313 |
The «decl», «define» and «operator» functions are not defined, so they cannot be used |
|
314 |
accidentally by having a syntax error i.e. in a «decl» statement. If you want to use such |
|
315 |
a function, i.e. «decl()», you have to ¬#decl declare it explicitely¬: |
|
316 |
>> |
|
317 |
||
318 |
Code || |
|
319 |
decl decl; |
|
320 |
decl(); |
|
321 |
|| |
|
322 |
||
323 |
p > will result in: |
|
324 |
||
325 |
Code | <decl/> |
|
326 |
||
327 |
h2 id=decl > Declaring Functions: decl |
|
328 |
||
329 |
p >> |
|
330 |
As default, each Function Call generates one XML tag, which has the same name. To be exact, |
|
331 |
the XML tag has dashes in it's name where the YML function has underscores. |
|
332 |
>> |
|
333 |
||
334 |
p >> |
|
335 |
To define, how tags and attributes look like, which are created by a Function Call, you |
|
336 |
can use the «decl» statement. |
|
337 |
>> |
|
338 |
||
339 |
h3 > Trivial Declarations |
|
340 |
||
341 |
p > In a trivial declaration, you're just declaring the Function Name and so the XML tag name: |
|
342 |
||
343 |
Code | decl html, head, title, body, p, a; |
|
344 |
||
345 |
p > As seen in the example, multiple declarations can be done in a comma separated list. |
|
346 |
||
347 |
p >> |
|
348 |
Because trivial declarations are done automatically, if you're using a function for the |
|
349 |
first time, you usually don't need to declare this way. |
|
350 |
>> |
|
351 |
||
352 |
h3 > Specifying Unnamed Parameters |
|
353 |
||
354 |
p >> |
|
355 |
To specifiy Unnamed Parameters, give the parameter list comma separated in parentheses |
|
356 |
or provide one or more brackets with parameter lists in them: |
|
357 |
>> |
|
358 |
||
359 |
Code | decl a(href), img[src]; |
|
360 |
||
361 |
p >> |
|
362 |
If you're using the corresponding functions a() and img() together with an unnamed parameter |
|
363 |
in a call, then these attributes are used for applying the values, respectively: |
|
364 |
>> |
|
365 |
||
366 |
Code | a "http://www.ccc.de" "The Club Homepage" img "logo.png"; |
|
367 |
||
368 |
p > These Function Calls generate: |
|
369 |
||
370 |
Code | <a href="http://www.ccc.de">The Club Homepage</a><img src="logo.png"/> |
|
371 |
||
372 |
h3 id=defaultattr > Giving Default Values for parameters |
|
373 |
||
374 |
p >> |
|
375 |
To give default values for generating XML attributes, assign a literal to each named parameter |
|
376 |
in the declaration parentheses or brackets. Two examples, which do the same: |
|
377 |
>> |
|
378 |
||
379 |
Code |
|
380 |
|| |
|
381 |
decl img(src, alt="picture"); |
|
382 |
decl img[src][alt="picture"]; |
|
383 |
|| |
|
384 |
||
385 |
h3 id=alias > Aliasing: using different YML functions for the same XML tag for different tasks |
|
386 |
||
387 |
p >> |
|
388 |
Sometimes tags are used in different ways to do different things. For this case, you can |
|
389 |
use aliasing. Aliasing means, the YML function name and the XML tag name differ. For example: |
|
390 |
>> |
|
391 |
||
392 |
Code | decl a(href), target(name) alias a; |
|
393 |
||
394 |
p > Both defined YML functions then generate «<a />» tags – but the Unnamed Parameter differs. |
|
395 |
||
396 |
p >> |
|
397 |
The alias name «-» has a special meaning: it omits the tag in the output. That is especially |
|
398 |
sensible if you have a ¬#defaultbody default body¬. Then an alias to «-» has the same meaning |
|
399 |
as starting the function call with the «&» character: only the body is emitted. |
|
400 |
>> |
|
401 |
||
402 |
h3 id=descending > Specifying Descending Attributes |
|
403 |
||
404 |
p >> |
|
405 |
Maybe you want to write something like this: |
|
406 |
>> |
|
407 |
||
408 |
Code || |
|
409 |
Module ERP { |
|
410 |
Interface Customer { |
|
411 |
// ... |
|
412 |
} |
|
413 |
} |
|
414 |
|| |
|
415 |
||
416 |
p > Without any extras, this compiles to: |
|
417 |
||
418 |
Code || |
|
419 |
<Module> |
|
420 |
<ERP> |
|
421 |
<Interface> |
|
422 |
<Customer /> |
|
423 |
</Interface> |
|
424 |
</ERP> |
|
425 |
</Module> |
|
426 |
|| |
|
427 |
||
428 |
p >> |
|
429 |
For this case, it would be practical, if «ERP» would not be interpreted as extra tag |
|
430 |
but as value for an attribute «name». This you can achive with Descending Attributes: |
|
431 |
>> |
|
432 |
||
433 |
Code | decl Module @name, Interface @name; |
|
434 |
||
435 |
p > With this declaration, the code sample above is compiling to: |
|
436 |
||
437 |
Code || |
|
438 |
<Module name="ERP"> |
|
439 |
<Interface name="Customer" /> |
|
440 |
</Module> |
|
441 |
|| |
|
442 |
||
443 |
p >> |
|
444 |
Descending attributes can also be used this way: |
|
445 |
>> |
|
446 |
||
447 |
Code || |
|
448 |
decl module +name; |
|
449 |
decl element +name; |
|
450 |
||
451 |
module Some { |
|
452 |
element { |
|
453 |
one; |
|
454 |
two; |
|
455 |
three; |
|
456 |
} |
|
457 |
element { |
|
458 |
four; five; six |
|
459 |
} |
|
460 |
} |
|
461 |
|| |
|
462 |
||
463 |
p >> |
|
464 |
The above generates: |
|
465 |
>> |
|
466 |
||
467 |
Code || |
|
468 |
<?xml version='1.0' encoding='UTF-8'?> |
|
469 |
<module name="Some"> |
|
470 |
<element name="one"/> |
|
471 |
<element name="two"/> |
|
472 |
<element name="three"/> |
|
473 |
<element name="four"/> |
|
474 |
<element name="five"/> |
|
475 |
<element name="six"/> |
|
476 |
</module> |
|
477 |
|| |
|
478 |
||
479 |
h3 id=descending_pointer > Specifying Descending Pointers |
|
480 |
||
481 |
p >> |
|
482 |
Like with descending attributes, you can use descending ¬#pointer pointers¬. Instead of preceding the |
|
483 |
name of an attribute with a «+» sign (like with ¬#descending descending attributes¬), precede it with an asterisk «*». |
|
484 |
>> |
|
485 |
||
486 |
p >> |
|
487 |
Like with ¬#pointer pointers¬ in general, it's a good idea to combine that with a ¬#defaultbody default body¬: |
|
488 |
>> |
|
489 |
||
490 |
Code || |
|
491 |
decl f *p { some tags with *p }; |
|
492 |
||
493 |
f value; |
|
494 |
|| |
|
495 |
||
496 |
p >> |
|
497 |
This generates: |
|
498 |
>> |
|
499 |
||
500 |
Code || |
|
501 |
<?xml version='1.0' encoding='UTF-8'?> |
|
502 |
<f> |
|
503 |
<some> |
|
504 |
<tags> |
|
505 |
<with>value</with> |
|
506 |
</tags> |
|
507 |
</some> |
|
508 |
</f> |
|
509 |
|| |
|
510 |
||
511 |
h3 id=defaultbody > Supplying a Default Body |
|
512 |
||
513 |
p >> |
|
514 |
Additionally, you can supply a Default Body for each tag. For that case, add a YML function |
|
515 |
block in braces to your declaration: |
|
516 |
>> |
|
517 |
||
518 |
Code || |
|
519 |
decl pageContent alias body { |
|
520 |
a name=top; |
|
521 |
include heading.en.yhtml2; |
|
522 |
div id=entries |
|
523 |
content; |
|
524 |
}; |
|
525 |
|| |
|
526 |
||
527 |
p > The sample above is used for generating this homepage, for example. |
|
528 |
||
529 |
p > See the ¬#contentfc content function¬. |
|
530 |
||
531 |
h3 id=inheritance > Inheritance |
|
532 |
||
533 |
p >> |
|
534 |
Declarations can ¬http://en.wikipedia.org/wiki/Inheritance_(computer_science) inherit¬ |
|
535 |
information from previous declarations. For that case, there is the |
|
536 |
possibility to use an «is» clause to give a function name to inherit from. |
|
537 |
>> |
|
538 |
||
539 |
p > The following is an example from the YSLT specification: |
|
540 |
||
541 |
Code || |
|
542 |
decl stylesheet(version="1.0", xmlns:xsl="http://www.w3.org/1999/XSL/Transform"); |
|
543 |
||
544 |
decl estylesheet is stylesheet ( |
|
545 |
xmlns:exsl='http://exslt.org/common', |
|
546 |
xmlns:math='http://exslt.org/math', |
|
547 |
xmlns:func='http://exslt.org/functions', |
|
548 |
xmlns:str='http://exslt.org/strings', |
|
549 |
xmlns:dyn='http://exslt.org/dynamic', |
|
550 |
xmlns:set='http://exslt.org/sets', |
|
551 |
extension-element-prefixes='exsl func str dyn set math' |
|
552 |
); |
|
553 |
||
554 |
decl textstylesheet is estylesheet { |
|
555 |
output "text"; |
|
556 |
const "space", !"'" + " " * 200 + "'"!; |
|
557 |
param "autoindent", 4; |
|
558 |
content; |
|
559 |
}, tstylesheet is textstylesheet; |
|
560 |
|| |
|
561 |
||
562 |
p >> |
|
563 |
Here «estylesheet» inherits the tag name and the Default Values from «stylesheet», |
|
564 |
while «textstylesheet» inherits all from «estylesheet» again. «estylesheet» then adds |
|
565 |
a Default Body, and «tstylesheet» does exactly the same as «textstylesheet». |
|
566 |
>> |
|
567 |
||
568 |
p > All of these YML functions output «stylesheet» XML tags, but with different defaults. |
|
569 |
||
570 |
h3 id=shapes > Shapes |
|
571 |
||
572 |
p >> |
|
573 |
Shapes are comparable to ¬#inheritance inheritance¬. Declaring a shape inherits |
|
574 |
every property beside the name. |
|
575 |
>> |
|
576 |
||
577 |
Code || |
|
578 |
decl coords(x=0, y=0); |
|
579 |
decl point <coords> (name); |
|
580 |
||
581 |
point "origin"; |
|
582 |
|| |
|
583 |
||
584 |
p > compiles to: |
|
585 |
||
586 |
Code | <point y="0" x="0" name="origin"/> |
|
587 |
||
588 |
p >> |
|
589 |
It's possible to have more than one shape, too. Multiple shapes |
|
590 |
are patching each other in the sequence they're listed: |
|
591 |
>> |
|
592 |
||
593 |
Code || |
|
594 |
decl coords(x=0, y=0); |
|
595 |
decl named +name; |
|
596 |
decl point <coords, named>; |
|
597 |
||
598 |
point origin; |
|
599 |
|| |
|
600 |
||
601 |
p > compiles to: |
|
602 |
||
603 |
Code | <point y="0" x="0" name="origin" /> |
|
604 |
||
605 |
h3 > Namespaces |
|
606 |
||
607 |
p >> |
|
608 |
¬http://www.w3.org/TR/xml-names/ XML namespaces¬ can be used just by providing an |
|
609 |
«alias» clause. Additionally, they can be used by an «in» clause; these two lines |
|
610 |
are equivalent: |
|
611 |
>> |
|
612 |
||
613 |
Code || |
|
614 |
decl apply(select) alias xsl:apply-templates; |
|
615 |
in xsl decl apply(select) alias apply-templates; |
|
616 |
|| |
|
617 |
||
618 |
p > «in» clauses also can be used with a block of declarations in braces: |
|
619 |
||
620 |
Code || |
|
621 |
in xsl { |
|
622 |
decl template(match); |
|
623 |
decl apply(select) alias apply-templates; |
|
624 |
||
625 |
decl function(name) alias template; |
|
626 |
decl call(name) alias call-template; |
|
627 |
} |
|
628 |
|| |
|
629 |
||
630 |
h3 id=pointer > Pointers |
|
631 |
||
632 |
p >> |
|
633 |
In some situations, it is good to have information in a Function Call, which then |
|
634 |
changes the way XML tags are generated. For this case, there are Pointers. |
|
635 |
>> |
|
636 |
||
637 |
p >> |
|
638 |
The name should not mislead you; I took it because I chose the «*» symbol to declare them, |
|
639 |
and that is the meaning of this symbol in the programming language C. The concept behind |
|
640 |
is very easy. |
|
641 |
>> |
|
642 |
||
643 |
p >> |
|
644 |
For example, it could be a good idea to generate a small HTML document containing some |
|
645 |
content. For this case, the title of the page is a good case for using pointers: |
|
646 |
>> |
|
647 |
||
648 |
Code || |
|
649 |
decl page(*title) alias html { |
|
650 |
head { |
|
651 |
title *title; |
|
652 |
} |
|
653 |
body { |
|
654 |
h1 *title; |
|
655 |
content; |
|
656 |
} |
|
657 |
}; |
|
658 |
|| |
|
659 |
||
660 |
p >> |
|
661 |
In the example above, calling «page('My Page') { p 'hello, world'; }» will result in |
|
662 |
this XML output: |
|
663 |
>> |
|
664 |
||
665 |
Code || |
|
666 |
<html> |
|
667 |
<head> |
|
668 |
<title>My Page</title> |
|
669 |
</head> |
|
670 |
<body> |
|
671 |
<h1>My Page</h1> |
|
672 |
<p>hello, world</p> |
|
673 |
</body> |
|
674 |
</html> |
|
675 |
|| |
|
676 |
||
677 |
p >> |
|
678 |
Pointers can be referenced in any place in the Default Body of a «decl» statement, also for |
|
679 |
generating extra tags. Then the value for a Pointer will be the tag name. |
|
680 |
>> |
|
681 |
||
682 |
p >> |
|
683 |
Additionally, you can insert the value of a pointer as text by calling it with two leading |
|
684 |
asterisks, i.e. if the pointer is defined as «*x», you can insert its value as text using: «**x». |
|
685 |
>> |
|
686 |
||
687 |
h4 id=pwt > Pointers without tags |
|
688 |
||
689 |
p >> |
|
690 |
To give a literal a name, you can define pointers to literals. |
|
691 |
>> |
|
692 |
||
693 |
Code || |
|
694 |
define *answer = 42; |
|
695 |
something *answer; |
|
696 |
|| |
|
697 |
||
698 |
p > will compile to: |
|
699 |
||
700 |
Code | <something>42</something> |
|
701 |
||
702 |
p >> |
|
703 |
The «define» keyword as well as the asterisk «*» can be omitted. So this is |
|
704 |
equivalent to the statements above: |
|
705 |
>> |
|
706 |
||
707 |
Code || |
|
708 |
answer = 42; |
|
709 |
something *answer; |
|
710 |
|| |
|
711 |
||
712 |
h4 > The pointer *_debug_trace |
|
713 |
||
714 |
p >> |
|
715 |
If you're calling ¬toolchain#processor yml2proc¬ with ¬toolchain#debug --debug¬, then this pointer is filled |
|
716 |
with tracing info text, otherwise it's an empty string. |
|
717 |
>> |
|
718 |
||
719 |
h3 id=macros, "Macros"; |
|
720 |
||
721 |
p >> |
|
722 |
Macros are a way to generate values for attributes with variable content. Macros can be set |
|
723 |
like any other parameters; they're used for a text search & replace in the values of attributes |
|
724 |
when attributes are generated. |
|
725 |
>> |
|
726 |
||
727 |
p >> |
|
728 |
Parameters, which represent macros, are determined with a preceding «%» sign. They're |
|
729 |
accounted for before any other parameter is accounted for in a function call, even if |
|
730 |
they were defined after other parameters. |
|
731 |
>> |
|
732 |
||
733 |
p > An example: |
|
734 |
||
735 |
Code || |
|
736 |
decl foo(%macro, myAttr="something %macro for testing"); |
|
737 |
||
738 |
testing |
|
739 |
foo "nice"; |
|
740 |
|| |
|
741 |
||
742 |
p > This generates: |
|
743 |
||
744 |
Code || |
|
745 |
<testing> |
|
746 |
<foo myAttr="something nice for testing"/> |
|
747 |
</testing> |
|
748 |
|| |
|
749 |
||
750 |
h3 id=nullfunction > The Null Function |
|
751 |
||
752 |
p >> |
|
753 |
The function with the name «_» (underscore) is called Null Function. If you define this |
|
754 |
function, then you're switching off the default behaviour, that trivial declares are done |
|
755 |
automatically. |
|
756 |
>> |
|
757 |
||
758 |
p >> |
|
759 |
Instead, unknown functions now call the Null Function. This can be very sensible together |
|
760 |
with ¬#descending Descending Attributes¬: |
|
761 |
>> |
|
762 |
||
763 |
Code || |
|
764 |
decl _ +type +name alias func; |
|
765 |
decl interface +name; |
|
766 |
||
767 |
interface Testcase { |
|
768 |
void f(in string input); |
|
769 |
long getOptions(); |
|
770 |
} |
|
771 |
|| |
|
772 |
||
773 |
p > compiles to: |
|
774 |
||
775 |
Code || |
|
776 |
<interface name="Testcase"> |
|
777 |
<func type="void" name="f"> |
|
778 |
<parm> |
|
779 |
<in/> |
|
780 |
<string/> |
|
781 |
<input/> |
|
782 |
</parm> |
|
783 |
</func> |
|
784 |
<func type="long" name="getOptions"/> |
|
785 |
</interface> |
|
786 |
|| |
|
787 |
||
788 |
h2 id=quoting > Quoting Operators |
|
789 |
||
790 |
p > Five different quoting operators implement different functionality: |
|
791 |
||
792 |
h3 id=quote > Quote > |
|
793 |
||
794 |
p > The «>» operator quotes into text nodes, doing XML escaping of text. An example: |
|
795 |
||
796 |
Code | > this text will be put into a text node and these angle brackets <> will be quoted |
|
797 |
||
798 |
p > Additionally, it can be used to implement an indention system, see ¬yslt YSLT¬ below. |
|
799 |
||
800 |
p >> |
|
801 |
Then an integer literal can be the first part of the operator; it gives the indention |
|
802 |
level. For example: |
|
803 |
>> |
|
804 |
||
805 |
Code || |
|
806 |
0> this text is indented to the actual level and then output, |
|
807 |
> followed by this text.\\n |
|
808 |
||
809 |
1> this text is indented one indention level\\n |
|
810 |
2> two levels\\n |
|
811 |
1> one level again\\n |
|
812 |
|| |
|
813 |
||
814 |
p >> |
|
815 |
Quote text is being output by the ¬#textfunction «text» function¬. |
|
816 |
>> |
|
817 |
||
818 |
h3 id=blockquote > Block Quote >> |
|
819 |
||
820 |
p { |
|
821 |
> To include more lines of text into a single quoted area, use double «>>». The lines |
|
822 |
> are concatenated together then. An example: |
|
823 |
} |
|
824 |
||
825 |
Code || |
|
826 |
p >> |
|
827 |
This generates a text paragraph for HTML. All this text, which you can find in |
|
828 |
these lines, is being concatenated together to one single text node, and then put |
|
829 |
into the body of the <p> ... </p> tag. |
|
830 |
>> |
|
831 |
|| |
|
832 |
||
833 |
p >> |
|
834 |
Block quote text is being output by the ¬#textfunction «text» function¬. |
|
835 |
>> |
|
836 |
||
837 |
h3 > Line Quote | |
|
838 |
||
839 |
p > The «|» operator does the same as the «>» operator, adding a newline character to the text node. |
|
840 |
||
841 |
p > Additionally, it can be used to implement an indention system, see ¬yslt YSLT¬ below. |
|
842 |
||
843 |
p > Then it's used together with additional «>» symbols showing the grade of indention: |
|
844 |
||
845 |
Code || |
|
846 |
| not indented |
|
847 |
|> single indent |
|
848 |
|>> double indent |
|
849 |
(...) |
|
850 |
|| |
|
851 |
||
852 |
p >> |
|
853 |
Line quote text is being output by the ¬#textfunction «text» function¬. |
|
854 |
>> |
|
855 |
||
856 |
h3 > Block Line Quote || |
|
857 |
||
858 |
p >> |
|
859 |
The «||» operator opens and closes a block of lines, which then are handled like if each of |
|
860 |
them would be preceeded with a Line Operator «|». |
|
861 |
>> |
|
862 |
||
863 |
p > Sample: |
|
864 |
||
865 |
Code { |
|
866 |
| || |
|
867 |
|| |
|
868 |
this is code being quoted through |
|
869 |
this is the second line |
|
870 |
|| |
|
871 |
| || |
|
872 |
} |
|
873 |
||
874 |
p > is equivalent to: |
|
875 |
||
876 |
Code { |
|
877 |
|| |
|
878 |
| this is code being quoted through |
|
879 |
| this is the second line |
|
880 |
|| |
|
881 |
} |
|
882 |
||
883 |
p >> |
|
884 |
Block line quote text is being output by the ¬#textfunction «text» function¬. |
|
885 |
>> |
|
886 |
||
887 |
h3 > Inserting Commands |
|
888 |
||
889 |
p >> |
|
890 |
Just like with a ¬http://en.wikipedia.org/wiki/Shell_(computing)#Unix_shells Unix shell¬, |
|
891 |
you can insert statements into text by using backticks: |
|
892 |
>> |
|
893 |
||
894 |
Code ] | Click `a href="http://fdik.org/yml/" "this link"`, please! |
|
895 |
||
896 |
p { |
|
897 |
>> |
|
898 |
Being in a Block Line Quote «||», you additionally can use the Line Command operator |
|
899 |
(two backquotes, |
|
900 |
>> |
|
901 |
] ``). |
|
902 |
} |
|
903 |
||
904 |
p > This is very interesting to have in YSLT, for example: |
|
905 |
||
906 |
Code { |
|
907 |
| || |
|
908 |
| some code |
|
909 |
] `` |
|
910 |
> apply "myTemplate";\n |
|
911 |
| some other code |
|
912 |
| || |
|
913 |
} |
|
914 |
||
915 |
h3 id=userop > User defined in-text Operators |
|
916 |
||
917 |
p > You can define short cuts for inserting commands into text by defining operators. |
|
918 |
||
919 |
p >> |
|
920 |
Therefore, you need a ¬http://en.wikipedia.org/wiki/Regular_expression regular expression¬ |
|
921 |
for matching text and YML text for replacing with. Here an example, how this is used by YSLT: |
|
922 |
>> |
|
923 |
||
924 |
Code ] define operator "«(.*?)»" as value "%1"; |
|
925 |
||
926 |
p > The RegEx have ¬http://docs.python.org/library/re.html Python syntax¬. |
|
927 |
||
928 |
p >> |
|
929 |
In this example all matches to the RegEx will be replaced by the YML text in the «as» clause. |
|
930 |
The text of the first group in the RegEx will replace the «%1» in the resulting YML text. You |
|
931 |
can do that for more than one group – just use «%2» for the second group, «%3» for the third |
|
932 |
one and so on. |
|
933 |
>> |
|
934 |
||
935 |
p > The «define» keyword can be omitted. |
|
936 |
||
937 |
h3 id=quotethrough > Quote Through ] |
|
938 |
||
939 |
p >> |
|
940 |
The ¬http://en.wikipedia.org/wiki/Apple_II_series Apple ][¬ prompt operator just quotes |
|
941 |
through directly into XML what it gets. |
|
942 |
>> |
|
943 |
||
944 |
p >> |
|
945 |
If the first character of a command is a «<», then quote through is applied |
|
946 |
automatically. |
|
947 |
>> |
|
948 |
||
949 |
p > This is the preferred way to output XML tags directly in YML: |
|
950 |
||
951 |
Code || |
|
952 |
<output me="directly" /> |
|
953 |
||
954 |
] <!-- |
|
955 |
] add some comment, which then appears in XML |
|
956 |
] --> |
|
957 |
|| |
|
958 |
||
959 |
h2 id=including > Including YML files |
|
960 |
||
961 |
p >> |
|
962 |
You can include a second YML script file into an existing YML script file |
|
963 |
at any place using one of the following: |
|
964 |
>> |
|
965 |
||
966 |
Code || |
|
967 |
include something.yml2 |
|
968 |
include "something else.yml2" |
|
969 |
include 'anything addionally.yml2' |
|
970 |
|| |
|
971 |
||
972 |
a name="ymlpath"; |
|
973 |
p >> |
|
974 |
If you're not starting the filename with '.' or '/' as in the example above, then |
|
975 |
if the «YML_PATH» environment variable is set to a colon separated list of directories, |
|
976 |
these directories are being searched for the given filename. Otherwise, the local |
|
977 |
directory is searched. |
|
44
4e5f42d51cc4
docs: Include files are always searched at standard location, too.
Hartmut Goebel <h.goebel@crazy-compilers.com>
parents:
0
diff
changeset
|
978 |
The system location for «.yml2» and «.ysl2» files is always searched afterwards. |
0 | 979 |
>> |
980 |
||
981 |
p >> |
|
982 |
Filename ¬http://en.wikipedia.org/wiki/Glob_(programming) globbing¬ using «*» and «?» |
|
983 |
placeholders is supported to include more than one file at a time: |
|
984 |
>> |
|
985 |
||
986 |
Code | include part*.yml2 |
|
987 |
||
988 |
p >> |
|
989 |
Filename globbing also can be used reverted; that means, the files are included in reverse |
|
990 |
order: |
|
991 |
>> |
|
992 |
||
993 |
Code | include reverse part*.yml2 |
|
994 |
||
74
c3c5a089072a
feature: include from *pointer
Volker Birk <vb@pep-project.org>
parents:
44
diff
changeset
|
995 |
p > If there are the files part1.yml2, part2.yml2 and part3.yml2, part3.yml2 is included first now. |
0 | 996 |
|
997 |
p > To include plain text as text nodes, you can use: |
|
998 |
||
999 |
Code | include text some.txt |
|
1000 |
||
1001 |
p > To include ready made XML, use: |
|
1002 |
||
1003 |
Code | include xml some.xml |
|
1004 |
||
74
c3c5a089072a
feature: include from *pointer
Volker Birk <vb@pep-project.org>
parents:
44
diff
changeset
|
1005 |
p > If there is a file mask or a filename in a pointer you can include indirectly: |
c3c5a089072a
feature: include from *pointer
Volker Birk <vb@pep-project.org>
parents:
44
diff
changeset
|
1006 |
|
c3c5a089072a
feature: include from *pointer
Volker Birk <vb@pep-project.org>
parents:
44
diff
changeset
|
1007 |
Code || |
c3c5a089072a
feature: include from *pointer
Volker Birk <vb@pep-project.org>
parents:
44
diff
changeset
|
1008 |
declare files = "*.yml2" |
c3c5a089072a
feature: include from *pointer
Volker Birk <vb@pep-project.org>
parents:
44
diff
changeset
|
1009 |
include from *files |
c3c5a089072a
feature: include from *pointer
Volker Birk <vb@pep-project.org>
parents:
44
diff
changeset
|
1010 |
|| |
c3c5a089072a
feature: include from *pointer
Volker Birk <vb@pep-project.org>
parents:
44
diff
changeset
|
1011 |
|
0 | 1012 |
h2 id=python > Escaping into Python – the Escape Operator ! |
1013 |
||
1014 |
p > You can insert a Python command at any place by using the «!» operator: |
|
1015 |
||
1016 |
Code | !class X(str): pass |
|
1017 |
||
1018 |
h3 > Python script Operator !! |
|
1019 |
||
1020 |
p > You can use the double «!!» to include more than one line of Python code: |
|
1021 |
||
1022 |
Code || |
|
1023 |
!! |
|
1024 |
def fak(n): |
|
1025 |
if n == 0: |
|
1026 |
return 1 |
|
1027 |
else: |
|
1028 |
return n * fak(n - 1) |
|
1029 |
||
1030 |
def getName(id): |
|
1031 |
return SQL("select name from customers where id='"+str(id)+"';")[0] |
|
1032 |
!! |
|
1033 |
|| |
|
1034 |
||
1035 |
h3 > Python generated parameters in Function Calls |
|
1036 |
||
1037 |
p >> |
|
1038 |
You may use Python expressions to generate names and/or values in Function Calls. |
|
1039 |
To do so, embed the Python expression in «! ... !»: |
|
1040 |
>> |
|
1041 |
||
1042 |
Code || |
|
1043 |
f x=!fak(5)!; |
|
1044 |
customer name=!getName(42)!; |
|
1045 |
tag !getNextAttributeName()!=42; |
|
1046 |
|| |
|
1047 |
||
1048 |
h3 > Python generated Function Calls |
|
1049 |
||
1050 |
p >> |
|
1051 |
You can generate text with a Python expression, which represents an YML Function Call. |
|
1052 |
The resulting YML function is then executed. Also here, embed the Python expression |
|
1053 |
in «! ... !»: |
|
1054 |
>> |
|
1055 |
||
1056 |
Code | !getTagName() + " " + getAttrib() + "='" + getValue() + "'"! |
|
1057 |
||
1058 |
h3 > Using Pointers as values in Python function calls |
|
1059 |
||
1060 |
p >> |
|
1061 |
Sometimes it is useful to call a generating Python function using information of a |
|
1062 |
YML Function Call. For that case, there is the «python» statement in YML. You can |
|
1063 |
call there a single Python function using YML Pointers as parameters. |
|
1064 |
>> |
|
1065 |
||
1066 |
p > This is used in the YSLT specification, for example: |
|
1067 |
||
1068 |
Code || |
|
1069 |
decl apply(select, *indent=1) alias apply-templates { |
|
1070 |
python withIndent(*indent); |
|
1071 |
content; |
|
1072 |
}; |
|
1073 |
|| |
|
1074 |
||
1075 |
h2 id=comments > Comments //, /* */ |
|
1076 |
||
1077 |
p > Comments are written like in Java or C++: |
|
1078 |
||
1079 |
Code || |
|
1080 |
// this is a comment |
|
1081 |
something() { // this is a comment after a tag |
|
1082 |
/* this is some comment, too */ |
|
1083 |
|| |
|
1084 |
||
1085 |
p > After Quoting Operators, comments are not possible. Instead, they're quoted through: |
|
1086 |
||
1087 |
Code || |
|
1088 |
// the following line you'll find in the output document |
|
1089 |
> this text is being output // and this too |
|
1090 |
|| |
|
1091 |
||
1092 |
div id=bottom { |
|
1093 |
> ¬programming << Using YML 2¬ |
|
1094 |
> ¬#top ^Top^¬ |
|
1095 |
> ¬yslt >> show me YSLT¬ |
|
1096 |
> ¬features.en.yhtml2 (source)¬ |
|
1097 |
} |
|
1098 |
} |