Temgen can be used for generating any text containing repeatable patterns. All generation logic is contained in templates, so Temgen can be applied to generating texts in any languages, such as C, Perl, HTML, or even natural languages.
Mechanism @embed and @emit allows to create templates generating code in several files in the same time.
Temgen invocation | |
---|---|
temgen [options] file ... |
Available options:
Basis | Commands | Built in functions |
---|---|---|
Generating flow is following: Whole source files are parsed one after another and then interpreted in the same order. Each file is interpreted line by line, but the order can be modified with the control lines. Source file (template) consists of two kind of lines: control lines and data lines.
Each control line starts with @ and command identifier. Command identifiers are enumerated in the table and described below. The command purpose is changing control flow (ex. @if, @switch), defining function ( @function ), interpreting code fragments in order to initialize variables ( @ ), and setting output file and emit point (the point where output text is to be placed ( @output, @embed, @emit ). Control lines can be continued in next row. Continued line should end with backslash and the next line has to start with @.
Control line continuation: | |
---|---|
@if ( $very_long_expression == \ @ $another_very_long_expression ) |
Data lines contain text of the generated code. The text is expanded - encountered expressions are substituted with values. After expansion the text is inserted in embed point. The embed point defaults to end of current output file, but can be changed with the two commands: @emit and @embed. The output file can be set by @output command.
Data lines (template and output) | |
---|---|
@ $name = "Alaska" $name is the best ! | Alaska is the best ! |
The strings can be escaped with backslash in order to prevent interpretation.
Escaping (template and output) | |
---|---|
@ $name = "Alaska" (variable \$name) | (variable $name) |
Scalars, arrays and structures: | |
---|---|
@ $s = "BAR" @ $n = 2 @ $tab[1] = "foo" @ $tab[2] = "bar" @ $str = [ name: "FOO", count: 4 ] $s $tab[ 1 ] $tab[ $n ] $str.name, $str.count | BAR foo bar FOO, 4 |
Arrays and structures can be expanded dynamically. The iteration over all elements is supported:
Arrays and structures - iterating | |
---|---|
@ $tab = ["a","b","c",1000] @ $str = [ name: "FOO", count: 4, val: 1.20 ] @for ($i=0; $i<$size($tab); $i++) item $i: $tab[ $i ] @endfor STRUCTURE: @for ($i in $str) $i: $str.$i @endfor | item 0: a item 1: b item 2: c item 3: 1000 STRUCTURE: name: FOO count: 4 val: 1.200000 |
Arrays and structures may be nested.
Nested data structures: | |
---|---|
@ $data = [ "scalar", [a:"Alaska", b:"Bar"], \ @ [1,2,3,4], \ @ 10 ] |
Available operators (semantics as in C): | |
---|---|
- == ++ (postfix and prefix) + != -- (postfix and prefix) * = && / < || -= > += <= *= >= /= ! |
Expression examples: | |
---|---|
1 1.01 "foo" 'bar' $x -= 10 [ 1, 2, "FOO" ] [ name: "foo", val: 0 ] $fun( 10, $x ) $var.x $var.$field $tab[ 10 ] $( 'Foo bar bazoola' ) | numbers and strings arithmetic expression array constructor structure constructor function call selector (field access) selector (access by name) selector (item access) parenthesed expression |
Each data line is expanded by substituting expression with calculated values. For function calls, value is the string returned from function with @return command. The data lines interpreted inside the function do not cause text emitting. When the function is called from control line, the rule is reversed: returned value is ignored and data lines from the function body are expanded and emitted. This sounds complicated, so you should read the example:
Function call: | |
---|---|
@function fun() inline text @ return "RESULT TEXT" @endfunction called from data line: $fun() @ $fun() | called from data line: RESULT TEXT inline text |
Control commands
Expression instructions | |
---|---|
@ $fun() @ $x = 1 |
@break command works as C language break instruction. It breaks @for loop and @switch instruction.
@break command: | |
---|---|
@for ( $i=0; $i<10; $i++ ) iteration $i @ break @endfor @switch ( 1 ) @ case 1: branch 1 @ break @ case 2: branch 2 @endswitch | iteration 0 branch 1 |
The two commands @embed and @emit allow to change order of generated lines. @embed defines point in which the text will be emitted, @emit redirects output stream to emit point declared in other place. This is important that emit point can be declared in different source file before - or after - @emit command. It can emit text to different output file. The four commands: @emit, @embed, @push, @pop are probably the most robust mechanism of Temgen .
@embed and @emit accept any expression as argument, not only constant strings.
@embed 'Name' means: emit here after finding @emit 'Name'.
@emit 'Name' means: emit in point marked with @embed 'Name'.
Emit points: | |
---|---|
@embed "header" @embed "body" @embed "footer" @emit "body" BODY TEXT @emit "footer" FOOTER TEXT @emit "header" HEADER TEXT | HEADER TEXT BODY TEXT FOOTER TEXT |
The basic form of @for works similar as in C language. The loop can be broken with the @break command. The second form is used for iterating over structure fields.
Loops: | |
---|---|
@for ( $i=0; $i<3; $i++ ) item $i @endfor @ $str = [ a: "FOO", b: "BAR" ] @for ( $fld in $str ) $fld: $str.$fld @endfor | item 0 item 1 item 2 a: FOO b: BAR |
@function command starts function definition. Argument names are enumerated in function header. @return command is used to return function result. As explained before, function call effect depends on the function call place. Functions can be called in any template file, before or after function declaration. The command @local is used to declare local variables.
Function: | |
---|---|
@function factor( n ) @ if ( $n == 1 ) @ return 1 @ else @ return $n * $factor( $n - 1 ) @ endif @endfunction @for ( $i=1; $i<8; $i++ ) $i ! = $factor($i) @endfor | 1 ! = 1 2 ! = 2 3 ! = 6 4 ! = 24 5 ! = 120 6 ! = 720 7 ! = 5040 |
The conditional command @if is classic. It is presented in many examples here.
The @local command allows to declare local variable in function.
Local variable: | |
---|---|
@function abc(a,b) @local c $a $b $c @ $a='anew' @ $b='bnew' @ $c='cnew' $a $b $c @endfunction @ $a='a' @ $b='b' @ $c='c' $a $b $c @ $abc( $a, $b ) $a $b $c | a b c a b anew bnew cnew a b c |
Command @output interpretation causes switching output file to file named in argument. Together with the four command: @embed, @emit, @pop and @push it constitutes command set used to control generation output. Special file name "stdout" is used to redirect text to standard output of generator.
Controlling output: | |
---|---|
@output "foo" FOO @output "stdout" STDOUT |
@pop and push are used to save and restore emit point. Emit point is set by commands @output (file) and @emit (line). @pop and @push are useful inside function body, allowing to restore emit point to its state before function entry.
@Push and @pop: | |
---|---|
@function decl( d ) @ push @ output "example.h" $d @ pop @endfunction @output "example.c" #include "example.h" @ $decl( "int i;" ) int main() { @ $decl( "int result;" ) return result; } | example.h: int i; int result; example.c: #include "example.h" int main() { return result; } |
The @return ends function call and returns result.
The @switch command has syntax similar to switch instruction in C language. The difference is in @case labels. One can use any expressions as @case labels, not only constant literals, as in C. The @break is used analogous to language C.
@switch command: | |
---|---|
@function string( len ) @ if ( $len == 1 ) @ return "z" @ else @ return "z" + $string( $len-1 ) @ endif @endfunction @switch "zz" @ case $string(1) : 1 @ break @ case $string(2) : 2 @ break @ case $string(3) : 3 @ break @endswitch | 2 |
@use command: | |
---|---|
@use "foo.tg" @ $foo() | FOO |
$printf() | |
---|---|
$printf( "%-10s %d 0x%02X", "foo", 10, 10 ) | foo 10 0x0A |
The $size function returns size (number of fields) of compound object.
$size() | |
---|---|
@ $x = 1 @ $y = [ 1, 2, 3 ] @ $z = [ a:"foo", b:10 ] $size($x) $size($y) $size($z) $size($undef) | 0 3 2 0 |
The $strlen function returns length of string.
$strlen() | |
---|---|
@ $x = 1 @ $y = "Foo Bar" $strlen($x) $strlen($y) $strlen($undef) | 0 7 0 |
$substr() | |
---|---|
$substr( "ABCDEFGHIJK", 2, 5 ) $substr( "ABCDEFGHIJK", 2 ) $substr( "ABCDEFGHIJK", 2, 50 ) | CDEFG CDEFGHIJK CDEFGHIJK |
The $system function executes system command, reads the command output and returns its content.
$system() | |
---|---|
$system("ps") | PID TTY TIME CMD 348 pts/0 00:00:00 bash 713 pts/0 00:00:00 tg 714 pts/0 00:00:00 ps |
The two functions returns current file name and line number in template.
$tplfile(), $tplline() | |
---|---|
\#line $tplline() \"$tplfile()\" | #line 2 "sample.tg" |