Home Page   We Generate Your Software.
Products Services Company Technology Demo Contact Site Map Search

Full list of in-depth articles - Feedback and questions - Request demo -


A programmer's introduction to Tefigel

  1  Plain text processing
  2  Simple scripting
  3  Scripts and text
  4  Variables
  5  Control flow and data constructs
  6  Subroutines and functions
  7  Tefigel sections and text sections
  8  Basic template-driven code generation
  9  Native XML processing
  10  Native CSV file processing
  Appendix A  Further information

Tefigel is a language expressly designed for code and documentation generation. The current version (103) of Tefigel represents a major step forward in terms of usability of this generation-oriented language. "Tefigel" stands for text file generation language.

This 10-step introduction will show you simple examples of the main features of Tefigel. You can freely download the Community Edition of SoProMach, which includes the Tefigel language processor. The Community Edition packages provide full-fledged examples of the software that you can generate with SoProMach.

Enough said, let's get down to programming in Tefigel.

1 - Plain text processing

Input files to Tefigel are plain text files. Input files with no instructions are copied unaltered to output.

Input to Tefigel [ File "01_plain_text" ]
Hello, my role here is that of presenting Tefigel templates.
I look like a simple plain text file. Most of the time white is
WHITE, black is BLACK, and grey is GREY. But sometimes things get
mixed up. For instance, two plus two usually yields four, but that
may also depend on the context.

Output from "/opt/somusar/bin/tefigel 01_plain_text" [ File "output/01_plain_text.out" ]
Hello, my role here is that of presenting Tefigel templates.
I look like a simple plain text file. Most of the time white is
WHITE, black is BLACK, and grey is GREY. But sometimes things get
mixed up. For instance, two plus two usually yields four, but that
may also depend on the context.

2 - Simple scripting

The other type of input files to Tefigel are scripts with variables, control structures, and subprograms, both built-in and user-defined.

Input to Tefigel [ File "02_simple_script" ]
@ tefigel

loop i=1,3
  echo Hello, world! (i)
endloop

for fruit=apple,orange,strawberry
   echo Fruit fruit_counter of fruit_loops is fruit
endfor

echo Today is ~date and it is now ~time

Output from "/opt/somusar/bin/tefigel 02_simple_script" [ File "output/02_simple_script.out" ]
Hello, world! (1)
Hello, world! (2)
Hello, world! (3)
Fruit 1 of 3 is apple
Fruit 2 of 3 is orange
Fruit 3 of 3 is strawberry
Today is Tue Nov 02 2004 and it is now 11:14:11.109

3 - Scripts and text

Scripts can use both external scripts and external text files as subprograms in a broad sense.

Input to Tefigel [ File "03_script_and_text" ]
@ tefigel

echo -------------- Use text as a subroutine
01_plain_text

echo -------------- Set some placeholders to new values, then reuse text
set     two=4
set    four=8
set context=circumstances

set BLACK="#000000"
set WHITE="#FFFFFF"
set  GREY="#888888"

01_plain_text

echo -------------- Use text without modifying its contents
attach 01_plain_text

Output from "/opt/somusar/bin/tefigel 03_script_and_text" [ File "output/03_script_and_text.out" ]
-------------- Use text as a subroutine
Hello, my role here is that of presenting Tefigel templates.
I look like a simple plain text file. Most of the time white is
WHITE, black is BLACK, and grey is GREY. But sometimes things get
mixed up. For instance, two plus two usually yields four, but that
may also depend on the context.
-------------- Set some placeholders to new values, then reuse text
Hello, my role here is that of presenting Tefigel templates.
I look like a simple plain text file. Most of the time white is
"#FFFFFF", black is "#000000", and grey is "#888888". But sometimes things get
mixed up. For instance, 4 plus 4 usually yields 8, but that
may also depend on the circumstances.
-------------- Use text without modifying its contents
Hello, my role here is that of presenting Tefigel templates.
I look like a simple plain text file. Most of the time white is
WHITE, black is BLACK, and grey is GREY. But sometimes things get
mixed up. For instance, two plus two usually yields four, but that
may also depend on the context.

4 - Variables

Tefigel variables are loosely typed. All variables can be used as string placeholders.

Input to Tefigel [ File "04_data" ]
@ tefigel

# Plain variables
set string=Hello, world!
set integer=123
set float=123.5

eval boolean float>integer

set result=integer
add result float

echo Some plain variables: "string", integer + float = result, and boolean.

Output from "/opt/somusar/bin/tefigel 04_data" [ File "output/04_data.out" ]
Some plain variables: "Hello, world!", 123 + 123.5 = 246.500000000000000, and 1.

5 - Control flow and data constructs

All most common control structures are available (if, case, several loop types). Main data structures are lists and data groups. The latter is a sort of last-minute data record. Several operators can be dynamically defined.

Input to Tefigel [ File "05_constructs_and_flow" ]
@ tefigel

# Data groups and lists
new_list(fruit_colors)

# Fill up the list
for fruit=apple,chestnut,strawberry

   for color=green,reddish-brown,red
      
      # Build a |-separated record and add it to the list
      set dg=~group(|,color,fruit)
      add_item(fruit_colors,dg)

   endfor

endfor

# Expand and print list contents
echo The fruit/color list contains

# Define a content concatenation operator
dash +
for item=~list_contents(fruit_colors)

   case item
      when=green|strawberry
         set opinion=immature
      when=green|chestnut
         set opinion=rather unlikely
      otherwise
         set opinion=ok
   endcase

   # Expand the |-separated record
   ungroup(item,|,color,fruit)

   if opinion=ok
      set recommendation=, you can eat it
   else
      set recommendation=
   endif

   # Use concatenation operator
   echo    Item item_counter/item_loops: color fruit: opinion+recommendation.

endfor
dash

Output from "/opt/somusar/bin/tefigel 05_constructs_and_flow" [ File "output/05_constructs_and_flow.out" ]
The fruit/color list contains
   Item 1/9: green apple: ok, you can eat it.
   Item 2/9: reddish-brown apple: ok, you can eat it.
   Item 3/9: red apple: ok, you can eat it.
   Item 4/9: green chestnut: rather unlikely.
   Item 5/9: reddish-brown chestnut: ok, you can eat it.
   Item 6/9: red chestnut: ok, you can eat it.
   Item 7/9: green strawberry: immature.
   Item 8/9: reddish-brown strawberry: ok, you can eat it.
   Item 9/9: red strawberry: ok, you can eat it.

6 - Subroutines and functions

External user-defined functions and subroutines are called by means of their path name. Arguments are associated with positional parameters. The number of arguments can vary. Return values are strings.

Input to Tefigel [ File "06_subprograms" ]
@ tefigel

echo This is main, calling subprogram/greeting_f(Hello,Welcome!,Goodbye)
echo that returns ~subprogram/greeting_f(Hello,Welcome!,Goodbye)

echo
echo This is main, calling subprogram/greeting_s(Hello,Welcome!,Goodbye)
echo that prints out:
subprogram/greeting_s(Hello,Welcome!,Goodbye)

Output from "/opt/somusar/bin/tefigel 06_subprograms" [ File "output/06_subprograms.out" ]
This is main, calling subprogram/greeting_f(Hello,Welcome!,Goodbye)
that returns "Goodbye - Welcome! - Hello"

This is main, calling subprogram/greeting_s(Hello,Welcome!,Goodbye)
that prints out:
   Greeting you with "Hello"
   Greeting you with "Welcome!"
   Greeting you with "Goodbye"

A function returning a string [ File "subprogram/greeting_f" ]
@ tefigel

interface(greetingA,greetingB,greetingC)

retvalue="greetingC - greetingB - greetingA"

A subprogram generating text [ File "subprogram/greeting_s" ]
@ tefigel

interface(...)

while REG_COUNT>0
   echo    Greeting you with "REG_0"
   shift
endwhile

7 - Tefigel sections and text sections

Generating software often requires to switch between scripting mode and text mode. Tefigel provides ad-hoc constructs for this purpose.

Input to Tefigel [ File "07_file_sections" ]
By default, Tefigel input files are processed as text files.
   Blanks and quotes are treated as letters and numbers:
   leading blanks, quoted tabs '	' , quoted quotes: "'",
are copied unmodified.

But input files may contain Tefigel sections, and Tefigel sections
may contain in turn text sections:
@ tefigel

   loop i=1,3
      echo    We are now in a Tefigel section
      if i=3
         echo    ...and this was the last loop.
      endif
   endloop

   echo Start a text section with some Tefigel commands embedded

@  text

Back to plain text, but you can still use Tefigel code:
@     set greeting=Hello!
   Greet you with "greeting"
@     unset greeting
   Greet you with "greeting"
Close text section, switch back to Tefigel section.

@  endtext

echo Back to Tefigel, but you can still produce text:

   set greeting=Hello!
   echo    Greet you with "greeting"

   unset greeting
   echo    Greet you with "greeting"

echo Close Tefigel section, switch back to text section.
@ endtefigel

That's all for script "~cur_input()".

Output from "/opt/somusar/bin/tefigel 07_file_sections" [ File "output/07_file_sections.out" ]
By default, Tefigel input files are processed as text files.
   Blanks and quotes are treated as letters and numbers:
   leading blanks, quoted tabs '	' , quoted quotes: "'",
are copied unmodified.

But input files may contain Tefigel sections, and Tefigel sections
may contain in turn text sections:
   We are now in a Tefigel section
   We are now in a Tefigel section
   We are now in a Tefigel section
   ...and this was the last loop.
Start a text section with some Tefigel commands embedded

Back to plain text, but you can still use Tefigel code:
   Greet you with "Hello!"
   Greet you with "greeting"
Close text section, switch back to Tefigel section.

Back to Tefigel, but you can still produce text:
   Greet you with "Hello!"
   Greet you with "greeting"
Close Tefigel section, switch back to text section.

That's all for script "07_file_sections".

8 - Basic template-driven code generation

Complex generators take advantage of the file-system-oriented design of Tefigel, that allows to map complex template hierarchies directly onto the file-system's hierarchy. Internal hierarchical structures (for instance, metadata) are generally stored in lists.

Input to Tefigel [ File "08_templates" ]
@ tefigel

# Define two simple classes. All members are strings
new_list(Customer,name,address,email)
new_list(Product,code,description)

# Create a list of the classes
new_list(Classes,Customer,Product)

# Generate a Java and a C# class file for each class in the list
for ThisClass=~list_contents(Classes)

   for language=java,cs

      # Expand the appropriate template for each language into 
      # a different class file under directory "output"
      output output/ThisClass.language
      template/language(ThisClass)

   endfor

endfor

A simple Java template [ File "template/java" ]
@ interface(ThisClass)
@ set Attributes=~list_contents(ThisClass)

public class ThisClass {

@ for Attribute=Attributes
   private String Attribute;
@ endfor

@ for Attribute=Attributes
   public String get~to_Upper(Attribute)() {
      return Attribute;
   }

   public void set~to_Upper(Attribute)(String Attribute) {
      this.Attribute = Attribute;
   }

@ endfor
}

A simple C# template [ File "template/cs" ]
@ interface(ThisClass)
@ set Properties=~list_contents(ThisClass)

public class ThisClass {

@ for Property=Properties
   private string Property;
@ endfor

@ for Property=Properties
   public string ~to_Upper(Property) {
      get {
         return Property;
      }
      set {
         Property = value;
      }
   }

@ endfor
}

Output from "/opt/somusar/bin/tefigel 08_templates" [ File "output/Customer.java" ]

public class Customer {

   private String name;
   private String address;
   private String email;

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public String getAddress() {
      return address;
   }

   public void setAddress(String address) {
      this.address = address;
   }

   public String getEmail() {
      return email;
   }

   public void setEmail(String email) {
      this.email = email;
   }

}

Output from "/opt/somusar/bin/tefigel 08_templates" [ File "output/Customer.cs" ]

public class Customer {

   private string name;
   private string address;
   private string email;

   public string Name {
      get {
         return name;
      }
      set {
         name = value;
      }
   }

   public string Address {
      get {
         return address;
      }
      set {
         address = value;
      }
   }

   public string Email {
      get {
         return email;
      }
      set {
         email = value;
      }
   }

}

Output from "/opt/somusar/bin/tefigel 08_templates" [ File "output/Product.java" ]

public class Product {

   private String code;
   private String description;

   public String getCode() {
      return code;
   }

   public void setCode(String code) {
      this.code = code;
   }

   public String getDescription() {
      return description;
   }

   public void setDescription(String description) {
      this.description = description;
   }

}

Output from "/opt/somusar/bin/tefigel 08_templates" [ File "output/Product.cs" ]

public class Product {

   private string code;
   private string description;

   public string Code {
      get {
         return code;
      }
      set {
         code = value;
      }
   }

   public string Description {
      get {
         return description;
      }
      set {
         description = value;
      }
   }

}

9 - Native XML processing

Tefigel processes XML files using callbacks to user-provided functions. Complex XML hierarchies can be mapped onto corresponding file-system hierarchies of element processors, possibly grouped together. XML is one of the favorite sources of metadata for SoProMach.

Input to Tefigel [ File "09_xml_process" ]
@ tefigel

new_list(Classes)

# Read a list of simple metadata from an XML model file
set TARGET_TAG_PATH=model/class
tag_file_process(model.xml,subprogram)

for ThisClass=~list_contents(Classes)
   echo Class ThisClass contains:~list_contents(ThisClass, )
endfor

XML input to Tefigel [ File "model.xml" ]
<model>
   <class name="Customer">
      <attribute>
         <name>name</name>
      </attribute>
      <attribute>
         <name>address</name>
      </attribute>
      <attribute>
         <name>email</name>
      </attribute>
   </class>

   <class name="Product">
      <attribute>
         <name>code</name>
      </attribute>
      <attribute>
         <name>description</name>
      </attribute>
   </class>
</model>

Output from "/opt/somusar/bin/tefigel 09_xml_process" [ File "output/09_xml_process.out" ]
Class Customer contains: name, address, email
Class Product contains: code, description

Entering a tag [ File "subprogram/tag_node.in" ]
@ tefigel

if TAG_ID=class
   globset Class=tp_name
   new_list(Class)
endif

Processing a tag's content [ File "subprogram/tag_node.tval" ]
@ tefigel

if TAG_PATH~class/attribute/name
   add_item(Class,TAG_TEXT)
endif

Exiting from a tag [ File "subprogram/tag_node.out" ]
@ tefigel

if TAG_ID=class
   add_item(Classes,Class)
   unset Class
endif

10 - Native CSV file processing

Tefigel processes CSV files using a callback to a user-provided function, which receives the data values from the CSV file as call arguments. CSV files are also one of the favorite sources of metadata for SoProMach.

Input to Tefigel [ File "10_csv_process" ]
@ tefigel

new_list(Classes)

# Read a list of simple metadata from a CSV model file
escape \
csv_file_process(model.csv,subprogram/mk_class_list,\,)
escape

for ThisClass=~list_contents(Classes)
   echo Class ThisClass contains:~list_contents(ThisClass, )
endfor

CSV input file to Tefigel [ File "model.csv" ]
Customer,name,address,email
Product,code,description

Output from "/opt/somusar/bin/tefigel 10_csv_process" [ File "output/10_csv_process.out" ]
Class Customer contains: name, address, email
Class Product contains: code, description

Processing a CSV record [ File "subprogram/mk_class_list" ]
@ tefigel

interface(...)

set Class=REG_0
shift

new_list(Class)

while REG_COUNT>0
   add_item(Class,REG_0)
   shift
endwhile

add_item(Classes,Class)

Appendix A - Further information

Download the source code of this page from here:

tefigel_intro.tar.gz 3926 bytes

The free Community Edition of SoProMach and the proofs-of-concept (POCs) provide extensive examples of use of Tefigel. You can download both SoProMach and the POCs from the download page.

All electronic booklets on Tefigel are freely available on line: see in particular the reference guide and a tutorial. Error and warning messages are described in the User's guide.

Tefigel is one half of SoProMach. The other half, Sisendel, is a higher-level metadata definition language that uses Tefigel to generate software. Several POCs make use of Sisendel. "Sisendel" stands for simple software entity design language.

All documentation on SoProMach is available on line. For more information please contact us.


Written on 2 November 2004
Full list of in-depth articles - Feedback and questions - Request demo -

http:// www.somusar.com  / company  / news  / in_depth  / quick_tefigel  - Powered by SoProMach
Copyright © 2003-2012 Somusar - Trademarks - Legal - Privacy - Webmaster