-- file BcdTreeBuild.mesa rewritten by PGS, 11-Aug-83 15:40
-- DO NOT CONVERT TO TIOGA!  (PGS requires that comments be mesa-style.)
-- last edited by Satterthwaite on January 10, 1983 2:26 pm
-- last edited by Lewis on 12-Mar-81 18:04:07
-- last edited by Maxwell on August 11, 1983 3:36 pm 

DIRECTORY
  P1: TYPE USING [
    ActionStack, LinkStack, Value, ValueStack, InputLoc, nullId, nullValue],
  ParseTable: TYPE USING [ProdDataRef, Symbol, tokenID],
  Tree: TYPE USING [Link, null],
  TreeOps: TYPE USING [
    PopTree, PushTree, PushHash, PushList, PushNode, SetAttr, SetInfo];

BcdTreeBuild: PROGRAM
    IMPORTS P1, TreeOps
    EXPORTS P1 = {
  OPEN TreeOps;

  -- local data base (supplied by parser)

  v: P1.ValueStack;
  l: P1.LinkStack;
  q: P1.ActionStack;
  proddata: ParseTable.ProdDataRef;

  AssignDescriptors: PUBLIC PROC [
      qd: P1.ActionStack, vd: P1.ValueStack, ld: P1.LinkStack, pp: ParseTable.ProdDataRef] ~
    {q ← qd;  v ← vd;  l ← ld;  proddata ← pp};


  -- the interpretation rules

  LinkToSource: PROC [index: CARDINAL] ~ INLINE {SetInfo[l[index]]};

  exportsALL: BOOL;

  LinkSpec: TYPE ~ {frame, defaultFrame, code, defaultCode};
  CodeLinks: TYPE ~ LinkSpec [$code .. $defaultCode];
  DefaultLinks: ARRAY LinkSpec OF LinkSpec ~ [
    $defaultFrame, $defaultFrame, $defaultCode, $defaultCode];
    
  linkSpec: LinkSpec;
        
  SetLinkAttrs: PROC ~ {
    SetAttr[$codeLinks, linkSpec IN CodeLinks];
    SetAttr[$explicitLinkLoc, linkSpec # DefaultLinks[linkSpec]]};
  

  ProcessQueue: PUBLIC PROC [qI, top: CARDINAL] ~ {
    save: Tree.Link;
    vTop: P1.Value;
    FOR i: CARDINAL IN [0 .. qI) DO
      top ← top-q[i].tag.pLength+1;  vTop ← v[top];
      SELECT proddata[q[i].transition].rule FROM

        0  =>	--
	    --TABLE: BcdParseData  TYPE: ParseTable  EXPORTS: SELF
	    --GOAL:  goal

	    --TERMINALS:
	    --    id 	str	,	;
	    --    :	←	=	~
	    --    ]	[	}	{	.

	    --  DIRECTORY	FROM	PACK	CONFIGURATION	CONFIG
	    --  IMPORTS	EXPORTS	CONTROL	BEGIN
	    --  END 	PLUS	THEN	LINKS
	    --  CODE	FRAME   ALL

	    --ALIASES:
	    --  id       tokenID
	    --  str      tokenSTR
	    --  .        initialSymbol

	    --  PRODUCTIONS:

		-- goal		  ::= . source 
          NULL;

        1  =>	-- source         ::= directory packing init config .
          {PushNode[$source,3];  LinkToSource[top]};

        2  =>	-- directory      ::= DIRECTORY includelist ;
          PushList[v[top+1].s];

        3  =>	-- includeitem    ::= id : FROM str
          BEGIN
          PushHash[v[top].r];  PushHash[v[top+3].r];  PushNode[$item,2];
          LinkToSource[top];
          END;

        4  =>	-- packing        ::= packlist ;
          PushList[v[top].s];

        5  =>	-- packlist       ::= PACK idlist 
          {PushList[v[top+1].s]; LinkToSource[top]; vTop ← [scalar[1]]};

        6  =>	-- packlist       ::= packlist ; PACK idlist
          {PushList[v[top+3].s]; LinkToSource[top]; vTop ← [scalar[v[top].s+1]]};

        7  =>	-- init           ::= 
          {linkSpec ← $defaultFrame;  exportsALL ← FALSE};

        8  =>	-- config         ::= id : CONFIG links imports exports control tilde body 
             	-- config         ::= id : CONFIGURATION links imports exports control tilde body 
          BEGIN
          save ← PopTree[];
	  PushHash[v[top].r];  PushTree[save];  PushNode[$config,5];
          SetAttr[$exportsALL, exportsALL];  LinkToSource[top];
          linkSpec ← v[top+3].s;  exportsALL ← v[top+5].s;  -- restore old values
          END;

        9  =>	-- links          ::= 
          {vTop ← [scalar[linkSpec]];  linkSpec ← DefaultLinks[linkSpec]};

       10  =>	-- links          ::= LINKS : CODE
          {vTop ← [scalar[linkSpec]];  linkSpec ← $code};

       11  =>	-- links          ::= LINKS : FRAME
          {vTop ← [scalar[linkSpec]];  linkSpec ← $frame};

       12  =>	-- imports        ::= IMPORTS itemlist
		-- body           ::= BEGIN statementlist END
		-- body           ::= { statementlist }
		-- leftside       ::= [ itemlist ]
          PushList[v[top+1].s];

       13  =>	-- control        ::= CONTROL idlist 
          PushList[v[top+1].s];

       14  =>	-- statement      ::= leftside ← module 
          {PushNode[$assign,2];  LinkToSource[top]};

       15  =>	-- statement      ::= leftside ← interface 
          {PushNode[$assign,2];  LinkToSource[top]};

       16  =>	-- statement      ::= item links
          BEGIN
          SetLinkAttrs[];
	  PushTree[Tree.null];  PushNode[$module,2];
          SetLinkAttrs[];  LinkToSource[top];
          linkSpec ← v[top+1].s;
          END;

       17  =>	-- module         ::= item [ ] links
          BEGIN
          SetLinkAttrs[];
          PushTree[Tree.null];  PushNode[$module,2];
          SetLinkAttrs[];  LinkToSource[top];
          linkSpec ← v[top+3].s;
          END;

       18  =>	-- module         ::= item [ idlist ] links
          BEGIN
          PushList[v[top+2].s];  save ← PopTree[];
          SetLinkAttrs[];
          PushTree[save];  PushNode[$module,2];
          SetLinkAttrs[];  LinkToSource[top];
          linkSpec ← v[top+4].s;
          END;

       19  =>	-- interface      ::= id 
          PushHash[v[top].r];

       20  =>	-- interface      ::= interface THEN id 
          {PushHash[v[top+2].r];  PushNode[$then,2];  LinkToSource[top]};

       21  =>	-- interface      ::= interface PLUS id 
          {PushHash[v[top+2].r];  PushNode[$plus,2];  LinkToSource[top]};

       22  =>	-- item           ::= id 
          BEGIN
          PushHash[v[top].r];  PushTree[Tree.null];  PushNode[$item,2];
          LinkToSource[top];
          END;

       23  =>	-- item           ::= id : id 
          BEGIN
          PushHash[v[top].r];  PushHash[v[top+2].r];  PushNode[$item,2];
          LinkToSource[top];
          END;

       24  =>	-- idlist         ::= id 
          {PushHash[v[top].r];  vTop ← [scalar[1]]};

       25  =>	-- idlist         ::= idlist , id 
          {PushHash[v[top+2].r];  vTop ← [scalar[v[top].s+1]]};

       26  =>	--  tilde        	::= ~
		--  tilde        	::= =
		--  statementlist	::= statementlist ;
		--  statement		::= module
		--  statement		::= config
		--  leftside		::= item
          NULL;

       27  =>	-- imports        ::= 
		-- control        ::= 
		-- directory      ::= 
		-- packing        ::= 
          {PushTree[Tree.null];  l[top] ← P1.InputLoc[]};

       28  =>	-- includelist    ::= includeitem
		-- statementlist  ::= statement
		-- itemlist       ::= item
          vTop ← [scalar[1]];

       29  =>	-- includelist    ::= includelist , includeitem
		-- statementlist  ::= statementlist ; statement
		-- itemlist       ::= itemlist , item
          vTop ← [scalar[v[top].s+1]];

       30  =>	-- exports        ::= EXPORTS expinit exportlist
          {vTop ← v[top+1];  PushList[v[top+2].s]};
	  
       31  =>	-- exports        ::= 
          {PushTree[Tree.null]; l[top] ← P1.InputLoc[]; vTop ← [scalar[exportsALL]]};
	  
       32  =>   -- expinit        ::= 
          {vTop ← [scalar[exportsALL]];  exportsALL ← FALSE};

       33  =>   -- exportlist     ::= item
          vTop ← [scalar[1]];

       34  =>	-- exportlist     ::= ALL
          {exportsALL ← TRUE;  vTop ← [scalar[0]]};

       35  =>   -- exportlist     ::= exportlist , item
          vTop ← [scalar[v[top].s+1]];

       36  =>	-- exportlist     ::= exportlist , ALL
          {exportsALL ← TRUE;  vTop ← v[top]};

       ENDCASE => ERROR;

      v[top] ← vTop;
      ENDLOOP};

  TokenValue: PUBLIC PROC [s: ParseTable.Symbol] RETURNS [P1.Value] ~ {
    RETURN [SELECT s FROM
      ParseTable.tokenID => P1.nullId,
      ENDCASE => P1.nullValue]};

  }.