file ArpaMTScannerImpl.mesa
derived from Compiler>Scanner.mesa
last edit by Schmidt, May 3, 1982 4:27 pm
last modified by Satterthwaite, June 6, 1983 4:06 pm
Last Edited by: Nichols, July 13, 1983 6:13 pm
Last Edited by: HGM, January 31, 1985 9:12:02 pm PST
John Larson, October 21, 1987 10:20:12 pm PDT
DIRECTORY
ArpaLex822: TYPE USING [LexToken, TokenType],
ArpaMTMiscOps: TYPE USING [Lookup, Table],
ArpaMTP1: TYPE --P1-- USING [Token, TValue, TerminalNode, nullTValue, Index, ScannerProc],
ArpaMTParseTable: TYPE ParseTable USING [ampmTok, atomTok, atSignTok, colonTok, commaTok, dateDummy, dayTok, dLitTok, dotTok, EOLTok, errorTok, lBracketTok, monthTok, nameDummy, qStringTok, rBracketTok, semiTok, TSymbol, zoneTok],
IO: TYPE USING [GetIndex, STREAM],
Rope: TYPE USING [ROPE, Fetch, Length];
ArpaMTScannerImpl: CEDAR PROGRAM
IMPORTS ArpaLex822, ArpaMTMiscOps, IO, Rope
EXPORTS ArpaMTP1 ~ {
OPEN P1~~ArpaMTP1, ArpaMTParseTable;
ROPE: TYPE = Rope.ROPE;
Tables of rope constants for the date tokens.
ampmTable: ArpaMTMiscOps.Table ~ LIST["am", "pm"];
dayTable: ArpaMTMiscOps.Table ~ LIST["sun", "sunday", "mon", "monday", "tue", "tuesday", "wed", "wednesday", "thu", "thursday", "fri", "friday", "sat", "saturday"];
monthTable: ArpaMTMiscOps.Table ~ LIST["jan", "january", "feb", "february", "mar", "march", "apr", "april", "may", "jun", "june", "jul", "july", "aug", "august", "sep", "sept", "september", "oct", "october", "nov", "november", "dec", "december"];
zoneTable: ArpaMTMiscOps.Table ~ LIST[
"ut", "gmt", "est", "edt", "cst", "cdt", "mst", "mdt", "pst", "pdt", "bst"];
the scanner proper
stream: IO.STREAMNIL;
nTokens: CARDINAL; -- token count
nErrors: CARDINAL;  -- lexical errors
eolSeen: BOOLEANFALSE; -- stop the parse at the end of a header
firstTime: BOOLEAN; -- to force dummy token
ScanName: PUBLIC P1.ScannerProc ~ {
tokenText, whiteSpace: ROPE;
tokType: ArpaLex822.TokenType;
IF firstTime THEN {
firstTime ← FALSE;
RETURN [[index~stream.GetIndex[], value~P1.nullTValue, class~nameDummy]];
};
IF eolSeen THEN
RETURN [[index~stream.GetIndex[], value~P1.nullTValue, class~EOLTok]];
token.index ← stream.GetIndex[];
[tokenText, whiteSpace, tokType] ← ArpaLex822.LexToken[stream];
token.value ← NEW[P1.TerminalNode ← [whiteSpace~whiteSpace, text~tokenText]];
token.class ← SELECT tokType FROM
atomTok => ArpaMTParseTable.atomTok,
domainLiteralTok => ArpaMTParseTable.dLitTok,
EOLTok => ArpaMTParseTable.EOLTok,
quotedStringTok => ArpaMTParseTable.qStringTok,
specialTok =>
SELECT tokenText.Fetch[0] FROM
'. => ArpaMTParseTable.dotTok,
', => ArpaMTParseTable.commaTok,
': => ArpaMTParseTable.colonTok,
'; => ArpaMTParseTable.semiTok,
'@ => ArpaMTParseTable.atSignTok,
'< => ArpaMTParseTable.lBracketTok,
'> => ArpaMTParseTable.rBracketTok,
ENDCASE => ArpaMTParseTable.errorTok,
ENDCASE => ArpaMTParseTable.errorTok;
IF token.class = EOLTok THEN
eolSeen ← TRUE
ELSE IF token.class = ArpaMTParseTable.errorTok THEN {
IF NOT eolSeen THEN nErrors ← nErrors+1
};
};
ScanDate: PUBLIC P1.ScannerProc ~ {
tokenText, whiteSpace: ROPE;
tokType: ArpaLex822.TokenType;
IF firstTime THEN {
firstTime ← FALSE;
RETURN [[index~stream.GetIndex[], value~P1.nullTValue, class~dateDummy]];
};
IF eolSeen THEN
RETURN [[index~stream.GetIndex[], value~P1.nullTValue, class~EOLTok]];
token.index ← stream.GetIndex[];
[tokenText, whiteSpace, tokType] ← ArpaLex822.LexToken[stream];
token.value ← NEW[P1.TerminalNode ← [whiteSpace~whiteSpace, text~tokenText]];
token.class ← SELECT tokType FROM
atomTok =>
SELECT TRUE FROM
ArpaMTMiscOps.Lookup[tokenText, monthTable] => ArpaMTParseTable.monthTok,
ArpaMTMiscOps.Lookup[tokenText, dayTable] => ArpaMTParseTable.dayTok,
ArpaMTMiscOps.Lookup[tokenText, ampmTable] => ArpaMTParseTable.ampmTok,
ArpaMTMiscOps.Lookup[tokenText, zoneTable] => ArpaMTParseTable.zoneTok,
NumericZone[tokenText] => ArpaMTParseTable.zoneTok,
MilitaryZone[tokenText] => ArpaMTParseTable.zoneTok,
ENDCASE => ArpaMTParseTable.atomTok,
domainLiteralTok =>
ArpaMTParseTable.dLitTok,
EOLTok =>
ArpaMTParseTable.EOLTok,
quotedStringTok =>
ArpaMTParseTable.qStringTok,
specialTok =>
SELECT tokenText.Fetch[0] FROM
'. => ArpaMTParseTable.dotTok,
', => ArpaMTParseTable.commaTok,
': => ArpaMTParseTable.colonTok,
'; => ArpaMTParseTable.semiTok,
'@ => ArpaMTParseTable.atSignTok,
'< => ArpaMTParseTable.lBracketTok,
'> => ArpaMTParseTable.rBracketTok,
ENDCASE => ArpaMTParseTable.errorTok,
ENDCASE => ArpaMTParseTable.errorTok;
IF token.class = EOLTok THEN
eolSeen ← TRUE
ELSE IF token.class = ArpaMTParseTable.errorTok THEN {
IF NOT eolSeen THEN nErrors ← nErrors+1
};
};
MilitaryZone: PROC [arg: ROPE] RETURNS[BOOL] = { -- A..Z except J
char: CHAR;
IF arg.Length[] # 1 THEN RETURN[FALSE];
char ← arg.Fetch[0];
IF char = 'J OR char = 'j THEN RETURN[FALSE];
IF ~(char IN['a..'z]) AND ~(char IN['A..'Z]) THEN RETURN[FALSE];
RETURN[TRUE]; };
NumericZone: PROC [arg: ROPE] RETURNS[BOOL] = { -- +HHMM or -HHMM
char: CHAR;
IF arg.Length[] # 5 THEN RETURN[FALSE];
char ← arg.Fetch[0];
IF char # '+ AND char # '- THEN RETURN[FALSE];
FOR i: INT IN [1..4] DO
char ← arg.Fetch[i];
IF ~(char IN['0..'9]) THEN RETURN[FALSE];
ENDLOOP;
RETURN[TRUE]; };
initialization/finalization
ScanInit: PUBLIC PROC[source: IO.STREAM] = {
stream ← source;
nTokens ← nErrors ← 0;
eolSeen ← FALSE;
firstTime ← TRUE;
};
ScanReset: PUBLIC PROC RETURNS[CARDINAL, CARDINAL] = {
RETURN [nTokens, nErrors]};
}.