-- file MobTreeBuild.pgs
-- Copyright Ó 1991 by Xerox Corporation. All rights reserved.
-- DO NOT CONVERT TO TIOGA! (PGS requires that comments be mesa-style.)
-- last edited by Satterthwaite on March 14, 1986 11:22:21 am PST
-- last edited by Lewis on 12-Mar-81 18:04:07
-- last edited by Maxwell on August 11, 1983 3:36 pm
-- Andy Litman May 11, 1988 5:27:57 pm PDT
-- JKF, May 25, 1990 10:15:28 am PDT

-- NPGS [defs: MobParseTable, grammar: CMesa] ← MobTreeBuild.pgs


DIRECTORY
 MobP1: TYPE USING [
  ActionStack, Index, LinkStack, Value, ValueStack, InputLoc, nullId, nullValue],
 MobParseTable: TYPE USING [ProdDataRef, Symbol, tokenID, Rule],
 MobTree: TYPE USING [Link, null],
 MobTreeOps: TYPE USING [
  PopTree, PushTree, PushHash, PushList, PushNode, SetAttr, SetInfo];

MobTreeBuild: PROGRAM
 IMPORTS MobP1, MobTreeOps
 EXPORTS MobP1 = {
 OPEN MobTreeOps;

 -- local data base (supplied by parser)

 v: MobP1.ValueStack;
 l: MobP1.LinkStack;
 q: MobP1.ActionStack;
 proddata: MobParseTable.ProdDataRef;

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


 -- the interpretation rules

 LinkToSource: PROC[index: MobP1.Index] ~ 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 ← $defaultFrame;
  
 SetLinkAttrs: PROC ~ {
  SetAttr[$codeLinks, (linkSpec IN CodeLinks)];
  SetAttr[$explicitLinkLoc, (linkSpec # DefaultLinks[linkSpec])]
  };


 ProcessQueue: PUBLIC PROC[qI, top: CARDINAL] ~ {
  FOR i: CARDINAL IN [0 .. qI) DO
   rule: MobParseTable.Rule;
   top ← top-q[i].tag.pLength+1;
   rule ← proddata[q[i].transition].rule;
   SELECT rule FROM
    < 18 => ProcessQueue1[top, rule];
    ENDCASE => ProcessQueue2[top, rule];
   ENDLOOP;
   };
  
 ProcessQueue1: PROC[top: CARDINAL, rule: MobParseTable.Rule] ~ {
  save: MobTree.Link;
  vTop: MobP1.Value;
  vTop ← v[top];
  SELECT rule FROM

 0 => --
  --TYPE: MobParseTable EXPORTS: SELF
  --GOAL: goal

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

 -- DIRECTORY FROM PACK CONFIGURATION CONFIG
 -- IMPORTS EXPORTS CONTROL BEGIN REQUESTS STATIC DYNAMIC
 -- 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
  {
  PushHash[LOOPHOLE[v[top].s]]; PushHash[LOOPHOLE[v[top+3].s]];
  PushNode[$item,2];
  LinkToSource[top];
  };

 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 statics dynamics control tilde body
  -- config ::= id : CONFIGURATION links imports exports statics dynamics control tilde body
  {
  save ← PopTree[];
  PushHash[LOOPHOLE[v[top].s]]; PushTree[save]; PushNode[$config,7];
  SetAttr[$exportsALL, exportsALL]; LinkToSource[top];
  linkSpec ← v[top+3].a; exportsALL ← v[top+5].a; -- restore old values
  };

 9 => -- links ::=
  {vTop ← [short[linkSpec,0]]; linkSpec ← DefaultLinks[linkSpec]};

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

  11 => -- links ::= LINKS : FRAME
  {vTop ← [short[linkSpec,0]]; 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
  {
  SetLinkAttrs[];
  PushTree[MobTree.null]; PushNode[$module,2];
  SetLinkAttrs[]; LinkToSource[top];
  linkSpec ← v[top+1].a;
  };

  17 => -- module ::= item [ ] links
  {
  SetLinkAttrs[];
  PushTree[MobTree.null]; PushNode[$module,2];
  SetLinkAttrs[]; LinkToSource[top];
  linkSpec ← v[top+3].a;
  };

 ENDCASE => ERROR;
 v[top] ← vTop;
 };

 ProcessQueue2: PROC[top: CARDINAL, rule: MobParseTable.Rule] ~ {
  save: MobTree.Link;
  vTop: MobP1.Value;
  vTop ← v[top];
  SELECT rule FROM

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

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

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

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

  22 => -- item ::= id
  {
  PushHash[LOOPHOLE[v[top].s]]; PushTree[MobTree.null]; PushNode[$item,2];
  LinkToSource[top];
  };

  23 => -- item ::= id : id
  {
  PushHash[LOOPHOLE[v[top].s]]; PushHash[LOOPHOLE[v[top+2].s]];
  PushNode[$item,2];
  LinkToSource[top];
  };

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

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

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

  27 => -- imports ::=
  -- statics ::=
  -- dynamics ::=
   -- control ::=
   -- directory ::=
   -- packing ::=
   {PushTree[MobTree.null]; l[top] ← MobP1.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[MobTree.null]; l[top] ← MobP1.InputLoc[]; vTop ← [short[exportsALL,0]]};
  
  32 => -- expinit ::=
  {vTop ← [short[exportsALL,0]]; 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]};

  37 => -- statics ::= STATIC REQUESTS strlist
  { PushList[v[top+2].s] };

  38 => -- dynamics ::= DYNAMIC REQUESTS strlist
  { PushList[v[top+2].s] };

  ENDCASE => ERROR;

 v[top] ← vTop;
 };

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

 }.