Graph grammar engineering: A software ... - Semantic Scholar

3 downloads 28801 Views 1MB Size Report
grammar, software engineering, software development environment. 1 Introduction ... [Br 83], [Bu 83]), and (2) a precise definition of the functional behaviour of a ...
Graph Grammar Engineering: A Software Specification Method G r e g o r Engels FB 17, Universitht Mainz Posffach 3980, D-6500 Mainz, West Germany Claus L e w e r e n t z I" Informatik III, RWTH Aachen Ahornstr. 55, D-5100 Aachen, West Germany W i l h e l m Sch~ifer Computer Science, lVlcGill University 805 Sherbrooke Street West, Montreal H3A 2K6, Canada

ABSTRACT. Graphs as conceptual data models are accepted and used in a wide range of different problem areas. Giving some examples we outline common aspects for modeling complex structures by graphs. We present a formal frame-work based on graph grammars to specify graph classes and the corresponding graph manipulations. We show that such a specification can be written in a systematic, engineering-like manner. This is achieved by an extension of the known programmed, attributed graph grammars. Node-set operators are introduced to facilitate graph queries. Concepts like abstraction, decomposition, refinement, parameterization, and integration have been adopted from software engineering to yield a comprehensive specification method. This method has successfully been applied to specify the central data structures in a software development environment project. Key words: specification, graph grammar, graph replacement system, programmed graph grammar, software engineering, software development environment

CONTENTS 1 Introduction 2 Graphs as Conceptual Data Model 3 The Specification Language 4 The Specification Method 5 Conclusion References

The aulhor is supported by Deutsche Forsehungsgemeinsehaft

187

1 Introduction The systematic development of large software systems requires a precise description of its desired behaviour. Depending on the used method such a specification of the functional behaviour is a more or less formal description on a conceptual level. Various specification languages and methods have been introduced (e.g. [EM 86], [JB 82], [St 77]). They are usually classified into three distinct approaches, namely the operational approach, the denotational approach, and the axiomatic approach (cf. [So 85]). We present an operational specification method based on graphs as the underlying conceptual data model. Nowadays developed software systems are usually highly interactive and deal with complex structured objects. The structure of these objects depends on a certain application. All objects within that application form a certain class of objects (e.g. circuit-layouts, programs, patterns, technical drawings). A correct functional behaviour of a software system usually requires that any manipulation of an object within a certain class of objects always yields an object within the same class. As we deal with highly interactive systems, in many cases, the manipulation of objects is initiated by a corresponding user input. Therefore, formal description of the functional behaviour of such a software system requires at least to specify all possible and allowed user input. Attributed directed graphs as the underlying data model have been introduced in various appIications, e.g. VLSI-design, pattern recognition, software development environments. They provide an adequate abstraction level as welI as a precise notion to describe the structure of the objects of a certain application, e.g. a circuit-layout, a pattern, or a program (cf. [Br 83], [Bu 83], [ES 85]). Of course, the set of graphs describing the set of all objects of a certain application is a subset of all attributed directed graphs. Graph grammars as the operational specification method are used to specify all allowed transformations on these graphs. Thereby, such a graph grammar specification is the formal definition of (1) the subset of all attributed directed graphs which are representations of the objects within the certain application (cf. [Br 83], [Bu 83]), and (2) a precise definition of the functional behaviour of a software system, as all input (e.g. all possible user commands) can be mapped to corresponding graph transformations (cf. [Go 83], [ES 85]). Furthermore, such a graph grammar specification is a mean to handle complexity. In some applications the underlying graphs can become very complex (e.g. [Go 83], [ES 85]). A careful design of these graphs is then necessary to make sure that the graph representation really expresses what it should express (e.g. the representation of a power plant in [Go 83], or a correct program in [ES 85]). Our specification method enables to divide the construction of very complex graphs into clear single steps. A careful design of these graphs can also be supported, if a syntax definition of the object structure within a certain application is already given (e.g. in an EBNF-Iike notation). Then, a graph grammar specification can be derived systematically from that syntax definition. In this paper we introduce a graph grammar specification method and show, how a specification using this method can be written in a systematic engineering-Iike manner. The method is an

188

extension of the known programmed attributed graph grammars (cf. [Bu 77]) by mainly the following two ideas: (1) the definition of node-set operators to provide a natural way of description of graph queries, and (2) the introduction of concepts as abstraction, decomposition, refinement, parameterization, and integration, which we have adopted from software engineering. Therefore, we call this method graph grammar engineering. A first version of this method was described in [ES 85]. That version was developed within a certain research context, namely the research project IPSEN (Incremental Programming Support Environment) (of. [Na 85]). It was used to specify the functional behaviour of all tools provided by a software development environment such as IPSEN. In the meantime, that method was improved by including the above mentioned extensions. Using the same example in this paper as in [ES 85] shows, how the newly introduced ideas facilitate the development of that specification. Furthermore, we present here a first step towards a formal framework for a clear and comprehensive specification method of arbitrary complex graph structures and transformations. It is, therefore, intended and should be possible to use that method also in other application areas than only software development environments.

2 Graphs as Conceptual Data Model As mentioned in the introduction, attributed directed graphs serve as a common high-level data model for a variety of applications. All these applications deal with complex structured objects the structure of which is frequently changed by a corresponding input. A graph structure is the appropriate abstraction level to express these complex structures and the possible and atlowed transformations of the objects. We are going to explain this graph representation of objects in more detail, now. Complex structured objects are constructed by using other predefined objects and regarding certain constraints how these basic components may be fitted into one another. A preferable formal final description has to be given to define precisely the construction rules and, thereby, defines the whole class of objects to be dealt with within a certain application. Usually, such a formal description is called a syntax definition. Such a syntax definition only enables to distinguish and control allowed and not allowed manipulations of an object, i.e. the syntax definition is the prerequisite for any computer-aided support in the manipulation of these objects. Coming to our software development environment example and here to the programming-inthe-small part, the complex structured objects to be manipulated are programs or single modules (in the sense of Modula-2). Their syntax definition usually consists of two parts, namely the definition of the contextfree and the contextsensitive syntax (sometimes called static semantics). The contextfree part defines the basic components (called syntactic constructs or syntactic categories) and how a module can be built from them. The contextsensitive part defines further relations between these constructs and certain constraints in fitting them into one another. The contextfree syntax definition is usually given in an EBNF-like notation or using syntax diagrams, etc. R can, however, also be directly given by a graph grammar description (e.g. [LN 84],

189

[Br 83]). The contextsensitive definition is often given by a natural language description, but sometimes more formal methods are used, e.g. attributed grammars ([KH 82]) or also graph grammars ([LN 84]). Independently of the used description method, a graph representation of an object can be derived from the syntax definition. The overall idea of this derivation process is to express all structural information about an object by labeled nodes and edges. All non-structural information is expressed by attributes which are usually attached to nodes and sometimes also to edges. In more detail, we distinguish the following steps: (1) A graph increment is associated with each syntactic construct of the contextfree definition. The root node of such an increment expresses the syntactic construct and the other nodes and edges express, how this construct is being built from others as defined in the syntax definition. These increments are called complex graph increments, and they can be divided into structure and list graph increments. As an example of a structure graph increment consider the graph representation of the syntactic construct 'while-statement' as part of a Modula-2 program in figure 2.1. List graph increments represent lists of elements which are identical syntactic constructs. AI1 list elements are connected with an anchor node by edges labeled by Elem. The order between the list elements is expressed by additional edges labeled by Next. As an example consider the graph representation of a statement-list in figure 2.1.

i W,,,e S,a ,

~ EStat_List, ~

Elem f Statement] t Next Elem "t Statement Next

t

i Next Elem "l Statement Figure 2.1: Representation of structure and list graph increments (2) Besides the relations expressed by the spanning tree, further relations between the graph increments are expressed by additional edges and sometimes additional nodes. Thereby, the whole contextsensitive syntax of an object is represented. Furthermore, all additional information which is needed to check and carry out all allowed manipulation on a certain object can be expressed. As an example for a contextsensitive information regard the connection between the declaration and use of variables in a program which is denoted by corresponding edges (cf. the edge labeled by EUseDec in fig. 2.2). As an example for further needed information regard that the control flow through a program is denoted by so-called 'control flow' edges and a node indicating the end of a syntactic construct (cf. fig. 2.2). These edges and nodes are used by an interpreter executing a program given in such a graph representation. If the structure of a syntactic construct is not of any further interest by any manipulation carried out on the graph, it will be represented by a single node together with an attribute.

190

These increments are called simple graph increments. As an example take identifiers or literals within a graph representation of a Modula-2 program (el. fig. 2.2).

PROCEDURE

P ;

iit!ii!N !ii!;iiiiiNili N @N !!iii!iiiiiii BEGIN •

o

,

WHILE

B DO

END ; END

P ;

.p.

#'A "

EDocl Next

t,

"C"

1 t I

Typel

EType Next Elem

"CARDINAL"

,~

E, ent

:~:~:~:~:~:~:~ List

'

EType Def

Type '

................................................. "

"BOOLEAN"

EStatList

Elem p

*

Control Elem

,~

Back "B

EExpr

~

Elem

EStatList 'J t ",~t TRUE

"

EUseDec

-I ....

. . m,

.

1 Control

EEndStat , ~ FALSE 't

vvm~u

I

Figure 2.2: Cutout of a graph representation of a Modula-2 program Neglecting the Next-edges, the composition of these increments form a tree, which is very similar to the well-known abstract syntax tree. This tree reflects the structural information of an object as given by the contextfree syntax. It is the spanning tree of the graph representa-

191

tion. The introduction of a so-called cursor-node and an edge labeled Get (cf. fig. 2.2) is another example for expressing further needed information by additional nodes and edges. 0 u r s o r - n o d e and G e t - e d g e reflect the current position within a representation of the module on the screen. As all manipulations of modules are syntax-oriented (cf. [Na 85]), the cursor on the screen always indicates a so-called current increment (the whole declaration part in the example in fig. 2.2), contrarily to a usual line- and column-oriented cursor. (3) All non-structural information is represented by additional attributes (analogously to the already introduced attributes of simple graph increments). As an example take the unparsing information for a syntactic construct. This information is needed by a program generating a user-oriented representation from the abstract graph representation (either textual or graphical).

3 The Specification Language It is quite natural to describe the functional behaviour of a software system by graph replacement rules, if graphs are used as the conceptual data model. In this section, we introduce a specification language which is based on the concepts of graph grammars or graph replacement systems ([Na 79]). We give a brief and informal introduction to our notions of 'graph' and 'graph replacement system'. An extended version of the formalization of our approach can be found in [En 86] and [Le 87]. The whole approach is heavily based on the ideas and notions of [Na 79]. In this section, we restrict ourselves to the description of the notions and formalisms forming a specification language. Examples for the use of this language are given in the next section, where we explain the specification method. All graphs of a certain graph class are constructed over three alphabets which are: a finite set of node labels, a finite set of edge labels, and a finite set of attributes. Additionally a function maps a finite set of attributes to each node label. Hence, a member of a graph class is a directed, node-attributed, n o d e - and edge-labeled graph. Each attribute, associated to a node of a graph, has a concrete value of a corresponding attribute domain. Such attribute domains are the domains of primitive data types like CARDINAL, INTEGER, REAL, CHAR, BOOLEAN, or STRING. These graphs are the data objects in our specification language. Any modification of such a data object is carried out by the application of an appropriate graph replacement rule. Each graph replacement rule consists of the following four components: two graphs, termed the left-hand and right-hand side of the rule, an embedding transformation, and a sequence of attribute assignments. These components control the application of a rule in several steps. The first step is to identify a subgraph in the current data object, the host graph, which is isomorphic to the left-hand side of the graph replacement rule. Contrarily to the usual approach, we allow that this isomorphic subgraph is an incomplete subgraph of the host graph. This means, for instance, that the corresponding complete subgraph of the host graph contains additional edges or additional node attributes.

192

This corresponding complete subgraph is removed in the second step of the application of a graph replacement rule, and replaced by a graph which is isomorphic to the right-hand side of the graph replacement rule. In the third step, the newly inserted graph has to be connected appropriately to the host graph by additional edges. The embedding of the inserted graph is described by the third component of a graph replacement rule, the embedding transformation. The embedding transformation consists of a list of embedding rules, where each rule has one of the following three kinds: • (nl) = (nrl . . . . . nrk)

• (nl NodeSet0p) elab ~ (nr~ . . . . . nrk) • (nl N o d e S e t 0 p ) , - - e l a b (nr~ . . . . . nrk) These different kinds of embedding rules have the following semantics: nl resp. nrl . . . . , nrk are so-called nodenumbers and denote nodes in the left-hand or right-hand side of a graph replacement rule. elab is an edge label and N o d e S e t O p is a node-set operator which will be explained below. Let nl' or. nrl', ...,nrk' be the nodes in the subgraph of the host graph which are isomorphic to corresponding nodes in the left-hand or right-hand side of the graph replacement rule. Then, the first kind of an embedding rule gives the identical embedding. This means that all inserted nodes nrl', ..., nrk' are being connected by the same edges to the host graph as the removed node nl' was connected before the application of the graph replacement rule. This kind of embedding rule allows the description of the connection of the inserted graph with its direct neighbourhood. Using the second and third kind, it is possible to describe the connection of an inserted node nri' with a node n' which can be reached from the node nl' by a path of arbitrary length. In the second kind an edge labeled by elab has to be drawn from n' to nr i ', and in the third kind an edge labeled by elab has to be drawn from nr i ' to n'. In both cases, the node n' has to be a member of the set of nodes which results from applying the node-set operator

NodeSetOp to the set {hi'}. Node-set operators are syntactically built up by atoms and operators, as it is known from regular expressions. Atoms are id, +elab, - e l a b , label in {nlab~ ..... nlabk }, attr {a}, and [sg]. Here, nlabj denotes a node label, elab denotes an edge label, a is a boolean expression over the set of attributes and constants of the corresponding attribute domains, and sg represents a subgraph. Operators are concatenation, indicated by juxtaposition of operators, or, and, without, .all,

*maXwhere, *mir~vhere . Parentheses are used for grouping, so that quite elaborate node-set operators may be constructed. The associated semantics of such node-set operators are functions, which may be applied to a subset of nodes of the current host graph and yield as result also a subset of nodes. The semantics of atoms and operators is defined as follows: Let S be a set of nodes of the host graph, and op, opl, and op2 be node-set operators. Then

193 •

S id := S denotes the identity function,

• S +elab := {n [ n is the target node of an edge labeled elab with source node n' ~ S } denotes the set of all successors according to an edge labeled by elab, * S -olab := {n I n is the source node of an edge labeled elab with target node n' ~ S } denotes the set of all predecessors according to an edge labeled by elab, * S label in {nlabl ..... nlabk } := {n I n • S and the node label of n is in {nlabl ..... nlabk } } denotes the restriction to all nodes of S with node labels nlabj • {nlabl ,..., nlabk }, •

S attr {a} := {n I n • S and the boolean expression a yields the value TRUE for the current

attribute values of n } denotes the restriction to all nodes with specific current attribute values. •

S [ $ g ] := {nout' [ nin' • S ; nin', nout' • Nodessg' ;

sg' = ( Nodessg', nodelabsf, Edgessg', attcondsg' ) • isomorphic (sg) }, where

sg = ( Nodes~g, nodelabsg, Edges~g, attcond~g ) with two marked elements nin, n o u t • Nodessg .

• S (op) : = S o p • S opl op2 := (S opl) op2 • S (opl o r o p 2 ) : = { n ' [ n ' • ( { n } o p l •

S (opl and op2) := {n' I n' • ( {n} opl

u {n}op2) : n • S } , n

{n} op2 ) : n



denotes the union.

S }, denotes the intersection.

• S (opl without op2) := {n' I n' e ( (n} opl \ {n} op2 ) : n e S }, denotes the difference• •

S o p *all :---

[J (S opJ), where opt := opop i-1 , op ° := id , i • N j=0

i

andn=min {i[

USop j=o

i+l J

-- U S o p J } ; j=o

denotes the complete transitive hull for iteration of an operator op. •

Sopl*rnirghere

op2:=

S o p 1 n , where

n=min(min{i

[ Sop1~op2~O } , i

i+l

min{i I USopi j=0

= USopl j }); j=o

denotes the conditional minimal path set for operators opl and op2. •

S opl*maXwhereop2 :=

S opl n , where

n=min (max{i

I S o p l o p 2 " ~ e }, i

rain

i+l

{ i I U s op¢ -- U s j=o

j=o

}

denotes the conditional maximal path set for operators opl and op2. The fourth and last component of a graph replacement rule is a sequence of attribute assignments. They are given as usual assignment statements known from programming languages, and

194 they describe how the attribute values of the inserted nodes have to be set. The execution of these attribute assignments is done as the last step of the application of a graph replacement rule. Applications of graph replacement rules are the elementary operations by which data objects of our specification language, i.e. the graphs, may be modified. Concrete examples of such replacement rules are given in the next section (cf. fig. 4.1 and 4.2). Besides these elementary operations, we provide additional features in the specification language, which allow to describe complex graph transformations in a very comprehensive and clear manner. The left-hand side of a graph replacement rule characterizes the location in the host graph, where a graph replacement rule can be applied, and which subgraph has to be replaced. In some cases, it is desirable to define this location more carefully by giving additional constraints for the context of this subgraph in the host graph. Therefore, we allow the use of node-set operators also in the left-hand side of a graph replacement rule, to describe a certain context where a graph replacement rule can be applied. The two possible kinds are described schematically by the two following rules: 1

2

1

2

(1)=(1);

1

1 [21

NodeSetOp~

(2)=(2);

2

:= (i) = (1) ;

Fig. 3.1: Graph replacement rules containing node-set operators NodeSetOp

is the name of a node-set operator, which may be defined at another place. In

the first case, the set of all isomorphic subgraphs within the hostgraph, i.e. all node pairs labeled by A and B, is restricted to those connected by a path, described with NodeSetOp. In the second case, N o d e S e t O p has to be applied to a set containing all nodes of the host graph, and the node labeled by A has to be a member of the resulting set. Sometimes, it is necessary to express that the application of graph replacement rules should be carried out in a certain order. In order to provide an appropriate mechanism to meet such a requirement, each graph replacement rule has a name, and control structures like the sequence of rules, conditional and loop statements together with subgraph tests as boolean expressions are introduced in our language. Furthermore, such parts of a specification can be grouped by a ModuIa-2 like procedure, termed control procedure. Of course, graph replacement rules and control procedures may be parameterized as usual procedures by node or edge labels or attribute values (el. fig. 4.2 and fig. 4.4). The syntactical and semantical definition of these control struc-

195

tures and control procedures are adopted from Modula-2 ([Wi 82]). A call-by-value parameter passing scheme is assumed for all parameters. To sum up, we have explained in this section the syntax and (operational) semantics of a specification language, where each specification is a graph replacement system. Such a graph replacement system consists of the following components which are: three alphabets, namely node labels, edge labels, and attributes, the association of attributes to node labels, the attribute domains, a set of node-set operators, and a set of graph replacement rules. If it also contains control procedures, such a graph replacement system is called a programmed graph replacement system. In the next section, we illustrate, how this specification language can be used to specify the functional behaviour of a planned software system.

4 The Specification Method We illustrate the use of the above introduced specification language by giving a brief overview of the specification of the programming-in-the-small part (cf. EEn 86], [Sc 86]) of the software development environment IF'SEN (cf. [Na 85]) as a concrete example. The tools of the programming-in-the-small part of IPSEN cover all activities to edit, analyze, instrument and test a Modula-2 module. In order to realize these tooIs, such a Modula-2 module together with all tooI-specific informations is expressed on a conceptual level by an attributed directed graph, called module graph. A cutout of such a module graph is given in figure 2.2. Each tool activity which is invoked by a corresponding user command, is modeled as a modification of this abstract representation of the currently handled Modula-2 module. As explained in section 2, a module graph is built up by graph increments which can be systematically derived from a given contextfree syntax definition. Thereby, main parts of the three alphabets of node labels, and edge labels, and attributes of the specification are fixed, too. These alphabets are extended, if further, tool-specific informations have to be represented in a module graph. The same holds true for choosing attribute domains and determining the association of attributes to node labels. Having fixed these components of a specification, all allowed modifications of module graphs can be specified by appropriate graph replacement rules. We give some concrete examples to illustrate the formalism introduced in the last section. The insertion of a graph increment means that the current increment which is a placeholder node in that case, has to be replaced by a subgraph representing the graph increment. This can be specified by a simple graph replacement rule. For instance, the graph replacement rule in figure 4.1 describes the insertion of a structure graph increment representing a while-statement.

196 RULE

InsertWhlleStatement

2

Statement

3

2

"'=

EExpr , ~

I While_Stat I

/Go,t

Est~t Li~t 'I

4

Opt-StaULi~t I

(1)=(1); ( 2 ) = ( 2 ) ;

Figure 4.1: Insertion of a structure graph increment

The next example (of. figure 4.2) shows a parameterized graph replacement rule with rather complex context constraints for the left hand side of the rule. It describes the following modification of the module graph (cf. figure 2.2): Let us assume that after the insertion of a boolean identifier in the loop condition of a while-statement, an edge which is labeled by EUseDec, has to be drawn from this identifier node to the identifier node in the corresponding declaration. As this current while-statement may be nested within the body of a procedure declaration, and this procedure declaration may be nested within further procedure declarations, the distance between the applied occurrence of the boolean identifier and its declaration node heavily depends on the current shape of the module graph.

The operator EditCursor identifies the current location for the application of the rule. The operator InnermostVarDecl is parameterized with the name of the variable identifier under consideration. It describes the path to find the innermost declaration of the given variable identifier according to the scope rules of Modula-2. Here, named suboperators are used to achieve an understandable specification. Starting at the applied occurrence of the variable the operator CurrentProcDecl gives the directly enclosing procedure declaration. From there the minimal surrounding procedure declaration is searched where a local declaration of the variable identifier can be found. This conditional iteration is expressed by the operator PrevProcDecl, the minimal set operator (starting with the zeroiteration), and the parameterized condition VarDecl . Applying this operator to the found procedure declaration results in the desired identifier node.

The example shows how rather long and complex paths with non-trivial properties may be expressed in a compact and readable form using the proposed node-set operators. It is very important, too, that the module graph has been constructed systematically. For instance, this implies that the path between a nested while-statement and the surrounding procedure declaration is labeled alternately by Elem and EStatList. So, this systematic proceeding heavily supports the development of an easily understandable specification.

197 RULE

InsertUseDecEdge ( Currentldent : STRING )

2

2

InnermostVarDecl(Currentldent)

eDec

Edit_Cursor .............. ~ 1

(1)=(1);

OPERATOR EditCursor IS

/abe/in{Cursor}

OPERATOR InnermostVarDecl

(Identifier : STRING)

CurrentProcDecl (PrevProcDecl

(2) = (2) ;

+Get ; IS

*minwhereVarDecl(Identifier) )

VarDecl(Identifier)

OPERATOR CurrentProcDecl IS

-EE×pr (-Elem-EStatList~ a//

OPERATOR PrevProcDecl IS

-Elem-EDeclList

label in{

;

ProcDecl } ;

;

OPERATOR VarDecl (Identifier : STRING) IS +EDeclList+Elem

/abe/in{VarDeclList}+Elem

+EldentList+Elem

attr

{ Name=Identifier};

Figure 4.2: Example for the use of a more complex node-set operator In the above shown replacement rule describing the insertion of a contextsensitive relation in the module graph neither any test is made to check whether the variable is declared of the appropriate type (i.e. BOOLEAN), nor any error handling is regarded for that case or the situation that no declaration is found at all. To combine replacement rules with further tests, to put several rules into a fixed sequence, or to incorporate additional actions like error handling, we use control procedures. Figure 4.4 gives an example for that. The presented extensions to other known approaches to graph replacement systems, e.g. node-set operators and control procedures, are influenced by the aim to have a language which facilitates the specification of graph modifications in a comprehensive and clear manner. Besides these concepts supporting the so-called specification-in-the-small tasks, a systematic proceeding for the development of the whole specification is necessary, to overcome the complexity of the specification process and of the specification itself. Therefore, we have started to use concepts which are well-known from software engineering, namely decomposition, refinement, integration, and information hiding. We illustrate this by explaining the structure of the specification of the central data model in the programming-in-the-small part of IPSEN, the module graph class. Each tool activity is modeled by a modification of the module graph. Such modifications can be divided into insert, delete, or change operations of specific informations which are represented by nodes, edges, or attributes, and movements of e.g. edit or execute cursors which are represented

198

in the graph by additional nodes (cf. figure 2.2). Analogously, the specification of all allowed module graph operations can be divided in a top-down proceeding into four disjoint subspeeifications. This concept of decomposition decreases the complexity of the specification process, because it enables a separate development of each subspecification. Each subspecification can be refined in a second step by a further layer, which can also be decomposed in several disjoint graph replacement systems. For instance, insert operations can be distinguished into operations to insert • • • •

nodes and edges representing contextfree informations, nodes and edges representing contextsensitive informations, nodes and edges representing tool-specific informations, node attributes representing non-structural informations.

Hence, a cutout of the whole specification has the following schematic structure: Module Graph Operations

ii "...,

Insert Operations

tArbuesi Fig. 4.3: Cutout of the structure of the example specification This decomposition and refinement of the whole specification into subspecifications decreases the complexity of the specification. Each subspecification describes the modifications of a specific restricted part of the information contained in a module graph. Therefore, on one hand, only a subset of all aIlowed node and edge labels or node attributes has to be known in a subspecification. On the other hand, graph replacement rules of such subspecifications are applied to module graphs, which are built over the union of all node and edge label alphabets and attributes of all subspecifications. This enforces a slight modification of the definition of the application of graph repIacement rules introduced in section 3, namely the identical embedding rule is applied to all edges the label of which is not known in the current subspecification. Analogously, all attributes

199

which are not mentioned in the graph replacement rule, retain their old value. This enables the use of the information hiding principle within our specification method. We have given examples of graph replacement rules or control procedures which belong to subspeeifications of the basic layer of InsertOperations. The application of such rules and control procedures has to be coordinated and integrated in a higher layer. This integration of subspecifications can be done by the use of control procedures, too. For instance, regard the control procedure of figure 4.6, which is part of the subspecification Insert,

CONTROL PROCEDURE InsertldentAsLoopCondition

(Currentldent : STRING) ;

BEGIN IF BooleanDeclExists (Currentldent)

THEN

InsertldentAsExpression ;

(*

Setldent (Currentldent) ;

(* Attribute

InsertUseDecEdge (Currentldent)

(*

ContextFree

*)

*)

ContextSensitive

*)

ELSE Error ("Identifier not declared !") END END lnsertldentAsLoopCondition

;

Figure 4.4: Control procedure of the subspecification Insert

5 Conclusion We presented a specification language in this paper, which is appropriate if attributed graphs are chosen as the underlying data model on a conceptual level. This language is based on the concept of a programmed graph grammar (cf. [Bu 77], [Na 79]). In order to be able to develop complex but clear and comprehensive specifications by using this language, software engineering concepts have been adopted to our language, finally yielding a graph-based sl~ecification method. The combination of graph grammars and software engineering concepts within this method is the reason to call it graph grammar engineering. Up to now, the syntax and (operational) semantics of the specification language for the specification-in-the-small part has been formalized and was described in section 3. It is part of the current work to extend the definition of the syntax and semantics of our specification language, in order to get a specification language, which supports specification-in-the-small as well as specification-in-the-large tasks. Graph grammar engineering was heavily used to specify a large part of a huge software system, namely the software development environment IPSEN. One fundamental idea of IPSEN is the use of attributed graphs as the data model in all task areas. This specification of the tools for programming-in-the-small was sketched in section 4. For the task areas programming-in-thelarge, documentation, and project management, i.e. their underlying graph classes and the pro-

200

vided tools, specifications using the explained language have been completed (cf. [LN 84], [Le 87]). Any specification, which has been developed using graph grammar engineering, is directly executable by an appropriate interpreter, because it is an operational specification. This yields a rapid prototyping facility. The construction of such an interpreter is part of the current work. As interpretation, however, almost has the drawback of less efficiency (with respect to runtime), an alternative approach was chosen in IPSEN. The specification of all task areas was translated by hand, however, very systematically into an implementation. This was possible, because attributed graphs were used as the underlying data structures also on the implementation level. Such an implementation approach was feasible, because a so-called graph storage, a special non-standard data base system for the efficient storage of arbitrary attributed graphs was developed within IPSEN (cf. [BL 85]). It is worth to mention that this systematic translation step was done by a programmer with no former experience in using formal specifications. The concepts which we have presented here, fill the gaps which have been left open in our first paper on this specification method (el. [ES 85]). The main topic of [ES 85] were, firstly, the description of the systematic development of the graph grammar specification. We showed how the shape of a graph as the model for a certain document can be derived systematically from a given EBNF-description of the contextfree syntax of such a document. Secondly, we illustrated the above mentioned strategies to derive an implementation from such a specification in more detail. The main topics of this paper are the introduction of concepts which facilitate the development of such a specification. On one hand, we have introduced node-set operators to provide a natural way tO describe graph queries. On the other hand, we have shown how well-known concepts from software engineering can be adopted to structure a graph grammar specification. Hence, the paper [ES 85] and this paper present the basic ideas of our graph-based specification method. Finally, this method is extremely well-suited, if tool activities, i.e. graph modifications have to be specified. In this case, one should give preference to such an operational method over more descriptive approaches like attributed grammars (cf. [KH 82]). Our above mentioned implementation experiences in building tools for very different task areas of IPSEN underline this statement.

Acknowledgements The authors are indebted to M. Nagl, U. Schleef, A. Schfirr, and B. Westfechtel for a lot of fruitful discussions.

201

References [BL 85]

Brandes, Th./ Lewerentz, (2.: GRAS - A Nonstandard Data Base System within a Programing Support Environment, Proe. of the GTE-Workshop on Software Engineering Environments for Programming-in-the-Large, Cape Cod 1985, pp. 113-121

[Br 83]

Brendel, W.: Application of Attributed Graph Grammars to VLSI Design, in Nagl, M./ Perl, J.(eds.): Proc. of the WG '83, pp. 50-60, Linz: Trauner

[Bu 77]

Bunke, H.: Programmed graph grammars, LNCS 56, pp. 155-166, Berlin: Springer

[Bu 83]

Bunke, H.: Graph grammars as a generative tool in image understanding,in Ehrig, H./ Nagl, M./Rozenberg, G. (eds.): Graph-Grammars and Their Application to Computer Science, LNCS 153, pp. 8-19, Berlin: Springer

[EM 86] Ehrig, H./Mahr, B.: Fundamentals of Algebraic Specification 1, Berlin: Springer [En 86]

Engels, G.: Graphs as Central Data Structures in a Software Development Environment, Ph.D. thesis, (in german), Dfisseldorf: VDI-Verlag

[ES 85]

Engels, G./Sch~ifer, W.: Graph Grammar Engineering: A Method Used for the Development of an Integrated Programming Support Environment, in LNCS 186, 179-193, Berlin: Springer

[Go 83]

Ggttler, H.: Attributed graph grammars for graphics, in Ehrig, H./Nagl, M./Rozenberg, G. (eds.): Graph-Grammars and Their Application to Computer Science, LNCS 153, pp. 130-142, Berlin: Springer

[JB 82]

Jones, C.B./ Bjorner, D.: Formal Specifications and Software Development, London: Prentice-Hall

[KH 82] Kastens. U./ Hutt, B./ Zimmermann, E.: GAG: A Practical Compiler Generator, in LNCS 141, Berlin: Springer [Le 87]

Lewerentz, C.: Incremental Programming-in-the-Large, Ph.D. thesis (in german), Informatik l]I, RWTH Aachen, forthcoming

[LN 84] Lewerentz, C./Nagl, M.: A Formal Specification Language for Software Systems Defined by Graph Grammars, in Pape, U. (ed.): Proc. of the WG '84, pp. 224-241, Linz: Trauner [Na 79]

Nagl, M.: Graph-Grammatiken: Braunsehweig: Vieweg

Theorie,

Implementierung,

Anwendungen,

[Na 85]

Nagl, M.: An Incremental Programming Support Environment, in Computer Physics Communications 38, 245-276, Amsterdam: North-Holland

[So 86]

Schfifer, W.: An Integrated Software Development Environment: Concepts, Design, and Implementation, Ph.D. thesis, (in german), Diisseldorf: VDI-Verlag

[So 85]

Sommerville, I.: Software Engineering, Reading: Addison-Wesley

[St 77]

Stoy, J.E.: Denotational Semantics: The Scott Straehey Approach to Programming Languages, Cambridge, Mass: MIT-Press

[Wi 82]

Wirth, N.: Programming in Modula-2, Berlin: Springer