packages feed

language-oberon-0.1.1: examples/AGRS/Parser.Mod

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)<limit) DO
      Texts.Read(rd,ch);
      IF (rd.elem=NIL) & ~(ORD(ch) MOD SetBits IN 
           spaceChars.value[ORD(ch) DIV SetBits]) THEN
         BackSpace(rd);
         RETURN FALSE
      END;
   END;
   RETURN TRUE
END ParseEmpty;


PROCEDURE ExactParse(parser: ParserProc; VAR rd: Texts.Reader; limit: LONGINT): AGRS.Term;
VAR
   result: AGRS.Term;
BEGIN
   result:= parser(rd,limit);
   IF (result.indirection#AGRS.failName) & ParseEmpty(rd,limit) THEN
      RETURN result
   ELSE
      RETURN AGRS.Failure
   END
END ExactParse;


PROCEDURE ScanCharacter(chSeek: CHAR; 
      VAR rd: Texts.Reader; limit: LONGINT): BOOLEAN;
VAR
   chRead: CHAR;
BEGIN
   WHILE Texts.Pos(rd)<limit DO
      Texts.Read(rd,chRead);
      IF chSeek=chRead THEN
         RETURN TRUE
      END;
   END;
   RETURN FALSE
END ScanCharacter;


PROCEDURE ParseTheCharacter(chExpect: CHAR; 
      VAR rd: Texts.Reader; limit: LONGINT): BOOLEAN;
VAR
   chRead: CHAR;
BEGIN
   IF Texts.Pos(rd)<limit THEN
      Texts.Read(rd,chRead);
      IF chExpect=chRead THEN
         RETURN TRUE
      END;
   END;
   RETURN FALSE
END ParseTheCharacter;


PROCEDURE ParseTheString*(strExpect: ARRAY OF CHAR; 
      VAR rd: Texts.Reader; limit: LONGINT): BOOLEAN;
VAR
   chRead: CHAR;
   i: INTEGER;
BEGIN
   i:= 0;
   WHILE (Texts.Pos(rd)<limit) & (i<LEN(strExpect)) 
                               & (strExpect[i]#0X) DO
      Texts.Read(rd,chRead);
      IF strExpect[i]#chRead THEN
         RETURN FALSE
      END;
      INC(i);
   END;
   RETURN strExpect[i]=0X
END ParseTheString;


PROCEDURE ParseNumber(VAR rd: Texts.Reader; limit: LONGINT): AGRS.Term;
VAR
   ch: CHAR;
   minus: BOOLEAN;
   x: INTEGER;
BEGIN
   Texts.Read(rd,ch);
   IF ch='-' THEN
      minus:= TRUE;
      Texts.Read(rd,ch);
   ELSE
      minus:= FALSE;
      IF ch='+' THEN
         Texts.Read(rd,ch);
      END
   END;
   IF (ch<'0') OR (ch>'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 second<ch THEN
               RETURN AGRS.Failure
            END;
            WHILE ch<=second DO
               s.Include(ch);
               ch:= CHR(ORD(ch)+1);
            END;
            Texts.Read(rd,second);
         ELSE
            s.Include(ch);
         END;
         IF second#',' THEN
            IF second='}' THEN
               EXIT
            ELSE
               RETURN AGRS.Failure
            END;
         END;
         IF ParseEmpty(rd,limit) THEN
            RETURN AGRS.Failure
         END;
         Texts.Read(rd,ch);
      END;
   END;
   IF Texts.Pos(rd)>limit 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<MaxStrLength)
            & (Texts.Pos(rd)<limit) DO
         str[length]:= ch;
         INC(length);
         Texts.Read(rd,ch);
      END;
      IF ch=between THEN
         str[length]:= 0X;
         RETURN Library.NewString(Names.NewStringCopy(str))
      END;
   END;
   RETURN AGRS.Failure
END ParseString;


PROCEDURE ParseCustom(VAR rd: Texts.Reader; limit: LONGINT): AGRS.Term;
VAR
   id,result: AGRS.Term;
   startPos: LONGINT;
   
   
BEGIN
   startPos:= Texts.Pos(rd);
   id:= ParseIdentifier(rd,limit);
   Rewind(rd,startPos);
   IF id.indirection=AGRS.failName THEN
      RETURN AGRS.Failure
   END;
   sentenceName.Assign(Library.SubText(sentence,startPos,limit));
   idTerm.Init(id);
   result:= customParsersName.Evaluate(idTerm);
   sentenceName.Restore();
   Rewind(rd,limit);
   RETURN result
END ParseCustom;


PROCEDURE ParseSentence(VAR rd: Texts.Reader; limit: LONGINT): AGRS.Term;
VAR
   result: AGRS.Term;
   startPos,endPos: LONGINT;

			PROCEDURE ParseSequence(VAR rd: Texts.Reader; limit: LONGINT): AGRS.Term;
			VAR
         first,rest: AGRS.Term;
         newTerm: AGRS.SubTerm;
         scanner: Texts.Reader;
			BEGIN
			   startPos:= Texts.Pos(rd);
         Rewind(scanner,startPos);
         WHILE ScanCharacter(';',scanner,limit) DO
            Rewind(rd,startPos);
            first:= ParseCustom(rd,Texts.Pos(scanner)-1);
            IF first.indirection#AGRS.failName THEN
               Rewind(rd,Texts.Pos(scanner));
               IF ~ParseEmpty(rd,limit) THEN
                  rest:= ParseSequence(rd,limit);
                  IF rest.indirection#AGRS.failName THEN
                     NEW(newTerm);
                     newTerm.Init(first);
                     newTerm.InitQuery(rest);
                     RETURN newTerm
                  END;
               END;
            END;
         END;
         Rewind(rd,startPos);
         Rewind(scanner,startPos);
         WHILE ScanCharacter(')',scanner,limit) DO
			      endPos:= Texts.Pos(scanner);
         END;
         RETURN ParseSentence(rd,endPos-1);
			END ParseSequence;
BEGIN
   startPos:= Texts.Pos(rd);
   result:= ExactParse(ParseChar,rd,limit);
   IF result.indirection#AGRS.failName THEN
      RETURN result
   END;
   Rewind(rd,startPos);
   result:= ExactParse(ParseString,rd,limit);
   IF result.indirection#AGRS.failName THEN
      RETURN result
   END;
   Rewind(rd,startPos);
   result:= ExactParse(ParseNumber,rd,limit);
   IF result.indirection#AGRS.failName THEN
      RETURN result
   END;
   Rewind(rd,startPos);
   result:= ExactParse(ParseCharSet,rd,limit);
   IF result.indirection#AGRS.failName THEN
      RETURN result
   END;
   Rewind(rd,startPos);
   result:= ParseCustom(rd,limit);
   IF result.indirection#AGRS.failName THEN
      RETURN result
   END;
   IF ParseTheCharacter('(',rd,limit) & ~ParseEmpty(rd,limit) THEN
      result:= ParseSequence(rd,limit);
      IF result.indirection#AGRS.failName THEN
         IF ~ParseEmpty(rd,limit) THEN
            IF ParseTheCharacter(')',rd,limit) THEN
               RETURN result
            END;
         END;
      END;
   END;
   RETURN AGRS.Failure
END ParseSentence;


PROCEDURE ParseAttribute(VAR rd: Texts.Reader; limit: LONGINT): AGRS.Term;
VAR
   startPos: LONGINT;
   id,meaning,built: AGRS.Term;
   newTerm: AGRS.Tree;
   attrPos: INTEGER;
BEGIN
   startPos:= Texts.Pos(rd);
   id:= ParseIdentifier(rd,limit);
   IF (id.indirection#AGRS.failName) & ~ParseEmpty(rd,limit) 
         & ParseTheCharacter('=',rd,limit) & ~ParseEmpty(rd,limit) THEN
      meaning:= ParseSentence(rd,limit);
      IF meaning.indirection=AGRS.failName THEN
         RETURN AGRS.Failure
      END;
   ELSIF attrPosition>0 THEN
      Rewind(rd,startPos);
      IF ParseEmpty(rd,limit) THEN
         RETURN AGRS.Failure
      END;
      attrPos:= attrPosition;         
      meaning:= ParseSentence(rd,limit);
      IF meaning.indirection=AGRS.failName THEN
         RETURN AGRS.Failure
      END;
      id:= Names.FindOrdinalName(attrPos);
   ELSE
      RETURN AGRS.Failure
   END;
   built:= buildingName.indirection;
   WITH built: AGRS.Tree DO
      built.AddProperty(id(AGRS.Name),meaning);
      RETURN built
   ELSE
      NEW(newTerm);
      newTerm.Init(built);
      newTerm.AddProperty(id(AGRS.Name),meaning);
      RETURN newTerm
   END;
END ParseAttribute;


PROCEDURE ParseProperties(VAR rd: Texts.Reader; limit: LONGINT): AGRS.Term;
VAR
   startPos: LONGINT;
   attrPos: INTEGER;
   result: AGRS.Term;
   attributeReader: Texts.Reader;
BEGIN
   startPos:= Texts.Pos(rd);
   IF ParseTheCharacter(')',rd,limit) THEN
      RETURN buildingName.indirection
   END;
   attrPos:= attrPosition+1;
   Rewind(rd,startPos);
   WHILE ScanCharacter(',',rd,limit) DO
      attrPosition:= attrPos;
      Rewind(attributeReader,startPos);
      result:= ParseAttribute(attributeReader,Texts.Pos(rd)-1);
      IF result.indirection#AGRS.failName THEN
         IF ParseEmpty(rd,limit) THEN
            RETURN AGRS.Failure
         END;
         attrPosition:= attrPos;
         buildingName.Assign(result);
         result:= ParseProperties(rd,limit);
         buildingName.Restore();
         IF result.indirection#AGRS.failName THEN
            RETURN result
         END;
      END;
   END;
   Rewind(rd,startPos);
   Rewind(attributeReader,startPos);
   WHILE ScanCharacter(')',rd,limit) DO
      startPos:= Texts.Pos(rd);
   END;
   attrPosition:= attrPos;
   RETURN ParseAttribute(attributeReader,startPos-1)
END ParseProperties;


PROCEDURE ParseStandard(VAR rd: Texts.Reader; limit: LONGINT): AGRS.Term;
VAR
   id,result: AGRS.Term;
   startPos: LONGINT;
   result1: AGRS.SubTerm;
   result2: AGRS.Field;
   result3: AGRS.Tree;
BEGIN
   id:= ParseIdentifier(rd,limit);
   IF id.indirection=AGRS.failName THEN
      RETURN AGRS.Failure
   END;
   IF ParseEmpty(rd,limit) THEN
      RETURN id
   END;
   startPos:= Texts.Pos(rd);
   IF ParseTheCharacter('.',rd,limit) THEN
      result:= ParseStandard(rd,limit);
      IF result.indirection#AGRS.failName THEN
         IF (result IS AGRS.Name) OR (result IS AGRS.Field) THEN
            NEW(result2);
            result2.Init(id);
            result2.InitQuery(result);
            RETURN result2
         ELSE
            NEW(result1);
            result1.Init(id);
            result1.InitQuery(result);
            RETURN result1
         END;
      END;
      RETURN AGRS.Failure
   ELSE
      Rewind(rd,startPos);
      IF ParseTheCharacter('(',rd,limit) THEN
         IF ParseEmpty(rd,limit) THEN
            RETURN AGRS.Failure
         END;
         startPos:= Texts.Pos(rd);
         IF ParseTheCharacter(')',rd,limit) THEN
            NEW(result);
            result.Init(id);
         ELSE
            Rewind(rd,startPos);
            NEW(result3);
            result3.Init(id);
            buildingName.Assign(result3);
            attrPosition:= 0;
            result:= ParseProperties(rd,limit);
            buildingName.Restore();
         END;
         RETURN result
      ELSE
         Rewind(rd,startPos);
         RETURN id
      END;
   END;
END ParseStandard;


PROCEDURE ParseRule(VAR rd: Texts.Reader; limit: LONGINT): AGRS.Term;
VAR
   startPos: LONGINT;
   lhs,rhs,rest: AGRS.Term;
   ruleReader: Texts.Reader;
BEGIN
   startPos:= Texts.Pos(rd);
   WHILE ScanCharacter('=',rd,limit) DO
      Rewind(ruleReader,startPos);
      lhs:= ParseStandard(ruleReader,Texts.Pos(rd)-1);
      IF (lhs.indirection#AGRS.failName)
            & ~ParseEmpty(ruleReader,limit)
            & ParseTheCharacter('=', ruleReader,limit)
            & ~ParseEmpty(ruleReader,limit) THEN
         startPos:= Texts.Pos(ruleReader);
         WHILE ScanCharacter(',',rd,limit) DO
            Rewind(ruleReader,startPos);
            rhs:= ParseSentence(ruleReader,Texts.Pos(rd)-1);
            IF (rhs.indirection#AGRS.failName)
                  & ~ParseEmpty(ruleReader,limit)
                  & ParseTheCharacter(',', ruleReader,limit)
                  & ~ParseEmpty(ruleReader,limit) THEN
               rest:= ParseRule(ruleReader,limit);
               IF rest.indirection#AGRS.failName THEN
                  Rewind(rd,Texts.Pos(ruleReader));
                  RETURN AGRS.MakeAlternative(lhs,rhs) (* ,rest *)
               END;
            END;
         END;
         Rewind(rd,startPos);
         Rewind(ruleReader,startPos);
         WHILE ScanCharacter(')',rd,limit) DO
            startPos:= Texts.Pos(rd);
         END;
         rhs:= ParseSentence(ruleReader,startPos-1);
         IF rhs.indirection=AGRS.failName THEN
            RETURN AGRS.Failure
         END;
         IF lhs IS AGRS.Name THEN
            RETURN rhs
         ELSE
            RETURN AGRS.MakeAlternative(lhs,rhs) (* ,NIL *)
         END;
      END;
   END;
   RETURN AGRS.Failure
END ParseRule;


PROCEDURE ParseRules(VAR rd: Texts.Reader; limit: LONGINT): AGRS.Term;
BEGIN
   IF ParseTheString('RULE',rd,limit) & ~ParseEmpty(rd,limit)
         & ParseTheCharacter('(',rd,limit) & ~ParseEmpty(rd,limit) THEN
      RETURN ParseRule(rd,limit)
   ELSE
      RETURN AGRS.Failure
   END;
END ParseRules;

PROCEDURE ParseVar(VAR rd: Texts.Reader; limit: LONGINT): AGRS.Term;
BEGIN
   IF ParseTheString('VAR',rd,limit) THEN
      RETURN AGRS.Variable
   ELSE
      RETURN AGRS.Failure
   END;
END ParseVar;

PROCEDURE ParseBlock(VAR rd: Texts.Reader; limit: LONGINT): AGRS.Term;
VAR
   startPos: LONGINT;
   rest,id: AGRS.Term;
   vars: AGRS.Tree;
BEGIN
   IF ParseTheString('LOCAL',rd,limit) THEN
      Names.LocalBlock;
(*      Names.LocalNames; *)
      NEW(vars);
      vars.Init(Names.SystemRoot);
      LOOP
         IF ParseEmpty(rd,limit) THEN
            EXIT
         END;
         id:= ParseIdentifier(rd,limit);
         IF (id.indirection=AGRS.failName) OR ParseEmpty(rd,limit) THEN
            EXIT
         END;
         vars.AddProperty(id(AGRS.Name),AGRS.Variable);
         startPos:= Texts.Pos(rd);
         IF ~ParseTheCharacter(',',rd,limit) THEN
            Rewind(rd,startPos);
            IF ParseTheString('IN',rd,limit) & ~ParseEmpty(rd,limit) THEN
(*               Names.EndNames; *)
               rest:= ParseSentence(rd,limit);
               Names.EndBlock;
               IF rest.indirection=AGRS.failName THEN
                  RETURN AGRS.Failure
               ELSE
                  RETURN AGRS.MakeLocalBlock(vars,rest)
               END;
            ELSE
               EXIT
            END;
         END;
      END;
(*      Names.EndNames; *)
      Names.EndBlock;
   END;
   RETURN AGRS.Failure
END ParseBlock;

PROCEDURE ParseClass(VAR rd: Texts.Reader; limit: LONGINT): AGRS.Term;
VAR
   startPos: LONGINT;
   tree: AGRS.Term;
   result,tree1: AGRS.Class;
BEGIN
   startPos:= Texts.Pos(rd);
   IF ParseTheString('CLASS',rd,limit) THEN
      Rewind(rd,startPos);
      tree:= ParseStandard(rd,limit);
      IF tree IS AGRS.Tree THEN
         NEW(result);
         tree1:= SYSTEM.VAL(AGRS.Class,tree);
         result^:= tree1^;
         RETURN result
      END;
   END;
   RETURN AGRS.Failure
END ParseClass;


PROCEDURE pParse;
VAR
   txt,parsed: AGRS.Term;
   sentenceReader: Texts.Reader;
BEGIN
   txt:= sentenceName.Value();
   WITH txt: Library.Text DO
      sentence:= txt.base;
      Texts.OpenReader(sentenceReader,sentence,txt.startOffset);
      IF ~ParseEmpty(sentenceReader,txt.endOffset) THEN
         parsed:= ParseSentence(sentenceReader,txt.endOffset);
         IF parsed.indirection#AGRS.failName THEN
            IF ~AGRS.Continued() THEN
               AGRS.result:= parsed;
            END;
            RETURN
         END;
      END;
      parsed:= Library.NewError(Library.SyntaxError);
      parsed.Reduce;
   ELSE
      parsed:= Library.NewError(Library.NotTextType);
      parsed.Reduce;
   END;
END pParse;


PROCEDURE (t: ParseWrapper) Reduce*;
VAR
   txt,parsed: AGRS.Term;
   rd: Texts.Reader;
BEGIN
   txt:= sentenceName.Value();
   WITH txt: Library.Text DO
      sentence:= txt.base;
      Texts.OpenReader(rd,sentence,txt.startOffset);
      parsed:= ExactParse(t.handler,rd,txt.endOffset);
   ELSE
      parsed:= Library.NewError(Library.NotTextType);
   END;
   IF ~AGRS.Continued() THEN
      AGRS.result:= parsed;
   END;
END Reduce;

BEGIN
(* Inicijalizacija parametara i pomocnih promjenljivih. *)
   spaceChars:= Library.NewCharSet();
   spaceChars.Include(' ');
   spaceChars.Include(0X);
   spaceChars.Include(9X);
   spaceChars.Include(0AX);
   spaceChars.Include(0DX);
   Names.DefinePublicName(spaceCharsName,'SpaceCharacters',spaceChars);

   NEW(idTerm);

   NEW(sentenceParser);
   sentenceParser.Init(Names.SystemRoot);
   sentenceParser.handler:= ParseSentence;
   Names.DefinePublicName(temp,'SentenceParser',sentenceParser);

   NEW(standardParser);
   standardParser.Init(Names.SystemRoot);
   standardParser.handler:= ParseStandard;
   Names.DefinePublicName(temp,'StandardParser',standardParser);

   NEW(customParser);
   customParser.Init(Names.SystemRoot);
   customParser.handler:= ParseCustom;
   Names.DefinePublicName(temp,'CustomParser',customParser);

   NEW(attributeParser);
   attributeParser.Init(Names.SystemRoot);
   attributeParser.handler:= ParseAttribute;
   Names.DefinePublicName(temp,'AttributeParser',customParser);

   NEW(numberParser);
   numberParser.Init(Names.SystemRoot);
   numberParser.handler:= ParseNumber;
   Names.DefinePublicName(temp,'NumberParser',numberParser);

   NEW(stringParser);
   stringParser.Init(Names.SystemRoot);
   stringParser.handler:= ParseString;
   Names.DefinePublicName(temp,'StringParser',stringParser);

   NEW(charParser);
   charParser.Init(Names.SystemRoot);
   charParser.handler:= ParseChar;
   Names.DefinePublicName(temp,'CharParser',charParser);

   NEW(charSetParser);
   charSetParser.Init(Names.SystemRoot);
   charSetParser.handler:= ParseCharSet;
   Names.DefinePublicName(temp,'CharSetParser',charSetParser);

   NEW(rulesParser);
   rulesParser.Init(Names.SystemRoot);
   rulesParser.handler:= ParseRules;
   Names.DefinePublicName(temp,'RuleParser',rulesParser);
   
   NEW(varParser);
   varParser.Init(Names.SystemRoot);
   varParser.handler:= ParseVar;
   Names.DefinePublicName(temp,'VarParser',varParser);
   
   NEW(blockParser);
   blockParser.Init(Names.SystemRoot);
   blockParser.handler:= ParseBlock;
   Names.DefinePublicName(temp,'BlockParser',blockParser);
   
   NEW(classParser);
   classParser.Init(Names.SystemRoot);
   classParser.handler:= ParseClass;
   Names.DefinePublicName(temp,'ClassParser',classParser);

   Names.AddSystemName(parseName,'Parse',pParse);
   Names.AddArgument(sentenceName,'Sentence');
   Names.AddArgument(rulesName,'RULE');
   Names.AddArgument(varName, 'VAR');
   Names.AddArgument(blockName, 'LOCAL');
   Names.AddArgument(className, 'CLASS');
   NEW(collection);
   collection.Init(Names.SystemRoot);
   collection.AddProperty(rulesName,rulesParser);
   collection.AddProperty(varName,varParser);
   collection.AddProperty(blockName,blockParser);
   collection.AddProperty(className,classParser);
   collection.AddProperty(AGRS.otherwise,standardParser);
   Names.DefinePublicName(customParsersName,'CustomParsers',collection);
   NEW(buildingName);
   buildingName.Init(Names.SystemRoot);
END Parser.