DIRECTORY
Basics USING[LowHalf],
Convert USING[CardFromRope],
IO USING[STREAM, CharClass, Close, EndOf, EndOfStream, GetCedarTokenRope, GetLineRope, GetTokenRope, RIS, SP],
Rope USING[ROPE, Equal, Length],
SyntaxDescReaders USING[];
SyntaxDescReadersImpl: CEDAR PROGRAM IMPORTS Basics, Convert, IO, Rope EXPORTS SyntaxDescReaders =
BEGIN OPEN Basics, Convert, IO, Rope;
GenSimpleTermsFromStream: PUBLIC PROC[stream: STREAM, showTerm: PROC[name: ROPE, spelling: ROPE]] =
BEGIN
token: ROPE; skipped: INT;
BlankSepr: PROC[char: CHAR] RETURNS[CharClass] =
{RETURN[IF char = SP THEN sepr ELSE other]};
WHILE NOT EndOf[stream] DO
[token, skipped] ← GetTokenRope[stream, BlankSepr];
showTerm[token, token];
ENDLOOP;
END;
GenSpelledTermsFromStream: PUBLIC PROC[stream: STREAM, showTerm: PROC[name: ROPE, spelling: ROPE]] =
BEGIN
token: ROPE; skipped1: INT;
spelling: ROPE; skipped2: INT;
BlankSepr: PROC[char: CHAR] RETURNS[CharClass] =
{RETURN[IF char = SP THEN sepr ELSE other]};
WHILE NOT EndOf[stream] DO
[token, skipped1] ← GetTokenRope[stream, BlankSepr];
[spelling, skipped2] ← GetTokenRope[stream, BlankSepr];
showTerm[token, spelling];
ENDLOOP;
END;
GenGenericTermsFromStream: PUBLIC PROC[stream: STREAM, showTerm: PROC[name: ROPE, class: ROPE]] =
BEGIN
token: ROPE; skipped1: INT;
class: ROPE; skipped2: INT;
BlankSepr: PROC[char: CHAR] RETURNS[CharClass] =
{RETURN[IF char = SP THEN sepr ELSE other]};
WHILE NOT EndOf[stream] DO
[token, skipped1] ← GetTokenRope[stream, BlankSepr];
[class, skipped2] ← GetTokenRope[stream, BlankSepr];
showTerm[token, class];
ENDLOOP;
END;
GenNonTermsFromStream: PUBLIC PROC[stream: STREAM, showNonTerm: PROC[ROPE]] =
BEGIN
token: ROPE; skipped: INT;
BlankSepr: PROC[char: CHAR] RETURNS[CharClass] =
{RETURN[IF char = SP THEN sepr ELSE other]};
WHILE NOT EndOf[stream] DO
[token, skipped] ← GetTokenRope[stream, BlankSepr];
showNonTerm[token];
ENDLOOP;
END;
OneProductionFromStream: PUBLIC PROC[productionIndex: CARDINAL, stream: STREAM, leftSymbol: PROC[CARDINAL, ROPE], rightSymbol: PROC[ROPE]] =
BEGIN
token: ROPE; skipped: INT;
BlankSepr: PROC[char: CHAR] RETURNS[CharClass] =
{RETURN[IF char = SP THEN sepr ELSE other]};
[token, skipped] ← GetTokenRope[stream, BlankSepr]; leftSymbol[productionIndex, token];
[token, skipped] ← GetTokenRope[stream, BlankSepr]; IF NOT Equal[token, "←"] THEN ERROR;
WHILE NOT EndOf[stream] DO
[token, skipped] ← GetTokenRope[stream, BlankSepr];
rightSymbol[token];
ENDLOOP;
END;
GenSimpleTermsFromRope: PUBLIC PROC[rope: ROPE, showTerm: PROC[name: ROPE, spelling: ROPE]] =
BEGIN -- uses default IO.TokenProc
s: STREAM ← RIS[rope];
GenSimpleTermsFromStream[s, showTerm];
Close[s];
END;
GenSpelledTermsFromRope: PUBLIC PROC[rope: ROPE, showTerm: PROC[name: ROPE, spelling: ROPE]] =
BEGIN -- uses default IO.TokenProc
s: STREAM ← RIS[rope];
GenSpelledTermsFromStream[s, showTerm];
Close[s];
GenGenericTermsFromRope: PUBLIC PROC[rope: ROPE, showTerm: PROC[name: ROPE, class: ROPE]] =
BEGIN -- uses default IO.TokenProc
s: STREAM ← RIS[rope];
GenGenericTermsFromStream[s, showTerm];
Close[s];
GenNonTermsFromRope: PUBLIC PROC[rope: ROPE, showNonTerm: PROC[name: ROPE]] =
BEGIN -- uses default IO.TokenProc
s: STREAM ← RIS[rope];
GenNonTermsFromStream[s, showNonTerm];
Close[s];
OneProductionFromRope: PUBLIC PROC[productionIndex: CARDINAL, rope: ROPE, leftSymbol: PROC[CARDINAL, ROPE], rightSymbol: PROC[ROPE]] =
BEGIN -- uses default IO.TokenProc
s: STREAM ← RIS[rope];
OneProductionFromStream[productionIndex, s, leftSymbol, rightSymbol];
Close[s];
END;
PGSFormat: PUBLIC PROC[stream: STREAM, ut: PROC[ROPE, ROPE], gt: PROC[ROPE, ROPE], n: PROC[ROPE], l: PROC[CARDINAL, ROPE], r: PROC[ROPE]] =
BEGIN
BlankSepr: PROC[char: CHAR] RETURNS[CharClass] =
{RETURN[IF char = SP THEN sepr ELSE other]};
-- scan for table 1
WHILE TRUE DO
line: ROPE ← GetLineRope[stream];
lineStream: STREAM;
key: ROPE;
IF Length[line] = 0 THEN LOOP;
lineStream ← RIS[line];
key ← GetTokenRope[lineStream, BlankSepr].token;
Close[lineStream];
IF Equal[key, "||TABLE1"] THEN EXIT;
ENDLOOP;
-- process table 1 which contains the terminals, note that certain are treated special
WHILE TRUE DO
line: ROPE ← GetLineRope[stream];
lineStream: STREAM;
toss: ROPE;
terminal: ROPE;
IF Length[line] = 0 THEN LOOP;
lineStream ← RIS[line];
toss ← GetTokenRope[lineStream, BlankSepr].token;
IF Equal[toss, "||TABLE2"] THEN {Close[lineStream]; EXIT};
terminal ← GetTokenRope[lineStream, BlankSepr].token;
Close[lineStream];
SELECT TRUE FROM
Equal["id", terminal] => gt["id", "tokenID"];
Equal["num", terminal] => gt["num", "tokenDECIMAL"];
Equal["lnum", terminal] => gt["lnum", "tokenDECIMAL"];
Equal["flnum", terminal] => gt["flnum", "tokenREAL"];
Equal["string", terminal] => gt["string", "tokenROPE"];
Equal["lstring", terminal] => gt["lstring", "tokenROPE"];
Equal["char", terminal] => gt["char", "tokenCHAR"];
Equal["atom", terminal] => gt["atom", "tokenATOM"];
Equal["eof", terminal] => NULL;
Equal["'|", terminal] => ut["'|", "|"];
ENDCASE => ut[terminal, terminal];
ENDLOOP;
-- process table 2 which contains the non terminals
n["AugmentingGOAL"]; -- our special introduced goal to make it an augmented grammar
WHILE TRUE DO
line: ROPE ← GetLineRope[stream];
lineStream: STREAM;
toss: ROPE;
terminal: ROPE;
IF Length[line] = 0 THEN LOOP;
lineStream ← RIS[line];
toss ← GetTokenRope[lineStream, BlankSepr].token;
IF Equal[toss, "||TABLE3"] THEN {Close[lineStream]; EXIT};
terminal ← GetTokenRope[lineStream, BlankSepr].token;
Close[lineStream];
n[terminal];
ENDLOOP;
-- ignore table 3 which contains some info about certain terminals
WHILE TRUE DO
line: ROPE ← GetLineRope[stream];
lineStream: STREAM;
toss: ROPE;
IF Length[line] = 0 THEN LOOP;
lineStream ← RIS[line];
toss ← GetTokenRope[lineStream, BlankSepr].token;
IF Equal[toss, "||TABLE4"] THEN {Close[lineStream]; EXIT};
Close[lineStream];
ENDLOOP;
-- process table 4 which contains the productions
BEGIN
firstProduction: BOOLEAN ← TRUE;
leftSide: ROPE;
WHILE TRUE DO
line: ROPE;
lineStream: STREAM;
prodNumber: ROPE;
reductionNumber: ROPE;
operator: ROPE;
line ← GetLineRope[stream
! EndOfStream => {EXIT}];
IF Length[line] = 0 THEN LOOP;
lineStream ← RIS[line];
prodNumber ← GetTokenRope[lineStream, BlankSepr].token;
reductionNumber ← GetTokenRope[lineStream, BlankSepr].token;
IF Equal[reductionNumber, "C"] THEN reductionNumber ← GetTokenRope[lineStream, BlankSepr].token; -- the C indicates a chain rule
operator ← GetTokenRope[lineStream, BlankSepr].token;
IF NOT Equal[operator, "|"] THEN
BEGIN
leftSide ← operator;
operator ← GetTokenRope[lineStream, BlankSepr].token;
IF NOT Equal[operator, "::="] THEN ERROR;
END;
IF firstProduction THEN
BEGIN -- introduce our dummy production
firstProduction ← FALSE;
l[0, "AugmentingGOAL"];
r[leftSide];
END;
l[LowHalf[CardFromRope[prodNumber]], leftSide];
WHILE TRUE DO
token: ROPE ← GetTokenRope[lineStream, BlankSepr
! EndOfStream => {token ← NIL; EXIT}].token;
r[token];
ENDLOOP;
Close[lineStream];
ENDLOOP;
END;
-- Rec Function definition format
RecFcnDefFormat1Stream: PUBLIC PROC[stream: STREAM, ut: PROC[ROPE, ROPE], gt: PROC[ROPE, ROPE], n: PROC[ROPE], l: PROC[CARDINAL, ROPE], r: PROC[ROPE]] =
BEGIN
token: Rope.ROPE;
token ← GetCedarTokenRope[stream].token;
IF NOT Equal[token, "RecFcnDefFormat1"] THEN ERROR;
DO
token ← GetCedarTokenRope[stream].token;
SELECT TRUE FROM
Equal[token, "SimpleTerminals"] =>
BEGIN
IF NOT Equal[GetCedarTokenRope[stream].token, ":"] THEN ERROR;
DO
token ← GetCedarTokenRope[stream].token;
IF Equal[token, ";"] THEN EXIT;
ut[token, token];
ENDLOOP;
END;
Equal[token, "SpelledTerminals"] =>
BEGIN
IF NOT Equal[GetCedarTokenRope[stream].token, ":"] THEN ERROR;
DO
token2: ROPE;
token ← GetCedarTokenRope[stream].token;
IF Equal[token, ";"] THEN EXIT;
token2 ← GetCedarTokenRope[stream].token;
ut[token, token2];
ENDLOOP;
END;
Equal[token, "GenericTerminals"] =>
BEGIN
IF NOT Equal[GetCedarTokenRope[stream].token, ":"] THEN ERROR;
DO
case: ROPE;
token ← GetCedarTokenRope[stream].token;
IF Equal[token, ";"] THEN EXIT;
case ← GetCedarTokenRope[stream].token;
IF Equal[token, ";"] THEN ERROR;
gt[token, case];
ENDLOOP;
END;
Equal[token, "NonTerminals"] =>
BEGIN
IF NOT Equal[GetCedarTokenRope[stream].token, ":"] THEN ERROR;
DO
token ← GetCedarTokenRope[stream].token;
IF Equal[token, ";"] THEN EXIT;
n[token];
ENDLOOP;
END;
Equal[token, "Prod"] => EXIT;
ENDCASE => ERROR;
ENDLOOP;
DO
index: CARDINAL;
left: ROPE;
IF NOT Equal[token, "Prod"] THEN ERROR;
index ← CardFromRope[GetCedarTokenRope[stream].token];
IF NOT Equal[GetCedarTokenRope[stream].token, ":"] THEN ERROR;
left ← GetCedarTokenRope[stream].token;
l[index, left];
IF NOT Equal[GetCedarTokenRope[stream].token, "←"] THEN ERROR;
DO
right: ROPE;
right ← GetCedarTokenRope[stream].token;
IF Equal[right, ";"] THEN EXIT;
r[right];
ENDLOOP;
token ← GetCedarTokenRope[stream].token;
IF Equal[token, "EndOfSyntax"] THEN EXIT;
ENDLOOP;
END;
END..
-- RTE: November 1, 1984 11:16:17 am PST: ran into a grammar with start symbol = GOAL, which confilicted with our augmenting start symbol GOAL. So, change to AugmentingGOAL.