AÏOLI

What is Aļoli?

Aļoli is a toolkit to build interactive applications that manipulate data as tree. It is composed of 5 main components:
  1. VTP: an API for manipulating trees.
  2. METAL: a language for defining tree formalism.
  3. ANTLR: a tool for defining LL(k) parsers..
  4. PPML: a language for describing layout.
  5. GFXOBJ: an API for building interactive application,
To use Aļoli you simply need to add the directory of aioli classes to your classpath so if Aļoli is installed under net we have:
CLASSPATH:=/net/aioli/classes:$CLASSPATH
There are at the moment 3 contributions to Aļoli:Exp a simple interactive calculator, Lambda a definition of the lambda calculs, Java the definition of a viewer for Java.

VTP

Each tree in Aļoli belongs to a formalism. A formalism contains a set of operators and a set of phyla, i.e. subsets of the set of all operators. There are three kinds of operators:
  1. List operators have an arbitrary number of sons.
  2. The n-ary operators have a fixed number of sons.
  3. The atomic operators have no sons but contain an atomic value.
The notion of phylum allows to constrain which trees a given node accepts as son. The definition of a new operator gives for each son position a phylum. Note that our lists node are homogeneous so only one phylum is required for the definition of a list operators. Note also that a given operator may belong to several phyla.
For interactive application a special encapsulator for tree called variable is available. It is possible to attach tools to variables so that each modification on a variable will automatically be sent to the tool. In particular it is with the tool mechanism that layout update is implemented.

see: Forrmalism, Phylum, Operator, Tree, Variable

METAL

Eventhough it is possible to create formalism directly with the VTP Api, Metal is a dedicated language that eases this task. Here is the syntax definition of Metal:
program:  "formalism" "of" id "is"
                (def ";")*
          "end"
        ;

def:       op "->" sons
        | phylum "::=" (phylum|op)+
        ;

sons:     phylum "+.."
        | phylum "*.."
        |"implemented" "as" atomic
        | (phylum)*
        ;

atomic:   "STRING"
        | "INTEGER"
        ;

id: ("a".."z"|"A".."Z")("a".."z"|"A".."Z"|"_"|"0".."9")*
op: ("a".."z") ("a".."z"|"A".."Z"|"_"|"0".."9")*
phylum: ("A".."Z") ("a".."z"|"A".."Z"|"_"|"0".."9")*
A formalism description is composed of a list of definitions. Each definition introduces either an operator or a phylum. The operator definition gives the name of the operator, its arity and the phyla of its sons. We use the keywords "+...", "*..", "implemented as" to denote respectively list operators with at least one element, list operators possibly empty and atomic operators. The definition of a fixed arity operator simply list the phyla of its sons. The phylum definition gives the name of the phylum and the list of its components. Finally we use the syntactical convention that phylum names always start with an uppercase letter while operator names start with a lower case.

see: Metal definitions for Exp, Lambda, Java.

ANTLR

Antlr is a generic LL(k) parser generator. A complete introduction of Antlr can be found here, We have extended the Antlr syntax in order to handle Vtp constructs. It gives us an alternative way to write actions. The standard way to give action in Antlr is by directly writing Java code between curly brackets "{}" . Vtp actions use the double brackets "<<>>" as delimitators. Here is the syntax definition of Vtp actions:
action:   <<"" (constr ";")* ">>";

constr:   path ("=="|"="|"+="|"=+") pattern;

path:     id ("." int)*;

pattern:  var
        | node "(" (sons)? ")"
        | node "[" (sons)? "]"
        | node int
        | node string
        | node var ("^")?
        ;

var:      "*" (id)?;

node:     id (":" id)? ;

sons:     pattern ("," pattern)*;

string:     "\"" (~\"")* "\"";
int:        "0"|("1".."9")("0".."9")*
id:         ("a".."z"|"A".."Z") ("a".."z"|"A".."Z"|"_"|"0".."9")*
An action is composed of a sequence of atomic actions. There are 4 possible atomic actions:
  1. Var == Pattern defines the variable Var and gives it the value Pattern
  2. Path = Pattern changes the value denoted by Path with the value of Pattern.
  3. Path += Pattern inserts in first position of the subtree denoted by Path the value of Pattern.
  4. Path =+ Pattern inserts in last position of the subtree denoted by Path the value of Pattern.
A variable in Vtp action corresponds to the variable in Java with the same name. Note that when a variable is used in a pattern we prefix it with a "*" to avoid ambiguity. The type of the corresponding Java variable must be Tree. When we want to use a token to fill in an atomic variable, we also postfix the name with the symbol "^". In that case the type of the corresponding Java variable is then Token.
A Path is a variable name plus a possibly empty path using the standard Dewey notation.
The formalism used to build a node is either given explicitly in the construction FormalismName:Opname or is implicit. A special global variable vtpLanguage has been added in the Antlr definition to be able to set the default formalism.

see: Antlr definitions for Exp, Lambda, Java.

PPML

PPML is a language that describes an automatic translation from a tree representation into a more concrete representation. The conversion is given in term of a recursive traversal of the tree with respect to a set of layout rules. Each rule is composed of a right part that describes in which cases the rule should be trigerred, and a right part that describes the corresponding layout . A simple pattern-matching language is used to give the filters and a combinator-based language is used to express the expected layout. Here is the syntax definition of Ppml:
program:   "prettyprinter" id "of" id 
             ( "is" | "extends" id ("," id)* "with")
             ("auxillary" "package" string ";")?
             ( rule ";")*
           "end" "prettyprinter"
           ;

rule:      cpattern "->" box;

cpattern:  (id ":")? pattern  ("!" int)? (annot)?
            ("when" fun ("and" fun)*)?
           ;
pattern:     var ("as" pattern)?
           | id "(" (pattern ("," pattern)*)? ")"
           | id "[" (pattern ("," pattern)*)? "]"
           | id var           ;
           | id string           ;

fun:         fname "(" (farg ("," farg)*)? ")"
           ;

farg:        string
           | int
           | var
           | annot                   
           ;

box:         string
           | (id ":")? var  ("!" sint)?
           | (id ":")? annot  ("!" sint)?
           | "in" "class" "=" id ":" box
           | fname "(" var ")"
           | "(" (box)+  ")"
           | "[" combinator  (box)+ "]"
           | "if" fun ("then" box )? ("else" box )? "end"
           | "case" fun  (int ":" box)* ("default" ":" box)? "end"
           ;

combinator: "<" id (int ("," int)*)? ">"
           ;
var:        star | doublestar;

star :      "*" (id)?;
doublestar: "**" (id)?;
string:     "\"" (~\"")* "\"";
sint:       ("-"|"+") int 
int:        "0"|("1".."9")("0".."9")*
fname:        id ("." id)*
id:         ("a".."z"|"A".."Z") ("a".."z"|"A".."Z"|"_"|"0".."9")*
annot:      "^"  id
The traversal of the tree is done using a context name and an integer that gives an indication of the depth of the recursion. In a pattern it is possible to match these two quantities. Matching a context name can be used to define context dependent layout while matching the depth can be used to get layout of a large tree with a particular detail level. The initial context is the default context "0". A rule without context belongs to the default context.
The pattern language allows to match fixed-arity tree, list and atomic nodes. It accommodates aliasing and extra booleans constraints. Variables in patterns are used to represent either a single subtree or a list of subtree. We use the syntactically convention that the former ones are prefixed by a single star while the latter ones are prefixed by a double star. For example in the pattern node[*x,**y,*z], *x denotes the first subtree, *z the last one, and **y the immediate subtrees of the node except the first and the last one.
The combinator-based language allows to define box structures. Each box starts with a combinator that describes how the elements in the box have to be displayed. For the moment only 3 combinators are available:
  1. <h n> is the horizontal combinator. It displays the element of the box in an horizontal manner with an interword of n between them.
  2. <v n, m> is the vertical combinator. It displays the elements of the box in a vertical manner with an indentation of n with an interline of m.
  3. <hv n, m, p> is the paragraph combinator. It displays the elements of the box in a paragraph style using the page width with an interword of n, an indentation of m and an interline of p
Variables are used to do recursive calls. It is possible to explicitly change the context and increment or decrement the depth. Implicitly recursive calls without context are done in the default context and recursive calls without depth information are done with a decrement of one. Sublist variables are dealt by the recursor "()", for example [<h 0> ( **x ) ] generates a horizontal box whose elements are the recursive calls on the trees of the sublist **x. The language accommodates conditionnal layout by allowing conditionnal over external boolean functions (if) or external integer function (case). Terminal are represented by strings that can either be given explicitly or via an external function taking a variable as parameter. Finally it is possible to hook a graphic attribute class to box using the "in" keyword. Graphic attributes are used to retrieve the foreground color, background color and fonts. A terminal inherits the attribute class of its father. A box without attribute inherits of its father. The initial class atrribute is "default". Finally the keyword "auxillary package" is used to define which package is to be used for external function, if not specified the default package is aioli.lang.ppaux.

see: Ppml definitions for Exp, Lambda, Java

Gfxobj

Gfxobj contains a set of classes that helps building interactive application using Vtp trees. The main class is the Ctedit. It is displays a tree using a given prettyprinter, a page width and a detail level.