EDIFParsing2Impl.Mesa
Spreitzer, February 13, 1986 4:46:26 pm PST
DIRECTORY Atom, EDIFAndCore, EDIFfing, EDIFParsing2, IO, Rope;
EDIFParsing2Impl: CEDAR PROGRAM
IMPORTS Atom, Rope
EXPORTS EDIFParsing2
= {OPEN EDIFAndCore, EDIFfing, EDIFParsing2;
ParseError
: PUBLIC ERROR [
parseStack: ParseStack,
nonTerminal: ATOM,
syntaxRule: SyntaxRule]
= CODE;
Repeats: TYPE = REF SyntaxRuleList;
NewRepeats: PROC RETURNS [r: Repeats] = {r ← NEW [SyntaxRuleList ← NIL]};
In: PROC [sr: SyntaxRule, rs: Repeats] RETURNS [in: BOOL] = {
FOR srl: SyntaxRuleList ← rs^, srl.rest WHILE srl # NIL DO
IF srl.first = sr THEN RETURN [TRUE];
ENDLOOP;
};
Insert: PROC [sr: SyntaxRule, rs: Repeats] = {rs^ ← CONS[sr, rs^]};
Register
: PUBLIC PROC [
outerKey: ATOMNIL,
key: ATOM,
start: PROC [outerKey, key: ATOM, name: NameStuff, outerConv: REF ANY] RETURNS [conv: REF ANY] ← NIL,
finish: PROC [conv: REF ANY] ← NIL,
rule: SyntaxRule
]
= {
};
FetchRule: PROC [category: ATOM] RETURNS [sr: SyntaxRule] = {
ERROR --not yet implemented--;
};
Check: PROC [ptl: ParseTreeList, rule: SyntaxRule, repeats: Repeats, insist: BOOL, nonTerminal: ATOM, ps: ParseStack] RETURNS [outsist, ok: BOOL, ptr: ParseTreeList] = {
i0: INT = ps.first.index;
outsist ← insist;
WITH rule SELECT FROM
x: REF SyntaxRulePrivate.terminal => {
ok ← FALSE;
WITH x SELECT FROM
z: REF SyntaxRulePrivate.terminal.any => ok ← TRUE;
z: REF SyntaxRulePrivate.terminal.string => ok ← ptl.first.type = string;
z: REF SyntaxRulePrivate.terminal.identifier => ok ← ptl.first.type = identifier;
z: REF SyntaxRulePrivate.terminal.integer => WITH ptl.first SELECT FROM
y: REF ParseTreePrivate.integer => ok ← z.min <= y.i AND y.i <= z.max;
ENDCASE;
z: REF SyntaxRulePrivate.terminal.keyword => WITH ptl.first SELECT FROM
y: REF ParseTreePrivate.identifier => ok ← z.key.Equal[Atom.GetPName[y.id], FALSE];
ENDCASE;
ENDCASE => ERROR;
IF ok THEN {ptr ← ptl.rest; ps.first.index ← ps.first.index + 1};
};
x: REF SyntaxRulePrivate.nonTerminal => {
sr: SyntaxRule ← FetchRule[x.category];
[outsist, ok, ptr] ← Check[ptl, sr, repeats, insist, x.category, ps];
};
x: REF SyntaxRulePrivate.choice => {
ok ← FALSE;
FOR rl: SyntaxRuleList ← x.choices, rl.rest WHILE rl # NIL AND NOT ok DO
[, ok, ptr] ← Check[ptl, rl.first, repeats, FALSE, nonTerminal, ps];
ENDLOOP;
};
x: REF SyntaxRulePrivate.repeat => {
once: BOOLFALSE;
ptr ← ptl;
ok ← TRUE;
WHILE ptr # NIL AND ok DO
[, ok, ptr] ← Check[ptr, x.r, repeats, insist AND x.atLeastOnce AND NOT once, nonTerminal, ps];
IF ok THEN once ← TRUE;
ENDLOOP;
ok ← once OR NOT x.atLeastOnce;
};
x: REF SyntaxRulePrivate.series => {
ptr ← ptl;
ok ← TRUE;
FOR rl: SyntaxRuleList ← x.elts, rl.rest WHILE rl # NIL AND ok DO
[outsist, ok, ptr] ← Check[ptr, rl.first, NewRepeats[], outsist, nonTerminal, ps];
ENDLOOP;
};
x: REF SyntaxRulePrivate.optional => {
[outsist, ok, ptr] ← Check[ptl, x.r, repeats, FALSE, nonTerminal, ps];
IF NOT ok THEN {ok ← TRUE; outsist ← insist; ptr ← ptl};
};
x: REF SyntaxRulePrivate.nest => {
WITH ptl.first SELECT FROM
y: REF ParseTreePrivate.list => {
sps: ParseStack = CONS[[y, 0], ps];
subl: ParseTreeList; --note that EDIF documents randomly allege that we can discard trailing stuff not consumed in currently understood grammar.
[outsist, ok, subl] ← Check[y.children, x.r, NewRepeats[], insist, nonTerminal, sps];
IF ok THEN ptr ← ptl.rest;
};
ENDCASE => ok ← FALSE;
};
x: REF SyntaxRulePrivate.atMostOne => {
SELECT In[x.r, repeats] FROM
FALSE => {
[outsist, ok, ptr] ← Check[ptl, x.r, NewRepeats[], insist, nonTerminal, ps];
IF ok THEN Insert[x.r, repeats];
};
TRUE => ok ← FALSE;
ENDCASE => ERROR;
};
x: REF SyntaxRulePrivate.cut => {
ok ← outsist ← TRUE;
ptr ← ptl;
};
ENDCASE => ERROR;
IF NOT ok THEN {ptr ← ptl; ps.first.index ← i0; outsist ← insist};
IF ok OR NOT insist THEN RETURN;
ERROR ParseError[
parseStack: ps,
nonTerminal: nonTerminal,
syntaxRule: rule];
};
}.