SHOW:
|
|
- or go back to the newest paste.
| 1 | [/============================================================================= | |
| 2 | ||
| 3 | Gaea text template language! | |
| 4 | ||
| 5 | Thanks to hkaiser, VeXocide and heller !!! on Spirit IRC | |
| 6 | - | Thanks to Daniel James and Dave Abrahams for added comments |
| 6 | + | Thanks to Daniel James, Matias Capeletto and Dave Abrahams |
| 7 | - | and suggestions (Boost Docs List). |
| 7 | + | for added comments and suggestions (Boost Docs List). |
| 8 | ||
| 9 | ==============================================================================] | |
| 10 | ||
| 11 | Reserved tokens: | |
| 12 | [ | |
| 13 | ] | |
| 14 | - | [u |
| 14 | + | [u |
| 15 | - | [def |
| 15 | + | [def |
| 16 | - | [decl |
| 16 | + | [decl |
| 17 | - | [lambda |
| 17 | + | [lambda |
| 18 | - | [/ |
| 18 | + | [import |
| 19 | - | [" |
| 19 | + | [namespace |
| 20 | - | ["" |
| 20 | + | [/ |
| 21 | - | ""] |
| 21 | + | [^ |
| 22 | - | \[ |
| 22 | + | [" |
| 23 | - | \] |
| 23 | + | ["" |
| 24 | ""] | |
| 25 | - | (the last 2 is for escaping [ and ]) |
| 25 | + | \[ |
| 26 | \] | |
| 27 | ||
| 28 | (the last 2 is for escaping [ and ]) | |
| 29 | - | [/ comments. ] |
| 29 | + | |
| 30 | - | [/ nested [/ nested comments] comments. ] |
| 30 | + | |
| 31 | - | [/ balanced square braces [ and ] (i.e starts with [ and ends with ] and |
| 31 | + | |
| 32 | - | with equal number of [ and ]), are allowed inside comments. This is a |
| 32 | + | [/ comments. ] |
| 33 | - | good way to comment out code. ] |
| 33 | + | [/ nested [/ nested comments] comments. ] |
| 34 | [/ balanced square braces [ and ] (i.e starts with [ and ends with ] and | |
| 35 | with equal number of [ and ]), are allowed inside comments. This is a | |
| 36 | good way to comment out code. ] | |
| 37 | ||
| 38 | Markups: | |
| 39 | ||
| 40 | [*This is a markup] | |
| 41 | - | 3-element list. 2nd is a 2-element list where the first element |
| 41 | + | [orderedlist [a][b][c]] |
| 42 | - | has 1 element and the second has 2 elements. |
| 42 | + | |
| 43 | Markups are always significant, except inside escapes (see ["" Escapes | |
| 44 | below). Like HTML/XML spaces are coalesced unless they are inside the | |
| 45 | preformatted markup (see [^ Preformatted below). | |
| 46 | ||
| 47 | Markup Identifiers: | |
| 48 | ||
| 49 | Identifiers consist of one or more letters, digits and extended | |
| 50 | characters: ! $ % & * + - . : < = > ? @ _ ` # ' that | |
| 51 | cannot begin a number and cannot conflict with a reserved token. | |
| 52 | ||
| 53 | Examples: | |
| 54 | ||
| 55 | This-is-an-identifier | |
| 56 | ? | |
| 57 | * | |
| 58 | == | |
| 59 | ?WTH | |
| 60 | ||
| 61 | - | Strings: |
| 61 | + | Simple Strings: |
| 62 | ||
| 63 | This is a string | |
| 64 | ||
| 65 | Jack and Jill went up the hill to fetch a pail of water. | |
| 66 | Jack fell down and broke his crown, and Jill came tumbling after. | |
| 67 | ||
| 68 | 123 is a numeric string | |
| 69 | ||
| 70 | - | Markups ([...]) are always significant, except inside escapes |
| 70 | + | Grouped String: |
| 71 | - | (see ["" Escapes below). Like HTML/XML spaces are coalesced unless |
| 71 | + | |
| 72 | - | they are inside the preformatted markup (see [" Preformatted below). |
| 72 | + | ["This is grouped a string] |
| 73 | ||
| 74 | The [" and ] delimit the extent of the string. A simple form | |
| 75 | of grouped strings are allowed *ONLY* as list elements | |
| 76 | (see List below). | |
| 77 | ||
| 78 | [This grouped string is allowed *ONLY* as list element] | |
| 79 | ||
| 80 | The double quote is not necessary because bare markups are not | |
| 81 | allowed as list elements. If you need markups in list elements, | |
| 82 | put them in braces: | |
| 83 | ||
| 84 | - | [""[x]""] [/ Escapes all occurances of [ and ] in x. ] |
| 84 | + | [[*A marked-up list element]] |
| 85 | ||
| 86 | Marked up Strings: | |
| 87 | ||
| 88 | - | [" some-text] [/ Make spaces, tabs and newlines significant ] |
| 88 | + | This string [*contains] a markup. '*' should better be a |
| 89 | template, otherwise this is an error. | |
| 90 | - | Function: |
| 90 | + | |
| 91 | [*This] string contains a markup. '*' should better be a | |
| 92 | template, otherwise this is an error. | |
| 93 | ||
| 94 | Lists: | |
| 95 | ||
| 96 | A list may contain one or grouped-string or nested list. | |
| 97 | Examples: | |
| 98 | - | for documenting functions. |
| 98 | + | |
| 99 | [[a][b][c]] [/ 1st ] | |
| 100 | [[a][[b][c]]] [/ 2nd ] | |
| 101 | ||
| 102 | - | [def [foo] body] [/ nullary function def ] |
| 102 | + | |
| 103 | 3-element list [a][b][c]. 2nd is a 2-element list where the first | |
| 104 | - | [def foo body] [/ short for nullary function def ] |
| 104 | + | element is [a] and the second is a 2-element list [b][c]. |
| 105 | ||
| 106 | Formatting makes it clear: | |
| 107 | ||
| 108 | 1st: | |
| 109 | ||
| 110 | - | Function invocation: |
| 110 | + | |
| 111 | [a][b][c] | |
| 112 | - | [foo] [/ nullary function ] |
| 112 | + | |
| 113 | ||
| 114 | - | [dup apple pie] [/ unary function. argument is a string. ] |
| 114 | + | |
| 115 | ||
| 116 | - | [dup [apple pie]] [/ unary function. argument is a 1-element list. ] |
| 116 | + | |
| 117 | [a] | |
| 118 | [ | |
| 119 | [b][c] | |
| 120 | - | Function identifier: |
| 120 | + | |
| 121 | ] | |
| 122 | - | Function identifiers can either consist of: |
| 122 | + | |
| 123 | This is an erroneous list: | |
| 124 | - | An initial alphabetic character or the underscore, |
| 124 | + | |
| 125 | - | followed by zero or more alphanumeric characters or |
| 125 | + | [[a][b][c] duh!] [/ not a list ] |
| 126 | - | the underscore. This is similar to your typical C/C++ identifier. |
| 126 | + | |
| 127 | - | One to four character operator (a non-alphanumeric printable character) |
| 127 | + | There should never be "naked" list elements (those without |
| 128 | braces). That one above is not a list. It is a grouped string; | |
| 129 | - | Formal Arguments |
| 129 | + | and so is this: |
| 130 | ||
| 131 | - | Formal arguments are identifiers consisting of an initial |
| 131 | + | [duh! [a][b][c]] [/ not a list ] |
| 132 | - | alphabetic character or the underscore, followed by zero |
| 132 | + | |
| 133 | - | or more alphanumeric characters or the underscore. This is |
| 133 | + | Strings as lists: |
| 134 | - | similar to your typical C/C++ identifier. |
| 134 | + | |
| 135 | A string is just a special form of list with single character elements. | |
| 136 | ||
| 137 | List elements: | |
| 138 | - | [def [f3 a b c] |
| 138 | + | |
| 139 | - | [def d de Guzman] |
| 139 | + | [ |
| 140 | - | [a] [d], [b] [d], [c] [d] |
| 140 | + | [This is grouped a string] |
| 141 | ||
| 142 | [[*This is a markup]] | |
| 143 | - | [f3 [Joel][Mariel][Tenji]] [/ returns Joel de Guzman, Mariel de Guzman, Tenji de Guzman ] |
| 143 | + | |
| 144 | [[a][b][c]] [/ A nested list ] | |
| 145 | ||
| 146 | [This string [*contains] a markup] | |
| 147 | - | [decl [table title . rows]] |
| 147 | + | |
| 148 | [[*this] is still a string.] | |
| 149 | ||
| 150 | [[this is a single element list!]] | |
| 151 | ||
| 152 | ["[this is *not* a nested list!]] [/ the double quote " prevents this from | |
| 153 | becoming a list (see Protect below)] | |
| 154 | ] | |
| 155 | - | [table title |
| 155 | + | |
| 156 | Nil: | |
| 157 | ||
| 158 | [] | |
| 159 | ||
| 160 | A nil can be an empty string or an empty list. | |
| 161 | ||
| 162 | Unicode Code Points: | |
| 163 | ||
| 164 | [u2018] [/ Generates unicode code point (hexadecimal). ] | |
| 165 | ||
| 166 | Escapes: | |
| 167 | ||
| 168 | \[ [/ Escapes the open bracket] | |
| 169 | \] [/ Escapes the close bracket] | |
| 170 | [""x""] [/ Escapes all occurances of [ and ] in x. ] | |
| 171 | ||
| 172 | Preformatted: | |
| 173 | ||
| 174 | [^ some-text] [/ Make spaces, tabs and newlines significant ] | |
| 175 | ||
| 176 | Protect: | |
| 177 | ||
| 178 | ["* blah] [/ Don't expand * regardless if * is | |
| 179 | a template (or not) ] | |
| 180 | ["[x][y][z]] [/ Don't make this a list ] | |
| 181 | ||
| 182 | Protect ["* blah] is not really the same as [""* blah""]. Only the | |
| 183 | template * is not expanded. For example, ["* [bar]] will still expand | |
| 184 | bar, while [""* [bar]""] will not evaluate both * and bar. | |
| 185 | ||
| 186 | Template: | |
| 187 | Forward declarations: | |
| 188 | - | [decl [+ a b]] [/ Add a and b. both a and b are numeric integer strings. ] |
| 188 | + | |
| 189 | - | [decl [- a b]] [/ Subract a and b. both a and b are numeric integer strings. ] |
| 189 | + | |
| 190 | - | [decl [* a b]] [/ Multiply a and b. both a and b are numeric integer strings. ] |
| 190 | + | |
| 191 | - | [decl [/ a b]] [/ Divide a and b. both a and b are numeric integer strings. ] |
| 191 | + | |
| 192 | - | [decl [% a b]] [/ Remainder of a / b. both a and b are numeric integer strings. ] |
| 192 | + | |
| 193 | Forward declarations are good for recursion and is always perfect | |
| 194 | - | [decl [== a b]] [/ Returns 1 if a == b. ] |
| 194 | + | for documenting templates. |
| 195 | - | [decl [< a b]] [/ Returns 1 if a is less than b. ] |
| 195 | + | |
| 196 | - | [decl [&& a b]] [/ Returns a and b (boolean logic). ] |
| 196 | + | |
| 197 | - | [decl [|| a b]] [/ Returns a or b (boolean logic). ] |
| 197 | + | |
| 198 | - | [decl [if cond then else]] [/ Returns then if cond is 1, otherwise returns else. ] |
| 198 | + | [def [pi] 3.14159265] [/ nullary template def ] |
| 199 | ||
| 200 | [def pi 3.14159265] [/ short for nullary template def ] | |
| 201 | - | For example ! can be defined as [def [! x] [if [x][0][1]]], != can be defined |
| 201 | + | |
| 202 | - | as [def [!= a b] [![==[a][b]]]], etc. |
| 202 | + | |
| 203 | ||
| 204 | - | [decl [>> file]] [/ Loads file. ] |
| 204 | + | |
| 205 | - | [decl [<< file x]] [/ Saves x to file. ] |
| 205 | + | |
| 206 | Template expansion: | |
| 207 | - | >> processes files (i.e. markups are significant). If you want to load |
| 207 | + | |
| 208 | [pi] [/ nullary template ] | |
| 209 | ||
| 210 | - | [""[>> text.gia]""] |
| 210 | + | [dup apple pie] [/ unary template. argument is a string. ] |
| 211 | ||
| 212 | [dup [apple pie]] [/ unary template. argument is a 1-element list. ] | |
| 213 | ||
| 214 | [cat [apple][pie]] [/ 2 arguments. argument is a 2-element list. ] | |
| 215 | ||
| 216 | Optional Named Arguments: | |
| 217 | ||
| 218 | Any argument can be made optional by preceding the formal argument | |
| 219 | name with the tilde '~'. Example: | |
| 220 | ||
| 221 | [decl [$ path ~width ~height]] | |
| 222 | ||
| 223 | The $ template above can be used this way: | |
| 224 | ||
| 225 | [$image.jpg [~width 200px] [~height 200px]] | |
| 226 | - | [transform [list] [lambda [x] [dup [x]]]] |
| 226 | + | |
| 227 | Optional arguments can be placed anywhere in the template expansion. | |
| 228 | - | This doubles all elements of the list. |
| 228 | + | Order does not matter: |
| 229 | ||
| 230 | [$[~width 200px] image.jpg [~height 200px]] [/ OK] | |
| 231 | [$[~height 200px] [~width 200px] image.jpg] [/ OK] | |
| 232 | ||
| 233 | Notice too that image.jpg need not be placed inside braces. All optional | |
| 234 | arguments are gathered and what's left should conform to the rules for | |
| 235 | template expansion above; hence becomes: | |
| 236 | ||
| 237 | [$image.jpg] [/ nullary template ] | |
| 238 | ||
| 239 | Of course you can place them all inside braces if you want: | |
| 240 | ||
| 241 | [$[image.jpg] [~width 200px] [~height 200px]] | |
| 242 | ||
| 243 | Variable args: | |
| 244 | ||
| 245 | Example: | |
| 246 | ||
| 247 | [decl [table [~title] . rows]] | |
| 248 | ||
| 249 | The dot '.' before the last formal argument signifies variable | |
| 250 | number of arguments. It is only allowed before the final formal | |
| 251 | argument. The actual arguments passed are collected in one list. | |
| 252 | ||
| 253 | Example invocation: | |
| 254 | ||
| 255 | [table [~title My First Table] | |
| 256 | [[Heading 1] [Heading 2] [Heading 3]] | |
| 257 | [[R0-C0] [R0-C1] [R0-C2]] | |
| 258 | ] | |
| 259 | ||
| 260 | Again, the list may contain one or more markup, grouped-string or nested | |
| 261 | list. | |
| 262 | ||
| 263 | Intrinsics: | |
| 264 | ||
| 265 | [decl [head x]] [/ Get first element from x. ] | |
| 266 | [decl [tail x]] [/ Return a list or string without the first element of x. ] | |
| 267 | [decl [empty x]] [/ Return 1 if x is empty else 0. ] | |
| 268 | [decl [at x n]] [/ Return the nth element of x. ] | |
| 269 | [decl [size x]] [/ Return size of x. ] | |
| 270 | [decl [append x e]] [/ Append e to x. ] | |
| 271 | [decl [insert x e n]] [/ Insert e to x at position n. ] | |
| 272 | [decl [reverse x]] [/ Reverse x. ] | |
| 273 | [decl [join x y]] [/ Join x and y as one longer list. ] | |
| 274 | ||
| 275 | [decl [fold x s f]] [/ For a list x, initial state s, and binary function f, | |
| 276 | fold returns the result of the repeated application of | |
| 277 | [f e s] for each element e of list x, to the result | |
| 278 | of the previous f invocation (s if it is the first call). ] | |
| 279 | ||
| 280 | Many list operations can be implemented using fold. Yet, for the sake | |
| 281 | of efficiency, we provide these common operations as intrinsics. | |
| 282 | ||
| 283 | [decl [transform x f]] [/ For a list x and function f, transform returns a new | |
| 284 | list with elements created by applying [f e] to each | |
| 285 | element e of x. ] | |
| 286 | ||
| 287 | Since strings are just special forms of lists, all functions that accept | |
| 288 | lists can also accept strings. | |
| 289 | ||
| 290 | [decl [load file]] [/ Loads file. ] | |
| 291 | [decl [save file x]] [/ Saves x to file. ] | |
| 292 | ||
| 293 | load processes files (i.e. markups are significant). If you want to load | |
| 294 | files verbatim, enclose it in the escape markup. Example: | |
| 295 | ||
| 296 | [""[load text.gia]""] | |
| 297 | ||
| 298 | Load works similarly to C #include. It is possible to load a file inside | |
| 299 | a template body. All the templates in the loaded file will be available | |
| 300 | in the scope where it is loaded. | |
| 301 | ||
| 302 | [decl [add a b]] [/ Add a and b. both a and b are numeric integer strings. ] | |
| 303 | [decl [subt a b]] [/ Subract a and b. both a and b are numeric integer strings. ] | |
| 304 | [decl [mult a b]] [/ Multiply a and b. both a and b are numeric integer strings. ] | |
| 305 | [decl [div a b]] [/ Divide a and b. both a and b are numeric integer strings. ] | |
| 306 | [decl [mod a b]] [/ Remainder of a / b. both a and b are numeric integer strings. ] | |
| 307 | ||
| 308 | [decl [eq a b]] [/ Returns 1 if a == b. ] | |
| 309 | [decl [lt a b]] [/ Returns 1 if a is less than b. ] | |
| 310 | [decl [and a b]] [/ Returns a and b (boolean logic). ] | |
| 311 | [decl [or a b]] [/ Returns a or b (boolean logic). ] | |
| 312 | [decl [if cond then else]] [/ Returns then if cond is 1, otherwise returns else. ] | |
| 313 | ||
| 314 | Other comparisons and booleans can be synthesized from the basics above. | |
| 315 | For example not can be defined as: | |
| 316 | ||
| 317 | [def [not x] [if [x][0][1]]] | |
| 318 | ||
| 319 | ne (not-equal) can be defined as: | |
| 320 | ||
| 321 | [def [ne a b] [not [eq [a][b]]]], etc. | |
| 322 | ||
| 323 | Lambda Functions: | |
| 324 | ||
| 325 | Functions are first class and can be passed to and returned from other | |
| 326 | functions. For example, the transform intrinsic requires a lambda function | |
| 327 | for its last (f) argument. | |
| 328 | ||
| 329 | Here's an example of a lambda function: | |
| 330 | ||
| 331 | [lambda [x] [dup [x]]] | |
| 332 | ||
| 333 | Its syntax resembles a function definition. | |
| 334 | ||
| 335 | Here's a sample invocation of transform: | |
| 336 | ||
| 337 | [transform [[a][b][c]] [lambda [x] [dup [x]]]] | |
| 338 | ||
| 339 | This doubles all elements of the list: | |
| 340 | ||
| 341 | [[aa][bb][cc]] | |
| 342 | ||
| 343 | Function arguments: | |
| 344 | ||
| 345 | If the arity of the function argument is the same as the one expected, | |
| 346 | the argument (e.g. Transform expects its f argument to be a unary | |
| 347 | function. Likewise, dup is also a unary function), the function can | |
| 348 | be passed as-is. Example: | |
| 349 | ||
| 350 | [transform [[a][b][c]][dup]] | |
| 351 | ||
| 352 | Hence: | |
| 353 | ||
| 354 | [dup] | |
| 355 | ||
| 356 | is a shorthand equivalent to: | |
| 357 | ||
| 358 | [lambda [x] [dup [x]]] | |
| 359 | ||
| 360 | Scopes: | |
| 361 | ||
| 362 | Templates can be placed inside a namespace. Example: | |
| 363 | ||
| 364 | [namespace ns | |
| 365 | ||
| 366 | [decl [foo x]] | |
| 367 | [decl [bar x]] | |
| 368 | ] | |
| 369 | ||
| 370 | The template x can be referenced in other scopes using the | |
| 371 | dot notation. Example: | |
| 372 | ||
| 373 | [ns.foo hello, world!] | |
| 374 | ||
| 375 | You may import names from other scopes this way: | |
| 376 | ||
| 377 | [import [ns][foo][bar]] [/ Import foo and bar from ns ] | |
| 378 | ||
| 379 | Then you can use foo and bar without qualification: | |
| 380 | ||
| 381 | [foo hello, world!] | |
| 382 | ||
| 383 | You may also import a whole namespace: | |
| 384 | ||
| 385 | [import ns] [/ Import all templates in ns ] | |
| 386 | ||
| 387 | All the intrinsics are declared in namespace "std". There is an | |
| 388 | implicit | |
| 389 | ||
| 390 | [import std] | |
| 391 | ||
| 392 | before anything else. In case of ambiguity (when template names clash), | |
| 393 | you can use explicit qualification. Example: | |
| 394 | ||
| 395 | [std.plus [1][2]] | |
| 396 | ||
| 397 | ||
| 398 | ||
| 399 |