Reuseware Composition Framework
Components, Modules, Aspects or something new?
Introduce new Composition Techniques into your Language of Choice with Reuseware!


Basic Composition Language Refernce

This is a reference of the basic composition language provided by FraCoLa. The language can be used in any invasive composition system to compose fragment components independent of the component language. The abstract and concrete syntax definitions of the language are described like all languages in the Reuseware Framework and can be found at the end of this article.

Composition Statement

A composition program is a sequence of composition statements. The following composition statements are available in the basic composition language:

  • "fragment" type fragment-name "=" value ";"
    declares a fragment. A fragment has a type (i.e., the language construct it is an instance of) and a name. The value that is assigned can be:
    • "/" path-element )+ "." extension
      the path to a file containing the fragment.
    • name
      the name of another fragment that should be assigned to the new name.
    • "'" code-piece "'" "+" | fragment-name "+" )+ "." extension
      the code of a new fragment to construct. The extension identifies the concrete syntax the fragment is written in. The fragment code is a concatenation of defined code pieces and code pieces that are extracted from other fragments. This enables the construction of new fragments from existing ones based on their content only. The types of the existing fragments are irrelevant here.
  • "print" fragment-name "to" path ";"
    prints the fragment to the path (path definition is equal to path definition in fragment declarations).
  • "if" condition "{" if-body "}" ( "else" "{" else-body "}" )?
    evaluates the condition and executes either the composition statements contained in the if-body or in the else-body. The condition can be:
    • fragment-name1 "equals" fragment-name2
      that types and code of two fragments are equal.
    • fragment-name "instanceof" type
      that a fragment is an instance of a certain type (i.e., construct).
    • "isbound" slot "on" fragment-name!
      that a slot is bound (i.e., does not exist anymore) on a fragment.
  • "foreach" "(" fragment-name ":" fragment-list ")" "{" body "}"
    iterates over the fragment list and executes the body for every iteration. In every iteration, the current fragment in the list is made available under the given fragment name.
  • "traverse" "(" fragment-name ":" fragment-list ")" "{" body "}"
    traverses over the tree of sub-fragments of the fragments in the fragment list and executes the body for each sub-fragment. In every step, the current sub-fragment is made available under the given fragment name. The traversing of a sub-tree can be prevented by using the prune statement.

Composer Statements

Composer statements are special composition statements that execute composition operators. The composition language includes such statements for the primitive composition operators.

  • "bind" (slot-name "on")? fragment-name "with" value ;
    queries for the slot(s) in the fragment and binds them with the value. The value is a fragment and the ways of specifying it correspond to the ways of defining the value of a fragment declaration. If no slot name is specified, the fragment is replaced with the value.
  • "extend" (hook-name "on")? fragment-name "with" value ";"
    queries for the hook(s) in the fragment and extends them with the value. If no hook name is specified, the value is added to the list containing the fragment.
  • "prepend" (hook-name "on")? fragment-name "with" value ";"
    queries for the hook(s) in the fragment and prepends the value (specialization of extend).
  • "append" (hook-name "on")? fragment-name "with" value ";"
    queries for the hook(s) in the fragment and appends the value (specialization of extend).

Modularization and Composition

Composition programs are themselves composable. In particular, they may contain in-place bind operations that are especially applicable in composer definitions (see next section).

  • "->" value!
    Binds the value in-place.

In-place binds are available for values, fragment names, fragment types, and variation point names.

Composer Definitions

The basic composition language contains a construct to define complex composers. For each composer defined, a construct to call the composer has to exist in a specialized composition language.

  • "define" "composer" construct "(" arguments ",")* ")""{" statementList ("return" returnFragment ";")? "}"
    defines the composer for the construct utilized to call it. The arguments have to correspond to the references of the call construct. The statement list may contain any composition statement. The return fragment, if specified, is bound in-place after the composer's execution.

The arguments are accessible as fragments. Thus, they can be directly composed, meaning that the fragments passed to the composer are bound and extended with each other. However, often arguments configure the composer itself. In this case, they need to be bound in-place (e.g., one argument is the name of a slot the composer should address: bind ->slotNameArg on fragArg1 with fragArg2;).

Language Descriptions

Abstract syntax grammar

CompositionProgram       = statementList:CompositionStatementList; 
CompositionStatementList = statements:CompositionStatement*; 
CompositionStatement     = Composer | FragmentDeclaration | Print | Conditional | ForEachLoop | 
                           Traverse| Prune; 
FragmentDeclaration      = type:componentmodel.AbstractFragmentType, 
componentmodel.AbstractFragmentType = FragmentTypeBind; 
FragmentTypeBind    ==> Bind; 
AbstractFragmentName  = FragmentName | FragmentNameBind; 
FragmentNameBind    ==> Bind; 
FragmentName          = name:S, subFragment:AbstractFragmentName?, index:S?; 
Value                 = Location | AbstractFragmentName | FragmentDefinition | ValueBind; 
ValueBind           ==> Bind;
Location              = path:S; 
FragmentDefinition    = codePieces: CodePiece+, fileExtension:S; 
CodePiece             = ConcreteCodePiece | AbstractFragmentName | RandomPiece; 
ConcreteCodePiece     = code:S; 
Print                 = fragment:AbstractFragmentName, location:Location; 
ForEachLoop           = fragmentName:AbstractFragmentName, 
Traverse              = fragmentName:AbstractFragmentName, 
Conditional           = condition:ConcatenatedCondition, 
Condition             = InstanceofCondition | IsBoundCondition | EqualsCondition; 
ConcatenatedCondition = conditions:Condition+; 
InstanceofCondition   = fragment:AbstractFragmentName, 
IsBoundCondition      = fragment:AbstractFragmentName, 
EqualsCondition       = fragment1:AbstractFragmentName, fragment2:AbstractFragmentName; 
VariationPointNameBind                  ==> Bind; 
componentmodel.AbstractVariationPointName = Bind;
Composer  = Bind | Extend | Prepend | Append; 
Bind      = slot:componentmodel.AbstractVariationPointName?, 
            fragment:AbstractFragmentName?, value:Value; 
Extend    = hook:componentmodel.AbstractVariationPointName?, 
            fragment:AbstractFragmentName?, value:Value+; 
Prepend ==> Extend; 
Append  ==> Extend;

Concrete syntax grammar

CONCRETESYNTAX fcp FOR compositionlanguage 
CompositionProgram       ::= "composition" "program" statementList; 
CompositionStatementList ::= statements*; 
FragmentDeclaration ::= "fragment" type name "=" value ("," value)* ";"; 
Location            ::= path[(’/’ (’A’..’Z’|’a’..’z’|’0’..’9’|’_’|’.’|’’)+)+]; 
FragmentDefinition  ::= codePieces (’+’ codePieces)* "."fileExtension[(’A’..’Z’|’a’..’z’|’_’) 
ConcreteCodePiece   ::= code[ ’\’’ (~(’\’’))* ’\’’]; 
RandomPiece         ::= "?"; 
Bind    ::= "bind" (slot "on")? fragment "with" value ";"; 
Extend  ::= "extend" (hook "on")? fragment "with" value ("," value)* ";"; 
Prepend ::= "prepend" (hook "on")? fragment "with" value ";"; 
Append  ::= "append" (hook "on")? fragment "with" value ";"; 
Print   ::= "print" fragment "to" location ";"; 
ValueBind              ::= "->" value; 
FragmentNameBind       ::= "->" value; 
FragmentTypeBind       ::= "->" value; 
VariationPointNameBind ::= "->" value;
FragmentName ::= name[(’A’..’Z’|’a’..’z’|’_’)(’A’..’Z’|’a’..’z’|’_’|’0’..’9’)*] 
                 ("[" index[(’’)?(’0’..’9’)+] "]")? ("." subFragment)?; 
componentmodel.VariationPointName ::= name[(’A’..’Z’|’a’..’z’|’_’) 
componentmodel.FragmentType       ::= (language[(’A’..’Z’|’a’..’z’|’_’) 
                                      (’A’..’Z’|’a’..’z’|’_’|’0’..’9’)*] ".")? 
Conditional           ::= "if" "(" condition ")" "{" ifBody "}" ("else" "{" elseBody "}")?;
ConcatenatedCondition ::= conditions ("&&" conditions)*; 
InstanceofCondition   ::= fragment "instanceof" type; 
IsBoundCondition      ::= "isbound" slot "on" fragment; 
EqualsCondition       ::= fragment1 "equals" fragment2; 
ForEachLoop           ::= "foreach" "(" fragmentName ":" list ")" "{" body "}"; 
Traverse              ::= "traverse" "(" fragmentName ":" list ")" "{" body "}"; 
Prune                 ::= "prune" ";";