GetTreeImpl.Mesa
written by Paxton. May 1981
Paxton. August 24, 1982 10:39 am
Russ Atkinson, July 26, 1983 5:43 pm
GetTreeImpl:
CEDAR PROGRAM
IMPORTS TextNode, RopeEdit, RopeIO, RopeReader
EXPORTS GetTree
= BEGIN OPEN GetTree;
ReadIndent:
PUBLIC
PROC [fileName:
ROPE, tabIndent:
NAT ← 4]
RETURNS [root: RefTextNode] = {
input: ROPE ← RopeIO.FromFile[fileName];
rdr: RopeReader.Ref ← RopeReader.GetRopeReader[];
maxOpen: NAT = 40;
openNodes: ARRAY [0..maxOpen] OF RefTextNode;
openIndents: ARRAY [0..maxOpen] OF INTEGER;
level, lvl: NAT;
indent: INTEGER;
node: RefTextNode;
noMoreInput: BOOLEAN ← FALSE;
ReadLine:
PROC
RETURNS [
ROPE] = {
-- read line and set indent
tab: CHAR='I-100B;
space: CHAR=' ;
cr: CHAR='M-100B;
start, end: Offset ← 0;
indent ← 0;
DO
SELECT RopeReader.Get[rdr ! RopeReader.ReadOffEnd => {
noMoreInput ← TRUE; EXIT }] FROM
cr => EXIT; -- blank line
tab => indent ← indent+tabIndent;
space => indent ← indent+1;
0C => { noMoreInput ← TRUE; EXIT }; -- stop at first NULL char
ENDCASE => {
-- just saw the first nonblank char on the line
start ← RopeReader.GetIndex[rdr]-1;
DO
SELECT RopeReader.Get[rdr ! RopeReader.ReadOffEnd => {
end ← RopeReader.GetIndex[rdr]; noMoreInput ← TRUE; EXIT }] FROM
cr => { end ← RopeReader.GetIndex[rdr]-1; EXIT };
0C => { end ← RopeReader.GetIndex[rdr]-1; noMoreInput ← TRUE; EXIT };
ENDCASE;
ENDLOOP;
EXIT };
ENDLOOP;
RETURN [RopeEdit.Substr[input,start,end-start]] };
PlaceNode:
PROC = {
dest: RefTextNode;
SELECT lvl FROM
< level => {
-- insert as sibling of node at lvl+1
dest ← openNodes[level ← lvl+1];
dest.last ← FALSE; node.next ← dest.next; dest.next ← node };
= maxOpen => {
-- insert as sibling of node at max level
dest ← openNodes[level]; dest.last ← FALSE;
node.next ← dest.next; dest.next ← node };
ENDCASE => {
-- increase level
dest ← openNodes[level]; node.next ← dest; dest.child ← node;
level ← level+1 };
node.last ← TRUE; openIndents[level] ← indent; openNodes[level] ← node };
RopeReader.SetPosition[rdr,input,0];
openNodes[0] ← root ← TextNode.NewTextNode[];
root.last ← TRUE;
openIndents[0] ← -1; level ← 0;
UNTIL noMoreInput
DO
node ← TextNode.NewTextNode[];
IF (node.rope ← ReadLine[])=NIL THEN indent ← MAX[0,openIndents[level]];
FOR lvl ← level, lvl-1
DO
IF openIndents[lvl] < indent THEN { PlaceNode[]; EXIT };
ENDLOOP;
ENDLOOP;
RopeReader.FreeRopeReader[rdr] };