EDIFLexing.Mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Spreitzer, February 19, 1986 4:30:30 pm PST
DIRECTORY Ascii, Atom, BasicTime, CodeB, Convert, Core, EDIFAndCore, EDIFAndCorePrivate, IO, RefText, Rope;
EDIFLexing: CEDAR PROGRAM
IMPORTS Atom, CodeB, IO, RefText, Rope
EXPORTS EDIFAndCorePrivate
= {OPEN EDIFAndCore, EDIFAndCorePrivate;
SyntaxError: PUBLIC ERROR [stream: IO.STREAM, index: INT, complaint: ROPE] = CODE;
Digit: TYPE = INTEGER [0 .. 9];
LexEDIF: 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
') => {IF from.GetChar[] # ') THEN ERROR; EXIT};
'( => {
form: LORA = ParseStmt[];
[stmt, tail] ← Append[stmt, tail, form];
};
IN ['a .. 'z], IN ['A .. 'Z] => {
id: ATOM = ParseAtom[];
[stmt, tail] ← Append[stmt, tail, id];
};
'-, '+, IN ['0 .. '9] => {
ri: RefInt = ParseInt[];
[stmt, tail] ← Append[stmt, tail, ri];
};
'" => {
r: ROPE = ParseString[];
[stmt, tail] ← Append[stmt, tail, r];
};
ENDCASE => {
id: ATOM = Atom.MakeAtomFromChar[d];
[stmt, tail] ← Append[stmt, tail, id];
};
ENDCASE => SyntaxError[from, from.GetIndex[], IO.PutFR["Unrecognized token (beginning with [%c]=%03bC)", [character[c]], [integer[c - 0C]]]];
ENDLOOP;
stmt ← stmt;
};
ParseAtom: PROC RETURNS [id: 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;
id ← 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, '\012, '\015 => 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[];
};
LcA: PUBLIC PROC [a: ATOM] RETURNS [lc: ATOM] = {
lc ← NARROW[Atom.GetProp[a, lcProp]];
IF lc # NIL THEN RETURN;
lc ← Atom.MakeAtom[CodeB.Lowercase[Atom.GetPName[a]]];
Atom.PutProp[a, lcProp, lc];
};
lcProp: ATOM = $CoreEDIFLexingATOMToLowercase;
IDFromEDIF: PUBLIC PROC [a: ATOM] RETURNS [name: ROPE] = {
name ← Atom.GetPName[LcA[a]];
};
}.