Eli   Documents

General Information

 o Eli: Translator Construction Made Easy
 o Global Index
 o Frequently Asked Questions
 o Typical Eli Usage Errors

Tutorials

 o Quick Reference Card
 o Guide For new Eli Users
 o Release Notes of Eli
 o Tutorial on Name Analysis
 o Tutorial on Scope Graphs
 o Tutorial on Type Analysis
 o Typical Eli Usage Errors

Reference Manuals

 o User Interface
 o Eli products and parameters
 o LIDO Reference Manual
 o Typical Eli Usage Errors

Libraries

 o Eli library routines
 o Specification Module Library

Translation Tasks

 o Lexical analysis specification
 o Syntactic Analysis Manual
 o Computation in Trees

Tools

 o LIGA Control Language
 o Debugging Information for LIDO
 o Graphical ORder TOol

 o FunnelWeb User's Manual

 o Pattern-based Text Generator
 o Property Definition Language
 o Operator Identification Language
 o Tree Grammar Specification Language
 o Command Line Processing
 o COLA Options Reference Manual

 o Generating Unparsing Code

 o Monitoring a Processor's Execution

Administration

 o System Administration Guide

Mail Home

Name Analysis Reference Manual

Previous Chapter Next Chapter Table of Contents


Isomorphic Scope Graphs

Recall that when a language allows a programmer to use the same identifier to represent entities of different kinds in the same region of the program, the developer is required to use a distinct scope graph for each kind of identifier (see Scope graphs). Often a number of these graphs have the same ranges and the same relationships among those ranges. In that case the distinct scope graphs are isomorphic, and they can all be implemented by a single instantiation of the ScopeGraphs specification module.

A ScopeGraphs module instantiation always represents a set of isomorphic scope graphs; by default, that set has a single member. Ranges are represented by values of type NodeTuplePtr (see Establishing the Structure of a Scope Graph). These values are pointers to NodeTuple values, which are arrays of pointers to the actual scope nodes. A set of edges that are equivalent under the isomorphism is specified by giving NodeTuplePtr values for tail and tip; the module then creates the elements of the set. There is no additional mechanism needed for a larger set, one need only provide some additional information about particular identifier occurrences to specify the kind of identifier involved.

Let's consider a concrete example. A Java programmer may use the identifier ambig to represent a package, type, variable, and method in a single range. This requires four distinct scope graphs, one for each entity that ambig can represent. However, the language rules are such that these four scope graphs are isomorphic. Thus this set of scope graphs can be implemented by a single instantiation of the ScopeGraphs module. The NodeTuple corresponding to each range would be a four-element array in that implementation.

The number of elements in the set for a given instantiation of the ScopeGraphs module is given by the integer-valued *RootScope.*NumberOfIsoGraphs attribute. This synthesized attribute is set by a module computation to the value 1. A developer must override that computation when specifying several isomorphic scope graphs.

The *RootScope role is automatically inherited by the symbol at the root of the abstract syntax. The computation of the *NumberOfIsoGraphs attribute must be overridden by introducing a computation at that symbol. For example, if Java were the symbol at the root of the abstract syntax, the computation would be:

TREE SYMBOL Java COMPUTE SYNT.*NumberOfIsoGraphs=4; END;

The elements of the set of scope graphs implemented by a module instantiation are indexed by values @math{i}, @math{0 \leq i < *NumberOfIsoGraphs}. A specification is much more understandable if the possible graph indexes are named. Here is an appropriate set of graph index names for a Java specification:

enum { packageName, typeName, expressionName, methodName,
        packageOrTypeName, expressionOrTypeName, ambiguousName
     };

The first line names the kinds of entity that have scope graphs (an expressionName is a field name or a variable name).

Syntactic context must determine the specific kind of identifier at its defining occurrence. An applied occurrence at which the specific kind of identifier can be determined is called a strong context. In a weak context, the kind of identifier cannot be determined precisely although the set of possibilities could be narrowed. For example, in certain Java contexts an applied occurrence might refer to either a package or a type, but not to a method. Integer values @math{j}, @math{j \geq RootScope.NumberOfIsoGraphs} are used to specify the kind of identifier in a weak context. Meanings for these larger values are chosen by the developer, as shown in the second line of the enumeration.

An identifier occurrence's kind is specified to a computational role by the integer-valued GraphIndex attribute. This inherited attribute is set by a module computation to the value 0. The following computational roles provide the GraphIndex attribute:

*IdDefScope
*WLSimpleName
*WLQualName
*WLInsertDef
*GCSimpleName
*GCQualName

When there is more than one graph in the set, the default GraphIndex computations must be overridden. Here is a specific example:

TREE SYMBOL MethodIdDef INHERITS IdDefScope COMPUTE
  INH.GraphIndex = methodName;
END;

A module computation stores the value of the *IdDefScope.*GraphIndex attribute as the value of the GraphIndex property of the definition table key that is the value of *IdDefScope.*Key. Similarly, module computations establish values for the GraphIndex properties of the keys that are the values of the *UseKey attributes of the other roles listed above.

When the GraphIndex property of an applied occurrence indicates that the context is weak, searches are carried out in all graphs of the instantiation's set. If more than one binding is found, then NoKey is returned. The developer can change this behavior by providing a language-specific disambiguation function to determine the correct result (see Implementing Language-Specific Behavior).

Let `MaxIndex' be the maximum value of *RootScope.*NumberOfIsoGraphs over all instantiations of the ScopeGraphs module in the specification. If `MaxIndex' is greater than 1, then the developer must provide a file named `ScopeGraphs.h' as part of the specification. `ScopeGraphs.h' must contain the following declaration:

#define MaxIsoGraphs `MaxIndex'


Previous Chapter Next Chapter Table of Contents