<> <> <> DIRECTORY Ascii, Atom, BasicTime, Convert, Core, EDIFAndCore, EDIFAndCorePrivate, IO, RefText, Rope; ParseEDIF: CEDAR PROGRAM IMPORTS Atom, IO, RefText, Rope EXPORTS EDIFAndCorePrivate = {OPEN EDIFAndCore, EDIFAndCorePrivate; SyntaxError: PUBLIC ERROR [stream: IO.STREAM, index: INT, complaint: ROPE] = CODE; Digit: TYPE = INTEGER [0 .. 9]; ParseEDIF: PUBLIC PROC [from: IO.STREAM] RETURNS [stmt: LORA] = { ENABLE IO.EndOfStream => IF stream = from THEN SyntaxError[from, from.GetIndex[], "Incomplete something-or-other"]; Append: PROC [oldHead, oldTail: LORA, item: REF ANY] RETURNS [newHead, newTail: LORA] = { this: LORA = LIST[item]; IF oldHead = NIL THEN newHead _ newTail _ this ELSE {newHead _ oldHead; oldTail.rest _ newTail _ this}; }; ParseStmt: PROC RETURNS [stmt: LORA] = { c: CHAR _ from.GetChar[]; tail: LORA _ stmt _ NIL; IF c # '( THEN ERROR; DO d: CHAR; [] _ from.SkipWhitespace[flushComments: FALSE]; SELECT d _ from.PeekChar[] FROM ') => EXIT; IN ['a .. 'z], IN ['A .. 'Z] => { atom: ATOM = ParseAtom[]; [stmt, tail] _ Append[stmt, tail, atom]; }; '-, '+, IN ['0 .. '9] => { ri: RefInt = ParseInt[]; [stmt, tail] _ Append[stmt, tail, ri]; }; '" => { r: ROPE = ParseString[]; [stmt, tail] _ Append[stmt, tail, r]; }; ENDCASE => SyntaxError[from, from.GetIndex[], IO.PutFR["Unrecognized token (beginning with [%c]=%03bC)", [character[c]], [integer[c - 0C]]]]; ENDLOOP; stmt _ stmt; }; ParseAtom: PROC RETURNS [atom: ATOM] = { buff: REF TEXT _ RefText.New[10]; DO c: CHAR = from.PeekChar[]; SELECT c FROM IN ['a .. 'z], IN ['A .. 'Z], IN ['0 .. '9], '_ => { IF c # from.GetChar[] THEN ERROR; buff _ RefText.InlineReserveChars[buff, 1]; buff _ RefText.InlineAppendChar[buff, c]; }; ENDCASE => EXIT; ENDLOOP; atom _ Atom.MakeAtomFromRefText[buff]; }; ParseInt: PROC RETURNS [ri: RefInt] = { ri _ NEW [INT _ from.GetInt[!IO.Error => IF stream # from THEN NULL ELSE IF ec = SyntaxError THEN SyntaxError[from, from.GetIndex[], "Syntax error while parsing integer"] ELSE IF ec = Overflow THEN SyntaxError[from, from.GetIndex[], "EDIF integer too large for a Cedar INT --- you loose"] ]] }; ParseString: PROC RETURNS [r: ROPE] = { buff: REF TEXT _ RefText.New[100]; Append: PROC [c: CHAR] = INLINE { buff _ RefText.InlineReserveChars[buff, 1]; buff _ RefText.InlineAppendChar[buff, c]; }; GetDigit: PROC RETURNS [d: Digit] = { c: CHAR = from.GetChar[]; IF c IN ['0 .. '9] THEN RETURN [c - '0] ELSE SyntaxError[from, from.GetIndex[], IO.PutFR["Got [%c]=%03bC instead of a digit in an escape sequence in a string", [character[c]], [integer[c - 0C]]]]; }; IF from.GetChar[] # '" THEN ERROR; DO c: CHAR = from.GetChar[]; SELECT c FROM '" => EXIT; Ascii.TAB, '\n => NULL; '% => { d100: Digit = GetDigit[]; d10: Digit = GetDigit[]; d1: Digit = GetDigit[]; code: INT = (d100*100 + d10*10 + d1) MOD 128; Append[0C + code]; }; ENDCASE => Append[c]; ENDLOOP; r _ Rope.FromRefText[buff]; }; [] _ from.SkipWhitespace[flushComments: FALSE]; IF from.PeekChar[] # '( THEN SyntaxError[from, from.GetIndex[], "Not an EDIF statement"]; stmt _ ParseStmt[]; }; }.