<> <> DIRECTORY Atom, SymTab, IO, Rope, TDLexing; TDLexingImpl: CEDAR PROGRAM IMPORTS Atom, SymTab, 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: SymTab.Ref _ SymTab.Create[case: TRUE]; predefinedTypes: SymTab.Ref _ SymTab.Create[case: TRUE]; LoadIds: PROC [table: SymTab.Ref, 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.