File: ExprReadImpl.mesa
Copyright © 1984 by Xerox Corporation. All rights reserved.
Created by: Mayo, July 11, 1984 1:04:25 pm PDT
Last Edited by: Mayo, July 23, 1984 6:03:35 pm PDT
DIRECTORY
ExprRead,
Commander USING [CommandProc, Register],
Interpreter USING [Evaluate],
FS USING [StreamOpen, Error],
IO USING [STREAM, PutF, GetLineRope, rope, EndOfStream],
PrintTV USING [Print],
SymTab USING [Ref, Create, Pairs, Store, EachPairAction],
AMTypes USING [TV],
AMBridge USING [SomeRefFromTV, TVForROPE],
Rope
USING [
ROPE, SkipTo, SkipOver, Length, Substr, Fetch, Cat];
ExprReadImpl:
CEDAR
PROGRAM
IMPORTS Commander,
IO, FS, PrintTV, AMBridge, Interpreter, SymTab, Rope
EXPORTS ExprRead =
BEGIN
OPEN ExprRead;
Error: PUBLIC ERROR[ec: ErrorCode, msg: Rope.ROPE] = CODE;
whiteSpace: Rope.ROPE ← " \n\t";
Eval:
PUBLIC
PROC [expr: Rope.
ROPE, symTab: SymTab.Ref]
RETURNS [AMTypes.
TV] =
BEGIN
tv: AMTypes.TV;
none: BOOL;
err: Rope.ROPE;
[tv, err, none] ← Interpreter.Evaluate[rope: expr, symTab: symTab];
IF err #
NIL
THEN
ERROR Error[$CouldNotEval, Rope.Cat["Could not evaluate '", expr, "', error was '", err, "'."]]
ELSE
IF none
THEN
ERROR Error[$NoValue, Rope.Cat["Expression '", expr, "' did not return a value."]];
RETURN[tv];
END;
Assign:
PUBLIC
PROC [line: Rope.
ROPE, symTab: SymTab.Ref] =
BEGIN
var, expr: Rope.ROPE;
operatorPos: INT;
operator: CHAR;
tv: AMTypes.TV;
TrimWhite:
PROC [in: Rope.
ROPE]
RETURNS[Rope.
ROPE] =
BEGIN
i, j: INT;
i ← Rope.SkipOver[in, 0, whiteSpace];
FOR j ← Rope.Length[in] - 1, j ← j - 1
WHILE j >= 0
DO
ch: CHAR ← Rope.Fetch[in, j];
IF ch # ' AND ch # '\n AND ch # '\t THEN EXIT;
ENDLOOP;
ELSE
RETURN[Rope.Substr[in, i, j - i + 1]];
END;
operatorPos ← Rope.SkipTo[line, 0, "←~="];
IF operatorPos = Rope.Length[line]
THEN
ERROR Error[$Syntax, Rope.Cat["No '←', '=', or '~' operator in '", line, "', evaluation not done."]];
operator ← Rope.Fetch[line, operatorPos];
IF operatorPos = Rope.Length[line] - 1
THEN
ERROR Error[$Syntax, Rope.Cat["Empty expression in '", line, "', assignment not done."]];
expr ← Rope.Substr[line, operatorPos + 1, Rope.Length[line] - operatorPos];
-- evaluate RHS
IF operator = '←
THEN
tv ← Eval[expr, symTab]
ELSE {
-- don't evaluate RHS, store as ROPE
expr ← TrimWhite[expr];
TRUSTED {tv ← AMBridge.TVForROPE[expr];};
};
IF operatorPos > 0
THEN
BEGIN
start, end: INT;
-- parse the destination
var ← Rope.Substr[line, 0, operatorPos];
start ← Rope.SkipOver[var, 0, whiteSpace];
end ← Rope.SkipTo[var, 0, whiteSpace];
IF (end + 1 < Rope.Length[var])
AND (Rope.SkipOver[var, end + 1, whiteSpace] # Rope.Length[var])
THEN
BEGIN
ERROR Error[$Syntax, Rope.Cat["Variable '", var, "' is malformed, assignment not done."]];
END
ELSE
BEGIN
-- add into table
var ← Rope.Substr[var, start, end - start];
[] ← SymTab.Store[symTab, var, tv];
END;
END;
ReadFile:
PUBLIC PROC [fileName: Rope.
ROPE, symTab: SymTab.Ref] =
BEGIN
file: IO.STREAM ← NIL;
msg: Rope.ROPE ← NIL;
file ← FS.StreamOpen[fileName !FS.Error => IF error.group = user THEN {
msg ← error.explanation; CONTINUE }];
IF msg # NIL THEN ERROR Error[$FileError, msg];
DO
EOF: BOOL ← FALSE;
i: INT;
line: Rope.ROPE;
line ← file.GetLineRope[ ! IO.EndOfStream => {EOF ← TRUE; CONTINUE}];
IF EOF THEN EXIT;
i ← Rope.SkipOver[line, 0, whiteSpace];
IF i = Rope.Length[line] THEN LOOP;
IF Rope.Fetch[line, i] = '- AND i+1 < Rope.Length[line] AND Rope.Fetch[line, i+1] = '- THEN LOOP;
Assign[line, symTab];
ENDLOOP;
END;
TVToRope:
PUBLIC
PROC [tv: AMTypes.
TV]
RETURNS[Rope.
ROPE] =
BEGIN
ref: REF ANY;
TRUSTED {ref ← AMBridge.SomeRefFromTV[tv];};
WITH ref
SELECT
FROM
r: REF Rope.ROPE => RETURN[r^];
ENDCASE => RETURN[NIL];
END;
TVToListOfRope:
PUBLIC
PROC [tv: AMTypes.
TV]
RETURNS[
LIST
OF Rope.
ROPE] =
BEGIN
ref: REF ANY;
rr, rf: LIST OF Rope.ROPE ← NIL;
TRUSTED {ref ← AMBridge.SomeRefFromTV[tv];};
WITH ref
SELECT
FROM
refR: REF LIST OF Rope.ROPE => RETURN[refR^];
r: LIST OF Rope.ROPE => RETURN[r];
refL:
REF LIST
OF
REF
ANY => {
FOR la:
LIST
OF
REF
ANY ← refL^, la.rest
WHILE la #
NIL
DO
WITH la.first
SELECT
FROM
r: Rope.ROPE => rr ← CONS[r, rr];
ENDCASE => RETURN[NIL];
ENDLOOP;
};
l:
LIST
OF
REF
ANY => {
FOR la:
LIST
OF
REF
ANY ← l, la.rest
WHILE la #
NIL
DO
WITH la.first
SELECT
FROM
r: Rope.ROPE => rr ← CONS[r, rr];
ENDCASE => RETURN[NIL];
ENDLOOP;
};
ENDCASE => RETURN[NIL];
FOR la:
LIST
OF Rope.
ROPE ← rr, la.rest
WHILE la #
NIL
DO
rf ← CONS[la.first, rf];
ENDLOOP;
RETURN[rf];
END;
TVToInt:
PUBLIC PROC [tv: AMTypes.
TV]
RETURNS[
REF
INT] =
BEGIN
ref: REF ANY;
TRUSTED {ref ← AMBridge.SomeRefFromTV[tv];};
WITH ref
SELECT
FROM
i: REF INT => RETURN[i];
c:
REF
CARDINAL => {
int: REF INT ← NEW[INT ← c^];
RETURN[int];
};
ENDCASE => RETURN[NIL];
END;
TVToCardinal:
PUBLIC PROC [tv: AMTypes.
TV]
RETURNS[
REF
CARDINAL] =
BEGIN
ref: REF ANY;
TRUSTED {ref ← AMBridge.SomeRefFromTV[tv];};
WITH ref
SELECT
FROM
i:
REF
INT => {
IF i^ < 0
THEN
RETURN[NIL]
ELSE {
card: REF CARDINAL ← NEW[CARDINAL ← i^];
RETURN[card];
};
};
c: REF CARDINAL => RETURN[c];
ENDCASE => RETURN[NIL];
END;
TVToAtom:
PUBLIC PROC [tv: AMTypes.
TV]
RETURNS[
ATOM] =
BEGIN
ref: REF ANY;
TRUSTED {ref ← AMBridge.SomeRefFromTV[tv];};
WITH ref
SELECT
FROM
a: REF ATOM => RETURN[a^];
ENDCASE => RETURN[NIL];
END;
Test: Commander.CommandProc =
BEGIN
PrintVals: SymTab.EachPairAction =
BEGIN
-- PROC [key: Key, val: Val] RETURNS [quit: BOOL]
cmd.out.PutF["%g = ", IO.rope[key]];
PrintTV.Print[NARROW[val], cmd.out];
cmd.out.PutF["\n"];
RETURN[FALSE];
END;
tab: SymTab.Ref ← SymTab.Create[];
in: Rope.ROPE;
cmd.out.PutF["FileName? "];
in ← cmd.in.GetLineRope[];
ReadFile[in, tab];
cmd.out.PutF["--- VARIABLES SET ---\n"];
[] ← SymTab.Pairs[tab, PrintVals];
END;
Commander.Register[key: "ExprReadImplTest", proc: Test, doc: "test program"];
END.