Proceedings of the 33rd Hawaii International Conference on System Sciences - 2000
Compiler/Interpreter Generator System LISA Marjan Mernik, Mitja Leni, Enis A University of Maribor Faculty of Electrical Engineering and Computer Science Smetanova 17, 2000 Maribor, Slovenia
[email protected] Abstract This paper describes the LISA system which is a generic interactive environment for programming language development. From the formal language specifications of a particular programming language LISA produces a language specific environment that includes a languageknowledgable editor, a compiler/interpreter and other graphic tools. The paper focuses on design decisions, implementation issues and tools integration in the system LISA. The main reasons for developing a new compiler/interpreter generator system were: support for incremental language development, support for language design in a visual manner and the portability of the system and the generated environment. LISA is a set of related tools such as scanner generators, parser generators, compiler generators, graphic tools, editor and conversion tools, which are integrated by well designed interfaces. Therefore, it has the advantages of a single system and federated environment. LISA and the generated environment are written in Java which enables high portability to different platforms.
1. Introduction The primary function of software tools and environments has always been to make the programmer more productive. Software tools also enhance the programmer's productivity indirectly by facilitating the development of new programming languages. Tools such as lex and yacc are such examples. The development of the first compilers in the late fifties without adequate tools was a very complicated and time consuming task. For instance, the implementation of the compiler for the programming language FORTRAN took about 18 human years. Later on, some formal methods were developed which made the implementation of the programming languages easier and finally contributed to the automatic implementation of the programming languages. The possibility of the automatic generation of the interpreters or compilers for the formally defined language enables the language developer a quick and simple evaluation of his
ideas in the process of language definition. For each language component there are different formal methods for its definition. The lexical part of the language is usually described with the regular definitions and the syntax part is described with the context free grammars using a variant of the BNF notation. These two formal methods have almost achieved the status of a standard in the field. There is a quite different situation in the area of semantics. The semantics of the programming language is more difficult to describe than the syntax and there is no acknowledged standard formal method for its description. Different approaches for its definition have been developed, such as: axiomatic semantics, operational semantics, denotational semantics and attribute grammars. Languages defined with the formal methods are more concise, have less exceptions and are easier to learn. Therefore, the role of formal methods is very important in software engineering. In [1] formal methods are classified to weak and strong formal methods. The essential requirement for a method to be formal in a strong sense is that it is supported by software tools that can perform a meaningful semantical analysis. Many tools have been built to support formal methods for programming language specifications [2]. In the paper a new version of the compiler/interpreter generation system LISA ver. 2.0 is described. Its features are: support for incremental language development, support for language design in a visual manner, portability, and efficiency. The paper is organised as follows. In section 2 the main design decisions for a new compiler/interpreter system are described. In section 3 the high level architecture of the system and implementation issues are presented. Related work and the conclusion are presented in sections 4 and 5.
2. Design decisions Many tools have been built in the past years, based on the different formal methods and implementing different parts of language such as: scanner generators, parser generators and compiler generators. Several tools for language implementation have been built based on
0-7695-0493-0/00 $10.00 (c) 2000 IEEE
1
Proceedings of the 33rd Hawaii International Conference on System Sciences - 2000
attribute grammars, such as GAG [3], TOOLS [4], FNC-2 [5], PCCTS [6], Eli [7], and based on denotational semantics, such as MESS [8]. Do we need another compiler/interpreter generator tool? None of the currently available tools support incremental language development, so the language designer had to design new languages from scratch or by scavenging old specifications. Therefore, our first goal was to implement a tool which supports incremental language development. On the other hand we wanted to support language design in a visual manner and achieve high portability. We had experience with the first version of the LISA 1.0 [9, 10], which had been implemented for MS Windows environment. Generated compilers or interpreters were written in C++ programming language and for proper operation of the LISA 1.0 Visual C++ ver. 1.5 compiler was necessary. This prevents portability to different platforms. When choosing the implementation language for the new version of the system LISA 2.0 we hesitated between C++ in the Unix environment and Java programming language. Finally, we decided for Java programming language [11, 12] since it offers much higher portability to different platforms than C++, especially in the area of graphics components [13], which were going to be used in the new version of the tool. Also, the Java programming language is architecture independent, portable, parallel, efficient and similar to C++. We used our compiler/interpreter generator system LISA 2.0 for almost two years for research work on
programming languages where Unix workstations are used, and also for teaching activities where mainly PCs are used. Therefore, our decision to use the Java programming language was correct from the portability perspective. Another goal of the new system is to enable language design in a visual manner. Current compiler generators use linear textual specifications, which are for designer less suitable than visual presentation. The main reasons for this are much easier implementation of the tool and easier processing of textual information. Nowadays, developing software with integrating development environments and powerful graphics hardware is much more user friendly. Unfortunately, these trends are not detected in the area of programming language design and implementation. In the compiler/interpreter generator system LISA 2.0 the programming language can be specified in visual manner with finite state automata (fig. 1), syntax diagrams and semantic diagrams which are then internally transformed to textual specifications. In the fig. 2 a finite state automata for comment in programming language C, which is defined with following regular expression \/\*([^*]*\*[^/])*[^*]*\*\/, is presented. Comment described with regular expression is much harder to understand than with finite state automata.
Fig. 1. FSA Toolbox displays the standard operations in building finite state automata such as: adding the (final) state and transition to the automata. For selection and moving the state and transition a pointer is used. Property window display properties of selected object.
0-7695-0493-0/00 $10.00 (c) 2000 IEEE
2
Proceedings of the 33rd Hawaii International Conference on System Sciences - 2000
[^*] / A
* B
/
* C
D
E
[^/] Fig. 2. Finite state automata for comment in programming language C Language design and implementation are still one of the challenges in computer science. Programmers use a variety of languages in their daily work, and new domain specific languages appear frequently. With formal methods for programming language description a language designer has a chance to automatically generate a compiler or an interpreter. Unfortunately, current formal methods do not support incremental language development and reuse of various specification fragments. The language design process should be supported by modularity and abstraction in a manner that allows incremental changes as easily as possible. This is one of the strategic directions of further research on programming languages [14]. When introducing a new concept the designer has difficulties trying to integrate it into the language in an easy way. Therefore, inheritance can be very helpful since it is a language mechanism that allows new definitions to be based on the existing ones. We have applied inheritance, a characteristic feature of object-oriented programming, in attribute grammars. Attribute grammars [15, 16, 17, 18] are proven to be useful in specifying the semantics of programming languages, in automatic constructing of compilers/interpreters [19], in specifying and generating interactive programming environments [20, 21] and in many other areas. Attribute grammars are a generalization of context-free grammars in which each symbol has an associated set of attributes that carry semantic information, and with each production a set of semantic rules with attribute computations is associated. In attribute grammars semantics is given in declarative rather than operational notation. However, ordinary attribute notation has deficiencies which become apparent in specifications for real programming languages. Such specifications are large, unstructured and are hard to understand, modify and maintain. Yet worse, small modifications of some parts in the specifications will have widespread effects on the other parts of specifications. Therefore, such specifications are not modular, extensible and reusable. We overcome the drawbacks of ordinary attribute grammars with concepts from object-oriented programming, i.e. templates and multiple inheritance. In [22] the multiple attribute grammar inheritance and templates are introduced only in the informal manner
through examples of a simple calculator language, and in [23] a formal definition of multiple attribute grammar inheritance is presented. Multiple attribute grammar inheritance is a structural organisation of attribute grammars where the attribute grammar inherits the specifications from ancestor attribute grammars, may add new specifications, and may override some specifications from ancestor specifications. With inheritance we can extend the lexical, syntax and semantic parts of programming language specification. In object-oriented languages the properties that consist of instance variables and methods are subject to modification. Since in attribute grammars semantic rules are tightly coupled with particular production rules, properties in multiple attribute grammar inheritance consist of lexical regular definitions, attribute definitions, rules which are generalized syntax rules that encapsulate semantic rules and methods on semantic domains. In our opinion the main weakness of multiple attribute grammar inheritance approach is that it does not help the designer in the case when languages have similar semantics and a very different syntax. For this reasons templates are also introduced. A template in attribute grammars is a polymorphic abstraction of a semantic rule parameterized with attribute occurrences which can be associated with many production rules with different nonterminal and terminal symbols. Further, at template instantiation appropriate semantic rules are generated at compiler generation time which is similar to templates in object-oriented languages where the code is generated at compile time. In fig. 3 the specification for very simple language Exp of arithmetic expressions is presented, where only addition of numbers is allowed. If later designer needs expressions with variables the symbol table (represented by attribute inEnv) have to be distributed to sub-expressions. In the specification for a new language ExprEnv (fig. 4) only new attribute computations have to be written and others are inherited. This is very simple and trivial example, but more concrete language would require several pages. language Expr { lexicon { Number Operator ignore } attributes
[0-9]+ \+ [\0x09\0x0A\0x0D\ ]
int *.val;
rule Expression1 { EXPR ::= EXPR + TERM compute { EXPR[0].val = EXPR[1].val + TERM.val; }; } rule Expression2 { EXPR ::= TERM compute { EXPR.val = TERM.val; }; }
0-7695-0493-0/00 $10.00 (c) 2000 IEEE
3
Proceedings of the 33rd Hawaii International Conference on System Sciences - 2000
rule Term1 { TERM ::= #Number compute { TERM.val = Integer.valueOf( #Number.value()).intValue(); }; } }
Fig. 3. Language Expr language ExprEnv extends Expr { lexicon { Identifier [a-z]+ } attributes Hashtable *.inEnv; rule extends Expression1 { compute { valueDistribution }; } rule extends Expression2 { compute { valueDistribution }; } rule Term2 { TERM ::= #Identifier compute { TERM.val = ((Integer)TERM.inEnv.get( #Identifier.value())).intValue(); }; } }
Fig. 4. Language ExprEnv The benefits of multiple attribute grammar inheritance and templates are: • specifications are extensible since the language designer writes only new and specialised specifications, • specifications are reusable since specifications are inherited from ancestor specifications, • the language designer can construct the programming language specification from multiple specifications, • specifications are more readable and maintainable since templates are at a higher abstraction level than assignment statements, • specifications are reusable since the templates are independent of the structure of grammar productions, and • language designers can create their own templates. The successful implementation of various small but real programming languages, such as PLM [24] and COOL, justified our ideas that incremental specifications which are modular, extensible and reusable are now feasible.
3. Architecture of the tool LISA 2.0 LISA consists of several tools: editor, scanner generators, parser generators, compiler generators, graphic tools, and conversion tools such as fsa2rex, etc. There are three basic methods of packaging tools into an integrated environment: to build the environment as a single system, as a set of independent tools (federated environment) or as a set of related tools which communicate [25]. Each of these approaches has its own advantages and disadvantages. Single-system programming environments have a high degree of integration, because the tools share the same data structures. On the other hand, it is very difficult to add new tools, especially those designed outside the environment. While it is relatively easy to add new tools into a federated environment, this approach has the following shortcomings: risk of poor performance, consistent and integrated environment do not exist, tools may have different interfaces and there is little if any communication among the tools. The third approach offers many of the advantages of both the single system and the federated environment, but require a powerful integration mechanism, such as in the FIELD environment [26]. The architecture of the system LISA is modular and uses the last approach. Integration is achieved with strictly defined interfaces that describe the behavior and type of integration of the modules. An example of a such interface is in fig. 5. public interface Automata { public abstract void setEdge(int aState, int aCharacter, int aNextState) throws AutomataException; public abstract void setFiniteState(int aState, int aType); public abstract void setStateName(int aState, String aName); public abstract int getStartState(); public abstract int getEdge(int aState, int aCharacter) throws AutomataException; public abstract Vector getEdgeVector(int aState, int aCharacter); public abstract int getFiniteStateType(int aState); public abstract String getName(int aType); public abstract int getType(String aName); public abstract String getFiniteStateName(int aState); public abstract boolean isDeterministic(); public abstract int getMaxChar(); public abstract int getMaxState();
0-7695-0493-0/00 $10.00 (c) 2000 IEEE
4
Proceedings of the 33rd Hawaii International Conference on System Sciences - 2000
public abstract void removeEpsilonEdges() throws AutomataException; public abstract Vector getFiniteVector(int aState); public abstract boolean convertToDeterministic() throws AutomataException; public abstract boolean minimize() throws AutomataException; public abstract int getMaxType(); }
Fig. 5. Interface for Automata Each module can register actions when it is loaded into the core environment (fig. 6). Actions are methods accessible from the environment. These actions can be executed via class reflection. Their existence is not verified until invocation, so actions are dynamically linked with module methods. registerAction("compile.aCompile", this, "compile"); public void compile(ActionEvent e) { ... }
Fig. 6. Registration of actions The module can also give the description of properties, their default values and domain, from which the graphics interface is automatically generated. The interface of the module is obtained through its property class returned by the prescribed method. Module settings are written in the LISA configuration file. Property class contains the properties that can be set by the user (fig. 7). ... compileMenu.compile=Compile compileMenu.compile-Action = compile.aCompile compileMenu.compile-Key=Alt+C compileMenu.compileIcon=images/Menus/object.gif ... compilerOptions.parser.parsers = Lisa.Parser.LR.LR0.CLR0, Lisa.Parser.LR.SLR.CSLR1,Lisa.Parser.CStack ParserGenerator, Lisa.Parser.LR.SOP.CSimplePrecParser,Lisa.P arser.LR.LR1.CLR1Parser ...
The module can be integrated in the environment as a visual or core module. Visual modules are used for the graphical user interface and visual representation of data structures. Core modules are non-visual components, such as the LISA language compiler. This approach is based on class reflection and is similar to JavaBeans technology [27]. With class reflection (java.lang.reflect.* package) we can dynamically obtain a set of public methods and public variables of a module, so we can dynamically link module methods with actions. When the action is executed, the proper method is located and invoked with the description of the action event (note that the method compile in the fig. 6 has one argument ActionEvent). With this architecture it is also possible to add modules with different input preprocessors. This gives us an opportunity to import specifications from other attribute grammar systems like FNC-2 or LISA 1.0. This feature is very useful because there is no standard for attribute grammar specification language. We can also upgrade our system with different types of scanners, parsers and evaluators which are presented as modules. This was achieved with a strict definition of communication data structures. The scanner and the parser communicate with data objects named tokens. Token represents basic elements in the lexical analysis. The parser and the evaluator communicate via syntax tree equipped with tokens. In the process of evaluation, attributes are added into nodes, which gives us a semantic tree. The input program is evaluated with a proper order of visits to nodes and a proper execution of semantic functions in the node. Modules for scanners, parsers and evaluators use templates for code generation, which can be easily changed and improved. In the fig 8. the high level architecture of the tool LISA is presented. Input to the compiler/interpreter generator LISA can be textual or visual. If textual, formal language specification is written in the domain specific specification language which supports multiple attribute grammar inheritance and templates (fig. 3 and 4). This specification (.lisa) which consists of lexical, syntax and semantic specifications is the input to the preprocessor. Its job is template instantiation - generation of semantic rules from templates. After this step there are no templates in specifications. Further, multiple attribute grammar inheritance is transformed to monolithic specifications.
Fig. 7. LISA configuration file
0-7695-0493-0/00 $10.00 (c) 2000 IEEE
5
Proceedings of the 33rd Hawaii International Conference on System Sciences - 2000
.lisa
preprocessor
visual specifications
LISA compiler
VISUAL compiler
monolitic specifications
language specific editor
compiler generator
scanner
parser templates evaluator templates
compiler/interpreter input program
scanner templates
parser
evaluator
output
Fig. 8. High level architecture of the tool LISA If the input is visual with finite state automata, syntax and semantic diagrams, then this visual presentation is also transformed to monolithic specifications. From this point, a classic compiler generation follows with the generation of lexical, syntax and semantic analysers. From formal language definition also the languageknowledgable editor is generated, which is a compromise between text editors and structure editors. The generated editor also colors the different parts of a program (comments, operators, reserved words, etc.) to enhance understandability and readability of programs. Generated lexical, syntax and semantic analysers, also written in Java, can also be compiled in an integrated environment without issuing a command to javac (Java compiler). This is possible due to the existing class sun.tools.javac.Main. Programs written in the newly defined language can be also executed and evaluated. Users of the generated compiler/interpreter also have the possibility to visually observe the work of lexical, syntax and semantic analyzers by watching the animation of finite state automata, parse and semantic tree. The animation shows the program in action and the graphical representation of finite state automata, the syntax and the semantic tree are automatically updated as the program executes. Animated visualizations help explain the inner workings of programs and are a useful tool for debugging and teaching. In short, the system LISA is a compiler/interpreter generator with the following features: • it supports language design in a visual manner (fig 1), • LISA is platform independent since it is written in Java,
• it offers the possibility to work in a textual or visual environment, • it offers an integrated development environment (fig. 9) where users can specify - generate - compileon-the-fly – execute programs in a newly specified language, • lexical, syntax and semantic analysers can be of different types and can operate standalone; the current version of LISA supports LL, SLR, LALR, and LR parsers, tree-walk, parallel, L-attribute and Katayama evaluators, • visual presentation of different structures, such as finite state automata, BNF, syntax tree, semantic tree, dependency graph (fig. 10), • animation of lexical (fig. 11), syntax and semantic analysers (fig. 12) • the specification language supports multiple attribute grammar inheritance and templates which enable to design a language incrementally or reuse some fragments from other programming language specifications. The system LISA is designed and developed using component technology and is implemented in the class based object-oriented programming language Java [27]. LISA is about 55.000 lines of the reasonably documented Java code.
0-7695-0493-0/00 $10.00 (c) 2000 IEEE
6
Proceedings of the 33rd Hawaii International Conference on System Sciences - 2000
Fig 9. In LISA integrated development environment users can write specification in domain specific specification language which support multiple attribute grammar inheritance and templates, generate the compiler, compile-on-the-fly the generated compiler and finally execute programs in a newly specified language. In this figure the semantic function currently under execution is highlighted in specification source file. The following program a=5; b:=a+3+[a:=8]+a of the language ExprSideEffect [23] is evaluated.
Fig. 10. The order of attribute evaluation is driven by simple fact that attribute atr1 which depends on other attribute atr2 can be only evaluated after evaluation of attribute atr2. The attribute grammar is well-defined if there is no circularity between attributes. Dependency graph shows dependencies between attributes and is useful tool for circularity detection.
0-7695-0493-0/00 $10.00 (c) 2000 IEEE
7
Proceedings of the 33rd Hawaii International Conference on System Sciences - 2000
Fig. 11. Finite state automata animation displays process of scanning. Currently, in the stream of characters the token identifier is recognized.
Fig. 12. In attribute grammars to each nonterminal a set of attributes carrying semantic information is associated. For example to nonterminal EXPR attributes inEnv, outEnv and val are associated. In the evaluation process this attributes have to be evaluated. Therefore the animation of evaluation process is very helpful in the debugging process.
0-7695-0493-0/00 $10.00 (c) 2000 IEEE
8
Proceedings of the 33rd Hawaii International Conference on System Sciences - 2000
4. Related Work Several systems for language implementation have been built based on attribute grammars, such as FNC-2 [5] and Eli [7], which had different design goals. For example, FNC-2 is a versatile system that consists of several independent tools (federated environment) such as asx (an attributed abstract syntax compiler), fnc2 (the OLGA compiler, OLGA is the input language used by FNC-2 to describe attribute grammars), ppat (a pretty printer for attribute trees), SYNTAX (parser generator), XVISU (dependency graph visualisation), etc. The most important features of FNC-2 are: efficient and incremental attribute evaluation, space optimizations, modularity and portability of generated evaluators, complete environment for application development. However, the FNC-2 does not support incremental language development, language design in a visual manner and animation of compiler inner workings. The last observation is also true in the case of Eli - a complete and flexible compiler construction system. Eli [7] is also a federated environment of several tools such as: LIDO (computations in trees), PTG (Pattern-based TextGenerator), Maptool (mapping concrete and abstract syntaxes), etc. Specifications in Eli can be reusable since it is possible to define the attribution module which can be reused in a variety of applications. The attribution module can only be constructed for those attribute computations where the attribute depends only on remote attributes. In this case computation is associated to a symbol rather than to a production. With the inheritance described in [28] an attribute computation can be further independent from symbols used in particular language definitions. The CENTAUR system [29] is a generic interactive environment which produces a language specific environment from formal specifications written in Natural Semantics, a kind of operational semantics. This resulting environment includes a structure editor, an interpreter and other graphic tools. In this regard, such an environment is very close to our generated environment. Since the CENTAUR system is a single system it is very difficult to add new tools, especially those designed outside the system. Also, the CENTAUR system does not support incremental language development, language design in a visual manner and animation of interpreter inner workings. The compiler/interpreter generated from LISA is visualised in a manner similar to [30] where an illustrated compiler for a simple block structured language PL/0 was implemented. The illustrated compiler in [30] was handwritten and many graphical views were static, for example the finite state machine and the syntax diagram do not change, since the user can not change the specification of the language, as is possible in our case.
Some visualisation aspects were influenced by other systems, such as Pecan [31] for displaying various source code representations, and Tango [32] which is a framework for algorithm animation.
5. Conclusion Many applications today are written in well-understood domains. One trend in programming is to provide software development tools designed specifically to handle such applications and thus to greatly simplify their development. These tools take a high-level description of the specific task and generate a complete application. One of such well established domain is compiler construction [2], because there is a long tradition of producing compilers, underlying theories are well understood and there exist many application generators which automatically produce compilers or interpreters from programming language specifications. In the paper the design decisions, the architecture and the implementation of new compiler/interpreter generator system LISA 2.0 are presented. The system LISA has many improvements to the earlier version and to similar systems. It is a set of related tools which are integrated by well designed interfaces. Therefore, it has the advantages of both, the single system and the federated environment. The system LISA supports incremental language development, language design in a visual manner, visual presentation of different structures and animation of compiler/interpreter inner workings. It is developed in Java which enables high portability to different platforms.
6. References [1] Wolper P. The meaning of "formal": from weak to strong formal methods. International Journal on Software Tools for Technology Transfer, Vol. 1, No. 1+2, pp. 6 - 8, 1997. [2] Aho A.V., Sethi R., Ullman J. Compilers, Principles, Techniques, and Tools. Reading, MA, Addison-Wesley, 1986. [3] Kastens U., Hutt B., Zimmermann E. GAG: A Practical Compiler Generator. Lecture Notes in Computer Science 141, Springer-Verlag, 1982. [4] Koskimies K., Paakki J. Automating Language Implementation. Ellis Horwood, 1990. [5] Jourdan M., Parigot D. The FNC-2 System User's Guide and Reference Manual. Release 1.19, INRIA Rocquencourt, 1997. [6] Paar T.J., Dietz H.G., Cohen W.E. PCTTS reference manual. ACM Sigplan Notices Vol. 27, No. 2, pp. 88 165, 1992. [7] Gray R.W., Heuring V. P., Levi S.P., Sloan A.M., Waite W.M. Eli: a complete, flexible compiler
0-7695-0493-0/00 $10.00 (c) 2000 IEEE
9
Proceedings of the 33rd Hawaii International Conference on System Sciences - 2000
construction system. Communications of the ACM, Vol. 35, No. 2, pp. 121 - 131, 1992. [8] Lee P. Realistic Compiler Generation. MIT Press, 1989. [9] Mernik M., Korbar N., LISA: A Tool for Automatic Language Implementation. ACM Sigplan Notices, Vol. 30, No. 4, pp. 71 - 79, 1995. [10] umer V., Korbar N., Mernik M. Automatic Implementation of Programming Languages using Object Oriented Approach. Journal of Systems Architecture, Vol. 43, No. 1-5, pp. 203 - 210, 1997. [11] Arnold K., Gosling J. The Java Programming Language. Sun Microsystsems, 1996. [12] Gosling J., Joy B., Steele G. The Java Language Specification. Sun Microsystems, 1996. [13] Swing 1.1 API Specification. Available at http://java.sun.com/products/jfc/swingdoc-api1.1/overview-summary.html [14] Hankin C., Nielson H. R., Palsberg J. Position Statements on Strategic Directions for Research on Programming Languages. ACM Sigplan Notices, Vol. 32, No. 1, pp. 59 - 65, 1997. [15] Knuth D. E. Semantics of contex-free languages. Math. Syst. Theory, Vol. 2, No. 2, pp. 127 - 145, 1968. [16] Deransart P., Jourdan M. (Eds.) Attribute Grammars and their Applications. Proceedings of 1st WAGA, Lecture Notes in Computer Science Vol. 461, Springer Verlag, 1990. [17] Alblas H., Melichar B. (Eds.) Attribute Grammars, Applications, and Systems. Proceedings of SAGA, Lecture Notes in Computer Science Vol. 545, Springer Verlag, 1991. [18] Parigot D., Mernik M. (Eds.) Attribute Grammars and their Applications. Proceedings of 2nd Workshop on WAGA, INRIA Publications, 1999. [19] Paakki J. Attribute Grammar Paradigms - A HighLevel Methodology in Language Implementation. ACM Computing Surveys, Vol. 27, No. 2, pp. 196 - 255, 1995. [20] Reps T.W., Teitelbaum T. The Synthesizer Generator - A System for Constructing Language-Based Editors. Springer-Verlag, 1989. [21] Lee P., Pfenning F., Rollins G., Scherlis W. The Ergo Support System: An Integrated Set of Tools for
Prototyping Integrated Environments. ACM Sigplan Notices, Vol. 24, No. 2, pp. 25 - 34, 1989. [22] Mernik M., The Template and Multiple Inheritance Approach into Attribute Grammars. International Conference on Computer Languages, ICCL-98, Chicago, pp. 102 – 110, 1998. [23] Mernik M., M., E., V. Multiple Attribute Grammar Inheritance. In Proceedings of 2nd WAGA, Parigot D., Mernik M. (Eds.), pp. 57-76, 1999. [24] Mernik M., M., E., V. A Reusable Object-Oriented Approach to Formal Specifications of Programming Languages. L'Objet Vol. 4, No. 3, pp. 273-306, 1998. [25] Taylor R.N., Belz F.C., Clarke L.A., Osterweil L., Selby R.W., Wileden J.C., Wolf A.L., Young M. Foundations for the Arcadia Environment Architecture. ACM Sigplan Notices, Vol. 24, No. 2, pp. 1 - 13, 1989. [26] Reiss S.P. FIELD: A Friendly Integrated Environment for Learning and Development. Kluwer Academic Publishers, 1994. [27] Horstmann C.S., Cornell G. Core Java: Volume II Advanced Features. Sun Microsystems, 1998. [28] Kastens U., Waite W.M. Modularity and reusability in attribute grammars. Acta Informatica Vol. 31, pp. 601 - 627, 1994. [29] Borras P., Clement D., Despeyroux Th., Incerpi J., Kahn G., Lang B., Pascual V. CENTAUR: The System. ACM Sigplan Notices, Vol. 24, No. 2, pp. 14 - 24, 1989. [30] Andrews K., Henry R., Yamamoto W. Design and Implementation of the UW Illustrated Compiler. Proceedings of the Sigplan’88 Conference on Programming Language Design and Implementation, pp. 105 -114, 1988. [31] Reiss S.P. PECAN: Program Development Systems that Support Multiple Views. IEEE Transactions on Software Engineering, Vol. 11, No. 3, pp. 276 - 285, 1985. [32] Stasko J.T. Tango: A Framework and System for Algorithm Animation. IEEE Computer, Vol. 23, No. 9, pp. 27 -39, 1990.
0-7695-0493-0/00 $10.00 (c) 2000 IEEE
10