DIRECTORY Globals, IO, Parse, Rope; ParseImpl: CEDAR PROGRAM IMPORTS IO, Rope EXPORTS Parse = BEGIN OPEN Parse, Globals; Args: PUBLIC PROC[line: Rope.ROPE] RETURNS [Arg] = BEGIN result: Arg _ NIL; prev: Arg _ NIL; cur: Arg; stream: IO.STREAM _ NIL; token1, token2: Rope.ROPE; length: INT; stream _ IO.RIS[line]; WHILE TRUE DO ENABLE IO.EndOfStream => EXIT; token2 _ NIL; [token: token1] _ IO.GetTokenRope[stream, WhiteSpace]; IF token1 = NIL THEN LOOP; length _ Rope.Length[token1]; IF length >= 2 THEN IF (Rope.Fetch[token1, 0] = '-) AND (Rope.Fetch[token1, 1] = '-) THEN EXIT; IF (Rope.Fetch[token1, 0] = '-) AND (length > 2) THEN BEGIN token2 _ Rope.Substr[base: token1, start: 2, len: length-2]; token1 _ Rope.Substr[base: token1, start: 0, len: 2]; END; cur _ NEW[ArgRec]; cur.rope _ token1; IF result = NIL THEN result _ cur; IF prev # NIL THEN prev.next _ cur; prev _ cur; IF token2 # NIL THEN BEGIN cur _ NEW[ArgRec]; cur.rope _ token2; prev.next _ cur; prev _ cur; END; ENDLOOP; RETURN [result]; END; Real: PUBLIC PROC[arg: Arg] RETURNS [parseOK: BOOLEAN, val: REAL] = BEGIN ENABLE ANY => BEGIN parseOK _ FALSE; val _ 0.0; CONTINUE; END; IF arg = NIL THEN RETURN [FALSE, 0.0]; val _ IO.GetReal[IO.RIS[arg.rope]]; RETURN [TRUE, val]; END; Int: PUBLIC PROC[arg: Arg] RETURNS [parseOK: BOOLEAN, val: INT] = BEGIN ENABLE ANY => BEGIN parseOK _ FALSE; val _ 0; CONTINUE; END; IF arg = NIL THEN RETURN [FALSE, 0]; val _ IO.GetInt[IO.RIS[arg.rope]]; RETURN [TRUE, val]; END; Lookup: PUBLIC PROC[rope: Rope.ROPE, table: DESCRIPTOR FOR ARRAY OF Rope.ROPE] RETURNS [index: INT] = TRUSTED BEGIN botIndex: INTEGER _ 0; topIndex: INTEGER _ LENGTH[table] - 1; char: CHAR; FOR i: INTEGER IN [0..1000) DO IF i >= Rope.Length[rope] THEN BEGIN IF botIndex = topIndex THEN RETURN [botIndex]; RETURN [-1]; END; char _ Rope.Fetch[rope, i]; WHILE TRUE DO IF Rope.Length[table[botIndex]] > i THEN IF Rope.Fetch[table[botIndex], i] = char THEN EXIT; IF botIndex = topIndex THEN RETURN [-2]; botIndex _ botIndex + 1; ENDLOOP; WHILE TRUE DO IF Rope.Length[table[topIndex]] > i THEN IF Rope.Fetch[table[topIndex], i] = char THEN EXIT; IF botIndex = topIndex THEN RETURN [-2]; topIndex _ topIndex - 1; ENDLOOP; ENDLOOP; RETURN [-2]; END; WhiteSpace: PUBLIC IO.BreakProc = BEGIN IF (char = IO.CR) OR (char = IO.TAB) OR (char = IO.LF) OR (char = IO.SP) THEN RETURN [sepr] ELSE RETURN[other]; END; END. πFILE: ParseImpl.mesa Last edited by John Ousterhout, January 24, 1984 1:06 pm Christian LeCocq April 29, 1986 1:08:52 pm PDT Turn the rope into a stream, then strip off the arguments one at a time. Things are a bit tricky if the first letter of the token is "-". In this case, the argument could be either a switch (like in Unix, remember?), or it could signify the beginning of a comment. If it's not a comment, make sure that the rope doesn't contain more than one more character, and if it does then chop off the stuff after the first character into a separate token. Generate either one or two Arg objects for the token(s). The search is carried out using two indices into the table. One index marches up from the start of the table, one marches down from the back of the table. The two indices delimit the entries of the table whose first characters match the part of rope that we've examined (this only works if the table is ordered monotonically). To do the match, we examine characters of rope one at a time, squeezing the indices together until we've got a match. Move botIndex up until we find a table entry that matches the current character of rope. Move topIndex down until we find a table entry that matches the current character of rope. ΚΓ˜Jšœ™šœ8™8Icode™.—J˜šΟk ˜ J˜Jšœ˜J˜J˜—J˜JšΟn œœ˜š˜Jšœ˜J˜—Jšœ˜J˜Jš˜Jšœ˜J˜J˜Jš žœœœ œœ˜2˜Jš˜Jšœœ˜Jšœ œ˜J˜ Jšœœœœ˜Jšœœ˜Jšœœ˜ J˜JšœH™HJ˜Jšœ œœ˜šœœœ˜Jšœœœ˜Jšœ œ˜ Jšœœ"˜6Jšœ œœœ˜J˜Jšœφ™φJ˜J˜šœ ˜šœœ˜@Jšœœ˜ ——šœœ˜5Jš˜J˜