JaMAndStyleAnalysesImpl.mesa
Copyright Ó 1992 by Xerox Corporation. All rights reserved.
Last tweaked by Mike Spreitzer on May 8, 1992 4:50 pm PDT
DIRECTORY Atom, BasicTime, EditNotify, IO, JaMAndStyleAnalyses, TDJaMScanner, MessageWindow, NodeProps, Rope, RopeReader, TextNode, TiogaRopes;
JaMAndStyleAnalysesImpl: CEDAR PROGRAM
IMPORTS Atom, BasicTime, EditNotify, IO, TDJaMScanner, MessageWindow, NodeProps, Rope, RopeReader, TextNode, TiogaRopes
EXPORTS JaMAndStyleAnalyses
=
BEGIN OPEN JaMAndStyleAnalyses;
LORA: TYPE = LIST OF REF ANY;
analysisProp: ATOM ¬ Atom.MakeAtom[IO.PutFR1["JaMAndStyleAnalysesImpl, loaded at %g, analysisProp", [time[BasicTime.Now[]]]]];
debug: BOOL ¬ FALSE;
Invalidate: PROC [root: TiogaNode] = {
NodeProps.PutProp[root, analysisProp, NIL];
IF debug THEN MessageWindow.Append["Flushing a JaM/Style Analysis", TRUE];
};
AnalysisFromRoot: PROC [root: TiogaNode] RETURNS [JSAnalysis] ~ {
IF root=NIL THEN RETURN [NIL];
RETURN [NARROW[NodeProps.GetProp[root, analysisProp]]]};
EventWatcher: PROC [change: REF READONLY EditNotify.Change] --EditNotify.EditNotifyProc-- = {
WITH change SELECT FROM
x: REF READONLY ChangingView EditNotify.Change => NULL;
x: REF READONLY ChangingText EditNotify.Change => {
root: TiogaNode ~ TextNode.Root[x.text];
anal: JSAnalysis ¬ AnalysisFromRoot[root];
IF anal # NIL THEN {
startPosition: INT = TextNode.LocOffset[[root, 0], [x.text, x.start]];
IF startPosition <= anal.prefixEnd THEN Invalidate[root];
};
};
x: REF READONLY ChangingSpanForPaste EditNotify.Change => NULL;
x: REF READONLY ChangingProp EditNotify.Change => IF x.name = NodeProps.nameComment THEN {
root: TiogaNode ~ TextNode.Root[x.node];
anal: JSAnalysis ¬ AnalysisFromRoot[root];
IF anal # NIL THEN {
startPosition: INT = TextNode.LocOffset[[root, 0], [x.node, 0]];
IF startPosition <= anal.prefixEnd THEN Invalidate[root];
};
};
x: REF READONLY MovingNodes EditNotify.Change => NULL--wrong, but I don't understand this kind, and it probably won't happen anyway--;
x: REF READONLY NodeNesting EditNotify.Change => NULL;
x: REF READONLY InsertingNode EditNotify.Change => {
root: TiogaNode ~ TextNode.Root[x.dest];
anal: JSAnalysis ¬ AnalysisFromRoot[root];
IF anal # NIL THEN {
startPosition: INT = TextNode.LocOffset[[root, 0], [x.new, 0]];
IF startPosition <= anal.prefixEnd THEN Invalidate[root];
};
};
ENDCASE => ERROR;
};
GetAnalysis: PUBLIC PROC [doc: TiogaNode, docName: ROPE, verbose: BOOL] RETURNS [anal: JSAnalysis] = {
anal ¬ NARROW[NodeProps.GetProp[doc, analysisProp]];
IF anal # NIL THEN RETURN;
IF verbose THEN MessageWindow.Append[Rope.Cat["Analyzing ", docName, " ..."], TRUE];
anal ¬ Analyze[doc, docName];
IF verbose THEN MessageWindow.Append[" done", FALSE];
NodeProps.PutProp[doc, analysisProp, anal];
};
SyntaxError: ERROR = CODE;
Token: TYPE = TDJaMScanner.Token;
Analyze: PROC [doc: TiogaNode, docName: ROPE] RETURNS [anal: JSAnalysis] = {
asRope: ROPE = TiogaRopes.RopeFromTioga[node: doc, skipCommentNode: TRUE];
reader: RopeReader.Ref = RopeReader.Create[];
stack: LORA ¬ NIL;
before: INT;
reader.SetPosition[asRope, 0];
anal ¬ NEW [JSAnalysisPrivate ¬ []];
{ENABLE SyntaxError => {
posn: INT = reader.GetIndex[];
MessageWindow.Append[
message: IO.PutFR["Syntax error in %g before %g", [rope[docName]], [integer[posn]]],
clearFirst: TRUE];
anal.bodyStart ¬ anal.prefixEnd ¬ posn;
CONTINUE;
};
DO
before ¬ reader.GetIndex[];
{token: Token = TDJaMScanner.GetToken[reader];
SELECT token.type FROM
nil => EXIT--end of file, right?--;
name => {
a: ATOM = NARROW[TDJaMScanner.ParseToken[token, asRope]];
SELECT a FROM
$BeginStyle => NULL;
$AttachStyle => IF stack # NIL
THEN WITH stack.first SELECT FROM
fileName: ROPE => anal.attachs ¬ CONS[fileName, anal.attachs];
ENDCASE => SyntaxError
ELSE SyntaxError;
run => IF stack # NIL
THEN WITH stack.first SELECT FROM
fileName: ROPE => anal.runs ¬ CONS[fileName, anal.runs];
ENDCASE => SyntaxError
ELSE SyntaxError;
equal => IF stack # NIL THEN stack ¬ stack.rest ELSE SyntaxError;
ENDCASE => EXIT--unrecognized operator, must be end of prefix--;
};
string, int, real => stack ¬ CONS[TDJaMScanner.ParseToken[token, asRope], stack];
lbrace, rbrace => EXIT--end of prefix--;
comment => NULL;
ENDCASE => ERROR;
}ENDLOOP;
anal.bodyStart ¬ before;
anal.prefixEnd ¬ reader.GetIndex[];
}};
run: ATOM = Atom.MakeAtom[".run"];
equal: ATOM = Atom.MakeAtom["="];
EditNotify.AddNotifyProc[EventWatcher, after, low];
END.