General Information
Tutorials
Reference Manuals
Libraries
Translation Tasks
Tools
Administration
|
LIDO -- Computations in TreesRemote Dependencies in TreesIn the previous section we considered dependencies between computations within one rule context and computations that are associated to pairs of adjacent contexts. It is often necessary to specify that a precondition of a computation is established rather far away in the tree, e. g. a value computed in the root context is used in several computations down in the tree. Instead of propagating it explicitly through all intermediate contexts it may be accessed directly by notations for remote dependencies. In the following we introduce three constructs for remote dependency specification:
These constructs can be used for value dependencies as well as for state dependencies. Since these constructs avoid specifications in the contexts between the remote computations, they abstract from the particular tree structure in between: It may be designed according to other aspects or be altered without invalidating those remote dependencies.
Access to a Subtree Root
Assume that we have a language where
ATTR depth: int; RULE: Root ::= Block COMPUTE Block.depth = 0; END; RULE: Block ::= '{' Sequence '}' END; RULE: Sequence ::= Sequence Statement END; RULE: Sequence ::= Sequence Definition END; RULE: Sequence ::= END; RULE: Statement ::= Block COMPUTE Block.depth = ADD (INCLUDING Block.depth, 1); END; RULE: Statement ::= Usage END; RULE: Usage ::= 'use' Ident END; TERM Ident: int; RULE: Definition ::= `define' Ident COMPUTE printf ("%s defined on depth %d\n", StringTable (Ident), INCLUDING Block.depth); END;Figure 6: Nesting Depth of Blocks
The specification of Figure 6 solves the stated problem by remote
dependencies (
INCLUDING Block.depth
used in two computations accesses the In general, alternative subtree root symbols may be specified, e. g.
INCLUDING (Block.depth, Procedure.depth, Module.depth)
Then the root of the smallest enclosing subtree is accessed which
represents one of the given symbols. The tree grammar must guarantee
that such a subtree root can always be found. Such an alternative
has to be used especially
in an
Access to Contexts within a SubtreeAssume that we have a language for sequences of definitions and uses of names in arbitrary order. We want to produce an output text for each definition and each use, such that definition texts precede the use texts in the output. No specific order is required within the two text blocks.
RULE: Block ::= '{' Sequence '}' COMPUTE Block.DefDone = CONSTITUENTS Definition.DefDone; END; RULE: Definition ::= 'Define' Ident COMPUTE Definition.DefDone = printf ("%s defined in line %d\n", StringTable(Ident), LINE); END; RULE: Usage ::= 'use' Ident COMPUTE printf ("%s used in line %d\n", StringTable(Ident), LINE), <- INCLUDING BLOCK.DefDone; END;Figure 7: Sequencing Classes of Computations in a Subtree
The solution of the problem given in Figure 7 uses a state attribute
The following example demonstrates the remote access to values within a
subtree. We simply want to compute the number of
ATTR Count: int; RULE: Block ::= '{' Sequence '}' COMPUTE printf ("%d uses occurred\n", CONSTITUENTS Usage.Count WITH (int, ADD, IDENTICAL, ZERO)); END; RULE: Usage ::= 'use' Ident COMPUTE Usage.Count = 1; END;Figure 8: Adding Values of Subtree Components
The
The
WITH (t, combine, single, none)
where
WITH (int, ADD, IDENTICAL, ZERO) WITH (int, Maximum, IDENTICAL, ZERO) WITH (int, OR, IDENTICAL, ZERO) WITH (int, AND, IDENTICAL, ONE) WITH (listtype, Append, SingleList, NullList)Figure 9: Typical WITH Clauses
The applications of the
We must be aware that in our example the
CONSTITUENTS Usage.Count SHIELD Block WITH (...)
In general we may shield any class of subtrees from the
SHIELD (Block, Procedure, Module) ...
If no subtree should be shielded an empty
... SHIELD () ...
In this case our example would count the
In general several attributes may be specified for being accessed by a
CONSTITUENTS (X.a, Y.b)
Left-to-Right DependenciesAs an example for a simple left-to-right dependent computation we rewrite the translation of expressions into postfix form of Figure 4.
In Figure 10 the
CHAIN print: VOID; RULE: Root ::= Expr COMPUTE CHAINSTART HEAD.print = "yes"; printf ("\n") <- TAIL.print; END; RULE: Expr ::= Number COMPUTE Expr.print = printf ("%d ", Number. Sym) <- Expr.print; END; RULE: Opr ::= '+' COMPUTE Opr.post = printf ("+") <- Opr.pre; END; RULE: Expr ::= Expr Opr Expr COMPUTE Opr.pre = Expr[3].print; Expr[1].print = Opr.post; END;Figure 10: CHAIN for Producing Postfix Expressions
The
In the second context the
The
If it is necessary to locally deviate from
Opr.print = printf("Operator encountered\n") <- Opr.print;
it looks like being integrated into the print
The above example specifies a single
CHAIN RelAdr: int; RULE: Block ::= '{' Sequence '}' COMPUTE CHAINSTART HEAD.RelAdr = 0; END; RULE: Definition ::= 'define' Ident COMPUTE Definition.RelAdr = ADD (Definition.RelAdr, VariableSize); END;Figure 11: Computing Addresses of Variables
An individual
|