Next: , Up: Expressions


2.1 Values

The symbol on the left-hand side of a rule defining an expression node characterizes the expression's result. It inherits the ExpressionSymbol role. Here are appropriate inheritance specifications for Mystery:

     SYMBOL Expr INHERITS ExpressionSymbol END;

Two attributes of ExpressionSymbol describe its type:

Required
An inherited attribute whose DefTableKey value is the type required by the surrounding context. It may be provided by user computation at the root of the expression tree, and is computed by the module at all other nodes. A value of NoKey is provided at the root by default, indicating that no specific type of value is required.
Type
A synthesized attribute whose DefTableKey value is the type of the result delivered by the expression. It must be provided by user computation at the leaves of the expression tree, and is computed by the module at the root and all interior nodes.

The Mystery assignment statement illustrates two possible situations with respect to the Required attribute at the root of an expression tree:

     RULE: Stmt ::= Expr ':=' Expr
     COMPUTE Expr[2].Required=Expr[1].Type;
     END;

There is no specific requirement on the type defined by the left-hand expression, and therefore there is no need to override the default computation of Expr[1].Required. Because the type of the value returned by the right-hand expression of the assignment must match the type defined by the left-hand expression, however, that symbol computation is overridden here.

PrimaryContext(`e1',`type') is used to compute the value of the Type attribute at the leaves of an expression tree. Argument `e1' is the grammar symbol playing the ExpressionSymbol role at that leaf, and `type' must be the definition table key of the type delivered by the leaf.

Mystery constant and variable references are primary contexts:

     RULE: Expr ::= Number
     COMPUTE PrimaryContext(Expr,intType);
     END;
     
     RULE: Expr ::= ExpIdUse
     COMPUTE PrimaryContext(Expr,ExpIdUse.Type);
     END;

TransferContext(`e1',`e2') marks an expression node in which the result and one operand are identical with respect to type. Arguments `e1' and `e2' are grammar symbols playing the ExpressionSymbol role, with `e1' being the result.

The chain rule defining an argument as an expression in Mystery is an example of a transfer context:

     SYMBOL Actual INHERITS ExpressionSymbol END;
     
     RULE: Actual ::= Expr
     COMPUTE TransferContext(Actual,Expr);
     END;

Actual, a procedure argument, plays the role of an expression but has additional properties and is therefore represented by a distinct grammar symbol (see Procedure Definition and Call).

BalanceContext(`e1',`e2',`e3') marks an expression node in which the result and two operands are identical with respect to type. Arguments `e1', `e2', and `e3' are grammar symbols playing the ExpressionSymbol role, with `e1' being the result.

A conditional expression like that of C is an example of a balance context:

     RULE: Expr ::= Expr '?' Expr ':' Expr
     COMPUTE
       BalanceContext(Expr[1],Expr[3],Expr[4]);
       Expr[1].Required=scalarType;
     END;

(A scalar type in C is a pointer or a number.)