repetition.beh.html

Program{
	(@ Dictionary repdict; @)
	private void convertRepetition()via RepetitionClass bypassing-> *, nonempty, *to{ PlainSyntax, PrintIndent, PrintUnindent, PrintSkip, PrintSpace, ClassName }{
		(@
      Hashtable repdict = new Hashtable();
      ClassName classname;
      String container, linknode, linknodename;
      boolean inRepeatedPart;
    @)
		before ClassDef (@
      classname = host.get_classname();
      container = null;
    @)
		before RepetitionClass (@
      container = "= ";
      linknodename = RepetitionClass.makeLinknodeName(classname);
    @)
		before Syntax (@
      if (inRepeatedPart)
	linknode += host + " ";
      else
	container += host + " ";
    @)
		before RepeatedPart (@
      String first = "<first> " + linknodename;
      if (host.get_nonempty() == null) {
	// The repetition is possibly empty; make the link node optional.
	first = "[ " + first + " ] ";
      }
      container += first;
      inRepeatedPart = true;
      linknode = "[ ";
      LocalLookahead l = host.get_locallookahead();
      if (l != null) linknode += l + " ";
    @)
		before ClassName (@
      repdict.put(classname, host);
      linknode = "= <it> " + host + " " + linknode
	       + "<next> " + linknodename + " ";
    @)
		after RepeatedPart (@
      linknode += "].";
      inRepeatedPart = false;
    @)
		after RepetitionClass (@
      container += ".";
    @)
		after ClassDef (@
      if (container != null) {
	// Replace the repetition class with the new container class.
	host.set_classparts(ConstructionClass.parse(container));
	// Add the class definition for the new link node class.
	ClassDef linknodedef = host.deepCopy();
	linknodedef.set_paramclassname(ParamClassName.parse(linknodename));
	linknodedef.set_classparts(ConstructionClass.parse(linknode));
	Program.prog.addClassDef(linknodedef);
      }
    @)
		after Program (@ host.repdict = repdict; @)
	}
}

RepetitionClass{
	static String makeLinknodeName(ClassName classname)(@
    return "Nonempty_" + classname;
  @)
}

ClassName{
	boolean isOrWasRepetitionClass()(@
    ClassDef def;
    return wasRepetitionClass()
	   || ((def = Program.prog.findClassDef(this)) != null
	       && def.isRepetitionClass());
  @)
	boolean wasRepetitionClass()(@
    return Program.prog.repdict.get(this) != null;
  @)
}

Program{
	public void addEnumerationStuff()=allClassDefs{
		before ClassDef (@ 
      ClassName cn = host.get_classname();
      if (!cn.isOrWasRepetitionClass()) return;
      // if we get to here, host is (was) a repetition class.
      // add some methods
      ClassName ecn = (ClassName) Program.prog.repdict.get(cn); 
      String ln = RepetitionClass.makeLinknodeName(cn);
      host.addBehavior(ClassMethods.parse(
 "{"+Text.begin+"\n"
+"  private " + ln + " tail;\n"
+"  public void addElement(" + ecn + " e) { \n"
+"    checktail(); \n"
+"    if (tail == null) {\n"
+"      first = new " + ln + "(e,null); tail = first;\n"
+"    } else {\n"
+"	tail.set_next(new " + ln + "(e,null)); tail = tail.get_next();\n"
+"    }\n"
+"  }\n\n"
+"  public void push(" + ecn + " e) { first = new " + ln + "(e,first); }\n\n"
+"  public java.util.Enumeration elements() { return new "+cn+"(first); } \n\n"
+"  public int size() {\n"
+"    int i= 0;\n"
+"    for (java.util.Enumeration e=elements(); e.hasMoreElements(); i++)\n"
+"	e.nextElement();\n"
+"    return i;\n"
+"  }\n"
+"  public boolean isEmpty() { return (first == null); }\n\n"
+"  public boolean hasMoreElements() { return (first != null); }\n\n"
+"  public Object nextElement() {\n"
+"    " + ecn + " car = first.get_it();\n"
+"    first = first.get_next();\n"
+"    return (Object) car;\n"
+"  }\n\n"
+"  private void checktail() {\n"
+"    if (tail == null && first != null) {\n"
+"	tail = first;\n"
+"	while (tail.get_next() != null) tail = tail.get_next();\n"
+"    }\n"
+"  }\n"
+"  public boolean contains("+ecn+" e) {\n"
+"    java.util.Enumeration en = this.elements();\n"
+"    while (en.hasMoreElements())\n"
+"	if (e.equals(("+ecn+") en.nextElement())) return true;\n"
+"    return false;\n"
+"  }\n"
+Text.end+"}"));

      host.addInterface(Interface.parse("java.util.Enumeration."));
    @)
	}
}

ClassDef{
	void addInterface(Interface i)to Interface_Commalist{
		before ClassParents (@
      if (host.get_interfaces() == null)
	host.set_interfaces(new Interface_Commalist());
    @)
		before Interface_Commalist (@
      host.addElement(i);
    @)
	}
}