General Information
Tutorials
Reference Manuals
Libraries
Translation Tasks
Tools
Administration
|
Name Analysis Reference ManualTree Grammar PreconditionsThe ScopeGraphs specification module provides computational roles to be inherited by nonterminal symbols of the abstract syntax tree. To make effective use of these roles, the abstract syntax tree must be designed with them in mind. Generally speaking, that means that the abstract syntax tree structure will differ somewhat from the structure of the parse tree. Eli offers tools that aid in mapping a parse tree to an appropriate abstract syntax tree (see The Relationship Between Phrases and Tree Nodes of Syntactic Analysis). A developer can often use the parsing grammar provided by the language designer, and define simple mapping rules to obtain the desired abstract syntax tree (see Syntax development hints of Syntactic Analysis). Sometimes, however, a change in the parsing grammar is required. That can lead to difficulties, depending on the parsing algorithm (see How to Resolve Parsing Conflicts of Syntactic Analysis).
Representation of identifiers
An identifier is a basic symbol of the language being analyzed, and will
correspond to a named terminal symbol of the concrete grammar describing
the input text.
(Typically the terminal symbol is named `Identifier' or `Ident'.)
Named terminal symbols do not contribute to the trees specified by the tree
grammar, but a value derived from the basic symbol may be used in
computations associated with the rule of a production or with the symbol
on the left-hand side of a production
(see Productions of LIDO -- Reference Manual).
A unique integer value is typically derived from each identifier
by the token processor
Identifiers usually play different roles in different syntactic contexts.
We recommend that these distinctions not be made
in the concrete syntax.
The concrete syntax should use the same named terminal (e.g. Consider the concrete productions
ObjDecl: TypeDenoter Ident. TypeDenoter: Ident. Variable: Ident.We distinguish the different roles of identifiers by introducing new symbol names in the corresponding LIDO RULE s:
RULE: ObjDecl ::= TypeDenoter DefIdent END; RULE: TypeDenoter ::= TypeUseIdent END; RULE: Variable ::= UseIdent END;The new symbol names must, of course, be defined:
RULE: DefIdent ::= Ident END; RULE: UseIdent ::= Ident END; RULE: TypeUseIdent ::= Ident END;
Representation of rangesRecall that a range is a subtree of the abstract syntax tree that encompasses a scope. Most programming languages allow nested scopes, and allow the meaning of an identifier in an inner scope to differ from the meaning in an outer scope. In that case, we say that the identifier's binding from the outer scope is not visible in the inner scope. The developer's goal for the abstract syntax tree should be that each range encompasses a scope containing all occurrences of identifiers defined in that scope but not containing any defining occurrence whose binding is visible outside of that scope. For example, consider the following grammar fragment:
ProcedureDeclaration: 'procedure' ProcedureHeading ProcedureBody / Type 'procedure' ProcedureHeading ProcedureBody . ProcedureHeading: ProcedureIdentifier FormalParameterPart ';' ValuePart SpecificationPart . ProcedureIdentifier: Identifier . ProcedureBody: Statement .
A
The solution is to add a nonterminal
ProcedureDeclaration: 'procedure' ProcedureIdentifier ProcedureRange / Type 'procedure' ProcedureIdentifier ProcedureRange . ProcedureIdentifier: Identifier . ProcedureRange: ProcedureHeading ProcedureBody . ProcedureHeading: FormalParameterPart ';' ValuePart SpecificationPart . ProcedureBody: Statement .
Here the
The
ProcedureInterface: 'procedure' ProcedureIdentifier ProcedureHeading / Type 'procedure' ProcedureIdentifier ProcedureHeading . ProcedureImplementation: 'implementation' ProcedureIdentifier ProcedureBody .
The
The We have defined a scope as a contiguous sequence of program text, and said that the developer needs to map each scope to an abstract syntax subtree encompassing that scope (see Fundamentals of Name Analysis). In order to deal with separate interface and implementation, it is convenient to generalize these concepts by allowing a scope to be a set of disjoint contiguous sequences of program text, and requiring the developer to map these regions into an abstract syntax tree subforest that encompasses those sequences. The subforest then has the desired properties of a range: it contains all of the occurrences in the scope, and does not contain any defining occurrence whose binding is visible outside.
|