EDIFLexing.Mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Spreitzer, February 19, 1986 4:30:30 pm PST
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]];
};
}.