File ParserMain.Mesa
November 8, 1980 2:47 PM
Last Edited by: McCreight, March 12, 1985 1:58:38 pm PST
DIRECTORY
IO, ParserTypeDefs, ParserDefs, ParserUtilityDefs, IntDefs, ParserErrorDefs, ParserInputDefs, Rope;
ParserMain: CEDAR PROGRAM
IMPORTS IO, ParserInputDefs, ParserErrorDefs, IntDefs, ParserUtilityDefs, ParserTypeDefs, Rope
EXPORTS ParserDefs =
BEGIN
defInProg: BOOLEAN;
InitParser: PUBLIC PROCEDURE RETURNS [BOOLEAN] =
BEGIN
defInProg ← FALSE;
IF ~ParserInputDefs.InitInput[] OR ~ParserErrorDefs.InitError[] OR ~ParserTypeDefs.InitTypes[] THEN
RETURN[FALSE]
ELSE
RETURN[ParserUtilityDefs.InitUtilities[]];
END;
FinishParser: PUBLIC PROCEDURE RETURNS [BOOLEAN] =
BEGIN
IF ~ParserInputDefs.FinishInput[] OR ~ParserErrorDefs.FinishError[] OR ~ParserTypeDefs.FinishTypes[] THEN
RETURN[FALSE]
ELSE
RETURN[ParserUtilityDefs.FinishUtilities[]];
END;
ParseStatement: PUBLIC PROCEDURE RETURNS [ParserDefs.CommandType] =
BEGIN OPEN ParserUtilityDefs;
Command: ParserDefs.CommandType;
Diameter: LONG CARDINAL;
Center: ParserTypeDefs.Point;
CurPath: ParserTypeDefs.Path;
Length, Width: LONG CARDINAL;
XRotation, YRotation: LONG INTEGER;
SymbolNumber: LONG CARDINAL;
LayerName: REF TEXTNEW[TEXT[100]];
CurChar: CHARACTER;
UserCommand: [0..9];
CommentText, UserText: Rope.ROPE;
Multiplier, Divisor: LONG CARDINAL;
XTrans, YTrans: LONG INTEGER;
CurTList: ParserTypeDefs.TList;
BEGIN
ENABLE RecoverFromError =>
BEGIN OPEN ParserErrorDefs;
SELECT errorCode FROM
NullPath => Report["No Points in Path", FatalSyntax];
MissingLayer => Report["Layer Name Expected", FatalSyntax];
NumberTooBig => Report["Number Out Of Range", FatalSemantic];
MissingUnsigned => Report["Unsigned Integer Expected", FatalSyntax];
MissingSigned => Report["Signed Integer Expected", FatalSyntax];
MissingSemiColon => Report["Missing Semicolon, Inserted", FatalSyntax];
BadCommand => Report["Unknown Command Encountered", FatalSyntax];
BadComment =>
BEGIN
Report["End Of File Inside a Comment", FatalSyntax];
END;
BadDefineCommand => Report["No Such Define Command", FatalSyntax];
BadUserCommand =>
BEGIN
Report["End Of File Inside a User Command", FatalSyntax];
END;
IllegalAxis => Report["No Such Axis in Mirror Command", FatalSyntax];
NestDef => Report["Symbol Definitions Can't Nest", FatalSyntax];
NestDD => Report["DD Not Allowed Inside Symbol Definition", FatalSyntax];
NestEnd => Report["End Command Inside Symbol Definition", FatalSyntax];
NoDS => Report["DF Without DS", FatalSyntax];
BadTransCommand => Report["No Such Transformation Command", FatalSyntax];
InternalError => Report["Parser Internal Error", FatalInternal];
ENDCASE => Report["Uncaught PossibleError", Fatal];
IF errorCode # MissingSemiColon AND errorCode # InternalError AND ParserInputDefs.Flush[';] = ParserInputDefs.EOF THEN
Report["Unexpected End of Input File",FatalSyntax]
ELSE Blank[];
Command ← SyntaxError;
CONTINUE;
END;
CurPath ← ParserTypeDefs.AllocatePath[];
CurTList ← ParserTypeDefs.AllocateTList[];
flush all junk, sometimes redundant, but necessary for require files
Blank[];
SELECT (CurChar ← ParserInputDefs.GetChar[]) FROM
'P =>
BEGIN
GetPath[CurPath];
Command ← Polygon;
END;
'B =>
BEGIN
XRotation ← 1; YRotation ← 0;
Length ← UnsignedLong[]; Width ← UnsignedLong[];
Center ← GetPoint[]; Sep[];
IF (CurChar←ParserInputDefs.Peek[]) IN ['0..'9] OR CurChar = '- THEN
BEGIN
XRotation ← SignedLong[];
YRotation ← SignedLong[];
END;
Command ← Box;
END;
'R =>
BEGIN
Diameter ← UnsignedLong[];
Center ← GetPoint[];
Command ← Flash;
END;
'W =>
BEGIN
Width ← UnsignedLong[];
GetPath[CurPath];
Command ← Wire;
END;
'L =>
BEGIN
Blank[];
LayerName.length ← 0;
THROUGH [1..4] WHILE (CurChar ← ParserInputDefs.Peek[]) IN ['0..'9] OR CurChar IN ['A..'Z] DO
LayerName[LayerName.length] ← ParserInputDefs.GetChar[];
LayerName.length ← LayerName.length + 1;
ENDLOOP;
IF LayerName.length = 0 THEN ERROR RecoverFromError[MissingLayer];
Command ← Layer;
END;
'D =>
BEGIN
Blank[];
SELECT ParserInputDefs.GetChar[] FROM
'S =>
BEGIN
IF defInProg THEN ERROR RecoverFromError[NestDef];
SymbolNumber ← UnsignedLong[];
Sep[];
Multiplier ← Divisor ← 1;
IF ParserInputDefs.Peek[] IN ['0..'9] THEN
BEGIN
Multiplier ← UnsignedLong[];
Divisor ← UnsignedLong[];
END;
defInProg ← TRUE;
Command ← DefineStart;
END;
'F =>
BEGIN
IF ~defInProg THEN ERROR RecoverFromError[NoDS];
defInProg ← FALSE;
Command ← DefineEnd;
END;
'D =>
BEGIN
IF defInProg THEN ERROR RecoverFromError[NestDD];
SymbolNumber ← UnsignedLong[];
Command ← DeleteDef;
END;
ENDCASE => ERROR RecoverFromError[BadDefineCommand];
END;
'C =>
BEGIN OPEN ParserTypeDefs;
SymbolNumber ← UnsignedLong[];
Blank[];
WHILE TRUE DO
SELECT ParserInputDefs.Peek[] FROM
'T => BEGIN
[] ← ParserInputDefs.GetChar[];
XTrans ← SignedLong[];
YTrans ← SignedLong[];
AppendTList[CurTList,NEW[TranslateRec ← [
x: XTrans,y: YTrans]]];
END;
'M => BEGIN
[] ← ParserInputDefs.GetChar[];
Blank[];
SELECT ParserInputDefs.GetChar[] FROM
'X => AppendTList[CurTList,NEW[MirrorRec ← [coords: X]]];
'Y => AppendTList[CurTList,NEW[MirrorRec ← [coords: Y]]];
ENDCASE => ERROR RecoverFromError[IllegalAxis];
END;
'R => BEGIN
[] ← ParserInputDefs.GetChar[];
XRotation ← SignedLong[];
YRotation ← SignedLong[];
AppendTList[CurTList,NEW[RotateRec ← [
xRot: XRotation,yRot: YRotation]]];
END;
'; => EXIT;
ENDCASE => ERROR RecoverFromError[BadTransCommand];
Blank[];
ENDLOOP;
Command ← CallSymbol;
END;
'( =>
BEGIN
Level: CARDINAL ← 1;
CommentTextStream: IO.STREAMIO.ROS[];
WHILE Level > 0 DO
SELECT (CurChar←ParserInputDefs.GetChar[]) FROM
'( => BEGIN
Level ← Level+1;
CommentTextStream.PutChar['(];
END;
') => BEGIN
Level ← Level-1;
IF Level > 0 THEN CommentTextStream.PutChar[')];
END;
ParserInputDefs.EOF => ERROR RecoverFromError[BadComment];
ENDCASE => CommentTextStream.PutChar[CurChar];
ENDLOOP;
CommentText ← CommentTextStream.RopeFromROS[];
Command ← Comment;
END;
'E =>
BEGIN
IF defInProg THEN ERROR RecoverFromError[NestEnd];
Blank[];
IF NOT ParserInputDefs.EndOfFile[] THEN
ParserErrorDefs.Report["More Text Follows End Command", Advisory];
Command ← End;
IntDefs.IEnd[
! IntDefs.SemanticError =>
BEGIN
Command ← SemanticError;
CONTINUE;
END];
ParserTypeDefs.FreePath[CurPath];
ParserTypeDefs.FreeTList[CurTList];
RETURN[Command];
END;
'; =>
BEGIN
Blank[];
ParserTypeDefs.FreePath[CurPath];
ParserTypeDefs.FreeTList[CurTList];
RETURN[NullCommand];
END;
IN ['0..'9] =>
BEGIN
UserTextStream: IO.STREAMIO.ROS[];
UserCommand ← CurChar - '0;
WHILE NOT ParserInputDefs.EndOfFile[] AND ParserInputDefs.Peek[] = ' DO
[] ← ParserInputDefs.GetChar[];
ENDLOOP;
WHILE NOT ParserInputDefs.EndOfFile[] AND ParserInputDefs.Peek[] # '; DO
UserTextStream.PutChar[ParserInputDefs.GetChar[]];
ENDLOOP;
UserText ← UserTextStream.RopeFromROS[];
IF ParserInputDefs.EndOfFile[] THEN ERROR RecoverFromError[BadUserCommand];
Command ← UserCommand;
END;
ENDCASE => ERROR RecoverFromError[BadCommand];
IF Semi[] THEN
BEGIN OPEN IntDefs;
By now we have parsed a syntactically valid command
ENABLE IntDefs.SemanticError =>
BEGIN
Command ← SemanticError;
CONTINUE;
END;
SELECT Command FROM
Wire => IWire[Width, CurPath];
DefineStart => IDefineStart[SymbolNumber,Multiplier,Divisor];
DefineEnd => IDefineEnd[];
DeleteDef => IDeleteDef[SymbolNumber];
CallSymbol => ICallSymbol[SymbolNumber,CurTList];
Layer => ILayer[Rope.FromRefText[LayerName]];
Flash => IFlash[Diameter, Center];
Polygon => IPolygon[CurPath];
Box => IBox[Length, Width, Center, XRotation, YRotation];
Comment =>
BEGIN
IComment[CommentText ! IntDefs.SemanticError => CONTINUE];
END;
UserCommand =>
BEGIN
IUserCommand[UserCommand,UserText ! IntDefs.SemanticError => CONTINUE];
END;
ENDCASE => ERROR RecoverFromError[InternalError];
END
ELSE ERROR RecoverFromError[MissingSemiColon];
END;
ParserTypeDefs.FreePath[CurPath];
ParserTypeDefs.FreeTList[CurTList];
RETURN[Command];
END;
END.