General Information
Tutorials
Reference Manuals
Libraries
Translation Tasks
Tools
Administration
|
Tree ParsingActions Carried Out During ParsingEach rule has an associated action, written as an identifier:
N0 ::= s(Ni,aj) : Action1 N0 ::= N1 : Action2 N0 ::= s(t(Ni),Nj) : Action3 The action associated with a rule is carried out each time the rule is used in a derivation. Each rule may be associated with a distinct action, or a single action may be associated with several rules.
Actions and ValuesThe action carried out for each use of a rule in a derivation is a function application. The action identifier is the name of the function, and the arguments to which it is applied are the values of the nonterminals and attributes appearing on the right-hand side of the pattern. These values are taken in order from left to right. The result of the function becomes the value of the nonterminal appearing on the left-hand side of the pattern.
For example, consider one of the rules of the specification introduced above
(see Rules Describing Tree Nodes), augmented by an action called
IntReg ::= IntegerVal(int) : IntR_loadconstFor each use of the rule IntReg ::= IntegerVal(int) in some
derivation, the function named IntR_loadconst will be applied to the
integer-valued attribute of the leaf.
The result of this function application will become the value of the
IntReg nonterminal.
The types of the attribute values are stated explicitly in the rules.
A type is also associated with each nonterminal by means of a declaration
(see Summary of the Specification Language).
For example, the type associated with the nonterminal
typedef struct { int register; PTGNode code; } reg;Here the register field would be the number of the register holding
the result and the code field would be a representation of the
assembly language instructions producing the result in that register
(see Introduction of Pattern-Based Text Generator).
In this case, execution of
Here's another example of a rule, this time augmented by an action called
IntReg ::= Minus(IntReg,IntReg) : IntRR_subThe function named IntRR_sub will be applied to the values returned
by the two children of the Minus node for each use of
IntReg ::= Minus(IntReg,IntReg) in some derivation,
and the result will become the value of the IntReg nonterminal on
the left-hand side of the rule.
The first argument of IntRR_sub would be the value returned by the
action associated with the left child of the Minus node, and the
second would be the value returned by the right child.
Execution of
Each nonterminal is associated with a function whose
name is
A specification with all of the rules described so far
has only two nonterminals (
A derivation for the tree rooted in tree in which the root is
interpreted as an
A derivation for the tree rooted in tree in which the root is
interpreted as a The program will terminate abnormally when a requested derivation is not possible. This condition always arises from a design fault; either the patterns are incomplete, or the tree to be parsed is malformed. Implementing ActionsAn action is a function application, and the name of the action is the function to be invoked. The rule with which the action is associated determines the signature of the function: Recall that the arguments of the function are the nonterminals and attributes appearing on the right-hand side of the associated rule, in order from left to right. The result of the function becomes the value of the nonterminal appearing on the left-hand side of the associated rule. Each nonterminal and attribute has a fixed type. Function application can be implemented either by calling a macro or by invoking a routine. If the action requires a routine invocation, and the signature of the routine to be invoked matches the signature determined by the rule, then the routine name can be used directly as the action. Often, however, there is a mismatch between the signatures. In that case, the action can be made the name of a macro that rearranges arguments, inserts constants, or does whatever else is needed to correct the mismatch. Commutative ActionsMany computers have instruction sets that are asymmetric in their treatment of operands. For example, a machine with two-operand instructions may allow only the second of these operands to be a literal value. If two values in registers are being added, the "add register" instruction is used, but if a literal value were being added to a value in a register the "add immediate" instruction would be necessary. One rule characterizing an integer addition operation for such a machine, with an action to generate the "add immediate" instruction, might be the following:
IntReg ::= Plus(IntReg,IntLit) : IntRI_add(Here the nonterminal IntLit represents the interpretation
"a literal integer".)
Notice that the children of the
Because addition is commutative, however, it is possible to interchange
the children of the
This possibility is indicated by using
IntReg ::= Plus(IntReg,IntLit) :: IntRI_add
|