MODULE Parser; IMPORT AGRS,Names,Library,Texts,SYSTEM; CONST MaxStrLength= 60; SetBits*= MAX(SET)+1; TYPE ParserProc= PROCEDURE(VAR r:Texts.Reader; l:LONGINT): AGRS.Term; ParseWrapper*= POINTER TO RECORD(AGRS.TermDesc) handler*: ParserProc; END; VAR sentenceName*,spaceCharsName*,customParsersName*,parseName*: AGRS.Name; temp,buildingName*,rulesName,varName,blockName,className: AGRS.Name; sentenceParser*,attributeParser*,standardParser,customParser: ParseWrapper; rulesParser,varParser,blockParser,classParser: ParseWrapper; numberParser,stringParser,charParser,charSetParser: ParseWrapper; sentence: Texts.Text; (* Tekst koji se parsira. *) spaceChars: Library.CharSet; (* Delimiteri. *) collection: AGRS.ClosedClass; (* CustomParsers znacenje. *) idTerm: AGRS.Term; attrPosition: INTEGER; (* Redni broj trenutnog atributa. *) PROCEDURE Rewind*(VAR rd: Texts.Reader; newPos: LONGINT); BEGIN Texts.OpenReader(rd,sentence,newPos); END Rewind; PROCEDURE BackSpace(VAR rd: Texts.Reader); BEGIN Texts.OpenReader(rd,sentence,Texts.Pos(rd)-1); END BackSpace; PROCEDURE ParseEmpty*(VAR rd: Texts.Reader; limit: LONGINT): BOOLEAN; VAR ch: CHAR; BEGIN WHILE ~rd.eot & (Texts.Pos(rd)'9') THEN RETURN AGRS.Failure END; x:= 0; WHILE (ch>='0') & (ch<='9') & (Texts.Pos(rd)<=limit) DO IF x <= (MAX(INTEGER)-ORD(ch)+ORD('0')) DIV 10 THEN x:= 10*x+ORD(ch)-ORD('0'); END; Texts.Read(rd,ch); END; IF minus THEN x:= -x; END; BackSpace(rd); RETURN Library.NewNumber(x) END ParseNumber; PROCEDURE ParseChar(VAR rd: Texts.Reader; limit: LONGINT): AGRS.Term; VAR delimiter,chRead: CHAR; BEGIN Texts.Read(rd,delimiter); IF delimiter = "'" THEN Texts.Read(rd,chRead); Texts.Read(rd,delimiter); IF (delimiter="'") & (Texts.Pos(rd)<=limit) THEN RETURN Library.NewChar(chRead) END; END; RETURN AGRS.Failure END ParseChar; PROCEDURE ParseCharSet(VAR rd: Texts.Reader; limit: LONGINT): AGRS.Term; VAR ch,second: CHAR; s: Library.CharSet; complement: BOOLEAN; BEGIN Texts.Read(rd,ch); IF ch='~' THEN complement:= TRUE; Texts.Read(rd,ch); ELSE complement:= FALSE; END; IF ch#'{' THEN RETURN AGRS.Failure END; IF ParseEmpty(rd,limit) THEN RETURN AGRS.Failure END; s:= Library.NewCharSet(); Texts.Read(rd,ch); IF ch#'}' THEN LOOP IF ch='\' THEN Texts.Read(rd,ch); CASE ch OF |'0': ch:= 0X; |'s','S': ch:= ' '; |'t','T': ch:= 9X; |'n','N': ch:= 0DX; s.Include(0AX); ELSE RETURN AGRS.Failure; END; END; Texts.Read(rd,second); IF second='-' THEN Texts.Read(rd,second); IF secondlimit THEN RETURN AGRS.Failure END; IF complement THEN s.Complement(); END; RETURN s END ParseCharSet; PROCEDURE ParseIdentifier*(VAR rd: Texts.Reader; limit: LONGINT): AGRS.Term; VAR wd: AGRS.Name; str: ARRAY MaxStrLength OF CHAR; ch: CHAR; i: INTEGER; BEGIN i:= 0; REPEAT Texts.Read(rd,ch); str[i]:= ch; INC(i); UNTIL (ch<'0') OR (CAP(ch)>'Z') OR ((ch>'9') & (CAP(ch)<'A')) OR (Texts.Pos(rd)>limit); IF i=1 THEN RETURN AGRS.Failure; END; BackSpace(rd); str[i-1]:= 0X; wd:= Names.FindPublicName(str); IF wd=NIL THEN Names.AddArgument(wd,str); END; RETURN wd END ParseIdentifier; PROCEDURE ParseString(VAR rd: Texts.Reader; limit: LONGINT): AGRS.Term; VAR ch,between: CHAR; str: ARRAY MaxStrLength OF CHAR; length: INTEGER; BEGIN Texts.Read(rd,between); IF (between="'") OR (between='"') THEN length:= 0; Texts.Read(rd,ch); WHILE (ch#between) & (ch#0DX) & (length