% Computer Systems Research Group % University of Toronto % % File: New S/SL Processor V3.01 % Author: James R. Cordy % Date: 1 December 1979 (Revised 2 March 1983) % Copyright (C) 1979, 1980, 1983 The University of Toronto input: % Input in the S/SL processor: % Unlike the Turing compiler, the S/SL processor has % a single pass structure and hence the input Scanner % is included as part of the input mechanism. tSyntaxError = -1 tIdent 'ident' tString 'string' tInteger 'integer' tColon ':' tSemicolon ';' tEqual '=' tQuestionMark '?' tPeriod '.' tErrorSignal '#' tCall '@' tExit '>' tReturn '>>' tLeftParen '(' tRightParen ')' tCycle '{' % also 'DO' tCycleEnd '}' % also 'OD' tChoice '[' % also 'IF' tChoiceEnd ']' % also 'FI' tComma ',' tOr '|' % also '!' tOtherwise '*' % Keywords: % The S/SL Scanner converts all input identifiers and % keywords to lower case and hence will recognize any % capitalization. tInput 'INPUT' tOutput 'OUTPUT' tError 'ERROR' tType 'TYPE' tMechanism 'MECHANISM' tRules 'RULES' tEnd 'END' tNewLine '' % logical new line tEndOfFile tIllegal; output: % Output in the S/SL processor: % Unlike most compilers written in S/SL, th S/SL processor % output mechanism emits into an in-core table of values. % The emit primitive and emitting semantic operations write % into the output table sequentially as if it were a true % output stream. The "resolve" semantic operations modify % sections of the table already emitted by replacing null % addresses and values previously emitted. The "generate" % semantic operations generate text for output to the true % output stream of the processor, the constant and table % initialization code. % Primitive operations of S/SL aCall aReturn aRuleEnd aJump aInput aInputAny aInputChoice aEmit aError aChoice aChoiceEnd aSetParameter aSetResult aSetParameterFromInput; error: eCycleHasNoExits eDuplicateLabel eExitNotInCycle eIllegalParameterClass eIllegalResultClass eIllegalNonvaluedReturn eIllegalStringSynonym eIllegalValuedReturn eSymbolPreviouslyDefined eUndefinedSymbol eWrongDeclaredResultClass eWrongLabelClass eWrongParameterClass eWrongResultClass eWrongSymbolClass % Non-S/SL Semantic Errors eUnresolvedRule = 30 eSymbolTooLong eNumberTooLarge eStringTooLong eValueOutOfRange eJumpOutOfRange % Fatal Errors eSslStackOverflow = 40 eCallStackOverflow eTooManyTotalSymbolChars eTooManySymbols eTableTooLarge eCyclesTooDeep eTooManyExits eChoicesTooDeep eTooManyLabels eTooManyMerges eTooManyCalls eRuleTooLarge; % Semantic Mechanisms of the S/SL processor type Validity: invalid valid; type Integer: zero = 0 undefined = -9999; % The Call Table: % The Call Table is used to keep track of procedure calls in the % output table which will have to be resolved to table addresses % before the initialized table is generated. The table address of % the call and the Symbol Table index of the called procedure % are saved in the Call Table entry for each procedure call. % When the processor finishes processing the procedures section, % it uses the oResolveCalls operation to resolve all the procedure % calls before gnerating the output table. mechanism Call: oEnterCall oEmitNullCallAddress oResolveCalls; % The Symbol Table: % The Symbol Table mechanism is used to store information % about identifiers and string synonyms declared in the S/SL % program. Each entry has the symbol's name (or string), definition % class and associated value. There are 12 predefined classes of % defined symbols in S/SL. These are: cInput, cOutput, cInputOutput, % cError, cType, cMechanism, cUpdateOp, cParmUpdateOp, % cChoiceOp, cParmChoiceOp, cRule and cChoiceRule. % As well as these, each new type definition creates a new class % of defined symbols. The Symbol Table Mechanism keeps track of % the "current" class of definition being processed and enters that % class as the class of any new symbols entered in the Symbol Table. % For each class, a "current" next value is maintained and is the % default value for the next symbol entered of that class. % The "current" next value is always the value of the last symbol % declared in the class plus one. The Symbol Table also has a % "current" symbol entry which is set by the oLookupSymbol operation. % Symbol Table operations always act on the "current" symbol % entry by default. The Symbol Table mechanism also maintains an % "enclosing" symbol entry which is the mechanism or rule currently % being defined. Symbol Table operations use the word "New" for those % operations which act on the entry last entered rather than the % "current" entry. % Note: To satisfy Pascal 10-character identifier uniqueness requirements, % operation names which clash in the first 10 characters use x,y,z,v and w % as the second character of the identifier. % Symbol classes type SymbolClass: cNotFound % special class of non-existent symbols cInput cOutput cInputOutput cError cType cMechanism cUpdateOp cParmUpdateOp cChoiceOp cParmChoiceOp cRule cChoiceRule maxClasses = 50; mechanism Symbol: % Current class operations oSetClass(SymbolClass) oSetClassFromSymbolClass oxSetClassFromSymbolValue oySetClassFromSymbolResultClass ozSetClassFromSymbolParameterClass ovSetClassFromChoiceClass oChooseClass >> SymbolClass oSetClassValue owSetClassValueFromSymbolValue oIncrementClassValue % Symbol operations oEnterNewSymbol oLookupSymbol oChangeSymbolClass oChooseSymbolClass >> SymbolClass oVerifySymbolClass >> Validity oxEnterNewSymbolValue oEnterSecondNewSymbolValue % second most recently entered oEnterSymbolValueFromAddress oxChooseSymbolValue >> Integer oEmitSymbolValue oxVerifySymbolClassValue >> Validity oxEnterSymbolParameterClass oyEnterSymbolResultClass oyChooseSymbolResultClass >> SymbolClass oSaveEnclosingSymbol oRestoreEnclosingSymbol oSaveCurrentSymbol oRestoreCurrentSymbol; % The Cycle Stack: % The Cycle Stack is used to keep track of loop constructs in the % S/SL program. Each time the beginning of a loop is encountered % a new Cycle Stack entry is pushed, recording the start address of % the loop and the starting index of the Exit Stack frame for the % loop. When the end of a loop is encountered, the repeat branch % and loop exits are resolved using Cycle Stack operations and the % stack is popped. The Exit Stack is organized into frames displayed % by the Cycle Stack and is used to keep the table addresses of loop % exits which require table address resolution. mechanism Cycle: oPushCycle oPopCycle oChooseCycleDepth >> Integer oEmitCycleAddress oEnterCycleExit oResolveCycleExits oxChooseCycleExits >> Integer; % The Choice Stack: % The Choice Stack mechanism is used to keep track of input and % semantic choices in the S/SL program. Each time a choice is % encountered in the program, a new Choice Stack entry is pushed, % containing the class of the choice (i.e., is it an input choice or % a "value" (semantic) choice), the start index of the Merge and Label Stack % frames for the choice, and the table address of the choice. % When the end of the choice is encountered, Choice Stack operations % are used to resolve the "choice table" address, emit the choice table, % and resolve the merge branches from the alternatives of the Choice. % The Choice Stack entry is then popped. % The Merge Stack is organized into frames displayed by the Choice % Stack and is used to keep the table addresses of the merge branches % which follow each alternative and require table address resolution. % The Label Stack is organized into frames displayed by the Choice % Stack and is used to build up the list of (label value, table address) % pairs (the "choice table") for the choice. mechanism Choice: oPushChoice oPopChoice oChangeChoiceClass oChooseChoiceClass >> SymbolClass oVerifyChoiceSymbolLabel >> Validity oEnterChoiceSymbolLabel oxEnterChoiceMerge oResolveChoiceMerges oEmitChoiceTable oxResolveChoiceTableAddress oEmitFirstChoiceValue oxEmitFirstChoiceAddress; % The Rule Table: % The output S/SL table is assembled one rule at a time. % Each rule is saved in the Rule Table for later recall % and final assembly into the generated output table. mechanism Rule: oStartRules oBeginRule oSaveRule oEndRules; % The Generate Operations: % These operations generate the source language code for the internally % compiled symbol definitions and S/SL table. mechanism Generate: oGenerateDefinitions % of symbols oGenerateTable; % S/SL table % Miscellaneous Emitting Operations: % These operations are used to emit input or standard values % to the output table. mechanism InputOutput: oEmitValue oEmitNullAddress; rules Program: @InputOutputDefinitions @ErrorDefinitions @TypeAndMechanismDefinitions @RuleDefinitions oGenerateDefinitions oGenerateTable; InputOutputDefinitions: [ | 'INPUT': [ | 'OUTPUT': oSetClass(cInputOutput) @SymbolDefinitions | *: oSetClass(cInput) @SymbolDefinitions @OutputDefinitions ] | *: @OutputDefinitions ]; OutputDefinitions: [ | 'OUTPUT': oSetClass(cOutput) @SymbolDefinitions | *: ] [ | 'INPUT': 'OUTPUT' oSetClass(cInputOutput) @SymbolDefinitions | *: ]; SymbolDefinitions: ':' '' {[ | 'ident': @VerifyNewSymbol oEnterNewSymbol [ | 'string': [ oChooseClass | cInput, cOutput, cInputOutput: | *: #eIllegalStringSynonym ] @VerifyNewSymbol oEnterNewSymbol @Value oEnterSecondNewSymbolValue | *: @Value ] '' oIncrementClassValue | ';': > ]}; Value: [ | '=': [ | 'integer': oSetClassValue | 'ident', 'string': oLookupSymbol [ oChooseSymbolClass | cNotFound: #eUndefinedSymbol | *: ] owSetClassValueFromSymbolValue ] | *: ] oxEnterNewSymbolValue; ErrorDefinitions: [ | 'ERROR': oSetClass(cError) @SymbolDefinitions | *: ]; TypeAndMechanismDefinitions: {[ | 'TYPE': 'ident' @VerifyNewSymbol oSetClass(cType) oEnterNewSymbol oxEnterNewSymbolValue oIncrementClassValue oxSetClassFromSymbolValue @SymbolDefinitions | 'MECHANISM': 'ident' @VerifyNewSymbol oSetClass(cMechanism) oEnterNewSymbol oSaveEnclosingSymbol @OperationDefinitions | *: > ]}; OperationDefinitions: ':' '' {[ | 'ident': @VerifyNewSymbol oRestoreEnclosingSymbol oSetClass(cUpdateOp) % assume update operation, change later oEnterNewSymbol oxEnterNewSymbolValue oSaveCurrentSymbol [ | '(': oSetClass(cParmUpdateOp) oChangeSymbolClass 'ident' oLookupSymbol [ oChooseSymbolClass | cType: oxSetClassFromSymbolValue | cNotFound: #eUndefinedSymbol oSetClass(cNotFound) | *: #eIllegalParameterClass oSetClass(cNotFound) ] oRestoreCurrentSymbol oxEnterSymbolParameterClass ')' | *: ] [ | '>>': [ oChooseSymbolClass | cUpdateOp: oSetClass(cChoiceOp) | cParmUpdateOp: oSetClass(cParmChoiceOp) ] oChangeSymbolClass 'ident' oLookupSymbol [ oChooseSymbolClass | cType: oxSetClassFromSymbolValue | cNotFound: #eUndefinedSymbol oSetClass(cNotFound) | *: #eIllegalResultClass oSetClass(cNotFound) ] oRestoreCurrentSymbol oyEnterSymbolResultClass | *: ] oSetClassFromSymbolClass oIncrementClassValue '' | ';': > ]}; RuleDefinitions: 'RULES' '' oStartRules {[ | 'ident': oLookupSymbol [ | '>>': oSetClass(cChoiceRule) [ oChooseSymbolClass | cChoiceRule: [ oxChooseSymbolValue | undefined: | *: #eSymbolPreviouslyDefined ] | cNotFound: oEnterNewSymbol | *: #eSymbolPreviouslyDefined oEnterNewSymbol ] oySetClassFromSymbolResultClass oEnterSymbolValueFromAddress oSaveCurrentSymbol 'ident' oLookupSymbol [ oChooseSymbolClass | cType: [ oChooseClass | cNotFound: oxSetClassFromSymbolValue oRestoreCurrentSymbol oyEnterSymbolResultClass | *: [ oxVerifySymbolClassValue | valid: | *: #eWrongDeclaredResultClass ] ] | cNotFound: #eUndefinedSymbol | *: #eIllegalResultClass ] oRestoreCurrentSymbol | *: oSetClass(cRule) [ oChooseSymbolClass | cRule: [ oxChooseSymbolValue | undefined: | *: #eSymbolPreviouslyDefined ] | cNotFound: oEnterNewSymbol | *: #eSymbolPreviouslyDefined oEnterNewSymbol ] oEnterSymbolValueFromAddress ] oSaveEnclosingSymbol ':' '' oBeginRule @Actions ';' oRestoreEnclosingSymbol [ oChooseSymbolClass | cRule: .aReturn | cChoiceRule: .aRuleEnd ] oSaveRule | 'END': > ]} oEndRules oResolveCalls; Actions: { [ | 'string': @InputOperation | '?': @InputAny | '.': [ | 'ident': | 'string': ] @OutputOperation | '#': 'ident' @ErrorSignal | '@': 'ident' @RuleCall | '>>': @ReturnOperation | 'ident': @InputOrUpdateOperation | '{': @CycleAction | '>': @CycleExit | '[': [ | 'ident': @SemanticChoice | '@': @RuleChoice | '*': @InputLookaheadChoice | *: @InputChoice ] | *: > ] '' }; InputOperation: .aInput oLookupSymbol [ oChooseSymbolClass | cInput, cInputOutput: | cNotFound: #eUndefinedSymbol | *: #eWrongSymbolClass ] oEmitSymbolValue; InputAny: .aInputAny; OutputOperation: .aEmit oLookupSymbol [ oChooseSymbolClass | cOutput, cInputOutput: | cNotFound: #eUndefinedSymbol | *: #eWrongSymbolClass ] oEmitSymbolValue; ErrorSignal: .aError oLookupSymbol [ oChooseSymbolClass | cError: | cNotFound: #eUndefinedSymbol | *: #eWrongSymbolClass ] oEmitSymbolValue; RuleCall: .aCall oEmitNullCallAddress oLookupSymbol [ oChooseSymbolClass | cRule: oEnterCall | cNotFound: oSetClass(cRule) oEnterNewSymbol oEnterCall | *: #eWrongSymbolClass ]; ReturnOperation: oRestoreEnclosingSymbol [ | 'ident': [ oChooseSymbolClass | cChoiceRule: oySetClassFromSymbolResultClass oLookupSymbol [ oChooseSymbolClass | cNotFound: #eUndefinedSymbol | *: [ oVerifySymbolClass | valid: | *: #eWrongResultClass ] ] .aSetResult oEmitSymbolValue .aReturn | cRule: #eIllegalValuedReturn ] | *: [ oChooseSymbolClass | cRule: .aReturn | cChoiceRule: #eIllegalNonvaluedReturn ] ]; InputOrUpdateOperation: oLookupSymbol [ oChooseSymbolClass | cInput, cInputOutput: @InputOperation | *: [ | '(': [ oChooseSymbolClass | cParmUpdateOp: ozSetClassFromSymbolParameterClass oSaveCurrentSymbol 'ident' oLookupSymbol [ oChooseSymbolClass | cNotFound: #eUndefinedSymbol | *: [ oVerifySymbolClass | valid: | *: #eWrongParameterClass ] ] .aSetParameter oEmitSymbolValue oRestoreCurrentSymbol oEmitSymbolValue | cNotFound: #eUndefinedSymbol 'ident' | *: #eWrongSymbolClass 'ident' ] ')' | *: [ oChooseSymbolClass | cUpdateOp: oEmitSymbolValue | cNotFound: #eUndefinedSymbol | *: #eWrongSymbolClass ] ] ]; CycleAction: oPushCycle '' @Actions '}' .aJump oEmitCycleAddress [ oxChooseCycleExits | zero: #eCycleHasNoExits | *: ] oResolveCycleExits oPopCycle; CycleExit: [ oChooseCycleDepth | zero: #eExitNotInCycle | *: .aJump oEmitNullAddress oEnterCycleExit ]; SemanticChoice: oLookupSymbol [ | '(': [ oChooseSymbolClass | cParmChoiceOp: ozSetClassFromSymbolParameterClass oSaveCurrentSymbol 'ident' oLookupSymbol [ oChooseSymbolClass | cNotFound: #eUndefinedSymbol | *: [ oVerifySymbolClass | valid: | *: #eWrongParameterClass ] ] .aSetParameter oEmitSymbolValue oRestoreCurrentSymbol oySetClassFromSymbolResultClass oEmitSymbolValue | cNotFound: #eUndefinedSymbol oSetClass(cNotFound) 'ident' | *: #eWrongSymbolClass oSetClass(cNotFound) 'ident' ] ')' | *: [ oChooseSymbolClass | cChoiceOp: oEmitSymbolValue oySetClassFromSymbolResultClass | cNotFound: #eUndefinedSymbol oSetClass(cNotFound) | *: #eWrongSymbolClass oSetClass(cNotFound) ] ] .aChoice oEmitNullAddress @ChoiceBody; RuleChoice: .aCall oEmitNullCallAddress 'ident' oLookupSymbol [ oChooseSymbolClass | cChoiceRule: oEnterCall oySetClassFromSymbolResultClass | cNotFound: oSetClass(cChoiceRule) oEnterNewSymbol oEnterCall oSetClass(cNotFound) | *: #eWrongSymbolClass oSetClass(cNotFound) ] .aChoice oEmitNullAddress @ChoiceBody; InputLookaheadChoice: .aSetParameterFromInput .aChoice oEmitNullAddress oSetClass(cInput) @ChoiceBody; InputChoice: .aInputChoice oEmitNullAddress oSetClass(cInput) @ChoiceBody; ChoiceBody: '' oPushChoice oSaveCurrentSymbol % choice rule symbol if rule choice '|' @Labels ':' '' oRestoreCurrentSymbol % choice rule symbol [ oChooseSymbolClass | cChoiceRule: [ oyChooseSymbolResultClass | cNotFound: oyEnterSymbolResultClass % resolve result class % from label class | *: ] | *: ] @Actions {[ | '|': .aJump oEmitNullAddress oxEnterChoiceMerge [ | '*': ':' '' oxResolveChoiceTableAddress oEmitChoiceTable @Actions > | *: @Labels ':' '' @Actions ] | *: .aJump oEmitNullAddress oxEnterChoiceMerge oxResolveChoiceTableAddress oEmitChoiceTable [ oChooseChoiceClass | cInput: .aInput oEmitFirstChoiceValue .aJump oxEmitFirstChoiceAddress | *: .aChoiceEnd ] > ]} ']' oResolveChoiceMerges oPopChoice; Labels: ovSetClassFromChoiceClass {[ | 'ident', 'string': oLookupSymbol [ oChooseChoiceClass | cNotFound: oSetClassFromSymbolClass oChangeChoiceClass | *: ] [ oChooseClass | cInput: [ oChooseSymbolClass | cInput, cInputOutput: | cNotFound: #eUndefinedSymbol | *: #eWrongLabelClass ] | *: [ oChooseSymbolClass | cNotFound: #eUndefinedSymbol | *: [ oVerifySymbolClass | valid: | *: #eWrongLabelClass ] ] ] [ oVerifyChoiceSymbolLabel | valid: | *: #eDuplicateLabel ] oEnterChoiceSymbolLabel [ | ',': | *: > ] ]}; VerifyNewSymbol: oLookupSymbol [ oChooseSymbolClass | cNotFound: | *: #eSymbolPreviouslyDefined ]; end