//Artefact:SoftwareComponent/com/sphenon/engines/Generator
Usage/Operation - Manual
How to invoke the generator
The most easiest way to invoke the generator is the command line
interface, since no Java programming is needed. When learning how
to write templates, this is a good start.
Operation Class
The generator package provides a class named
.
This class implements the
Operation
interface, which declares an execute
method.
The class can be used in two ways. First, it provides a
main
method, which can be used from the
command line. Simply invoke it without arguments and you get an
explanation of it's usage.
Secondly, you can create instances of the class, specify the
respective parameters and call the
execute
method. This is what the main
method also
does internally.
And finally, there are some static
execute
methods with several
arguments. They are provided simply for convenience. Internally,
they create an instance, set the parameters and invoke the
non-static execute
method.
Command Line Invocation
The generator package contains an example bash script that performs
the aboveexplained invokation. Just invoke it without arguments and
get more information. Basically, it expects the name of a template
you want to process.
Emacs Integration
To invoke the generator from emacs dired buffers, you need to
include some lisp code provided in the file
generator.el
. Either you copy&paste that
code into your emacs.el file, or you load that file with
(load "my_generator").
Then, in a dired buffer you just press
hyper-g
(or whatever key you configure in your loadfile) on a template and
emacs invokes the command line bash script.
DynamicString Integration
A very convenient and interesting way to embed generator
capabilities into your application is the
DynamicString
interface.
In the default configuration, you just create a
DynamicString
instance, with an argument of
"g:..."
, where you replace the dots with a
generator template. Then, you can call the get
method to get the evaluated contents of the dynamic
string. Internally, a template is prepared and the generator is
invoked, but you aren't bothered with any details of this!
Programming Interface
In many cases the
Operation_Generate
class
(see above) is already sufficient to invoke the generator from within
your programs.
But there is another API beneath that class, providing more fine
grained and exhaustive control over the various generator features.
Please refer to the generator API documentation for more details.
Usage - Tutorial
Tutorial
A Simple Template
The following example shows a simple OOGenerator Template.
| helloworld.template |
|---|
G-2.0-plain_java-1.0
Hello world!
|
Test Execution
To execute the test, the following command can be used. It is
assumed, that the jar- and template-file are located in the current directory.
| Testaufruf |
|---|
java -classpath oogenerator.jar com.sphenon.engines.generator.operations.Operation_Generate helloworld.template helloworld.out
|
Example0000_Unicode
| Example0000_Unicode |
|---|
G-2.0-plain_java-1.0
Maybe the most striking feature of the OOGenerator is it's nice and compact
unicode syntax. While it is eye-catching, it's just syntactic sugar, and
besides it is optional. There's an alternative syntax available, which is
pretty JSP-like. If you don't like both: no problem - just plugin your own
syntax frontend.
Since unicode syntax looks best - at least we do think so - it is used in
the examples here. It is important to use an appropriate unicode font to
view them correctly. Most moderately recent browsers should have no problem
with this, while some text editors might need tuning.
If you prefer to use the ASCII (JSP like) syntax, note that there is a
converter available, which transforms one syntax into the other in both
directions.
-------------------------------------------------------------------------
Here is a list of correspondences between Unicode and ASCII syntax:
« java code » <% java code %>
⊰ comment ⊱ <%-- comment --%>
⊰✉ message ⊱ <%--#{message} message --%>
⊰✏ doclet ⊱ <%--#{doclet} doclet --%>
⊰⚒ work ⊱ <%--#{work} work --%>
◂ print code ▸ <%= print code %>
◂ print code ⌘encoding▸ <%= print code %%encoding%>
◂⊙▸ <%=#{current}()%>
◂Ⓘ▸ <%=#{index}()%>
▼ file level code (import) ▼ <%@ file level code (import) %>
▲ class level code (declaration) ▲ <%! class level code (declaration) %>
⊏ template code ⊐ <%? template code ?%>
⊏ signature(...) ⊐ <%? signature(...) ?%>
⊏ ➜ somepart(...) ⊐ <%? #{insert} somepart(...) ?%>
⊏ ⌘ ⊐...⊏ /⌘ ⊐ <%? %% ?%>...<%? /%% ?%>
◂‖"Ⓧ/./path/expression"▸ <%= ::"XPath/./path/expression"%>
◂‖"Ⓟ/..."▸ <%= ::"Property/..."%>
◂‖"✦/..."▸ <%= ::"XModel/..."%>
◂ recoded ⌘xml/html▸ <%= recoded %%xml/html%>
⊏ ⌘... ⊐ also recoded ⊏ /⌘ ⊐ <%? %%... ?%> also recoded <%? /%% ?%>
⊏ Ⓣ somepart(...) ⊐...⊏ /Ⓣ ⊐ <%? #{template} somepart(...) ?%>...<%? /#{template} ?%>
⊏ ◧ (...) ⊐...⊏ /◧ ⊐ <%? #{partition} (...) ?%>...<%? /#{partition} ?%>
≤ Java Template ≥ <- Java Template ->
≦ Model Template ≧ <= Model Template =>
⑊◂ escaped ⑊▸ ◂ escaped ▸ (i.e., escapes unicode interpretation)
⋖ tag(a,b,c) ⋗ <@ tag(a,b,c) @>
●(...){ ... }/● #{select}(...){ ... }/#{select}
∃(...){ ... }/∃ #{exists}(...){ ... }/#{exists}
¬∃(...){ ... }/¬∃ #{notexists}(...){ ... }/#{notexists}
⁇(...){ ... }/⁇ #{isvalid}(...){ ... }/#{isvalid}
¬⁇(...){ ... }/¬⁇ #{isinvalid}(...){ ... }/#{isinvalid}
∅(...){ ... }/∅ #{empty}(...){ ... }/#{empty}
¬∅(...){ ... }/¬∅ #{notempty}(...){ ... }/#{notempty}
⇾(...){ ... }/⇾ #{isa}(...){ ... }/#{isa}
∀(...){ ... }/∀ #{for}(...){ ... }/#{for}
∀(...∪...){ ... }/∀ #{for}(...#{union}...){ ... }/#{for}
∀(...){ ➀{...}∨{...}/➀ ... }/∀ #{for}(...){ #{first}(){...}#{else}(){...}/#{first} ... }/#{for}
∀(...){ ¬➀{...}∨{...}/¬➀ ... }/∀ #{for}(...){ #{notfirst}(){...}#{else}(){...}/#{notfirst} ... }/#{for}
➀:(...) #{declarepass}(...)
➀{ ... }/➀ #{first}(){ ... }/#{first}
➀(...){ ... }/➀ #{first}(...){ ... }/#{first}
➀: #{declarepass}
¬➀{ ... }/¬➀ #{notfirst}(){ ... }/#{notfirst}
¬➀(...){ ... }/¬➀ #{notfirst}(...){ ... }/#{notfirst}
ⓝ{ ... }/ⓝ #{last}(){ ... }/#{last}
¬ⓝ{ ... }/¬ⓝ #{notlast}(){ ... }/#{notlast}
⋈: #{declareduplicates}
⋈(...){ ... }/⋈ #{duplicates}(...){ ... }/#{duplicates}
¬⋈(...){ ... }/¬⋈ #{notduplicates}(...){ ... }/#{notduplicates}
}∨{ }#{else}(){
¶(...) /¶ #{indent}(...) /#{indent}
🅁pattern=replacement ~~~pattern=replacement (at start of line, template preprocessing)
⏎ \n
… \
⋮ <%|
⟦ expression ⟧ {* expression *} (prefixes and disables unicode interpretation)
ˮ \" (within expression)
␀ null
✔ true
✘ false
≡ .equals
≔ define
⟜ option
Ⓧ XPath
Ⓙ JPath
Ⓟ Property
✦ XModel
Ⓕ File
Ⓢ SQL
Ⓞ OQL
▢ Space
⁂ OCP
‖ ::
┃ oorl://
∈(...){ ... }/∈ #{element}(...){ ... }/#{element}
¬∈(...){ ... }/¬∈ #{notelement}(...){ ... }/#{notelement}
∉(...){ ... }/∉ #{notelement}(...){ ... }/#{notelement}
⊙ #{current}()
Ⓘ(...) #{index}(...)
Ⓘ #{index}()
Ⓘ: #{declareindex}
⊕ #{add}
⊖ #{remove}
⊛ #{create}
¬ #{not}
∨ ||
∧ &&
⤙ items to join to string ⤚ --( items to join to string )--
⚡ °° config property
★{} new java.util.HashMap<String,String>()
★[] new java.util.ArrayList<String>()
★ new
⚙ (*)
‹ <
› >
⎆ placeholder
❓ |?|
╏ |:|
↯ catch
⌚ #{time}
⬒⌚ #{datetime}
⬒ #{date}
⌾ #{format}
⌗ #{size}
⌀ #{average}
∏ #{product}
∑ #{sum}
⤓ #{minimum}
⤒ #{maximum}
⇵ #{reverse}
Ⓡ( ... ) RegularExpression(context, ... )
Ⓡ RegularExpression
≋( ... ) .tryGetMatches(context, ... )
|
Example0010_HelloWorld
| Example0010_HelloWorld |
|---|
G-2.0-plain_java-1.0
⊰
This templates creates a text with the famous words "Hello, world!".
⊱
Hello, world!
|
Example0020_Comment
| Example0020_Comment |
|---|
G-2.0-plain_java-1.0
⊰
This templates does not produce any output, but an empty file.
It demonstrates the use of template comments.
These comments do not show up anywhere except in the template source.
⊱
|
Example0030_Expression
| Example0030_Expression |
|---|
G-2.0-plain_java-1.0
⊰
This templates demonstrates the use of embedded java expressions.
⊱
⊰
The first example is just another way to say "Hello, world!".
The placeholder ◂...▸ is replaced by the value of the java expression
between the filled arrows.
⊱
Hello, ◂"world"▸!
⊰
So, any valid java expression is usable.
⊱
Hello, ◂"w"+"o"+"r"+"l"+"d"▸!
2 * 21 = ◂2*21▸
|
Example0040_Argument
| Example0040_Argument |
|---|
G-2.0-plain_java-1.0
⊰
This templates allows to greet arbitrary planets (not just worlds).
It demonstrates the use of template arguments.
When invoked, this templated receives an argument named "my_arg".
E.g., if the actual invocation argument is "Mars", it creates the text
"Hello, Mars!"
⊱
⊏ signature(String my_arg) ⊐
Hello, ◂my_arg▸!
⊰
Note the special characters "⊏" and "⊐" around the signature. These are
socalled "template code delimiters". The code inside them is processed by
the template parser, in contrast to java code inside "«" and "»". The
latter - Java code - is passed directly to the created intermediate Java
generator class.
It is useful to keep these different processing levels in mind.
⊱
|
Example0050_DefaultValue
| Example0050_DefaultValue |
|---|
G-2.0-plain_java-1.0
⊰
This templates allows to greet arbitrary planets, but by default the world.
It demonstrates the use of default values for template arguments.
If invoked without an argument, it prints "Hello, world!".
⊱
⊏ signature(String my_arg = "world") ⊐
Hello, ◂my_arg▸!
|
Example0060_PrettySyntax
| Example0060_PrettySyntax |
|---|
G-2.0-plain_java-1.0
⊰
This template demonstrates how to keep your templates readable.
There are three tiny syntactic helpers to solve three frequently encountered
problems.
⊱
⊰
To illustrate the first problem, note that between the first comment and
the second one (this one) there is a line break. This line break appears
not only in the template, but in the output, too. You will want your
template being reasonable layouted, while at the same time having nicely
layouted results. How to achieve this?
First, note the three tiny continuation dots '…' behind the following comment
end delimiter:
⊱…
⊰
They simple say: please ignore the line break (they are comparable to the
use of a backslash in programming languages like C or C++).
⊱…
⊰
Another problem often encountered is the indentation depth mismatch between
template code and result code. E.g.
⊱…
Hello, world!
⊰
is of course indented in the output by 30 spaces. How to avoid this,
without compromising template layout? That's the purpose of the indentation
character '⋮', like here
⊱…
⋮Hello, world!
⊰
The '⋮' character says: please ignore every whitespace between it and the
beginning of the line.
So, if you combine these concepts, you might e.g. write
⊱…
⋮Hello, …
⋮◂"world"▸…
⋮!…
⊰
which creates again "Hello, world!", without any additional spaces or line
breaks before, after of within the output.
⊱…
⊰
And finally, sometimes you may need the contrary of the continuation dots:
a linebreak in the output, but not in the template. This is the purpose of
the 'Return' sign '⏎'.
The following code produces 50 emtpy lines in the output:
⊱…
⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎⏎
|
Example0070_JavaCode
| Example0070_JavaCode |
|---|
G-2.0-plain_java-1.0
⊰
This templates demonstrates how to embed Java code statements.
Like in the previous examples, it prints "Hello, world!"
(if invoked without an argument).
⊱…
⊏ signature(String my_arg = "world") ⊐…
⊰
The characters '«' and '»' are used as delimimeters for arbitrary
Java code statements.
⊱…
« String greeting = "Hello, " + my_arg; »…
◂greeting▸
|
Example0080_JavaCode2
| Example0080_JavaCode2 |
|---|
G-2.0-plain_java-1.0
⊰
This templates demonstrates the embedding of arbitrary
types of Java code.
⊱…
« String greeting = "Hello, world!"; »…
◂greeting▸
« if (1 == 2) { » Something is wrong here. « } »…
Countdown: « for (int i=10; i>=0; i--) { » ◂i▸« } »
|
Example0090_TemplateIsAClass
| Example0090_TemplateIsAClass |
|---|
G-2.0-plain_java-1.0
⊰
Each template is translated into a Java class with
the same name and in the same package.
Therefore, all features of Java classes are available
from within templates, too.
⊱…
⊰
Within two characters '▲...▲' you can define class level
code. I.e. you can declare variables and define methods.
⊱…
▲ protected void times(int a, int b) { return a * b; } ▲…
3 * 7 = ◂times(3, 7)▸
⊰
You can declare class level code multiple times, and at
arbitrary locations within your template.
⊱…
▲ static final protected float pi = 3.14159265; ▲…
« floar r = 1.0; »…
area : ◂ pi * r * r ▸
|
Example0100_Encoding
| Example0100_Encoding |
|---|
G-2.0-plain_java-1.0
⊰
Templates produce output. Such output might be just plain
ASCII, plain Unicode or might be encoded somehow, say HTML.
Furthermore, templates process input, which may or may not
be written in the same encoding.
And finally, the normal template text might have a third
encoding.
Let's assume you want to create a Java properties file
based on XML input. Then
- in the input we have '<', '>' and '&'.
- in our template text we just want to write normal Unicode.
- in the properties file everything non-ASCII (e.g. german
umlauts) must be escaped '\uXXXX'
In templates, such a situation is rather the rule then
an exception.
Instead of writing conversion calls each and everyplace,
we just can use the recoding operator '⌘':
⊱…
« String xml_input = " immer und überall gilt: 17 < 23 "; »…
◂xml_input⌘XML/JAVAPROP▸
⊰
You get the output
" immer und \u00FCberall gilt: 17 < 23 "
The '⌘...' sequence is called a 'recoding'.
It consists of a sequence of encoding names. The above
example reads 'convert XML to JAVAPROP'.
The encoding names are defined in an enumeration class
named 'Encoding'. You can use this class also from normal
Java code.
If we have many such expressions in our template, we can
define a default recoding:
⊱…
⊏ ⌘XML/JAVAPROP ⊐…
◂xml_input▸
⊏ /⌘ ⊐…
⊰
This yields the same result as above.
Default encodings can be nested (they apply to included
and subtemplates, too, but we do not know yet what these are).
⊱…
⊏ ⌘DOCBOOK/JAVAPROP ⊐…
⋮⊏ ⌘XML/JAVAPROP ⊐…
◂xml_input▸
⋮⊏ /⌘ ⊐…
⊏ /⌘ ⊐…
⊰
This again yields the same result as above.
Encodings need not be complete, they will be combined.
⊱…
⊏ ⌘XML/ ⊐…
◂xml_input⌘/JAVAPROP▸
⊏ /⌘ ⊐…
⊰
This again yields the same result as above.
Note, that a default encoding applies to embedded Java expressions
as well as normal template text. What if they are different, as
within our example?
Then you can apply a different default encoding to these
categories.
⊱…
⊏ ⌘[x]XML/JAVAPROP ⊐…
⊏ ⌘[t]UTF8/JAVAPROP ⊐…
◂xml_input▸
This '<' is not translated, since we're here in normal
template text, not in an expression.
◂"But this '<' is translated, since we're an expression"▸
⊏ /⌘ ⊐…
⊏ /⌘ ⊐…
⊰
As you might have guessed, 'x' stands for 'expression' and
't' for 'template text'.
⊱…
|
Example0110_TemplateTypes
| Example0110_TemplateTypes |
|---|
G-2.0-plain_java-1.0
⊰
Up to now, all templates begun with this cryptic line:
G-2.0-plain_java-1.0
It reads like this:
G-2.0 this template requires "Generator, Version 2.0"
plain_java-1.0 it is a template of type "plain_java, Version 1.0"
The generator version is specified for compatibility reasons. If the
generator behaviour changes in future versions, it is used to support old
templates, or at least issue a warning about possible problems.
The template type specifies the context within which the template is
interpreted and executed. "plain_java" means: there's nothing but plain
Java available.
Some common contexts are:
plain_java-1.0 nothing special, just plain Java
plain_java_jspstyle-1.0 same, but enabling ASCII (JSP like) syntax
java_jpp-1.0 plain Java with a special preprocessor enabled
xml-1.0 for processing xml files
xml_string-1.0 for processing xml, passed as Strings
These contexts will be introduced in more detail in following examples.
⊱…
|
Example0120_ParserConfiguration
| Example0120_ParserConfiguration |
|---|
G-2.0-plain_java-1.0
⊰
This example explains how the parser configuration works.
It can be safely skipped on a first reading.
In the previous example template types were introduced. How do they affect
the generation process?
When interpreting a template, the first information read is the
introductory string:
G-2.0-plain_java-1.0
This is translated straight forward to the name of a template parser
configuration by replacing the "G" with "TP":
TP-2.0-plain_java-1.0
The parsers are very modularized and consist of several exchangable
building blocks. A parser configuration is a construction plan for a
specific parser, made of such components.
To build the parsers, Object Construction Plans (OCPs) are used. For
details on OCPs, please refer to <http://www.xocp.org>. Specifically, the
parser configurations are placed in the ocp package:
com/sphenon/engines/generator/parsers
Putting the pieces together, the above parser configuration is found in
a file in the ocp path at:
com/sphenon/engines/generator/parsers/TP-2.0-plain_java-1.0.ocp
In our example, it contains the following plan:
<?xml version="1.0" encoding="UTF-8"?>
<parser CLASS="TemplateParser" xmlns="http://xmlns.sphenon.com/com/sphenon/engines/generator">
<TOMParser>
<BeginHandler OID="mth" CLASS="TCHMain">
<SourceHandler CLASS="TCHCompactUnicodeSyntax2ASCII">
<ASCIISourceHandler CLASS="TCHLanguageDispatcher">
<TextHandler CLASS="TCHText"/>
<JavaCodeHandler CLASS="TCHJavaCode"/>
<JavaExpressionHandler CLASS="TCHJavaExpression"/>
<TemplateCommentHandler CLASS="TCHTemplateComment"/>
<TemplateCodeHandler CLASS="TCHTemplateCode"/>
<TagHandler CLASS="TCHTag"/>
<PPTagHandler CLASS="TCHPPTag"/>
</ASCIISourceHandler>
</SourceHandler>
</BeginHandler>
<SourceHandler OIDREF="mth"/>
<EndHandler OIDREF="mth"/>
</TOMParser>
</parser>
⊱…
|
Example0130_Locators
| Example0130_Locators |
|---|
G-2.0-java_jpp-1.0
⊰
This example is a bit lengthy, but it's worth reading.
One of the major issues with generator templates is their tendency to
become clumsy over time, and often plain unreadable. The purpose of
templates is to write the desired target output easily and concise -
unfortunately, this interferes with controlling code.
We've already seen how unicode syntax (Example0000_Unicode) and tiny syntax
helpers (Example0060_PrettySyntax) help to keep templates tidy. Another
means is of course moving longer code sequences into helper classes. Here's
a fourth possibility.
A very common type of template code is navigation code. I.e., given some
instance, the programmer invokes a sequence of methods to navigate to a
target instance. A simple example is:
« Person person = ...;
Address address = person.getAddress();
Vector<Phone> phones = address.getPhones();
Phone phone = phones.get(2);
Prefix prefix = phone.getPrefix();
»
If we just want to print the prefix, we can abbreviate like this:
The prefix is: ◂person.getAddress().getPhones().get(2).getPrefix()▸
The brackets and "gets" still look a bit clumsy, it looks better with
pathes:
The prefix is: ◂‖[person]"Ⓟ/Address/Phones/2/Prefix"▸
This is in fact a valid expression that can be used in templates of an
appropriate type.
Pathes are not directly built into the template parser - this is where
"Locators" come into play. The above statement is translated into an
invocation of a locator, which handles the path at runtime. The translated
code looks similar to this:
Locator.resolve("//Property/Address/Phones/2/Prefix", person);
(note the translation of the unicode "Ⓟ" into "//Property")
At runtime, the locator then translates this into a sequences of "gets",
like we've seen before. Admittedly, in this example, the syntactic
difference is not too big. But locators are much more powerful than this!
In fact, there's a universal concept behind them (you may want to
check out <http://www.oorl.org>, too). With pluggable locator extensions,
locators can be used to navigate through arbitrary structured
data. Instances and their relations are just an example. Other's are:
‖"//File//home/me/myfile.txt" a file in the file system
‖"//Space/company/workplace" a space
‖"//XPath/article/section/title" an element in a xml file
‖"//JavaResource/com/sphenon/basics" a resource in your classpath
‖"//Artefact/org/oomodels" a resource in a project
‖"//Model/org/uml/stereotypes" an element of a UML model
‖"//Address/Germany/Hamburg//Barkenkoppel" a street in a city
Moreover, locators can be concatenated
‖"//File//home/me/mytext.dbk/,//XPath/article/title"
The last example reads a file in your home directory, parses it with an xml
parser and retrieves it's title.
In addition to properties, the following unicode abbreviations are
predefined in the default preprocessor (CUS2ASCII):
Ⓟ Property (Java POJO property access)
Ⓧ XPath (navigation in xml, see www.w3c.org and xerces.apache.org)
Ⓕ File (navigation in file system)
✦ XModel (UML XModel extension property access)
To supported different locator syntaxes, several delimiters are supported:
‖'...'
‖"..."
‖(...)
‖{...}
‖§...§
To use locators, the parser has to know a little bit about the objects that
are retrieved. For simple cases like property access, it's enough to
declare the template type like we've done in this example:
G-2.0-java_jpp-1.0
The associated parser configuration enables the Java preprocessor, and
declares the default object type for locators as "Object". For property
access this is sufficient.
To complete this example here's some more working code.
First, we declare two test classes:
⊱…
▲
public class Planet {
public String getName() { return "world"; }
}
public class SolarSystem {
public Planet getPlanet() { return new Planet(); }
}
▲
⊰
Then, we create a SolarSystem and use a property to access it's sole
planet's name:
⊱…
« SolarSystem solar_system = new SolarSystem(); »…
Hello, ◂‖[solar_system]"Ⓟ/Planet/Name"▸!
⊰
This, of course, prints "Hello, world!" again.
⊱…
|
Example0140_LocatorTargets
| Example0140_LocatorTargets |
|---|
G-2.0-java_jpp-1.0
⊰
As mentioned in the previos example, the parser sometimes needs to know
something about the instances a locator returns. This is done by declaring
a socalled "locator target":
⊱…
⋮⊏ locatortarget Object = (Object object) ⊐…
⊰
The above statement is a declaration. It delares a locator target named
"Object" with an instance type of "Object" and a variable name of "object".
To switch between locator targets, the following selector can be used:
⊱…
⋮⊏ locatortarget Object ⊐…
⊰
Note that the declaration of a locator target also implicitly selects
it. Therefore, it is not necessary to write:
⊱…
⋮⊏ locatortarget Object = (Object object) ⊐…
⋮⊏ locatortarget Object ⊐…
|
Example0150_ParserInclusion
| Example0150_ParserInclusion |
|---|
G-2.0-inclusion_test-1.0
⊰
Now that we know how the parser configuration works, and how a template
type selects a configuration, we can define our own template type.
Let's assume we want to make a value magically available in all our
templates of this new type:
⊱…
The magic value is ◂magic_value▸ !
⊰
First, we define a template type, in our example this is
G-2.0-inclusion_test-1.0
As we know now, this type points to a configuration in this OCP file
com/sphenon/engines/generator/parsers/TP-2.0-inclusion_test-1.0.ocp
This OCP file contains:
<?xml version="1.0" encoding="UTF-8"?>
<parser CLASS="TemplateParser" xmlns="http://xmlns.sphenon.com/com/sphenon/engines/generator">
<TOMParser>
...
<IncludeModules>
<Module>com.sphenon.engines.generator.test.Example0150_ParserInclusion_MagicValueDefinition</Module>
</IncludeModules>
</TOMParser>
</parser>
This configuration specifies an include module Example0150_ParserInclusion_MagicValueDefinition.
Modules have the file extension ".template.module" to distinguish them from
normal templates. Syntactically, they are normal templates.
The next example shows the content of this module.
⊱…
|
Example0160_ParserInclusion_MagicValueDefinition (Module)
| Example0160_ParserInclusion_MagicValueDefinition (Module) |
|---|
G-2.0-plain_java-1.0
⊰
As described in the previous example, Example0150_ParserInclusion, this is
a template module. In our example, it defines a magic value, which is now
available in all our templates of the newly introduced template type.
⊱…
« int magic_value = 42; »…
|
Example0170_ControlBlocks
| Example0170_ControlBlocks |
|---|
G-2.0-java_jpp-1.0 -*- coding: utf-8; -*-
⊰
As mentioned in the previos example, the parser sometimes needs to know
something about the instances a locator returns. This is done by declaring
a socalled "locator target":
⊱…
« Vector friends = new Vector();
friends.add("Hans");
friends.add("Willy");
friends.add("Susi");
»…
⊰
⊱…
«∀(friend:friends){»…
◂friend▸
«}/∀»…
⊰
⊱…
«∀(friends){»…
◂object▸
«}/∀»…
⊰
⊱…
«∀(friends){»…
◂⊙▸
«}/∀»…
⊰
⊱…
« object = vector; »…
«∀(⊙){»…
◂⊙▸
«}/∀»…
⊰
⊱…
«∀(enemies){»…
⋮«∀(-friend:friends){»…
◂⊙▸ prints current enemy!
◂friend⊙▸ prints current friend
⋮«}/∀»…
«}/∀»…
⊰
⊱…
«¬∅(⊙){»…
Nicht leer! (FEHLER)
«}/¬∅»…
⊰
⊱…
«∅(⊙){»…
Leer!
«}/∅»…
⊰
⊱…
«∀(⊙){»«➀{»My friends: «}∨{», «}/➀»◂⊙▸«}/∀»
⊰
⊱…
My friends: «∀(⊙){»«¬➀{», «}/¬➀»◂⊙▸«}/∀»
⊰
⊱…
⋮«➀:(xy)»…
My friends, 2 times: «∀(⊙){»«¬➀(xy){», «}/¬➀»◂⊙▸«}/∀»«∀(⊙){»«¬➀(xy){», «}/¬➀»◂⊙▸«}/∀»
⊰
⊱…
«∀(⊙){»…
Friend number ◂Ⓘ▸ : ◂⊙▸
«}/∀»…
⊰
⊱…
«Ⓘ:(my_index)»…
«∀(⊙){»…
Friend number ◂Ⓘ(my_index)++▸ : ◂⊙▸
«}/∀»…
⊰
⊱…
String friend = "Hans";
«∃(⊙){»…
I've got a friend: ◂⊙▸
«}/∃»…
⊰
⊱…
«∃(friend:⊙){»…
I've got a friend: ◂friend▸
«}/∃»…
⊰
⊱…
String friend = null;
«¬∃(⊙){»…
I'm so lonely!
«}/¬∃»…
⊰
⊱…
boolean sun_is_shining = true;
«⁇(sun_is_shining){»…
Nice day!
«}/⁇»…
⊰
⊱…
sun_is_shining = false;
«¬⁇(sun_is_shining){»…
:-(
«}/¬⁇»…
|

