The EBNF Grammar for Editor Specifications
An editor specification starts with an optional package declaration
(it is strongly encouraged to really declare a package),
followed by the declarations of the edge types (diagram components and
relations of the SRHG, terminal and nonterminal edges of the HGM). The
declaration of the constraint manager which is used in the editor's
intelligent mode is optional, too. If this declaration is omitted,
intelligent mode is not available for the specified editor. The actual
diagram language specification consists of the reducer
(lexical analysis) and the hypergraph grammar (used by
syntactic and semantic analysis).
Finally, complex operations may be specified in order to support
syntax-directed editing.
The package declaration for the generated files. If specified, all files
are generated in this package. The directory
of this package has a path which starts at the base directory. This is
either the working directory or the base directory which has to be
specified by using the -b option of the generator.
The declaration of the edge types which are used in this specification.
Declarations can be written down in any order.
Edge types for the SRHG are either diagram components or relation edges.
You can declare more that one component or relation edge in one declaration
by separating declared edge types by commas.
Each SRHG edge type is specified by its name and the edge
arity (i.e., its number of tentacles) in brackets. Optionally,
a supertype may be declared. This supertype has to be
a declared type of the same kind (i.e., component, relation,
or link) with an arity which is not less than the arity of
the edge type which is just being declared.
A component edge declaration either defines a fixed
or a variable number of attachment areas.
A component edge declaration must specify exactly one
implementation class, or no implementation class if
this edge type is used as an (abstract) supertype.
A component edge declaration must specify exactly one
implementation class, or no implementation class if
this edge type is used as an (abstract) supertype.
A relation edge declaration must specify at least one
implementation, or no implementation if
this edge type is used as an (abstract) supertype.
A relation can be implemented in the form of an explicit skeleton
class similar to a component skeleton class. Alternatively, the
implementation declaration can specify only a static relation test
method, which is indicated by paretheses around the attachment
declarations instead of brackets. In this case, an anonymous
implementation is automatically generated, which calls the
specified static relation test method
A link edge declaration must not specify an implementation class.
Link edges may be declared as transient; those link edges are
always removed from the srhg after the next reducing process
An implementation declaration for a component or a relation edge
must specify a list of connector names:
- For component edges, this list
specifies the types of the corresponding connectors and thus the
types of the corrsponding hyperedge tentacles. The length of this list
has to correspond to the arity of the hyperedge type.
- For relation edges, this list has to consist of two connector
types which have to be specified in some component edge declaration. The
specified relation
edge will only be created between nodes which are visited by tentacles
of the specified type (but of course only if the test method of the
specified class returns true.)
Edge types for the HGM (i.e., which are used by the grammar) are either
terminal or nonterminal.
You can declare more that one terminal or nonterminal edge in one declaration
by separating declared edge types by commas.
Each terminal or nonterminal edge type is specified by its name, the edge
arity (i.e., its number of tentacles) in brackets and an optional list
of attribute declarations. Constraint variables, which are used for
automatic layout, have to be specified in this list.
An attribute declaration list has a similar syntax as the declaration
of member variables in Java. Type names may be qualified class names
(if the class name is not qualified,
the class is expected to exist in the package which has been specified
in the package declaration). A special
type name is Variable which specifies constraint variables.
The optional constraint manager specification. Currently, only
QOCA (use
diagen.editor.param.QocaLayoutConstraintMgr as qualified name) and
application specific layouters which have to be programmed manually (use
diagen.editor.param.CustomizedConstraintMgr) are really supported.
The optional specification of a diagram model class. Usually the
default class diagen.editor.graph.GraphModel will be sufficient
here, but you can use your own subclass instead, e.g. if you need
to associate additional information with you diagrams
The reducer (lexical analysis) consists of a list of reduction rules.
Each rule has to be terminated by a semicolon.
Each reduction rule consists of an LHS, an arrow "==>", an RHS,
an optional list of actions which are executed if this rule is applied, and
an optional condition (boolean expressions, path expressions, etc.)
which must hold if this rule is going to be applied. The LHS consists of
a non-empty list of component or relation edges and, optionally, of
negative contexts. The RHS consists of an optionally empty list of
terminal edges and/or unification of nodes. LHS and RHS edges may be
labeled by arbitrary identifiers which may be used in the action list
to refer to the corresponding edges.
The semantics of such a rule are as follows:
- The LHS edges and the negative context specifications describe
a hypergraph. The set of edges is explicitly specified in the corresponding
lists. The node names which are used in the edge specifications, define
the set of nodes. Nodes which are referred to by different edges, but which
carry the same name, are considered to be the same node. The RHS also
specifies a graph. However, nodes which carry the same label in the LHS and
RHS are not considered to be equal.
- The rule is applied if the hypergraph which is specified by the LHS can
be matched with a sub-hypergraph of the SRHG and none of the additionally
specified negative context
subgraphs can be matched, too. Furthermore, the optional logical condition
must hold, too
- If the rule is applied, the corresponding RHS is added to the HGM; the
SRHG is not modified by this rule. Nodes with the same label in the
LHS and the RHS refer to corresponding nodes of the SRHG and the HGM.
Therefore, the context hypergraph of the HGM, where the RHS has to fit in,
is specified by those nodes of
the rule which carry the same label in the LHS and RHS.
- If the rule is applied and the rule specifies unification of rules,
the corresponding nodes of the HGM are unified. This has NO effect on
the nodes of the SRHG.
- The specified actions are only executed if the rule is applied.
A negative context specifies a hypergraph together with an optional
logical condition (boolean expressions, path expressions, etc.).
A negative context is matched together with the LHS of a
reduction rule. But this context does not apply,
i.e., does not prevent application of a reduction rule, if the optional
condition does not hold. The condition has access to nodes and hyperedges of
this context as well as of the LHS of the corresponding reduction rule.
A reduction rule can assign values of LHS
components to attributes of RHS terminal edges, it can call a
static method, it can declare local constraint variables and it
may add constraints to the constraint network that determines the
layout.
If a reduction rule is applied, it may invoke
a method of the specified LHS diagram component which is represented by its
component hyperedge. The parameters of this method are LHS edges (of type
diagen.hypergraph.Edge) . The return value of this method, if any, is then
assigned to an attribute of an RHS terminal edge. Edges are referred to
by labels which must have been declared in the LHS resp. RHS of the
corresponding reduction rule.
An attribute of an edge is specified by the label of the edge which must
have been declared before, a ".", and the name of the attribute. An attribute
in angles indicates an array of corresponding attributes of all the rhs edges
of a set production instance.
If a reduction rule is applied, it may unify
nodes of the HGM. Nodes are referred to by node names which are used
in the LHS of the rule. These LHS nodes must have been matched with
SRHG nodes. However, these SRHG nodes are not unified, but their
corresponding HGM nodes. Node unification does not have any effect
on the SRHG.
A grammar specification consists of the specification of the grammar's
axiom, i.e., the starting edge type, and some productions. Currently,
DiaGen only supports context-free hypergraph grammars with
embeddings, i.e., each production is either a context-free one or an
embedding production.
The grammar's axiom is specified by a nonterminal hyperedge type. An
attribute of this edge type can optionally be specified. The value of
this attribute is then used as the semantic representation of the
subhypergraph, i.e., subdiagram, that is derived from an instance
of this starting edge (see method
semantics()
in class
DiagramModelEvent)
A context-free production's LHS consists of a single nonterminal edge.
This edge may be labeled by an identifier which may be used
to refer to this edge. You can specify multiple right-hand sides for
a single LHS edge by using "|".
The RHS of a context-free production
is a hypergraph which consists of terminal and nonterminal hyperedges
and which is augmented by conditions, semantic actions, and layout
constraints. Or it is a set of identically labeled edges which
visit the same nodes with specified tentacles.
The rhs of a set production consists of an optional multiplicity
specification, a nonterminal edge, and optional attribute evaluation
rules. The multiplicity specifies how often the specified edge has to
occur. The edge is specified with named nodes and
undetermined nodes (_). All edges which visit the same nodes with those
tentacles which are specified by named nodes form the rhs of the reduction.
The optional evaulation rules apply to each of these edges.
An embedding production embeds an edge (either terminal or
nonterminal) into a context hypergraph which consists of terminal and
nonterminal hyperedges and which is augmented by conditions, semantic
actions, and layout constraints. The context hyperhraph must contain a
"*" for specifying the embedding position. "*" has to be specified
since the embedding edge has to be found by the parser as part of the
context hypergraph. The embedded edge may be labeled by an
identifier which may be used to refer to this edge.
The RHS of a context-free production which is not a set production or
the context hypergraph of an
embedding production. It consists of a hypergraph with terminal and/or
nonterminal edges, an optional "!" to enforce the test of the gluing
condition
(this test is omitted by default for error tolerant parsing), an optional
condition that must hold if the RHS hypergraph is going to be reduced
(either to the LHS if this belongs to a context-free production, or to
some intermediate structure which is responsible for detecting
embedding production instances). The optional list of actions is executed
if the corresponding production is reduced. This list may contain
constraints which are then added to the constraint system that determines
the diagram's layout.
The plain RHS hypergraph of a context-free production or the
plain context hypergraph of an embedding production. The hypergraph is
specified by a list of hyperedges. The nodes are implicitly specified
like in the LHS and RHS of a reduction rule. Edges
may be labeled by arbitrary identifiers which can be used to refer to
these edges.
The hyperedge list may be structured by brackets. The DiaGen
hypergraph parser requires productions to be in extended Chomsky normalform,
i.e., the RHS of a context-free production must not have more than two
hyperedges. The DiaGen generator transforms each RHS into a suitable
form if necessary. Brackets can be used to give hints to the generator
which parts of the RHS should be reduced first. The generator implicitly
adds brackets in a left-associative manner if no brackets or not all of
them are specified.
A special hyperedge symbol is "*" which is used to represent the embedded
hyperedge in an embedding production. The position of the "*" is crucial
since the parser has to find the embedded edge as part of its context.
The "*" therefore specifies when to search for the embedding edge relative
to its context. Brackets can also be used to influence this search process.
A production can have attritute evaluation rules, it can declare local
constraint variables,
and it may add constraints to the constraint network that determines
the layout.
An attribute evaluation rule is either a method call where the return
value, if any, is assigned to an attribute or an attribute assignment.
There is no prescribed order how to evaluate attributes (e.g., bottom-up
or top down in case of a syntax tree). Any dependency between attributes
can be specified. However, you can end up with circular dependencies
which cannot be solved.
A method call which is used in an attribute evaluation rule may call
a static method which is specified by its qualified name. If the
class name of the corresponding class is not fully qualified, the class is
expected to exist in the package which has been specified
in the package declaration.
The section which specifies complex editing operations. Each operation
may make use of simple transformation rules on the SRHG which have to be
specified in this section, too.
do-part to refer
to the edges.
The rule is applied if the hypergraph which is specified by the
LHS can be matched with a sub-hypergraph of the SRHG and none of the
additionally specified negative context
subgraphs can be matched, too. Furthermore, the optional logical condition
must hold, too. The LHS edges are tried to be matched against the SRHG
in the order as specified. Operations specify a partial match for the
LHS by defining the matching edges for a prefix of this LHS list.
Rules can be either primitive, or they can refer to other
rules. If a primitive rule (containing a "do" keyword) is applied
to the SRHG, the do-part adds and removes
individual SRHG edges. Non-primitive rules are use the "call"
keyword instead, followed by a sequence of operator actions, which
themselves refer to other (primitive or non-primitive) rules.
The optional return specification has to contain edges which have
been specified either in the LHS or as created edges in the
do-part. The rule returns the corresponding SRHG hyperedges, if
this rule is scuccessfully applied to the SRHG. Nodes which have
been matched can be returned, too. Nodes are specified by an
implicit hyperedge "node(x)" where "x" must be a valid node
label.
Note: The current generator implementation does not support
non-primitive rules that pass on return edges form called
rules. I.e. the following construction is not (yet) permitted:
rule outer arg:e(a)
call [res] = inner(arg)
return res; // could only return arg here
Edges which shall be matched by the LHS of a simple transformation rule
can be specified by an extended path expression which describes paths
starting at the specified edge. The kind of edge (component, relation,
or link) has to be specified, too, if this edge is going to be deleted
by the same rule. This is so since different kind of edges have to be
handled differently already in the generated code. Specifying the kind of
edge implicitly restricts the path expression, i.e., if "component" is
specified, this matcher will find components only.
Edges which shall be matched by the LHS of a simple transformation rule
can be specified by a plain edge.
The do-part of a simple SRHG transformation rule. It may delete relation and
component edges (relation edges which visit nodes of deleted component
edges are implicitly deleted, too) or create relation and component edges.
A rule action that deletes relation, component or link edges
(relation edges which visit nodes of deleted component edges are
implicitly deleted, too).
A rule action that creates relation, component or link edges. A
suitable initializer has to be specified if a component edge is
going to be created. It is this initializer's task to create a
diagram component of the desired type and to initialize attributes
of this component. When creating link edges, it is currently
required that all connected components are referred to explicitly
in the rule lhs; the corresponding nodes can not be taken from
relation edges.
A rule action that hides relation and component edges. hidden components
must be anchored to a component (resp. its edge)
A rule action that shows all hidden relation and component edges that
are referenced by the given anchor (compoent) edge
A rule action searches all relations and links that connect to one
node and creates copies connecting to the second node. relations
and links that connect to both nodes are not affected
Additionally to modifying the SRHG by adding and/or removing edges,
SRHG transformation rules are allowed to call static methods. LHS
edges may be specified as parameters.
The method which is either invoked
- if a component edge is going to be
created
- or if an explicit method call has been specified in the
do-part of a simple transformation
rule on the SRHG
- or as a manually programmed test method within the if clause
of a reduction rule or a simple transformation
rule.
The method has to be static and is specified by its qualified name. If the
class name of the corresponding class is not fully qualified, the class is
expected to exist in the package which has been specified
in the package declaration. The method is invoked
with an AppContext
instance as first parameter (this is an implicit parameter which is not
specified here) and a sequence of hyperedges. This first parameter
is omitted if the method belongs to a reduction rule!
The hyperedges which are
passed to this method belong to the SRHG and have either been matched
with LHS edges or have been created by a do-part action previously or they
are implicit edges of the form "node(x)" which specifies a node "x".
Previously labeled edges can be referred to by their label
or by explicitely specifying the edge.
A complex editing operation specification consists of a unique identifying
name, a string which briefly describes the operation, a string which contains
a path to an icon which is used to represent the operation (e.g., on a
button), the list of parameters which have to be specified by the user
("specify ...") and a do-part which triggers the
simple transformation rules which implement this operation.
If the user selects an operation to be applied, she has to provide
diagram components as actual parameters. The component hyperedges of those
components are then assigned to the formal parameters of this operations
(section "specify ..."), and the action sequence
is executed.
The specification of an edge which has to be specified by the user. This
edge acts as a formal parameter of the corresponding operation. The
specification consists of a label which will be used in the
action sequence of the operation to refer to the
user-specified SRHG edge. Furthermore, the edge type of the component that
has to be selected by the user and a suitable string which directs the
user to select such a component have to be specified.
The action sequence consists of alternatives of lists of operation sequences
which are executed sequentially.
A sequence of operation terms is executed sequentially.
An operation term is either an elementary operation, which may be executed
as often as possible (!) or optionally (?), or it is a nondeterministic
alternative of several simple transformation rules, or it is an iteration
operation.
An elementary operation is a plain rule application or an arbitrary
operation action in parantheses.
A nondeterministic alternative of several simple transformation rules.
This type of action is similar to an
AlternativeAction, but instead of chosing
the first applicable alternative, this type of compound action first
collects all possible matches for all the alternatives and then randomly
selects one possiblilty for application; equal probability is given to all
the matches.
An iteration operation typically looks like this:
forall [a,b,c]=rule(x,y,z) ( foo(a) | baz(b,c) )
The argument ([a,b,c]=rule(x,y,z)), which should not
change the hypergraph, searches for all matches for the rule
(rule) and executes the body (foo(a) | baz(b,c))
for each of these matches where the variables (a,b,c) are
bound according to the argument rule ([a,b,c]=rule(x,y,z)).
Note:
- All the matches of the argument rule are computed before the body is
executed.
- Beware of changing the hypergraph by the body in such a way that
a match which has been found before will become invalid.
Application of a simple transformation rule. The rule is identified by
its label. Previously matched or created edges can be passed as parameters.
These edges are referred to by labels, i.e., they are either formal
parameters of the operation, or they are return values of previous
rule applications. The rule may -- depending on its specification --
return edges as return values if the rule is successfully applied. The
return values are stored in variables (specified by identifiers) in a
bracketed list. The list length must correspond to the "return"
specification of the applied rule.
The return values are generally edges. But nodes may be returned, too.
They are represented by special, unary hyperedges "node(x)" which visit the
specified node "x" (See the specification of
returned nodes).
A logical expression is an or-combination of and-expressions.
An and-expression is an and-combination of elementary expressions.
An elementary expression is either the complement of an elementary
expression, or an invocation of a (boolean) method, or
a logical expression in parantheses, or a path expression (the starting node
has to be specified; the final node may be omitted), or a comparison
between coordinates of node.
A node coordinate may either be its x-coordinate ("x") or its
y-coordinate ("y").
Permitted comparison relations.
| RelOp |
::= |
">" |
|
| |
"<" |
|
| |
">=" |
|
| |
"<=" |
|
| |
"==" |
|
| |
"!=" |
|
A path expression consists of a sequence of simple path expressions.
A path satifies this path expression if it can be divided into a sequence
of sub-paths which satisfy the corresponding simple path expressions.
A simple path expression is an elementary path expression which may
be iterated ("+").
An elementary path expression either specifies a single hyperedge,
a production, some special path expression operators, or
it is an alternative of several path expressions.
Local constraint variables are introduced if a reduction rule is applied or
a grammar production is used in the derivation of the HGM. A local constraint
variable may only be used by the constraints which are assigned to this
rule resp. production.
A constraint declaration is a sequence of single constraints
specified by the constraints keyword.
Currently, DiaGen supports linear constraints, circle constraints, and
specifications of immutable variables.
A linear constraint consists of two linear combinations in
a certain relationship.
A linear combination is a sum of linear terms.
A linear term is either a plain number or a variable with a
factor.
A circle constraint (the name stems from ParCon) specifies
the Euklidean distance between two points.
Constraint variables may be declared as immutable, i.e., the
constraint solver is not allowed their values. This can be used for component
parameters which are set and made available to the constraint network by the
component, but which must not be modified when solving the network.
A constraint variable is either an access to an attribute, i.e., by
labeled access to an edge or a node, or a previously declared local variable,
specified by a plain identifier.
An edge of the SRHG is an edge whose name has previously been
declared of being either a relation identifier, a component
identifier or a link identifier.
An operation edge is an edge that has a name which has previously been
declared either as a relation identifier or as a
component identifier, or it is an implicit hyperedge "node(x)" which
specifies node "x".
A component edge is an edge that has a name which has previously been
declared as a component identifier.
A relation edge is an edge that has a name which has previously
been declared as relation identifier.
A link edge is an edge that has a name which has previously been
declared as SRHG link identifier. SRHG link edges are never created
by the scanner; they can only be created and deleted explicitly in
graph transformation rules
A terminal edge is an edge that has a name which has previously
been declared as terminal.
A nonterminal edge is an edge that has a name which has previously been
declared as nonterminal.
An edge is specified by a name and a, optionally empty, sequence
of nodes in paranthesis. The reserved words 'component', 'relation'
and 'link_edge' represent predefined edge types.
A node is either an identifier or a don't care specifier.
A qualified name is an identifier preceded by a, optionally empty,
dot-separated sequence of identifiers.
Identifiers start with a letter, followed by a sequence of letters,
digits, or underscores.
The return value identifier of a
simple tranformation rule on the SRHG is
either an identifier or a don't care specifier.
An integer is a non-empty sequence of digits, i.e.,
it is a non-negative integral number.
A floating point number consists of an optional integral share, a decimal
dot and a non-empty sequence of digits, i.e., it is a non-negative rational
number.