GetAnalysis:
PUBLIC
PROC [doc: TiogaNode, docName:
ROPE, verbose:
BOOL]
RETURNS [ma: MesaAnalysis] = {
ma ← NARROW[NodeProps.GetProp[doc, analysisProp]];
IF ma # NIL THEN RETURN;
IF verbose THEN MessageWindow.Append[Rope.Cat["Analyzing ", docName, " ..."], TRUE];
ma ← Analyze[doc, docName];
IF verbose THEN MessageWindow.Append[" done", FALSE];
NodeProps.PutProp[doc, analysisProp, ma];
};
Analyze:
PROC [doc: TiogaNode, docName:
ROPE]
RETURNS [ma: MesaAnalysis] = {
in: IO.STREAM = TiogaStreams.CreateInput[doc, discard];
l: TDLexing.Lexer = TDLexing.MakeLexer[in, GetSourcePosition];
AddIT:
PROC [namePos: PositionRange, name, typeClass, fileHint:
ROPE, usingList: SymbolTable]
RETURNS [it: InterfaceType] = {
it ← NEW [InterfaceTypePrivate ← [namePos, name, typeClass, fileHint, usingList]];
[] ← ma.interfaceTypes.Store[it.name, it];
[] ← ma.globalDefs.Store[it.name, it];
};
AddIR:
PROC [namePos: PositionRange, name:
ROPE, it: InterfaceType]
RETURNS [ir: InterfaceRecord] = {
ir ← NEW [InterfaceRecordPrivate ← [namePos, name, it]];
[] ← ma.interfaceRecords.Store[ir.name, ir];
[] ← ma.globalDefs.Store[ir.name, ir];
};
EnsureIT:
PROC [namePos: PositionRange, itName:
ROPE]
RETURNS [it: InterfaceType] = {
it ← NARROW[ma.interfaceTypes.Fetch[itName].value];
IF it = NIL THEN it ← AddIT[namePos, itName, itName, itName.Concat[".Mesa"], NIL];
};
EnsureIR:
PROC [namePos: PositionRange, irName:
ROPE]
RETURNS [ir: InterfaceRecord] = {
ir ← NARROW[ma.interfaceRecords.Fetch[irName].value];
IF ir =
NIL
THEN {
it: InterfaceType = EnsureIT[namePos, irName];
ir ← AddIR[namePos, irName, it];
};
};
ParseDirectory:
PROC = {
toke: Token = l.GetToken[];
IF NOT toke.rope.Equal["DIRECTORY"] THEN {l.ReturnToken[toke]; RETURN};
DO
name, class, fileHint: ROPE;
usingList: SymbolTable ← NIL;
namePos: PositionRange ← [l.GetPosition[beforeNext], 0];
name ← class ← l.GetRope[tokenID];
namePos.after ← l.GetPosition[afterLast];
fileHint ← name.Concat[".Mesa"];
IF l.NextIs[":"]
THEN
SELECT l.GetKwd[]
FROM
$TYPE => {
toke2: Token = l.GetToken[];
IF toke2.kind = tokenID
AND
NOT TDLexing.ReservedWord[toke2.rope]
THEN class ← toke2.rope
ELSE l.ReturnToken[toke2];
};
$FROM => fileHint ← Convert.RopeFromLiteral[l.GetRope[tokenROPE]];
ENDCASE => SyntaxError[];
IF l.NextIs["USING"]
THEN {
usingList ← CreateSymbolTable[];
IF NOT l.NextIs["["] THEN SyntaxError[];
IF
NOT l.NextIs["]"]
THEN {
DO
eltName: ROPE = l.GetRope[tokenID];
[] ← usingList.Insert[eltName, $T];
IF NOT l.NextIs[","] THEN EXIT;
ENDLOOP;
IF NOT l.NextIs["]"] THEN SyntaxError[];
};
};
{it: InterfaceType = AddIT[namePos, name, class, fileHint, usingList];
ir: InterfaceRecord = AddIR[namePos, name, it];
IF NOT l.NextIs[","] THEN EXIT;
}ENDLOOP;
IF NOT l.NextIs[";"] THEN SyntaxError[];
};
ParseModuleType:
PROC
RETURNS [mt: ModuleType] = {
IF l.NextIs["DEFINITIONS"] THEN RETURN [defs];
IF l.NextIsA[LIST["SAFE", "UNSAFE"]] THEN NULL;
IF l.NextIs["PROGRAM"] THEN mt ← prog
ELSE IF l.NextIs["MONITOR"] THEN mt ← monitor
ELSE SyntaxError[];
};
ParseImports:
PROC = {
IF NOT l.NextIs["IMPORTS"] THEN RETURN;
DO
irName: ROPE;
namePos: PositionRange ← [l.GetPosition[beforeNext], 0];
irName ← l.GetRope[tokenID];
namePos.after ← l.GetPosition[afterLast];
IF l.NextIs[":"]
THEN {
itName: ROPE;
itNamePos: PositionRange ← [l.GetPosition[beforeNext], 0];
itName ← l.GetRope[tokenID];
itNamePos.after ← l.GetPosition[afterLast];
{it: InterfaceType = EnsureIT[itNamePos, itName];
[] ← AddIR[namePos, irName, it];
}};
IF NOT l.NextIs[","] THEN EXIT;
ENDLOOP;
};
ParseOpen:
PROC = {
IF
NOT l.NextIs["OPEN"]
THEN {
ma.bodyStart ← l.GetPosition[afterLast];
[] ← l.GetToken[];
ma.prefixEnd ← l.GetPosition[afterLast]+1;
RETURN;
};
DO
n1: ROPE;
namePos: PositionRange ← [l.GetPosition[beforeNext], 0];
n1 ← l.GetRope[tokenID];
namePos.after ← l.GetPosition[afterLast];
IF l.NextIsA[
LIST[":", "~~"]]
THEN {
n2: Token = l.GetToken[];
IF n2.kind # tokenID THEN SyntaxError;
{it: InterfaceType = EnsureIT[[n2.before, n2.after], n2.rope];
[] ← AddIR[namePos, n1, it];
}}
ELSE {
ir: InterfaceRecord = EnsureIR[namePos, n1];
IF ir.type.usingList #
NIL
THEN {
AddElt:
PROC [key, value:
REF
ANY]
RETURNS [quit:
BOOL ←
FALSE]
--HashTable.EachPairAction-- = {
eltName: ROPE = NARROW[key];
ie: InterfaceElement = NEW [InterfaceElementPrivate ← [eltName, ir]];
[] ← ma.interfaceElements.Store[eltName, ie];
[] ← ma.globalDefs.Store[eltName, ie];
};
[] ← ir.type.usingList.Pairs[AddElt];
}
ELSE {
ma.openedWithoutUsingList ← CONS[ir, ma.openedWithoutUsingList];
};
};
IF NOT l.NextIs[","] THEN EXIT;
ENDLOOP;
IF NOT l.NextIs[";"] THEN SyntaxError[];
ma.bodyStart ← ma.prefixEnd ← l.GetPosition[afterLast];
};
ma ←
NEW [MesaAnalysisPrivate ← [
moduleType: defs,
globalDefs: CreateSymbolTable[],
interfaceRecords: CreateSymbolTable[],
interfaceTypes: CreateSymbolTable[],
interfaceElements: CreateSymbolTable[],
bodyStart: 0, prefixEnd: 0
]];
{
ENABLE SyntaxError => {
MessageWindow.Append[
message: IO.PutFR["Syntax error in %g before %g", [rope[docName]], [integer[l.GetPosition[afterLast]]]],
clearFirst: TRUE];
ma.bodyStart ← ma.prefixEnd ← l.GetPosition[beforeNext];
CONTINUE;
};
ParseDirectory[];
ma.moduleName ← l.GetRope[tokenID];
IF NOT l.NextIs[":"] THEN SyntaxError[];
IF l.NextIs["CEDAR"] THEN NULL;
ma.moduleType ← ParseModuleType[];
l.SkipTo[LIST["IMPORTS", "SHARES", "~", "="]];
ParseImports[];
l.SkipTo[LIST["~", "="]];
IF NOT l.NextIsA[LIST["~", "="]] THEN ERROR;
IF l.NextIsA[LIST["PUBLIC", "PRIVATE"]] THEN NULL;
IF ma.moduleType # defs AND l.NextIsA[LIST["CHECKED", "TRUSTED", "UNCHECKED"]] THEN NULL;
IF NOT l.NextIsA[LIST["BEGIN", "{"]] THEN SyntaxError[];
ParseOpen[];
};
};