We now define some auxiliary predicates that were used in the above specifications.
(The checks could also be written ``inline'' using conditional statements. We refrained from doing so in order to keep the number of concepts small in the example compiler).
362 'action' CheckInt(Type: TYPE, Pos: POS) 363 'rule' CheckInt(integer, Pos) 364 'rule' CheckInt(T, Pos) : Error("Integer expected", Pos) 365 'action' CheckBool(Type: TYPE, Pos: POS) 366 'rule' CheckBool(boolean, Pos) : 367 'rule' CheckBool(T, Pos) : Error("Boolean expected", Pos) 368 'action' CheckSimple(Type: TYPE, Pos: POS) 369 'rule' CheckSimple(integer, _) 370 'rule' CheckSimple(real, _) 371 'rule' CheckSimple(boolean, _) 372 'rule' CheckSimple(T, Pos) : Error("simple type expected", Pos) 373 'action' CheckArrayType(Type: TYPE, Pos: POS 374 -> Lwb: INT, Upb: INT, ElemType: TYPE) 375 'rule' CheckArrayType(array(Lwb, Upb, ElemType), Pos 376 -> Lwb, Upb, ElemType) 377 'rule' CheckArrayType(T, Pos -> 0, 0, none) : 378 Error("Subscripted var is not an array", Pos) 379 'action' CheckDesignator(E: EXPR, Pos: POS -> D: DESIG) 380 'rule' CheckDesignator(desig(D), _ -> D) 381 'rule' CheckDesignator(E, Pos -> none) : 382 Error("VAR parameter expected", Pos) 383 'action' CheckEquiv(T1: TYPE, T2: TYPE, Pos: POS) 384 'rule' CheckEquiv(T1, T2, Pos) : eq(T1, T2) 385 'rule' CheckEquiv(T1, T2, Pos) : 386 Error("Types are not equivalent", Pos) 387 'action' CheckType(Type: TYPE, Pos: POS) 388 'rule' CheckType(array(Lwb, Upb, ElemType), Pos) : 389 CheckBounds(Lwb, Upb, Pos) CheckType(ElemType, Pos) 390 'rule' CheckType(_, _) : 391 'action' CheckBounds(Lwb: INT, Upb: INT, Pos: POS) 392 'rule' CheckBounds(Lwb, Upb, _): le(Lwb, Upb) 393 'rule' CheckBounds(_, _, Pos): 394 Error("lower bound exceeds upper bound", Pos) 395 'action' CheckNotYetDeclared(Obj: OBJ, Lev: INT, Pos: POS) 396 'rule' CheckNotYetDeclared(none, Level, Pos) : 397 'rule' CheckNotYetDeclared(object(_, ObjLev, _), Level, Pos) : 398 lt(ObjLev, Level) 399 'rule' CheckNotYetDeclared(_, _, Pos) : 400 Error("id already declared", Pos) 401 'action' CheckProcedure(OBJ, POS -> DECLLIST, INT, LABEL) 402 'rule' CheckProcedure(object(procobj(Start,Formals),Level,_),_ 403 -> Formals, Level, Start) 404 'rule' CheckProcedure(_, Pos -> nil, 0, Null): 405 Error("procedure expected", Pos) 406 NewLabel(-> Null) 407 'action' Error(Msg: STRING, Pos: POS) |
|
The above predicates check their first argument for semantic constraints. If it is erroneous, then an error message is issued using the library predicate Error(Msg, Pos)).
Some predicates return certain characteristics of their argument.
For example, CheckArrayType(Type, Pos -> Lwb, Upb, ElemType) checks whether the argument is an array type, and returns the lower and upper bound and the element type if this is true.
408 'var' CurNestingLevel: INT 409 'action' SetCurrentNesting(N: INT) 410 'rule' SetCurrentNesting(N): CurNestingLevel <- N 411 'action' GetCurrentNesting(-> INT) 412 'rule' GetCurrentNesting(-> N): CurNestingLevel -> N 413 'action' TypeCode(Type: TYPE -> Code: INT) 414 'rule' TypeCode(integer -> 1) 415 'rule' TypeCode(real -> 2) 416 'rule' TypeCode(boolean -> 3) 417 'action' TypeSize(Type: TYPE -> Size: INT) 418 'rule' TypeSize(integer -> 1) 419 'rule' TypeSize(real -> 1) 420 'rule' TypeSize(boolean -> 1) 421 'rule' TypeSize(array(Lwb, Upb, ElemType) 422 ->((Upb-Lwb)+1)*ElemSize) : 423 TypeSize(ElemType -> ElemSize) |
|
The current nesting level of procedures is implemented as a global variable, the predicates SetCurrentNesting and GetCurrentNesting are used to set and get its value.
The predicates TypeCode and TypeSize compute the encoding and the size of a type.