TDLexingImpl.mesa
Mike Spreitzer November 4, 1986 11:56:20 am PST
DIRECTORY Atom, HashTable, IO, Rope, TDLexing;
TDLexingImpl:
CEDAR
PROGRAM
IMPORTS Atom, HashTable, IO, Rope
EXPORTS TDLexing
=
BEGIN OPEN TDLexing;
SyntaxError: PUBLIC ERROR = CODE;
MakeLexer:
PUBLIC
PROC [in:
IO.
STREAM,
GetIndex: IndexGetter ←
NIL
--means VanillaIndexGetter--, filterComments:
BOOL ←
TRUE]
RETURNS [l: Lexer] = {
IF GetIndex = NIL THEN GetIndex ← VanillaIndexGetter;
l ← NEW [LexerPrivate ← [in, filterComments, GetIndex]];
l.afterLast ← l.GetIndex[l.in];
[] ← l.in.SkipWhitespace[l.filterComments];
l.beforeNext ← l.GetIndex[l.in];
};
VanillaIndexGetter:
PUBLIC
PROC [in:
IO.
STREAM]
RETURNS [index:
INT]
--IndexGetter-- = {
index ← in.GetIndex[];
};
GetToken:
PUBLIC
PROC [l: Lexer]
RETURNS [token: Token] = {
IF l.tokenStack #
NIL
THEN {
token ← l.tokenStack.first;
l.afterLast ← token.after;
l.tokenStack ← l.tokenStack.rest;
l.beforeNext ← IF l.tokenStack # NIL THEN l.tokenStack.first.before ELSE l.GetIndex[l.in];
RETURN};
token.afterPrev ← l.afterLast;
token.before ← l.beforeNext;
IF l.in.EndOf[]
THEN {
token.kind ← tokenEOF;
token.rope ← NIL;
token.after ← token.before;
RETURN};
[token.kind, token.rope] ← l.in.GetCedarTokenRope[l.filterComments];
token.after ← l.afterLast ← l.GetIndex[l.in];
[] ← l.in.SkipWhitespace[l.filterComments];
l.beforeNext ← l.GetIndex[l.in];
};
GetPosition:
PUBLIC
PROC [l: Lexer, side: WhichPosition]
RETURNS [position:
INT] = {
position ←
SELECT side
FROM
afterLast => l.afterLast,
beforeNext => l.beforeNext,
ENDCASE => ERROR;
};
ReturnToken:
PUBLIC
PROC [l: Lexer, token: Token] = {
l.tokenStack ← CONS[token, l.tokenStack];
l.afterLast ← token.afterPrev;
l.beforeNext ← token.before;
};
GetRope:
PUBLIC
PROC [l: Lexer, kind:
IO.TokenKind]
RETURNS [rope:
ROPE] = {
toke: Token = GetToken[l];
IF toke.kind # kind THEN SyntaxError[];
rope ← toke.rope};
GetKwd:
PUBLIC
PROC [l: Lexer]
RETURNS [kwd:
ATOM] = {
kwd ← Atom.MakeAtom[GetRope[l, tokenID]];
};
NextIs:
PUBLIC
PROC [l: Lexer, rope:
ROPE]
RETURNS [is:
BOOL] = {
toke: Token = GetToken[l];
is ← toke.rope.Equal[rope];
IF NOT is THEN ReturnToken[l, toke];
};
NextIsSeq:
PUBLIC
PROC [l: Lexer, seq: ROPEList]
RETURNS [is:
BOOL] = {
IF seq = NIL THEN RETURN [TRUE];
{token: Token = GetToken[l];
is ← token.rope.Equal[seq.first] AND NextIsSeq[l, seq.rest];
IF NOT is THEN ReturnToken[l, token];
}};
NextIsA:
PUBLIC
PROC [l: Lexer, ropes: ROPEList]
RETURNS [is:
BOOL] = {
toke: Token = GetToken[l];
is ← FALSE;
FOR ropes ← ropes, ropes.rest
WHILE ropes #
NIL
AND
NOT is
DO
IF ropes.first.Equal[toke.rope] THEN is ← TRUE;
ENDLOOP;
IF NOT is THEN ReturnToken[l, toke];
};
SkipTo:
PUBLIC
PROC [l: Lexer, oneOf: ROPEList] = {
DO
toke: Token = GetToken[l];
IF toke.kind = tokenEOF THEN SyntaxError[];
FOR ropes: ROPEList ← oneOf, ropes.rest
WHILE ropes #
NIL
DO
IF ropes.first.Equal[toke.rope]
THEN {
ReturnToken[l, toke];
RETURN;
};
ENDLOOP;
l ← l;
ENDLOOP;
};
ReservedWord:
PUBLIC
PROC [id:
ROPE]
RETURNS [reserved:
BOOL] = {
reserved ← reservedWords.Fetch[id].found;
};
PredefinedType:
PUBLIC
PROC [id:
ROPE]
RETURNS [is:
BOOL] = {
is ← predefinedTypes.Fetch[id].found;
};
reservedWords: HashTable.Table ← HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope];
predefinedTypes: HashTable.Table ← HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope];
LoadIds:
PROC [table: HashTable.Table, list: ROPEList] = {
table.Erase[];
FOR list ← list, list.rest
WHILE list #
NIL
DO
[] ← table.Insert[list.first, $T];
ENDLOOP;
list ← list;
};
Start:
PROC = {
LoadIds[reservedWords, LIST["ABS", "ALL", "AND", "ANY", "APPLY", "ARRAY", "BASE", "BEGIN", "BROADCAST", "CEDAR", "CHECKED", "CODE", "COMPUTED", "CONS", "CONTINUE", "DECREASING", "DEFINITIONS", "DEPENDENT", "DESCRIPTOR", "DIRECTORY", "DO", "ELSE", "ENABLE", "END", "ENDCASE", "ENDLOOP", "ENTRY", "ERROR", "EXIT", "EXITS", "EXPORTS", "FINISHED", "FIRST", "FOR", "FORK", "FRAME", "FREE", "FROM", "GO", "GOTO", "IF", "IMPORTS", "IN", "INLINE", "INTERNAL", "ISTYPE", "JOIN", "LAST", "LENGTH", "LIST", "LOCKS", "LONG", "LOOP", "LOOPHOLE", "MACHINE", "MAX", "MIN", "MOD", "MONITOR", "MONITORED", "NARROW", "NEW", "NIL", "NOT", "NOTIFY", "NULL", "OF", "OPEN", "OR", "ORD", "ORDERED", "OVERLAID", "PACKED", "PAINTED", "POINTER", "PORT", "PRED", "PRIVATE", "PROC", "PROCEDURE", "PROCESS", "PROGRAM", "PUBLIC", "READONLY", "RECORD", "REF", "REJECT", "RELATIVE", "REPEAT", "RESTART", "RESUME", "RETRY", "RETURN", "RETURNS", "SAFE", "SELECT", "SEQUENCE", "SHARES", "SIGNAL", "SIZE", "START", "STATE", "STOP", "SUCC", "THEN", "THROUGH", "TO", "TRANSFER", "TRASH", "TRUSTED", "TYPE", "UNCHECKED", "UNCOUNTED", "UNSAFE", "UNTIL", "USING", "VAL", "VAR", "WAIT", "WHILE", "WITH", "ZONE"]];
LoadIds[predefinedTypes, LIST["ATOM", "BOOL", "BOOLEAN", "CARD", "CARDINAL", "CHAR", "INT", "INTEGER", "NAT", "REAL", "TEXT", "UNSPECIFIED", "WORD"]];
};
Start[];
END.