[e-cvs] cvs commit: e/src/jsrc/org/quasiliteral/term Term.java TermBuilder.java TermLexer.java TermParser.java term.y Functor.java

markm@eros.cs.jhu.edu markm@eros.cs.jhu.edu
Thu, 6 Dec 2001 01:25:10 -0500


markm       01/12/06 01:25:10

  Modified:    src/jsrc/org/capml/dom Element.java Node.java Text.java
               src/jsrc/org/erights/e/elang/syntax EBuilder.java
                        ELexer.java EParser.java
               src/jsrc/org/erights/e/elib/prim E.java
               src/jsrc/org/erights/e/elib/tables FlexMap.java
               src/jsrc/org/quasiliteral/astro ASTBuilder.java Astro.java
                        AstroBuilder.java AstroLexerSharedInputState.java
                        AstroSchema.java AstroTag.java AstroToken.java
                        BaseSchema.java
               src/jsrc/org/quasiliteral/syntax BaseLexer.java
               src/jsrc/org/quasiliteral/term Term.java TermBuilder.java
                        TermLexer.java TermParser.java term.y
  Added:       src/jsrc/org/quasiliteral/astro AstroAST.java AstroArg.java
               src/jsrc/org/quasiliteral/quasiterm QuasiBuilder.java
                        QuasiBuilderAdaptor.java
  Removed:     src/jsrc/org/quasiliteral/term Functor.java
  Log:
  It all compiles again.  Functors are gone.  Long live flat Terms.

Revision  Changes    Path
1.7       +4 -4      e/src/jsrc/org/capml/dom/Element.java

Index: Element.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/capml/dom/Element.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- Element.java	2001/12/03 03:30:54	1.6
+++ Element.java	2001/12/06 06:25:07	1.7
@@ -23,6 +23,7 @@
 import org.erights.e.elib.tables.EmptyTwine;
 import org.quasiliteral.astro.AstroBuilder;
 import org.quasiliteral.astro.AstroTag;
+import org.quasiliteral.astro.Astro;
 
 import java.io.IOException;
 
@@ -155,15 +156,14 @@
      *
      * @return :Node (see {@link AstroBuilder})
      */
-    public Object build(AstroBuilder builder) {
+    public Astro build(AstroBuilder builder) {
         AstroTag tag = builder.getSchema().getTagForName(myTagName);
-        Object func = builder.leafTag(tag.getOptTypeCode(),
-                                      EmptyTwine.THE_ONE);
+        Astro func = builder.leafTag(tag, EmptyTwine.THE_ONE);
         Object args = builder.argList();
         int len = myChildren.size();
         for (int i = 0; i < len; i++) {
             Node child = (Node)myChildren.get(i);
-            args = builder.argList(args, child.build(builder));
+            args = builder.argList(args, builder.arg(child.build(builder)));
         }
         return builder.node(func, args);
     }



1.9       +2 -1      e/src/jsrc/org/capml/dom/Node.java

Index: Node.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/capml/dom/Node.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- Node.java	2001/12/03 03:30:54	1.8
+++ Node.java	2001/12/06 06:25:07	1.9
@@ -24,6 +24,7 @@
 import org.erights.e.elib.tables.Iteratable;
 import org.erights.e.elib.tables.Selfless;
 import org.quasiliteral.astro.AstroBuilder;
+import org.quasiliteral.astro.Astro;
 
 import java.io.IOException;
 
@@ -156,6 +157,6 @@
      *
      * @return :Node (see {@link AstroBuilder})
      */
-    public abstract Object build(AstroBuilder builder);
+    public abstract Astro build(AstroBuilder builder);
 }
 



1.7       +2 -1      e/src/jsrc/org/capml/dom/Text.java

Index: Text.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/capml/dom/Text.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- Text.java	2001/12/03 03:30:54	1.6
+++ Text.java	2001/12/06 06:25:07	1.7
@@ -22,6 +22,7 @@
 import org.erights.e.elib.tables.ConstList;
 import org.erights.e.elib.tables.EmptyTwine;
 import org.quasiliteral.astro.AstroBuilder;
+import org.quasiliteral.astro.Astro;
 
 import java.io.IOException;
 
@@ -155,7 +156,7 @@
      *
      * @return :Node (see {@link AstroBuilder})
      */
-    public Object build(AstroBuilder builder) {
+    public Astro build(AstroBuilder builder) {
         return builder.node(builder.leafData(myData, EmptyTwine.THE_ONE),
                             builder.argList());
     }



1.89      +12 -12    e/src/jsrc/org/erights/e/elang/syntax/EBuilder.java

Index: EBuilder.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elang/syntax/EBuilder.java,v
retrieving revision 1.88
retrieving revision 1.89
diff -u -r1.88 -r1.89
--- EBuilder.java	2001/12/02 18:42:01	1.88
+++ EBuilder.java	2001/12/06 06:25:07	1.89
@@ -262,7 +262,7 @@
 
         String verbName;
         if (verb instanceof AstroToken) {
-            verbName = (String)((AstroToken)verb).getData();
+            verbName = (String)((AstroToken)verb).getOptTokenData();
         } else {
             verbName = (String)verb;
         }
@@ -636,7 +636,7 @@
      */
     /*package*/
     Pattern atNoun(Object token) {
-        String str = (String)((AstroToken)token).getData();
+        String str = (String)((AstroToken)token).getOptTokenData();
         str = hilbert(str);
         if ("_".equals(str)) {
             return ignore();
@@ -694,7 +694,7 @@
      */
     /*package*/
     EExpr dollarNoun(Object token) {
-        String str = (String)((AstroToken)token).getData();
+        String str = (String)((AstroToken)token).getOptTokenData();
         str = hilbert(str);
         return noun(str);
     }
@@ -1018,7 +1018,7 @@
     /*package*/
     LiteralExpr literal(Object token) {
         AstroToken tokn = (AstroToken)token;
-        return new LiteralExpr(tokn.getData());
+        return new LiteralExpr(tokn.getOptTokenData());
     }
 
     /**
@@ -1203,7 +1203,7 @@
                                   eScript);
         } else if (isLiteralToken(optOName)) {
             return object(docComment,
-                          ((AstroToken)optOName).getData(),
+                          ((AstroToken)optOName).getOptTokenData(),
                           auditors,
                           eScript);
 
@@ -1270,7 +1270,7 @@
 
         for (int i = 0; i < qList.length; i++) {
             if (isQuasiPart(qList[i])) {
-                buf.append(((AstroToken)qList[i]).getData());
+                buf.append(((AstroToken)qList[i]).getOptTokenData());
 
             } else {
                 EExpr eExpr = (EExpr)qList[i];
@@ -1298,7 +1298,7 @@
     /*package*/
     QuasiLiteralExpr quasiLiteralExpr(Object litIndex) {
         AstroToken lit = (AstroToken)litIndex;
-        int index = ((Number)lit.getData()).intValue();
+        int index = ((Number)lit.getOptTokenData()).intValue();
         return new QuasiLiteralExpr(index);
     }
 
@@ -1308,7 +1308,7 @@
     /*package*/
     QuasiLiteralPatt quasiLiteralPatt(Object litIndex) {
         AstroToken lit = (AstroToken)litIndex;
-        int index = ((Number)lit.getData()).intValue();
+        int index = ((Number)lit.getOptTokenData()).intValue();
         return new QuasiLiteralPatt(index);
     }
 
@@ -1329,7 +1329,7 @@
 
         for (int i = 0; i < qList.length; i++) {
             if (isQuasiPart(qList[i])) {
-                buf.append(((AstroToken)qList[i]).getData());
+                buf.append(((AstroToken)qList[i]).getOptTokenData());
 
             } else if (qList[i] instanceof EExpr) {
                 EExpr eExpr = (EExpr)qList[i];
@@ -1359,7 +1359,7 @@
     /*package*/
     QuasiPatternExpr quasiPatternExpr(Object litIndex) {
         AstroToken lit = (AstroToken)litIndex;
-        int index = ((Number)lit.getData()).intValue();
+        int index = ((Number)lit.getOptTokenData()).intValue();
         return new QuasiPatternExpr(index);
     }
 
@@ -1369,7 +1369,7 @@
     /*package*/
     QuasiPatternPatt quasiPatternPatt(Object litIndex) {
         AstroToken lit = (AstroToken)litIndex;
-        int index = ((Number)lit.getData()).intValue();
+        int index = ((Number)lit.getOptTokenData()).intValue();
         return new QuasiPatternPatt(index);
     }
 
@@ -1845,7 +1845,7 @@
 
         } else if (isLiteralToken(optOName)) {
             return oType(docComment,
-                         ((AstroToken)optOName).getData(),
+                         ((AstroToken)optOName).getOptTokenData(),
                          auditors,
                          mTypes);
 



1.72      +34 -33    e/src/jsrc/org/erights/e/elang/syntax/ELexer.java

Index: ELexer.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elang/syntax/ELexer.java,v
retrieving revision 1.71
retrieving revision 1.72
diff -u -r1.71 -r1.72
--- ELexer.java	2001/12/05 00:46:09	1.71
+++ ELexer.java	2001/12/06 06:25:07	1.72
@@ -28,6 +28,7 @@
 import org.quasiliteral.astro.AstroTag;
 import org.quasiliteral.astro.AstroBuilder;
 import org.quasiliteral.astro.ASTBuilder;
+import org.quasiliteral.astro.Astro;
 import org.quasiliteral.syntax.BaseLexer;
 import org.quasiliteral.syntax.FileFeeder;
 import org.quasiliteral.syntax.LineFeeder;
@@ -99,15 +100,15 @@
     /**
      * @return :Leaf (see {@link AstroBuilder}
      */
-    public Object nextToken() throws IOException, SyntaxException {
-        Object result;
+    public Astro nextToken() throws IOException, SyntaxException {
+        Astro result;
         try {
             result = getNextToken();
         } finally {
             myOptStartPos = -1;
             myOptStartText = null;
         }
-        if (EParser.isContinuer(myBuilder.getCodeOfLeaf(result))) {
+        if (EParser.isContinuer(result.getOptTagCode())) {
             return continuer(result);
         } else {
             return result;
@@ -117,7 +118,7 @@
     /**
      * Separated out for use by '>'
      */
-    protected Object continuer(Object result) throws IOException {
+    private Astro continuer(Astro result) throws IOException {
         if (isWhite(myPos, myLData.length)) {
             myContinueFlag = true;
             skipLine();
@@ -128,7 +129,7 @@
     /**
      *
      */
-    protected Object getNextToken() throws IOException, SyntaxException {
+    protected Astro getNextToken() throws IOException, SyntaxException {
         if (myDelayedNextChar) {
             nextChar();
             myDelayedNextChar = false;
@@ -150,7 +151,7 @@
                 {
                     char c = (char)myChar;
                     nextChar();
-                    return leafTag(c, endToken());
+                    return leafTag((short)c, endToken());
                 }
             case EOFCHAR:
                 {
@@ -210,7 +211,7 @@
                         myIndenter.pop('$', name);
                         return composite(EParser.DollarIdent, key, name);
                     }
-                    return leafTag('$', endToken());
+                    return leafTag((short)'$', endToken());
                 }
             case '@':
                 {
@@ -244,7 +245,7 @@
                         myIndenter.pop('@', name);
                         return composite(EParser.AtIdent, key, name);
                     }
-                    return leafTag('@', endToken());
+                    return leafTag((short)'@', endToken());
                 }
             case '.':
                 {
@@ -257,7 +258,7 @@
                         }
                         return leafTag(EParser.OpThru, endToken());
                     }
-                    return leafTag('.', endToken());
+                    return leafTag((short)'.', endToken());
                 }
             case '^':
                 {
@@ -266,7 +267,7 @@
                         nextChar();
                         return leafTag(EParser.OpAssXor, endToken());
                     }
-                    return leafTag('^', endToken());
+                    return leafTag((short)'^', endToken());
                 }
             case '+':
                 {
@@ -279,7 +280,7 @@
                         syntaxError("token \"++\" is reserved");
                         return null; //keep compiler happy
                     }
-                    return leafTag('+', endToken());
+                    return leafTag((short)'+', endToken());
                 }
             case '-':
                 {
@@ -295,7 +296,7 @@
                         syntaxError("token \"--\" is reserved");
                         return null; //keep compiler happy
                     }
-                    return leafTag('-', endToken());
+                    return leafTag((short)'-', endToken());
                 }
             case ':':
                 {
@@ -307,7 +308,7 @@
                         nextChar();
                         return leafTag(EParser.Audit, endToken());
                     }
-                    return leafTag(':', endToken());
+                    return leafTag((short)':', endToken());
                 }
             case '<':
                 {
@@ -335,12 +336,12 @@
                         }
                         return leafTag(EParser.OpAsl, endToken());
                     } else if (isIdentifierStart((char)myChar)) {
-                        Object optResult = optUri();
+                        Astro optResult = optUri();
                         if (null != optResult) {
                             return optResult;
                         }
                     }
-                    return leafTag('<', endToken());
+                    return leafTag((short)'<', endToken());
                 }
             case '>':
                 {
@@ -357,7 +358,7 @@
                         return leafTag(EParser.OpAsr, endToken());
                     }
                     Twine closer = endToken();
-                    Object result = leafTag('>', closer);
+                    Astro result = leafTag((short)'>', closer);
                     if (myIndenter.getCloser() == '>') {
                         myIndenter.pop('>', closer);
                         return result;
@@ -388,7 +389,7 @@
                         syntaxError("'/*..*/' comments are reserved. " +
                                     "Use '#' or '//' on each line instead");
                     }
-                    return leafTag('*', endToken());
+                    return leafTag((short)'*', endToken());
                 }
             case '/':
                 {
@@ -405,7 +406,7 @@
                         syntaxError("'/*..*/' comments are reserved. " +
                                     "Use '#' or '//' on each line instead");
                     }
-                    return leafTag('/', endToken());
+                    return leafTag((short)'/', endToken());
                 }
             case '#':
                 {
@@ -427,8 +428,8 @@
                         myContinueFlag = true;
                         skipLine();
                         stopToken();
-                        Object result = getNextToken();
-                        if (myBuilder.getCodeOfLeaf(result) ==
+                        Astro result = getNextToken();
+                        if (result.getOptTagCode() ==
                           EParser.EOFTOK) {
                             needMore("continued line");
                             return null; //make compiler happy
@@ -455,7 +456,7 @@
                         nextChar();
                         return leafTag(EParser.OpAssRemdr, endToken());
                     }
-                    return leafTag('%', endToken());
+                    return leafTag((short)'%', endToken());
                 }
             case '!':
                 {
@@ -467,7 +468,7 @@
                         nextChar();
                         return leafTag(EParser.MisMatch, endToken());
                     }
-                    return leafTag('!', endToken());
+                    return leafTag((short)'!', endToken());
                 }
             case '=':
                 {
@@ -499,7 +500,7 @@
                         nextChar();
                         return leafTag(EParser.OpButNot, endToken());
                     }
-                    return leafTag('&', endToken());
+                    return leafTag((short)'&', endToken());
                 }
             case '|':
                 {
@@ -511,7 +512,7 @@
                         nextChar();
                         return leafTag(EParser.OpAssOr, endToken());
                     }
-                    return leafTag('|', endToken());
+                    return leafTag((short)'|', endToken());
                 }
             case '\'':
                 {
@@ -580,20 +581,20 @@
      * Note that E keywords are case insensitive, so 'name' is first
      * toLowerCase()d.
      */
-    private int optKeywordType(String name) {
+    private short optKeywordType(String name) {
         name = name.toLowerCase();
         AstroTag optTag = myBuilder.getSchema().getOptTagForName(name);
         if (null == optTag) {
             return -1;
         } else {
-            return optTag.getOptTypeCode();
+            return optTag.getOptTagCode();
         }
     }
 
     /**
      * Called with myChar as the first character of the identifier.
      */
-    protected Object identifier() throws IOException, SyntaxException {
+    protected Astro identifier() throws IOException, SyntaxException {
         do {
             nextChar();
         } while (myChar != EOFCHAR && isIdentifierPart((char)myChar));
@@ -614,7 +615,7 @@
             }
         }
         Twine source = endToken();
-        int ttype = optKeywordType(source.bare());
+        short ttype = optKeywordType(source.bare());
         if (-1 == ttype) {
             return composite(EParser.ID, source.bare(), source);
         } else {
@@ -628,7 +629,7 @@
      * source, we need four ttypes rather than the current two: QuasiOpen
      * and QuasiClose.
      */
-    private Object quasiPart() throws IOException, SyntaxException {
+    private Astro quasiPart() throws IOException, SyntaxException {
         StringBuffer buf = new StringBuffer();
         while (true) {
             while (QUASI_ENDER.indexOf(myChar) == -1) {
@@ -696,7 +697,7 @@
      * is not immediately followed by a ":", return null and cause no side
      * effects -- in particular, do not effect the current position.
      */
-    private Object optUri() throws IOException, SyntaxException {
+    private Astro optUri() throws IOException, SyntaxException {
         int len = myLData.length;
         int pos = myPos + 1;
         while (pos < len && isIdentifierPart(myLData[pos])) {
@@ -763,17 +764,17 @@
         ELexer lex = new ELexer(lr, false, false);
         while (true) {
             try {
-                Object t;
+                Astro t;
                 do {
                     t = lex.nextToken();
                     //XXX should print t as a Functor.
                     stdout.println(t);
-                    if (lex.getCodeOfLeaf(t) == EParser.EOL) {
+                    if (t.getOptTagCode() == EParser.EOL) {
                         stdout.print("stack: ",
                                      lex.myIndenter.toString(),
                                      "\n");
                     }
-                } while (lex.getCodeOfLeaf(t) != EParser.EOFTOK);
+                } while (t.getOptTagCode() != EParser.EOFTOK);
                 return;
             } catch (SyntaxException sex) {
                 TextWriter err = new TextWriter(PrintStreamWriter.err(),



1.109     +8 -8      e/src/jsrc/org/erights/e/elang/syntax/EParser.java

Index: EParser.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elang/syntax/EParser.java,v
retrieving revision 1.108
retrieving revision 1.109
diff -u -r1.108 -r1.109
--- EParser.java	2001/12/05 00:46:09	1.108
+++ EParser.java	2001/12/06 06:25:07	1.109
@@ -1146,7 +1146,7 @@
 static public final StaticMaker EParserMaker =
     StaticMaker.make(EParser.class);
 
-/** 
+/**
  * caches previous simple parses (as is used for quasi-parsing)
  */
 static private IdentityCacheTable OurCache =
@@ -1155,7 +1155,7 @@
 /**
  *
  */
-static private final ConstMap DefaultProps = 
+static private final ConstMap DefaultProps =
   ConstMap.fromProperties(System.getProperties());
 
 
@@ -1163,7 +1163,7 @@
 /** contains all the tokens after yylval */
 private ELexer myLexer;
 
-/** 
+/**
  * Do we escape after parsing only one expression, or do we parse the
  * entire input?
  */
@@ -1265,7 +1265,7 @@
 
 /**
  * If the input is empty, returns the null expression e`null`, rather
- * than null. 
+ * than null.
  */
 public ENode parse() {
     ENode result = optParse();
@@ -1605,7 +1605,7 @@
 /**
  * These are the tokens that may appear at the end of a line, in which
  * case the next line is a (to be indented) continuation of the
- * expression. 
+ * expression.
  * <p>
  * Note that &gt; isn't on the list because of its role in closing a
  * calculated URI expression.
@@ -1703,7 +1703,7 @@
 //###############################################################
 // method: yyparse : parse input and execute indicated items
 //###############################################################
-int yyparse() 
+int yyparse()
 {
 int yyn;       //next next thing to do
 int yym;       //
@@ -1719,7 +1719,7 @@
   while (true) //until parsing is done, either correctly, or w/error
     {
     doaction=true;
-    if (yydebug) debug("loop"); 
+    if (yydebug) debug("loop");
     //#### NEXT ACTION (from reduction table)
     for (yyn=yydefred[yystate];yyn==0;yyn=yydefred[yystate])
       {
@@ -2660,7 +2660,7 @@
 break;
 case 260:
 //#line 977 "e.y"
-{ yyval = ((AstroToken)val_peek(0)).getData(); }
+{ yyval = ((AstroToken)val_peek(0)).getOptTokenData(); }
 break;
 case 261:
 //#line 978 "e.y"



1.63      +19 -0     e/src/jsrc/org/erights/e/elib/prim/E.java

Index: E.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/prim/E.java,v
retrieving revision 1.62
retrieving revision 1.63
diff -u -r1.62 -r1.63
--- E.java	2001/12/02 06:01:45	1.62
+++ E.java	2001/12/06 06:25:08	1.63
@@ -589,6 +589,7 @@
         if (cond) {
             return;
         }
+        //****** This is a good place to breakpoint *******
         Thunk optThunk = null;
         Ejector ej = new Ejector();
         try {
@@ -642,5 +643,23 @@
         require(false, E.call(E.call(prob0, "add", prob1),
                               "add",
                               prob2));
+    }
+
+    /**
+     * If cond isn't true, then 'require(false, prob0 + prob1 + prob2)'
+     */
+    static public void require(boolean cond,
+                               Object prob0,
+                               Object prob1,
+                               Object prob2,
+                               Object prob3) {
+        if (cond) {
+            return;
+        }
+        require(false, E.call(E.call(E.call(prob0, "add", prob1),
+                                     "add",
+                                     prob2),
+                              "add",
+                              prob3));
     }
 }



1.30      +12 -4     e/src/jsrc/org/erights/e/elib/tables/FlexMap.java

Index: FlexMap.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/tables/FlexMap.java,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -r1.29 -r1.30
--- FlexMap.java	2001/12/02 06:01:47	1.29
+++ FlexMap.java	2001/12/06 06:25:08	1.30
@@ -224,18 +224,26 @@
     }
 
     /**
-     *
+     * @see #interning(Class, int)
      */
     static public FlexMap interning(Class valType) {
-        //XXX should use an interning column
         return new FlexMapImpl(String.class, valType);
     }
 
     /**
-     *
+     * The resulting table should optimize for the assumption that keys are
+     * typically interned, but should work regardless.
+     * <p>
+     * A good strategy would be to use an IdentityKeyColumn internally, and
+     * first try looking up the presented key by identity.  If this fails,
+     * intern the key and try again.  Only interned keys would be stored.
+     * XXX We currently don't do any such optimization.
+     * <p>
+     * Were we to do this optimization, the interned keys may not ever be
+     * garbage collected.  One would hope that Java's interning table were
+     * weak, but no where does it state this in the spec.
      */
     static public FlexMap interning(Class valType, int capacity) {
-        //XXX should use an interning column
         return new FlexMapImpl(String.class, valType, capacity);
     }
 



1.2       +49 -44    e/src/jsrc/org/quasiliteral/astro/ASTBuilder.java

Index: ASTBuilder.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/quasiliteral/astro/ASTBuilder.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ASTBuilder.java	2001/12/05 00:46:11	1.1
+++ ASTBuilder.java	2001/12/06 06:25:08	1.2
@@ -7,13 +7,13 @@
 
 /**
  * The default implementation (and default superclass) for implementing
- * AstroBuilder simply, for building Astro-trees with AstroToken leaves.
+ * AstroBuilder simply, for building AstroAST-trees with AstroToken leaves.
  * <p>
  * The type parameterization of AstroBuilder is: <pre>
  *     Leaf is AstroToken
- *     Node is Astro
- *     Arg is Astro
- *     Args is null (for empty list) or Astro (for it and its siblings).
+ *     Node is AstroAST
+ *     Arg is AstroAST
+ *     Args is null (for empty list) or AstroAST (for it and its siblings).
  * </pre>
  *
  * @author <a href="mailto:markm@caplet.com">Mark Miller</a>
@@ -36,7 +36,7 @@
      *
      */
     public String toString() {
-        return "<building ASTs for " + mySchema.getName() + ">";
+        return "<building ASTs for " + mySchema.getSchemaName() + ">";
     }
 
     /**
@@ -49,8 +49,8 @@
     /**
      * @return :AstroToken
      */
-    public Object leafTag(int typeCode, Twine source) {
-        return new AstroToken(mySchema.getTagForCode(typeCode), null, source);
+    public Astro leafTag(AstroTag tag, Twine source) {
+        return new AstroToken(tag, null, source);
     }
 
     /**
@@ -58,8 +58,10 @@
      * @param source
      * @return :AstroToken
      */
-    public Object leafData(Object data, Twine source) {
-        return new AstroToken(mySchema.getLiteralDataTag(data), data, source);
+    public Astro leafData(Object data, Twine source) {
+        return new AstroToken(mySchema.getTypeTag(data.getClass()),
+                              data,
+                              source);
     }
 
     /**
@@ -68,38 +70,31 @@
      * @param data Nust not be null
      * @return :AstroToken
      */
-    public Object composite(int typeCode, Object data, Twine source) {
-        return new AstroToken(mySchema.getTagForCode(typeCode), data, source);
+    public Astro composite(AstroTag tag, Object data, Twine source) {
+        return new AstroToken(tag, data, source);
     }
 
     /**
-     * @param leaf :AstroToken
+     * @param func :(AstroToken | AstroAST)
+     * @return :AstroAST
      */
-    public int getCodeOfLeaf(Object leaf) {
-        return ((AstroToken)leaf).getType();
-    }
-
-    /**
-     * @param func :(AstroToken | Astro)
-     * @return :Astro
-     */
-    public Object node(Object func) {
-        if (func instanceof Astro) {
-            return func;
+    public Astro node(Astro leaf) {
+        if (leaf instanceof AstroAST) {
+            return leaf;
         }
-        return new Astro((AstroToken)func);
+        return new AstroAST((AstroToken)leaf);
     }
 
     /**
      * @param func :AstroToken
-     * @param args :(Astro | null)
-     * @return :Astro
+     * @param args :(AstroAST | null)
+     * @return :AstroAST
      */
-    public Object node(Object func, Object args) {
-        AstroToken funcToken = (AstroToken)func;
-        Astro optArgs = (Astro)args;
-        Astro result = new Astro(funcToken);
-        for (; null != optArgs; optArgs = (Astro)optArgs.getNextSibling()) {
+    public Astro node(Astro leaf, Object args) {
+        AstroToken funcToken = (AstroToken)leaf;
+        AstroAST optArgs = (AstroAST)args;
+        AstroAST result = new AstroAST(funcToken);
+        for (; null != optArgs; optArgs = (AstroAST)optArgs.getNextSibling()) {
             result.addChild(optArgs);
         }
         return result;
@@ -115,11 +110,11 @@
     /**
      * Returns 'first' after severing its nest sibling pointer
      *
-     * @param first :Astro
-     * @return :Astro
+     * @param first :AstroAST
+     * @return :AstroAST
      */
-    public Object argList(Object first) {
-        Astro result = (Astro)first;
+    public Object argList(AstroArg first) {
+        AstroAST result = (AstroAST)first;
         result.setNextSibling(null);
         return result;
     }
@@ -128,25 +123,35 @@
      * Modifies the last sibling in 'list' to be 'next', which is modified to
      * not have any further siblings.
      *
-     * @param list :(Astro | null)
-     * @param next :Astro
-     * @return :Astro
-     */
-    public Object argList(Object list, Object next) {
-        Astro optList = (Astro)list;
-        Astro nextNode = (Astro)next;
+     * @param list :(AstroAST | null)
+     * @param next :AstroAST
+     * @return :AstroAST
+     */
+    public Object argList(Object list, AstroArg next) {
+        AstroAST optList = (AstroAST)list;
+        AstroAST nextNode = (AstroAST)next;
         nextNode.setNextSibling(null);
         if (null == optList) {
             return next;
         }
-        Astro sib = optList;
+        AstroAST sib = optList;
         while (true) {
-            Astro optNextSib = (Astro)sib.getNextSibling();
+            AstroAST optNextSib = (AstroAST)sib.getNextSibling();
             if (null == optNextSib) {
                 sib.setNextSibling(nextNode);
                 return optList;
             }
             sib = optNextSib;
         }
+    }
+
+    /**
+     * Just an identity function on AstroASTs
+     *
+     * @param node :AstroAST
+     * @return :AstroAST
+     */
+    public AstroArg arg(Astro node) {
+        return (AstroAST)node;
     }
 }



1.7       +82 -216   e/src/jsrc/org/quasiliteral/astro/Astro.java

Index: Astro.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/quasiliteral/astro/Astro.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- Astro.java	2001/12/05 00:46:11	1.6
+++ Astro.java	2001/12/06 06:25:08	1.7
@@ -1,231 +1,97 @@
 package org.quasiliteral.astro;
 
-import antlr.BaseAST;
-import antlr.CommonToken;
-import antlr.Token;
-import antlr.collections.AST;
+import org.erights.e.elib.tables.ConstList;
 import org.erights.e.elib.tables.Twine;
 
+//This file is hereby placed in the public domain
+
 /**
- * AST node implementation which stores tokens explicitly.
+ * The nodes of the kind of tree made by an {@link AstroBuilder}.
  * <p>
- * This is handy if you'd rather derive information from tokens on an
- * as-needed basis instead of snarfing data from a token as an AST
- * is being built.
+ * A leaf node is simply an Astro with no arguments.
  * <p>
- * In keeping with the nature of Antlr ASTs, Astros are mutable.  The
- * corresponding immutable, Persistent, & PassByCopy type is the
- * {@link org.quasiliteral.term.Term}.
+ * A particular AstroBuilder will make Astros of some particular kind.  For
+ * example, an {@link ASTBuilder} makes Antlr ASTs, a TermBuilder builds a
+ * Term tree, and a QuasiTermBuilder builds a QuasiTerm tree.
  *
- * @author <a href="mailto:markm@caplet.com">Mark S Miller</a>
- * @author Based on Danfuzz Bornstein's TokenAST
+ * @author <a href="mailto:markm@caplet.com">Mark Miller</a>
  */
-public class Astro extends BaseAST {
+public interface Astro {
+
+    /**
+     * Builds an Astro tree like this one, but the kind of Astro that's made
+     * by this builder.
+     * <p>
+     * Pattern-wise, the builder functions here as both as a factory, and
+     * sort-of as a visitor.  It's not quite a visitor, in that it only sees
+     * the tree in bottom-up order.
+     */
+    Astro build(AstroBuilder builder);
+
+    /**
+     * Represents the token-type of the functor.
+     */
+    AstroTag getTag();
+
+    /**
+     * Equivalent to 'getTag().getOptTypeCode()'
+     */
+    short getOptTagCode();
+
+    /**
+     * If this Astro represents a literal-data token, then this is
+     * the data, and getTag() must represent the canonical corresponding
+     * token-type for this kind of data in this schema.
+     * <p>
+     * If the getTag() has no schema, then its getTagName() must be the
+     * corresponding token-type name.
+     */
+    Object getOptData();
 
     /**
-     *
+     * Equivalent to either 'getOptData()' or, if that's null, to
+     * 'getArgs()[0] getOptData()'.
+     * <p>
+     * This exists as an optimization for composite Tokens, which act like
+     * 1-argument Astros, where the 1-argument is a data argument.  This
+     * operation allows us to avoid creating a singleton argument list just
+     * to access this data.
+     */
+    Object getOptTokenData();
+
+    /**
+     * What source text was originally lexed or parsed to produce this token?
+     * <p>
+     * The source-span annotations on the text are normally the significant
+     * part, not the text itself.  Absence of source information is indicated
+     * with an empty string, rather than null.
+     */
+    Twine getSource();
+
+    /**
+     * @return :(ConstList of(AstroArg)); In most domains, AstroArg is the
+     * same as Astro, so this usually returns (ConstList of(Astro)).
      */
-    private Token myOptToken;
+    ConstList getArgs();
 
     /**
-     * Construct an instance which (at least initially) is not associated
-     * with a token.
-     */
-    public Astro() {
-        myOptToken = null;
-    }
-
-    /**
-     * Construct an instance which is associated with the given token.
-     *
-     * @param optToken The (optional) token to associate this instance with
-     */
-    public Astro(Token optToken) {
-        initialize(optToken);
-    }
-
-    /**
-     *
-     */
-    public String toString() {
-        return "" + myOptToken;
-    }
-
-    /**
-     * Builds an equivalent of this AST using the building methods of
-     * 'builder'.
-     * <p>
-     * Pattern-wise, the schema functions here as both a visitor and as a
-     * factory.
-     *
-     * @return :Node
-     */
-    public Object build(AstroBuilder builder) {
-        Object func = AstroToken.build(myOptToken, builder);
-        Astro optSub = (Astro)getFirstChild();
-        if (null == optSub) {
-            //This case is broken out in order to allow 'func' to be a Node
-            //rather than a Leaf.  This would happen is myOptToken is
-            //a composite.
-            return builder.node(func);
-        }
-        Object args = builder.argList();
-        for (; null != optSub; optSub = (Astro)optSub.getNextSibling()) {
-            args = builder.argList(args, optSub.build(builder));
-        }
-        return builder.node(func, args);
-    }
-
-    /**
-     * Since not all {@link AST}s are Astros, this static method
-     * provides the equivalent of the build/1 instance method for ASTs in
-     * general.
-     * <p>
-     * In the understanding of non-Astro ASTs used here, their functor is
-     * only according to the AST's type code, for the tag, and the AST's text,
-     * for the source.
-     * <p>
-     * XXX This should probably be made into a sugar-instance-method of AST.
-     */
-    static public Object build(AST self, AstroBuilder builder) {
-        if (self instanceof Astro) {
-            return ((Astro)self).build(builder);
-        } else {
-            Object func = builder.leafTag(self.getType(),
-                                          Twine.fromString(self.getText()));
-            AST optSub = self.getFirstChild();
-            if (null == optSub) {
-                //See comment in build/1 above
-                return builder.node(func);
-            }
-            Object args = builder.argList();
-            for (; null != optSub; optSub = optSub.getNextSibling()) {
-
-                args = builder.argList(args, build(optSub, builder));
-            }
-            return builder.node(func, args);
-        }
-    }
-
-    /**
-     * Get the token text for this instance. If there is no token associated
-     * with this instance, then this returns the empty string
-     * (<code>""</code>), not <code>null</code>.
-     *
-     * @return non-null; the token text
-     */
-    public String getText() {
-        if (myOptToken == null) {
-            return "";
-        } else {
-            return myOptToken.getText();
-        }
-    }
-
-    /**
-     * Get the token type for this instance. If there is no token associated
-     * with this instance, then this returns {@link Token#INVALID_TYPE}.
-     *
-     * @return the token type
-     */
-    public int getType() {
-        if (myOptToken == null) {
-            return Token.INVALID_TYPE;
-        } else {
-            return myOptToken.getType();
-        }
-    }
-
-    /**
-     * Get the token associated with this instance. If there is no token
-     * associated with this instance, then this returns <code>null</code>.
-     *
-     * @return The token associated with this instance, or <code>mull</code>
-     *         if there is no associated token
-     */
-    public Token getOptToken() {
-        return myOptToken;
-    }
-
-    /**
-     * Set the token associated with this instance.
-     *
-     * @param optToken The new token (or null) to associate with this
-     *                 instance.
-     */
-    public void setOptToken(Token optToken) {
-        myOptToken = optToken;
-    }
-
-    /**
-     * Initialize this instance with the given token.
-     *
-     * @param optToken the token to associate with this instance
-     */
-    public void initialize(Token optToken) {
-        myOptToken = optToken;
-    }
-
-    /**
-     * Initialize this instance with the given token type and text.
-     * This will construct a new {@link CommonToken} with the given
-     * parameters and associate this instance with it.
-     *
-     * @param type the token type
-     * @param optText The token text, or null
-     */
-    public void initialize(int type, String optText) {
-        initialize(new CommonToken(type, optText));
-    }
-
-    /**
-     * Initialize this instance based on the given {@link AST}.
-     * If the given <code>AST</code> is in fact an instance of
-     * <code>Astro</code>, then this instance will be initialized
-     * to point at the same token as the given one. If not, then this
-     * instance will be initialized with the same token type and text
-     * as the given one.
-     *
-     * @param ast non-null; the <code>AST</code> to base this instance on
-     */
-    public void initialize(AST ast) {
-        if (ast instanceof Astro) {
-            initialize(((Astro)ast).getOptToken());
-        } else {
-            initialize(ast.getType(), ast.getText());
-        }
-    }
-
-    /**
-     * Set the token text for this node. If this instance is already
-     * associated with a token, then that token is destructively modified
-     * by this operation. If not, then a new token is constructed with
-     * the type {@link Token#INVALID_TYPE} and the given text.
-     *
-     * @param text the new token text
-     */
-    public void setText(String text) {
-        if (myOptToken == null) {
-            initialize(Token.INVALID_TYPE, text);
-        } else {
-            myOptToken.setText(text);
-        }
-    }
-
-    /**
-     * Set the token type for this node. If this instance is already
-     * associated with a token, then that token is destructively modified
-     * by this operation. If not, then a new token is constructed with
-     * the given type and an empty (<code>""</code>, not <code>null</code>)
-     * text string.
-     *
-     * @param type the new token type
-     */
-    public void setType(int type) {
-        if (myOptToken == null) {
-            initialize(type, "");
-        } else {
-            myOptToken.setType(type);
-        }
-    }
+     * An Astro just like this one, but without any arguments, which is
+     * therefore a leaf (and so may be a Token).
+     * <p>
+     * Even in the mutable AST domain, if this Astro has arguments,
+     * 'withoutArgs()' makes a copy rather than modifying this Astro in place.
+     */
+    Astro withoutArgs();
+
+    /**
+     * Given that this Astro is a leaf (has no arguments), this returns an
+     * Astro just like it but with these arguments.
+     * <p>
+     * Even in the mutable AST domain, if 'args' is non-empty,
+     * 'withArgs(..)' makes a copy rather than modifying this Astro in place.
+     * <p>
+     * If this Astro is not a leaf, this throws an exception even if 'args' is
+     * empty.
+     */
+    Astro withArgs(ConstList args);
 }



1.2       +49 -66    e/src/jsrc/org/quasiliteral/astro/AstroBuilder.java

Index: AstroBuilder.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/quasiliteral/astro/AstroBuilder.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- AstroBuilder.java	2001/12/05 00:46:11	1.1
+++ AstroBuilder.java	2001/12/06 06:25:08	1.2
@@ -7,24 +7,14 @@
 //This file is hereby placed in the public domain
 
 /**
- * Used to describe an Antlr grammar, and to build a tree that could represent
- * the results of parsing such a grammar.
+ * Used to build an Astro tree -- a tree that could represent the results of
+ * parsing a string according to a grammar.
  * <p>
- * Several arguments and return types are 'Object' below because the actual
- * types are to be determined by the implementors of AstroBuilder.  However,
- * these choices need to be consistent.  We express the required consistency
- * using pretend parameterized types encoded in the javadoc comments.
- * Concrete subclasses of AstroBuilder should say what concrete types they use
- * for these parameterized types.
- * <p>
- * The pretend parameterized types are: <pre>
- *     Leaf -- Leaves of the tree, representing tokens of the grammar.
- *     Node -- Lnternal nodes of the tree, looks like application of a Leaf
- *             as an functor to Args.
- *     Arg -- An individual argument in a list of arguments.  Typically the
- *            same as Node, but not always.  See QuasiTermBuilder.
- *     Args -- Represents a list of Arg.
- * </pre>
+ * Several arguments or return values below are declared 'Object', but
+ * pseudo-declared ":Args" in the javadoc comments.  For these, the concrete
+ * type represents a list of {@link AstroArg}s, but the particular type used
+ * to represent the list depends on the type of builder, and should be
+ * documented in that builder's class comment.
  *
  * @author <a href="mailto:markm@caplet.com">Mark Miller</a>
  */
@@ -36,71 +26,57 @@
     AstroSchema getSchema();
 
     /**
-     * Makes a Leaf (eg, a Token or Functor) not representing literal data,
-     * but just a type code
-     *
-     * @return :Leaf
+     * Makes a leaf (eg, a Token) not representing literal data, but just a
+     * token type, as identified by 'tag'.
+     * <p>
+     * The tag of the returned Astro should be according to the schema of this
+     * builder, even though the argument tag may represent a type in a
+     * different schema.  In this case, the correspondence is by type name,
+     * rather than type code.
      */
-    Object leafTag(int typeCode, Twine source);
+    Astro leafTag(AstroTag tag, Twine source);
 
     /**
-     * Makes a leaf (eg, a Token or Functor) representing literal data
-     *
-     * @return :Leaf
+     * Makes a leaf (eg, a Token) representing literal data.
      */
-    Object leafData(Object data, Twine source);
+    Astro leafData(Object data, Twine source);
 
     /**
-     * Makes a Leaf or Node representing the given type code as parameterized
-     * by the given data.
-     * <p>
-     * Exists to support legacy usage of Antlr Tokens, and in order to allow
-     * lexers, which wish to emit composites, to still emit only leaves if
-     * allowed by the concrete builder.
+     * Makes an Astro whose tag is according to 'tag', and whose one argument
+     * is a leaf according to 'data'.
      * <p>
-     * Builders that don't allow composite leaves (like TermBuilder) should
-     * instead emit the equivalent of <pre>
+     * Is equivalent to:<pre>
      *     node(leafTag(typeCode, src),
-     *          argList(node(leafData(data, src), argList())))
+     *          argList(node(leafData(data, src))))
      * </pre>
-     *
-     * @return :(Leaf | Node)
-     */
-    Object composite(int typeCode, Object data, Twine source);
-
-    /**
-     * Given a Leaf that could have been produced by this builder, return its
-     * type code.
-     *
-     * @param leaf :Leaf
-     * @return The leaf's type code.
+     * Exists to support legacy usage of Antlr Tokens, and in order to allow
+     * lexers, which wish to emit composites, to still emit only Tokens if
+     * allowed by the concrete builder.
      */
-    int getCodeOfLeaf(Object leaf);
+    Astro composite(AstroTag tag, Object data, Twine source);
 
     /**
-     * Names an internal node (eg, an AST or Term), for which 'func' is the
-     * "label" and there are no arguments.
+     * At the Astro-level of semantics, for leaf Astros, this is an identity
+     * function.
      * <p>
-     * To accomodate composites, which may be Leaves in one representation and
-     * Nodes in another, 'node' accepts a 'func' that's a Node, in which case
-     * that Node is returned.
-     *
-     * @param func :(Leaf | Node)
-     * @return :Node
+     * However, for kinds of trees for which there are separate types to
+     * represent leaves and internal nodes (eg, Antlr's Tokens vs ASTs), if
+     * 'leaf' is of the leaf-specific type, this will convert to the node
+     * type.
      */
-    Object node(Object func);
+    Astro node(Astro leaf);
 
     /**
-     * Names an internal node (eg, an AST or Term), for which 'func' is the
-     * "label" and 'args' are the arguments.
+     * Returns an internal node (eg, an AST or Term), for which 'leaf' is the
+     * functor and 'args' are the arguments.
      * <p>
-     * May be destructive of 'args'.
+     * 'leaf' must be a leaf (have no arguments).
+     * <p>
+     * May be destructive of 'leaf' and 'args'.
      *
-     * @param func :Leaf
      * @param args :Args
-     * @return :Node
      */
-    Object node(Object func, Object args);
+    Astro node(Astro leaf, Object args);
 
     /**
      * The empty args list
@@ -116,10 +92,9 @@
      * <p>
      * Should be equivalent to 'argList(argList(), first)'
      *
-     * @param first :Arg
      * @return :Args
      */
-    Object argList(Object first);
+    Object argList(AstroArg first);
 
     /**
      * Extend args list with an additional term, like a backwards cons.
@@ -127,8 +102,16 @@
      * May be destructive of 'list' and 'next'
      *
      * @param list :Args
-     * @param next :Arg
      * @return :Args
+     */
+    Object argList(Object list, AstroArg next);
+
+    /**
+     * Converts an Astro into a corresponding AstroArgs.
+     * <p>
+     * When an Astro and an AstroArg are the same, this is an identity
+     * function.  Otherwise, this converts 'node' into an arg
+     * representing the singleton list consisting of just node.
      */
-    Object argList(Object list, Object next);
+    AstroArg arg(Astro node);
 }



1.5       +1 -1      e/src/jsrc/org/quasiliteral/astro/AstroLexerSharedInputState.java

Index: AstroLexerSharedInputState.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/quasiliteral/astro/AstroLexerSharedInputState.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- AstroLexerSharedInputState.java	2001/12/05 00:46:11	1.4
+++ AstroLexerSharedInputState.java	2001/12/06 06:25:08	1.5
@@ -76,7 +76,7 @@
     }
 
     /**
-     * Annotate an {@link ExtentToken} based on this instance. It sets
+     * Annotate an {@link AstroToken} based on this instance. It sets
      * the end position information as well as the file name.
      *
      * @param token non-null; the token to annotate



1.7       +14 -11    e/src/jsrc/org/quasiliteral/astro/AstroSchema.java

Index: AstroSchema.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/quasiliteral/astro/AstroSchema.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- AstroSchema.java	2001/12/05 00:46:11	1.6
+++ AstroSchema.java	2001/12/06 06:25:08	1.7
@@ -7,6 +7,9 @@
 
 /**
  * Used to describe an Antlr grammar.
+ * <p>
+ * Each token-type-code in an Antlr grammar corresponds to an
+ * {@link AstroTag}.
  *
  * @author <a href="mailto:markm@caplet.com">Mark Miller</a>
  */
@@ -16,31 +19,31 @@
      * The name of the language this is a Schema for, for diagnostic purposes
      * only.
      */
-    String getName();
+    String getSchemaName();
 
     /**
      * Returns the tag represented by this type code in the grammar described
      * by this schema, or null.
      */
-    AstroTag getOptTagForCode(int typeCode);
+    AstroTag getOptTagForCode(short tagCode);
 
     /**
      * Returns the tag represented by this type code in the grammar described
      * by this schema
      */
-    AstroTag getTagForCode(int typeCode);
+    AstroTag getTagForCode(short tagCode);
 
     /**
      * Returns the tag represented by this type name in the grammar described
      * by this schema, or null
      */
-    AstroTag getOptTagForName(String typeName);
+    AstroTag getOptTagForName(String tagName);
 
     /**
      * Returns the tag represented by this type name in the grammar described
      * by this schema
      */
-    AstroTag getTagForName(String typeName);
+    AstroTag getTagForName(String tagName);
 
     /**
      * Gets the tag for representing character literals.
@@ -71,14 +74,14 @@
     AstroTag getLiteralStringTag();
 
     /**
-     * Gets the tag for literally representing the provided data, or null if
-     * data is the wrong kind.
+     * Gets the tag for literally representing instances of clazz, or
+     * null if clazz is the wrong kind.
      */
-    AstroTag getOptDataTag(Object data);
+    AstroTag getOptTypeTag(Class clazz);
 
     /**
-     * Gets the tag for literally representing the provided data, or throws
-     * if data is the wrong kind.
+     * Gets the tag for literally representing instances of clazz, or
+     * throws if clazz is the wrong kind.
      */
-    AstroTag getLiteralDataTag(Object data);
+    AstroTag getTypeTag(Class clazz);
 }



1.4       +110 -28   e/src/jsrc/org/quasiliteral/astro/AstroTag.java

Index: AstroTag.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/quasiliteral/astro/AstroTag.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- AstroTag.java	2001/12/05 00:46:11	1.3
+++ AstroTag.java	2001/12/06 06:25:08	1.4
@@ -4,70 +4,113 @@
 import org.erights.e.elib.serial.PassByConstruction;
 import org.erights.e.elib.serial.Persistent;
 import org.erights.e.elib.tables.Twine;
+import org.erights.e.elib.prim.E;
+import antlr.Token;
 
+import java.math.BigInteger;
+
 //This file is hereby placed in the public domain
 
 /**
- * Represents both an {@link AstroToken}'s token-type (and enumerated int code
- * specific to a grammar), and a Functor's type=name (the name of that
- * enumerated code in that grammar).
+ * Represents both a grammar's tag-type (corresponds to the enumerated token
+ * type code specific to an Antlr grammar), and a corresponding tag name (the
+ * name of that enumerated code in that grammar).
  * <p>
  * The notion of "specific to a grammar" is here abstracted into the notion
- * of an {@link AstroSchema}, within which these type-code/type-names are
+ * of an {@link AstroSchema}, within which these tag-codes/tag-names are
  * defined, and that provides the means for translating between the two.
+ * <p>
+ * An AstroTag always has a tag-name, but not necessarily a tag-code or a
+ * schema.
  * <p>
- * AstroTags are AstroSchemas can be used to describe Antlr grammars that use
- * only ASTs and Tokens as well.
+ * To convert between Astro tag-codes and Antlr type-codes, a type code is a
+ * tag code +1.  This also results in the non-tag-code (-1) being converted
+ * to {@link Token#INVALID_TYPE}, which happens to be 0.
  *
  * @author <a href="mailto:markm@caplet.com">Mark Miller</a>
  */
 public class AstroTag implements PassByConstruction, Persistent {
 
     /**
-     * The enumerated type code, or Token.INVALID_TYPE.
+     * The type-code for use by Antlr, which is the tag-code +1.
+     * <p>
+     * If the tag-code is -1, the returned type code will be
+     * {@link Token#INVALID_TYPE}
      */
-    private final int myOptTypeCode;
+    static public int tagCode2typeCode(short tagCode) {
+        return tagCode +1;
+    }
 
     /**
-     * The name of the enumerated type code.
+     *
      */
-    private final Twine myTypeName;
+    static public short typeCode2tagCode(int typeCode) {
+        return (short)(typeCode -1);
+    }
 
     /**
-     * The schema of which this tag is a member, or null.
+     * @serial The enumerated tag code, or -1.
+     */
+    private final short myOptTagCode;
+
+    /**
+     * @serial The interned name of the enumerated tag code.
+     */
+    private final String myTagName;
+
+    /**
+     * @serial The schema of which this tag is a member, or null.
      */
     private final AstroSchema myOptSchema;
 
     /**
+     * @serial If this tag is a normal symbolic tag, this is null.  If it's
+     * a tag for a literal data type, this is the canonical class for that
+     * data type -- one of Character.class, BigInteger.class, Double.class,
+     * or Twine.class.
+     */
+    private final Class myOptDataType;
+
+    /**
      *
-     * @param optTypeCode The enumerated type code, or Token.INVALID_TYPE.
-     * @param typeName The name of the enumerated type code.
+     * @param optTagCode The enumerated tag code, or -1.
+     * @param tagName The name of the enumerated type code.
      * @param optSchema The schema of which this tag is a member, or null.
+     * @param optDataType Either null, or the kind of data labeled by this
+     *                    tag.
      */
-    public AstroTag(int optTypeCode, Twine typeName, AstroSchema optSchema) {
-        myOptTypeCode = optTypeCode;
-        myTypeName = typeName;
+    /*package*/ AstroTag(short optTagCode,
+                         String tagName,
+                         AstroSchema optSchema,
+                         Class optDataType) {
+        myOptTagCode = optTagCode;
+        myTagName = tagName.intern();
         myOptSchema = optSchema;
+        myOptDataType = optDataType;
+        if (null != optDataType) {
+            E.require(null != optSchema,
+                      "internal: Can't have a data type without a schema");
+        }
     }
 
     public String toString() {
-        return "<" + myTypeName +
+        return "<" + myTagName +
           (null == myOptSchema ? "" : (":" + myOptSchema)) +
           ">";
     }
 
     /**
-     * The enumerated type code, or Token.INVALID_TYPE.
+     * The enumerated tag code, or -1.
      */
-    public int getOptTypeCode() {
-        return myOptTypeCode;
+    public short getOptTagCode() {
+        return myOptTagCode;
     }
 
     /**
-     * The name of the enumerated type code.
+     * The interned name of the enumerated tag code.
      */
-    public Twine getTypeName() {
-        return myTypeName;
+    public String getTagName() {
+        return myTagName;
     }
 
     /**
@@ -78,17 +121,56 @@
     }
 
     /**
-     *
+     * Indicates the type of data literally represented by this tag.
+     * <p>
+     * If this tag is a normal symbolic tag, this is null.  If it's
+     * a tag for a literal data type, this is the canonical class for that
+     * data type -- one of Character.class, BigInteger.class, Double.class,
+     * or Twine.class.
+     */
+    public Class getOptDataType() {
+        return myOptDataType;
+    }
+
+    /**
+     * Is this the tag implied by the type of optData?
+     * <p>
+     * If optData is null, the answer is true.
+     */
+    public boolean isTagForData(Object optData) {
+        if (null == optData) {
+            return true;
+        }
+        if (null == myOptDataType) {
+            return false;
+        }
+        //Doesn't matter what schema we use, since we're just canonicalizing
+        //the data type.
+        AstroTag optDataTag =
+          BaseSchema.MINIMAL.getOptTypeTag(optData.getClass());
+        if (null == optDataTag) {
+            return false;
+        }
+        return myOptDataType == optDataTag.getOptDataType();
+    }
+
+    /**
+     * if they have the same schema, or if either of both has no,
+     * schema, then they are compared based on their typeNames.
+     * <p>
+     * Otherwise, they are incomparable.
      */
     public double compareTo(AstroTag other) {
         if (Ref.same(myOptSchema, other.myOptSchema) ||
           null == myOptSchema ||
           null == other.myOptSchema) {
-            //if they have the same schema, or if either of both has no,
-            //schema, then they are compared based on their typeNames.
-            return myTypeName.compareTo(other.myTypeName);
+            if (myTagName == other.myTagName) {
+                //since we know they're interned, it's worth doing this
+                //check before the general compareTo.
+                return 0.0;
+            }
+            return (double)myTagName.compareTo(other.myTagName);
         } else {
-            //otherwise, they are incomparable.
             return Double.NaN;
         }
     }



1.10      +62 -39    e/src/jsrc/org/quasiliteral/astro/AstroToken.java

Index: AstroToken.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/quasiliteral/astro/AstroToken.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- AstroToken.java	2001/12/03 03:30:55	1.9
+++ AstroToken.java	2001/12/06 06:25:08	1.10
@@ -4,6 +4,8 @@
 import org.erights.e.elib.base.SourceSpan;
 import org.erights.e.elib.prim.E;
 import org.erights.e.elib.tables.Twine;
+import org.erights.e.elib.tables.EmptyTwine;
+import org.erights.e.elib.tables.ConstList;
 
 /**
  * A Kind of Antlr {@link Token} that preserves all the information in a
@@ -16,7 +18,7 @@
  * @author <a href="mailto:markm@caplet.com">Mark S Miller</a>
  * @author Based on ValueExtentToken by Danfuzz Bornstein
  */
-public class AstroToken extends Token {
+public class AstroToken extends Token implements Astro, AstroArg {
 
     /**
      *
@@ -38,8 +40,8 @@
     /**
      * Construct an instance.
      * <p>
-     * The instance will be of type {@link #INVALID_TYPE}, and have empty
-     * (<code>""</code>, not <code>null</code>) source twine.
+     * The instance will have the tag code -1, and have empty (<code>""</code>,
+     * not <code>null</code>) source twine.
      */
     public AstroToken() {
         super();
@@ -58,39 +60,29 @@
      *               provide no info, use "" rather than null.
      */
     public AstroToken(AstroTag tag, Object optData, Twine source) {
-        super(tag.getOptTypeCode());
+        super(AstroTag.tagCode2typeCode(tag.getOptTagCode()));
         myOptTag = tag;
+        //XXX should promote optData to its canonical type if necessary
         myOptData = optData;
         setSource(source);
+        Class type = myOptTag.getOptDataType();
+        if (null != myOptData && null != type) {
+            E.require(myOptData.getClass() == type,
+            "Literal tag mismatch: ", tag, " vs ", optData.getClass());
+        }
     }
 
     /**
-     * Builds an equivalent of this token using the building methods of
-     * 'builder'.
-     * <p>
-     * Pattern-wise, the builder functions here as both a visitor and as a
-     * factory.
      *
-     * @return :(Leaf | Node), because a composite token will build using
-     *         {@link AstroBuilder#composite(int, Object, Twine)}
      */
-    public Object build(AstroBuilder builder) {
-        int code;
+    public Astro build(AstroBuilder builder) {
         AstroSchema schema = builder.getSchema();
-        if (null == myOptTag) {
-            code = getType();
-        } else {
-            //this case should be sped up to avoid the hash lookup in the
-            //typical case.
-            String name = myOptTag.getTypeName().bare();
-            code = schema.getTagForName(name).getOptTypeCode();
-        }
         if (null == myOptData) {
-            return builder.leafTag(code, myOptSource);
-        } else if (schema.getOptDataTag(myOptData).getOptTypeCode() == code) {
+            return builder.leafTag(getTag(), myOptSource);
+        } else if (getTag().isTagForData(myOptData)) {
             return builder.leafData(myOptData, myOptSource);
         } else {
-            return builder.composite(code, myOptData, myOptSource);
+            return builder.composite(getTag(), myOptData, myOptSource);
         }
     }
 
@@ -106,7 +98,7 @@
      *
      * @return :(Leaf | Node)
      */
-    static public Object build(Token self, AstroBuilder builder) {
+    static public Astro build(Token self, AstroBuilder builder) {
         if (self instanceof AstroToken) {
             return ((AstroToken)self).build(builder);
         } else {
@@ -116,7 +108,9 @@
                                              self.getColumn(),
                                              self.getLine(),
                                              self.getColumn());
-            return builder.leafTag(self.getType(),
+            short tagCode = AstroTag.typeCode2tagCode(self.getType());
+            AstroTag tag = builder.getSchema().getTagForCode(tagCode);
+            return builder.leafTag(tag,
                                    Twine.fromString(self.getText(), span));
         }
     }
@@ -124,18 +118,12 @@
     /**
      *
      */
-    public AstroTag getOptTag() {
+    public AstroTag getTag() {
+        E.require(null != myOptTag, "Tag must first be set: ", this);
         return myOptTag;
     }
 
     /**
-     *
-     */
-    public AstroSchema getOptSchema() {
-        return myOptTag.getOptSchema();
-    }
-
-    /**
      * For when the type-code is already set by generic Antlr code, while
      * Astro-specific knowledge of the schema comes along later.
      * <p>
@@ -145,7 +133,7 @@
     public void setSchema(AstroSchema schema) {
         E.require(null == myOptTag, "Tag already set");
         E.require(INVALID_TYPE != getType(), "Type-code not yet set");
-        myOptTag = schema.getTagForCode(getType());
+        myOptTag = schema.getTagForCode(getOptTagCode());
     }
 
     /**
@@ -156,18 +144,28 @@
         super.setType(t);
     }
 
+    public short getOptTagCode() {
+        return AstroTag.typeCode2tagCode(getType());
+    }
+
     /**
      * If this token represents literal data, return that data,
      * else null.
      */
     public Object getOptData() {
-        return myOptData;
+        if (getTag().isTagForData(myOptData)) {
+            return myOptData;
+        } else {
+            //the data will be in args[0].  Or it can be directly accessed
+            //with getArgData()
+            return null;
+        }
     }
 
     /**
      *
      */
-    public Object getData() {
+    public Object getOptTokenData() {
         E.require(null != myOptData, "No data");
         return myOptData;
     }
@@ -175,8 +173,12 @@
     /**
      *
      */
-    public Twine getOptSource() {
-        return myOptSource;
+    public Twine getSource() {
+        if (null == myOptSource) {
+            return EmptyTwine.THE_ONE;
+        } else {
+            return myOptSource;
+        }
     }
 
     /**
@@ -257,5 +259,26 @@
     public void setText(String s) {
         E.require(null == myOptSource, "Source already set");
         setSource(Twine.fromString(s));
+    }
+
+    /**
+     *
+     */
+    public ConstList getArgs() {
+        throw new RuntimeException("XXX not yet implemented");
+    }
+
+    /**
+     *
+     */
+    public Astro withoutArgs() {
+        throw new RuntimeException("XXX not yet implemented");
+    }
+
+    /**
+     *
+     */
+    public Astro withArgs(ConstList args) {
+        throw new RuntimeException("XXX not yet implemented");
     }
 }



1.7       +143 -92   e/src/jsrc/org/quasiliteral/astro/BaseSchema.java

Index: BaseSchema.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/quasiliteral/astro/BaseSchema.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- BaseSchema.java	2001/12/05 00:46:11	1.6
+++ BaseSchema.java	2001/12/06 06:25:08	1.7
@@ -13,202 +13,253 @@
 
 /**
  * The default implementation (and default superclass) for implementing
- * AstroSchema simply, starting with an array of type names.
+ * AstroSchema simply, starting with an array of tag names.
  *
  * @author <a href="mailto:markm@caplet.com">Mark Miller</a>
  */
 public class BaseSchema implements AstroSchema {
 
+    static private final String[] MinimalTagNames = {
+        "LiteralChar",
+        "LiteralInteger",
+        "LiteralFloat64",
+        "LiteralString"
+    };
+
     /**
+     *
+     */
+    static public final AstroSchema MINIMAL =
+      new BaseSchema("Minimal", ConstList.fromArray(MinimalTagNames));
+
+    /**
      * For diagnostic purposes only.
      */
-    private final String myName;
+    private final String mySchemaName;
 
     /**
-     *
+     * Indexed by tag (a short)
      */
-    private final AstroTag[] myByTypeCodes;
+    private final AstroTag[] myByTagCode;
 
     /**
      * String (not Twine) => AstroTag
      */
-    private final ConstMap myByTypeName;
+    private final ConstMap myByTagName;
 
     /**
      *
      */
-    private transient AstroTag myOptLiteralCharTag = null;
+    private AstroTag myLiteralCharTag;
 
     /**
      *
      */
-    private transient AstroTag myOptLiteralIntegerTag = null;
+    private AstroTag myLiteralIntegerTag;
 
     /**
      *
      */
-    private transient AstroTag myOptLiteralFloat64Tag = null;
+    private AstroTag myLiteralFloat64Tag;
 
     /**
      *
      */
-    private transient AstroTag myOptLiteralStringTag = null;
+    private AstroTag myLiteralStringTag;
 
     /**
+     * The literal tag names default to their canonical names
+     */
+    public BaseSchema(String schemaName, ConstList tagNames) {
+        this(schemaName,
+             tagNames,
+             "LiteralChar",
+             "LiteralInteger",
+             "LiteralFloat64",
+             "LiteralString");
+    }
+
+    /**
      *
      */
-    public BaseSchema(String name, ConstList typeNames) {
-        myName = name;
+    public BaseSchema(String schemaName,
+                      ConstList tagNames,
+                      String literalCharTagName,
+                      String literalIntegerTagName,
+                      String literalFloat64TagName,
+                      String literalStringTagName) {
+        mySchemaName = schemaName.intern();
 
         FlexList byCodes = FlexList.fromType(AstroTag.class,
-                                             typeNames.size());
-        FlexMap byNames = FlexMap.fromTypes(String.class,
-                                            AstroTag.class,
-                                            typeNames.size());
-        for (int code = 0; code < typeNames.size(); code++) {
-            Twine optTypeName = (Twine)E.as(typeNames.get(code), Twine.class);
-            if (null != optTypeName) {
-                AstroTag tag = new AstroTag(code, optTypeName, this);
-                byCodes.ensureSize(code);
-                byCodes.put(code, tag);
-                byNames.put(optTypeName.bare(), tag, true);
+                                             tagNames.size());
+        FlexMap byNames = FlexMap.interning(AstroTag.class,
+                                            tagNames.size());
+
+        literalCharTagName = literalCharTagName.intern();
+        literalIntegerTagName = literalIntegerTagName.intern();
+        literalFloat64TagName = literalFloat64TagName.intern();
+        literalStringTagName = literalStringTagName.intern();
+
+        for (short tagCode = 0; tagCode < tagNames.size(); tagCode++) {
+            String optTagName = (String)E.as(tagNames.get(tagCode),
+                                             String.class);
+            if (null != optTagName) {
+                optTagName = optTagName.intern();
+                AstroTag tag;
+
+                if (optTagName == literalCharTagName) {
+                    tag = new AstroTag(tagCode, optTagName, this,
+                                       Character.class);
+                    myLiteralCharTag = tag;
+                    literalCharTagName = null;
+
+                } else if (optTagName == literalIntegerTagName) {
+                    tag = new AstroTag(tagCode, optTagName, this,
+                                       BigInteger.class);
+                    myLiteralIntegerTag = tag;
+                    literalIntegerTagName = null;
+
+                } else if (optTagName == literalFloat64TagName) {
+                    tag = new AstroTag(tagCode, optTagName, this,
+                                       Double.class);
+                    myLiteralFloat64Tag = tag;
+                    literalFloat64TagName = null;
+
+                } else if (optTagName == literalStringTagName) {
+                    tag = new AstroTag(tagCode, optTagName, this,
+                                       Twine.class);
+                    myLiteralStringTag = tag;
+                    literalStringTagName = null;
+
+                } else {
+                    tag = new AstroTag(tagCode, optTagName, this,
+                                       null);
+                }
+                byCodes.ensureSize(tagCode);
+                byCodes.put(tagCode, tag);
+                byNames.put(optTagName, tag, true);
             }
         }
-        myByTypeCodes = (AstroTag[])byCodes.getArray(AstroTag.class);
-        myByTypeName = byNames.snapshot();
+        E.require(null == literalCharTagName &&
+                  null == literalIntegerTagName &&
+                  null == literalIntegerTagName &&
+                  null == literalIntegerTagName,
+                  "Unmatched literal name for: ", mySchemaName);
+        myByTagCode = (AstroTag[])byCodes.getArray(AstroTag.class);
+        myByTagName = byNames.snapshot();
     }
 
     /**
      *
      */
     public String toString() {
-        return "<Schema for " + myName + ">";
+        return "<Schema for " + mySchemaName + ">";
     }
 
     /**
      *
      */
-    public String getName() {
-        return myName;
+    public String getSchemaName() {
+        return mySchemaName;
     }
 
     /**
      *
      */
-    public AstroTag getOptTagForCode(int typeCode) {
-        AstroTag optResult = myByTypeCodes[typeCode];
-        return optResult;
+    public AstroTag getOptTagForCode(short optTagCode) {
+        if (-1 == optTagCode) {
+            return null;
+        } else {
+            return myByTagCode[optTagCode];
+        }
     }
 
     /**
      *
      */
-    public AstroTag getTagForCode(int typeCode) {
-        AstroTag optResult = myByTypeCodes[typeCode];
-        E.requireSI(null != optResult, "No tag for type code: ", typeCode);
+    public AstroTag getTagForCode(short tagCode) {
+        AstroTag optResult = getOptTagForCode(tagCode);
+        E.requireSI(null != optResult, "No tag for type code: ", tagCode);
         return optResult;
     }
 
     /**
      *
      */
-    public AstroTag getOptTagForName(String typeName) {
-        AstroTag optResult = (AstroTag)myByTypeName.get(typeName, null);
-        return optResult;
+    public AstroTag getOptTagForName(String tagName) {
+        return (AstroTag)myByTagName.get(tagName, null);
     }
 
     /**
      *
      */
-    public AstroTag getTagForName(String typeName) {
-        AstroTag optResult = (AstroTag)myByTypeName.get(typeName, null);
-        E.require(null != optResult, "No tag named: ", typeName);
+    public AstroTag getTagForName(String tagName) {
+        AstroTag optResult = getOptTagForName(tagName);
+        E.require(null != optResult, "No tag named: ", tagName);
         return optResult;
     }
 
     /**
-     * The default implementation provided here just gets the tag whose name
-     * is "LiteralChar".
-     * <p>
-     * May be overridden to describe a grammar with different conventions.
+     *
      */
     public AstroTag getLiteralCharTag() {
-        if (null == myOptLiteralCharTag) {
-            myOptLiteralCharTag = getTagForName("LiteralChar");
-        }
-        return myOptLiteralCharTag;
+        return myLiteralCharTag;
     }
 
     /**
-     * The default implementation provided here just gets the tag whose name
-     * is "LiteralInteger".
-     * <p>
-     * May be overridden to describe a grammar with different conventions.
+     *
      */
     public AstroTag getLiteralIntegerTag() {
-        if (null == myOptLiteralIntegerTag) {
-            myOptLiteralIntegerTag = getTagForName("LiteralInteger");
-        }
-        return myOptLiteralIntegerTag;
+        return myLiteralIntegerTag;
     }
 
     /**
-     * The default implementation provided here just gets the tag whose name
-     * is "LiteralFloat64".
-     * <p>
-     * May be overridden to describe a grammar with different conventions.
+     *
      */
     public AstroTag getLiteralFloat64Tag() {
-        if (null == myOptLiteralFloat64Tag) {
-            myOptLiteralFloat64Tag = getTagForName("LiteralFloat64");
-        }
-        return myOptLiteralFloat64Tag;
+        return myLiteralFloat64Tag;
     }
 
     /**
-     * The default implementation provided here just gets the tag whose name
-     * is "LiteralString".
-     * <p>
-     * May be overridden to describe a grammar with different conventions.
+     *
      */
     public AstroTag getLiteralStringTag() {
-        if (null == myOptLiteralStringTag) {
-            myOptLiteralStringTag = getTagForName("LiteralString");
-        }
-        return myOptLiteralStringTag;
+        return myLiteralStringTag;
     }
 
     /**
      *
      */
-    public AstroTag getOptDataTag(Object data) {
-        if (data instanceof Character) {
-            return getLiteralCharTag();
-
-        } else if (data instanceof Number) {
-            if (data instanceof Byte ||
-              data instanceof Short ||
-              data instanceof Integer ||
-              data instanceof Long ||
-              data instanceof BigInteger) {
-                return getLiteralIntegerTag();
-            } else if (data instanceof Float || data instanceof Double) {
-                return getLiteralFloat64Tag();
+    public AstroTag getOptTypeTag(Class clazz) {
+        if (Character.class == clazz) {
+            return myLiteralCharTag;
+        }
+        if (Number.class.isAssignableFrom(clazz)) {
+            if (Double.class == clazz || Float.class == clazz) {
+                return myLiteralFloat64Tag;
+            } else if (BigInteger.class == clazz ||
+              Byte.class == clazz ||
+              Short.class == clazz ||
+              Integer.class == clazz ||
+              Long.class == clazz) {
+                return myLiteralIntegerTag;
+            } else {
+                throw new RuntimeException("Unrecognized number type: " +
+                                           clazz);
             }
-
-        } else if (data instanceof String || data instanceof Twine) {
-            return getLiteralStringTag();
+        }
+        if (Twine.class == clazz || String.class == clazz) {
+            return myLiteralStringTag;
         }
-        //not representable as a literal
         return null;
     }
 
     /**
      *
      */
-    public AstroTag getLiteralDataTag(Object data) {
-        AstroTag result = getOptDataTag(data);
-        E.require(null != result, "Not a literal type: ", data.getClass());
-        return result;
+    public AstroTag getTypeTag(Class clazz) {
+        AstroTag optResult = getOptTypeTag(clazz);
+        E.require(null != optResult, "Unrecognized type: ", clazz);
+        return optResult;
     }
 }



1.1                  e/src/jsrc/org/quasiliteral/astro/AstroAST.java

Index: AstroAST.java
===================================================================
package org.quasiliteral.astro;

import antlr.BaseAST;
import antlr.CommonToken;
import antlr.Token;
import antlr.collections.AST;
import org.erights.e.elib.tables.Twine;
import org.erights.e.elib.tables.ConstList;

/**
 * AST node implementation which stores tokens explicitly.
 * <p>
 * This is handy if you'd rather derive information from tokens on an
 * as-needed basis instead of snarfing data from a token as an AST
 * is being built.
 * <p>
 * In keeping with the nature of Antlr ASTs, Astros are mutable.  The
 * corresponding immutable, Persistent, & PassByCopy type is the
 * {@link org.quasiliteral.term.Term}.
 *
 * @author <a href="mailto:markm@caplet.com">Mark S Miller</a>
 * @author Based on Danfuzz Bornstein's TokenAST
 */
public class AstroAST extends BaseAST implements Astro, AstroArg {

    /**
     *
     */
    private AstroToken myOptToken;

    /**
     * Construct an instance which (at least initially) is not associated
     * with a token.
     */
    public AstroAST() {
        myOptToken = null;
    }

    /**
     * Construct an instance which is associated with the given token.
     *
     * @param optToken :AstroToken The (optional) token to associate this
     *                 instance with
     */
    public AstroAST(Token optToken) {
        initialize(optToken);
    }

    /**
     *
     */
    public String toString() {
        return "" + myOptToken;
    }

    /**
     * Builds an equivalent of this AST using the building methods of
     * 'builder'.
     * <p>
     * Pattern-wise, the schema functions here as both a visitor and as a
     * factory.
     *
     * @return :Node
     */
    public Astro build(AstroBuilder builder) {
        Astro func = myOptToken.build(builder);
        AstroAST optSub = (AstroAST)getFirstChild();
        if (null == optSub) {
            //This case is broken out in order to allow 'func' to be a Node
            //rather than a Leaf.  This would happen is myOptToken is
            //a composite.
            return builder.node(func);
        }
        Object args = builder.argList();
        for (; null != optSub; optSub = (AstroAST)optSub.getNextSibling()) {
            args = builder.argList(args,
                                   builder.arg(optSub.build(builder)));
        }
        return builder.node(func, args);
    }

    /**
     * Since not all {@link AST}s are Astros, this static method
     * provides the equivalent of the build/1 instance method for ASTs in
     * general.
     * <p>
     * In the understanding of non-Astro ASTs used here, their functor is
     * only according to the AST's type code, for the tag, and the AST's text,
     * for the source.
     * <p>
     * XXX This should probably be made into a sugar-instance-method of AST.
     */
    static public Astro build(AST self, AstroBuilder builder) {
        if (self instanceof AstroAST) {
            return ((AstroAST)self).build(builder);
        } else {
            AstroSchema schema = builder.getSchema();
            short tagCode = AstroTag.typeCode2tagCode(self.getType());
            Astro func = builder.leafTag(schema.getOptTagForCode(tagCode),
                                         Twine.fromString(self.getText()));
            AST optSub = self.getFirstChild();
            if (null == optSub) {
                //See comment in build/1 above
                return builder.node(func);
            }
            Object args = builder.argList();
            for (; null != optSub; optSub = optSub.getNextSibling()) {

                args = builder.argList(args,
                                       builder.arg(build(optSub, builder)));
            }
            return builder.node(func, args);
        }
    }

    /**
     * Get the token text for this instance. If there is no token associated
     * with this instance, then this returns the empty string
     * (<code>""</code>), not <code>null</code>.
     *
     * @return non-null; the token text
     */
    public String getText() {
        if (myOptToken == null) {
            return "";
        } else {
            return myOptToken.getText();
        }
    }

    /**
     * Get the token type for this instance. If there is no token associated
     * with this instance, then this returns {@link Token#INVALID_TYPE}.
     *
     * @return the token type
     */
    public int getType() {
        if (myOptToken == null) {
            return Token.INVALID_TYPE;
        } else {
            return myOptToken.getType();
        }
    }

    /**
     * Get the token associated with this instance. If there is no token
     * associated with this instance, then this returns <code>null</code>.
     *
     * @return The token associated with this instance, or <code>mull</code>
     *         if there is no associated token
     */
    public AstroToken getOptToken() {
        return myOptToken;
    }

    /**
     * Set the token associated with this instance.
     *
     * @param optToken The new token (or null) to associate with this
     *                 instance.
     */
    public void setOptToken(AstroToken optToken) {
        myOptToken = optToken;
    }

    /**
     * Initialize this instance with the given token.
     *
     * @param optToken :AstroToken the token to associate with this instance
     */
    public void initialize(Token optToken) {
        myOptToken = (AstroToken)optToken;
    }

    /**
     * Initialize this instance with the given token type and text.
     * This will construct a new {@link CommonToken} with the given
     * parameters and associate this instance with it.
     *
     * @param type the token type
     * @param optText The token text, or null
     */
    public void initialize(int type, String optText) {
        initialize(new CommonToken(type, optText));
    }

    /**
     * Initialize this instance based on the given {@link AST}.
     * If the given <code>AST</code> is in fact an instance of
     * <code>AstroAST</code>, then this instance will be initialized
     * to point at the same token as the given one. If not, then this
     * instance will be initialized with the same token type and text
     * as the given one.
     *
     * @param ast non-null; the <code>AST</code> to base this instance on
     */
    public void initialize(AST ast) {
        if (ast instanceof AstroAST) {
            initialize(((AstroAST)ast).getOptToken());
        } else {
            initialize(ast.getType(), ast.getText());
        }
    }

    /**
     * Set the token text for this node. If this instance is already
     * associated with a token, then that token is destructively modified
     * by this operation. If not, then a new token is constructed with
     * the type {@link Token#INVALID_TYPE} and the given text.
     *
     * @param text the new token text
     */
    public void setText(String text) {
        if (myOptToken == null) {
            initialize(Token.INVALID_TYPE, text);
        } else {
            myOptToken.setText(text);
        }
    }

    /**
     * Set the token type for this node. If this instance is already
     * associated with a token, then that token is destructively modified
     * by this operation. If not, then a new token is constructed with
     * the given type and an empty (<code>""</code>, not <code>null</code>)
     * text string.
     *
     * @param type the new token type
     */
    public void setType(int type) {
        if (myOptToken == null) {
            initialize(type, "");
        } else {
            myOptToken.setType(type);
        }
    }

    public AstroTag getTag() {
        return myOptToken.getTag();
    }

    public short getOptTagCode() {
        return myOptToken.getOptTagCode();
    }

    public Object getOptData() {
        return myOptToken.getOptData();
    }

    public Object getOptTokenData() {
        return myOptToken.getOptTokenData();
    }

    public Twine getSource() {
        return myOptToken.getSource();
    }

    public ConstList getArgs() {
        return myOptToken.getArgs();
    }

    public Astro withoutArgs() {
        throw new RuntimeException("XXX not yet implemented");
    }

    public Astro withArgs(ConstList args) {
        throw new RuntimeException("XXX not yet implemented");
    }
}



1.1                  e/src/jsrc/org/quasiliteral/astro/AstroArg.java

Index: AstroArg.java
===================================================================
package org.quasiliteral.astro;

//This file is hereby placed in the public domain

/**
 * An element of an {@link Astro} argument list.
 * <p>
 * Normally this is the same type as {@link Astro} (as in the AST and Term
 * trees).  But this is made a separate type for QuasiTerm trees, where they
 * can represent a pattern or generator for some number of Astros.
 *
 * @author <a href="mailto:markm@caplet.com">Mark Miller</a>
 */
public interface AstroArg {

}



1.1                  e/src/jsrc/org/quasiliteral/quasiterm/QuasiBuilder.java

Index: QuasiBuilder.java
===================================================================
package org.quasiliteral.quasiterm;

import org.quasiliteral.astro.AstroBuilder;
import org.quasiliteral.astro.Astro;
import org.quasiliteral.astro.AstroArg;

//This file is hereby placed in the public domain

/**
 * AstroBuilder extended with additional building methods for the expression
 * of quasi-literal tree expressions and patterns.
 * <p>
 * These additional methods correspond to the quasi-oriented productions of
 * term.y.  XXX Once this is converted to an Antlr-based term.g, then we
 * should use Antlr's support for grammar inheritance to split it up into
 * the base term.y and the derived quasiterm.y.  The former can then use only
 * an AstroBuilder for building, and only the latter would require a
 * QuasiBuilder.  At such a time, the org.quasiliteral.term package can
 * probably stop depending on the org.quasiliteral.quasiterm package, giving
 * us a happy layering rather than a sad cycle.
 * <p>
 * The pretend parameterized types from AstroBuilder are: <pre>
 *     Leaf -- Leaves of the tree, representing tokens of the grammar.
 *     Node -- Lnternal nodes of the tree, looks like application of a Leaf
 *             as an functor to Args.
 *     Arg -- An individual argument in a list of arguments.  Typically the
 *            same as Node, but not always.  See QuasiTermBuilder.
 *     Args -- Represents a list of Arg.
 * </pre>
 * QuasiBuilder adds to this list:<pre>
 *
 * </pre>
 *
 * @author <a href="mailto:markm@caplet.com">Mark Miller</a>
 */
public interface QuasiBuilder extends AstroBuilder {

    /**
     *
     */
    boolean doesQuasis();

    /**
     *
     */
    Astro termHole(Astro optIdent, Astro functorHole);

    /**
     *
     */
    AstroArg alt(AstroArg leftArg, AstroArg rightArg);

    /**
     *
     */
    AstroArg seq(Astro optTerm, String quant);

    /**
     *
     */
    AstroArg argGroup(Object args, String quant);

    /**
     *
     */
    Object unpack(Astro litString);

    /**
     *
     */
    Astro dollarHole(Astro litInt);

    /**
     *
     */
    Astro atHole(Astro litInt);
}



1.1                  e/src/jsrc/org/quasiliteral/quasiterm/QuasiBuilderAdaptor.java

Index: QuasiBuilderAdaptor.java
===================================================================
package org.quasiliteral.quasiterm;

import org.erights.e.elib.tables.Twine;
import org.quasiliteral.astro.AstroBuilder;
import org.quasiliteral.astro.AstroSchema;
import org.quasiliteral.astro.Astro;
import org.quasiliteral.astro.AstroTag;
import org.quasiliteral.astro.AstroArg;
import org.quasiliteral.term.TermBuilder;

//This file is hereby placed in the public domain

/**
 * Wraps an AstroBuilder to pretend to be of type QuasiBuilder.
 * <p>
 * This kludge exists only until we switch to Antlr, and make use of its
 * support for grammar inheritance.  Until then, the one grammar, term.y, must
 * support both literal and quasi-literal term trees, so it is therefore
 * defined in terms of the larger subtype -- QuasiBuilder.
 *
 * @author <a href="mailto:markm@caplet.com">Mark Miller</a>
 */
public class QuasiBuilderAdaptor implements QuasiBuilder {

    /**
     * Builds Term trees according to the term.y grammar
     */
    static public final QuasiBuilder FOR_TERMS =
      new QuasiBuilderAdaptor(TermBuilder.FOR_TERMS);

    /**
     * Builds ASTs according to the term.y grammar
     */
    static public final QuasiBuilder FOR_ASTS =
      new QuasiBuilderAdaptor(TermBuilder.FOR_ASTS);

    private AstroBuilder myBuilder;

    public QuasiBuilderAdaptor(AstroBuilder builder) {
        myBuilder = builder;
    }

    /**
     *
     */
    public String toString() {
        return "<adapting " + myBuilder.toString() + ">";
    }

    public AstroSchema getSchema() {
        return myBuilder.getSchema();
    }

    public Astro leafTag(AstroTag tag, Twine source) {
        return myBuilder.leafTag(tag, source);
    }

    public Astro leafData(Object data, Twine source) {
        return myBuilder.leafData(data, source);
    }

    public Astro composite(AstroTag tag, Object data, Twine source) {
        return myBuilder.composite(tag, data, source);
    }

    public Astro node(Astro leaf) {
        return myBuilder.node(leaf);
    }

    public Astro node(Astro leaf, Object args) {
        return myBuilder.node(leaf, args);
    }

    public Object argList() {
        return myBuilder.argList();
    }

    public Object argList(AstroArg first) {
        return myBuilder.argList(first);
    }

    public Object argList(Object list, AstroArg next) {
        return myBuilder.argList(list, next);
    }

    public AstroArg arg(Astro node) {
        return myBuilder.arg(node);
    }

    public boolean doesQuasis() {
        return false;
    }

    public Astro termHole(Astro optIdent, Astro functorHole) {
        throw new RuntimeException("not quasi-ing");
    }

    public AstroArg alt(AstroArg leftArg, AstroArg rightArg) {
        throw new RuntimeException("not quasi-ing");
    }

    public AstroArg seq(Astro optTerm, String quant) {
        throw new RuntimeException("not quasi-ing");
    }

    public AstroArg argGroup(Object args, String quant) {
        throw new RuntimeException("not quasi-ing");
    }

    public Object unpack(Astro litString) {
        throw new RuntimeException("not quasi-ing");
    }

    public Astro dollarHole(Astro litInt) {
        throw new RuntimeException("not quasi-ing");
    }

    public Astro atHole(Astro litInt) {
        throw new RuntimeException("not quasi-ing");
    }
}



1.4       +22 -25    e/src/jsrc/org/quasiliteral/syntax/BaseLexer.java

Index: BaseLexer.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/quasiliteral/syntax/BaseLexer.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- BaseLexer.java	2001/12/05 00:46:11	1.3
+++ BaseLexer.java	2001/12/06 06:25:09	1.4
@@ -2,6 +2,8 @@
 
 import org.erights.e.elib.tables.Twine;
 import org.quasiliteral.astro.AstroBuilder;
+import org.quasiliteral.astro.Astro;
+import org.quasiliteral.astro.AstroTag;
 
 import java.io.IOException;
 import java.math.BigInteger;
@@ -124,7 +126,7 @@
      *
      */
     public String toString() {
-        return "<Lexing " + myBuilder.getSchema().getName() + ">";
+        return "<Lexing " + myBuilder.getSchema().getSchemaName() + ">";
     }
 
     /**
@@ -234,7 +236,7 @@
     /**
      * @return :Leaf (see {@link AstroBuilder})
      */
-    public Object nextToken() throws IOException, SyntaxException {
+    public Astro nextToken() throws IOException, SyntaxException {
         try {
             return getNextToken();
         } finally {
@@ -360,53 +362,48 @@
     }
 
     /**
-     * Just forwards to myBuilder
-     */
-    public int getCodeOfLeaf(Object leaf) {
-        return myBuilder.getCodeOfLeaf(leaf);
-    }
-
-    /**
      *
      */
-    protected Object leafTag(int typeCode, Twine source) {
-        return myBuilder.leafTag(typeCode, source);
+    protected Astro leafTag(short tagCode, Twine source) {
+        AstroTag tag = myBuilder.getSchema().getTagForCode(tagCode);
+        return myBuilder.leafTag(tag, source);
     }
 
     /**
      *
      */
-    protected Object leafData(Object data, Twine source) {
+    protected Astro leafData(Object data, Twine source) {
         return myBuilder.leafData(data, source);
     }
 
     /**
      *
      */
-    protected Object composite(int typeCode, Object data, Twine source) {
-        return myBuilder.composite(typeCode, data, source);
+    protected Astro composite(short tagCode, Object data, Twine source) {
+        AstroTag tag = myBuilder.getSchema().getTagForCode(tagCode);
+        return myBuilder.composite(tag, data, source);
     }
 
     /**
      *
      */
-    protected abstract Object getNextToken()
+    protected abstract Astro getNextToken()
       throws IOException, SyntaxException;
 
     /**
      *
      */
-    protected Object openBracket(char closer) throws IOException {
-        int tokenType = myChar;
+    protected Astro openBracket(char closer) throws IOException {
+        short tagCode = (short)myChar;
         nextChar();
         Twine openner = endToken();
-        return openBracket(tokenType, openner, closer);
+        return openBracket(tagCode, openner, closer);
     }
 
     /**
      *
      */
-    protected Object openBracket(int tokenType,
+    protected Astro openBracket(short tagCode,
                                  Twine openner,
                                  char closer)
       throws IOException {
@@ -416,20 +413,20 @@
             //Indent the next line to right after the open.
             myIndenter.push(openner, closer, myPos);
         }
-        return leafTag(tokenType, openner);
+        return leafTag(tagCode, openner);
     }
 
     /**
      *
      */
-    protected Object closeBracket() throws IOException {
+    protected Astro closeBracket() throws IOException {
         char closerChar = (char)myChar;
         nextChar();
         Twine closer = endToken();
         //on mismatched close, throws SyntaxError at openner
         //on unmatched close, throws Syntax error at closer
         myIndenter.pop(closerChar, closer);
-        return leafTag(closerChar, closer);
+        return leafTag((short)closerChar, closer);
     }
 
     /**
@@ -502,7 +499,7 @@
     /**
      *
      */
-    protected Object charLiteral() throws IOException, SyntaxException {
+    protected Astro charLiteral() throws IOException, SyntaxException {
         nextChar();
         char value = charConstant();
         nextChar();
@@ -565,7 +562,7 @@
     /**
      *
      */
-    protected Object numberLiteral()
+    protected Astro numberLiteral()
       throws IOException, SyntaxException {
         // Now handles floating point numbers as well as integers
         boolean floating = false;
@@ -707,7 +704,7 @@
     /**
      *
      */
-    protected Object stringLiteral() throws IOException, SyntaxException {
+    protected Astro stringLiteral() throws IOException, SyntaxException {
         nextChar();
         Twine openner = (Twine)myLTwine.run(myOptStartPos, myPos);
         myIndenter.push(openner, '"', 0);



1.11      +214 -47   e/src/jsrc/org/quasiliteral/term/Term.java

Index: Term.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/quasiliteral/term/Term.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- Term.java	2001/12/05 00:46:11	1.10
+++ Term.java	2001/12/06 06:25:09	1.11
@@ -1,13 +1,21 @@
 package org.quasiliteral.term;
 
 import org.erights.e.elib.prim.StaticMaker;
+import org.erights.e.elib.prim.E;
 import org.erights.e.elib.serial.PassByConstruction;
 import org.erights.e.elib.serial.Persistent;
 import org.erights.e.elib.tables.ConstList;
 import org.erights.e.elib.tables.Selfless;
+import org.erights.e.elib.tables.Twine;
+import org.erights.e.elib.eio.TextWriter;
 import org.erights.e.develop.format.StringHelper;
 import org.quasiliteral.astro.AstroBuilder;
+import org.quasiliteral.astro.Astro;
+import org.quasiliteral.astro.AstroArg;
+import org.quasiliteral.astro.AstroTag;
 
+import java.io.IOException;
+
 //This file is hereby placed in the public domain
 
 /**
@@ -30,7 +38,8 @@
  * @author Many thanks also to Dean Tribble
  */
 public class Term
-  implements Selfless, PassByConstruction, Persistent {
+  implements Selfless, PassByConstruction, Persistent,
+  Astro, AstroArg {
 
     /**
      *
@@ -39,97 +48,255 @@
       StaticMaker.make(Term.class);
 
     /**
-     *
+     * @serial Represents the token-type of the functor of this term.
      */
-    private final Functor myFunctor;
+    private final AstroTag myTag;
 
     /**
-     *
+     * @serial If the functor represents a literal-data token, then this is
+     * the data, and myTag must represent the cononical corresponding
+     * token-type for this kind of data in this schema.
      */
-    private final ConstList myArgs;
+    private final Object myOptData;
 
     /**
-     *
+     * @serial What source text was originally lexed or parsed to produce
+     *         this term, or the functor of this term?
      */
-    public Term(Functor functor, ConstList args) {
-        myFunctor = functor;
-        myArgs = args;
-    }
+    private final Twine mySource;
 
     /**
-     *
+     * A term is a functor (the above three instance variables) as
+     * parameterized by a list of argument Terms.  These are the arguments.  A
+     * term of zero arguments is often refered to as a "functor", so there's
+     * no information beyond the functor-part.
      */
-    public String toString() {
-        return "term`" + toString("     ", true) + "`";
-    }
+    private final ConstList myArgs;
 
     /**
-     *
+     * Just used to decide how to pretty print.
+     * <p>
+     * Initialized lazily.  0 if uninitialized, so does not need to be
+     * recalculated on revival.
      */
-    public String toString(String prefix, boolean quasiFlag) {
-        String func = myFunctor.toString(quasiFlag);
-        int len = myArgs.size();
-        if (0 == len) {
-            return func;
-        }
-        StringBuffer buf = new StringBuffer(func);
-        buf.append("(");
-        int indentCount = func.length() + 1; //for the "("
-        String indent = prefix + StringHelper.multiply(" ", indentCount);
-        Term child = (Term)myArgs.get(0);
-        buf.append(child.toString(indent, quasiFlag));
-        for (int i = 1; i < len; i++) {
-            buf.append(",\n");
-            buf.append(indent);
-            child = (Term)myArgs.get(i);
-            buf.append(child.toString(indent, quasiFlag));
-        }
-        buf.append(")");
-        return buf.toString();
+    private transient int myHeight = 0;
+
+    /**
+     * @param tag Represents the token-type of the functor.
+     * @param optData Either literal data or null.  If not null, then the tag
+     *                must represent the canonical literal type for this
+     *                kind of data in this schema.
+     * @param source What source text was originally lexed or parsed to
+     *               produce this token?
+     * @param args This Term's argument list -- a list of Terms
+     */
+    public Term(AstroTag tag, Object optData, Twine source, ConstList args) {
+        myTag = tag;
+        myOptData = optData;
+        mySource = source;
+        myArgs = args;
     }
 
     /**
-     * Uses 'TermMaker new(myFunctor, myArgs)'
+     * Uses 'TermMaker new(myTag, myOptData, mySource, myArgs)'
      */
     public Object[] getCanonicalState() {
         Object[] result = {
-            TermMaker, "new", myFunctor, myArgs
+            TermMaker, "new", myTag, myOptData, mySource, myArgs
         };
         return result;
     }
 
     /**
-     * @return :Node
+     *
      */
-    public Object build(AstroBuilder builder) {
-        Object func = myFunctor.build(builder);
+    public Astro build(AstroBuilder builder) {
+        Astro func;
+        if (null == myOptData) {
+            func = builder.leafTag(myTag, mySource);
+        } else {
+            //Assumes tag adds no more info.
+            func = builder.leafData(myOptData, mySource);
+        }
         Object args = builder.argList();
         int len = myArgs.size();
         if (0 == len) {
-            //It shouldn't be possible for myFunctor to be turned into
-            //a composite, but just to accomodate this possibility, in order
-            //to keep the composition of contracts clean, we call node/1 when
-            //there are no args.
             return builder.node(func);
         }
         for (int i = 0; i < len; i++) {
-            Object arg = ((Term)myArgs.get(i)).build(builder);
+            AstroArg arg = builder.arg(((Term)myArgs.get(i)).build(builder));
             args = builder.argList(args, arg);
         }
         return builder.node(func, args);
     }
 
     /**
+     * Represents the token-type of the functor of this term.
+     */
+    public AstroTag getTag() {
+        return myTag;
+    }
+
+    /**
      *
+     */
+    public short getOptTagCode() {
+        throw new RuntimeException("XXX not yet implemented");
+    }
+
+    /**
+     * Either literal data or null.  If not null, then the tag
+     * must represent the canonical literal type for this
+     * kind of data in this schema.
      */
-    public Functor getFunctor() {
-        return myFunctor;
+    public Object getOptData() {
+        return myOptData;
     }
 
     /**
      *
      */
+    public Object getOptTokenData() {
+        throw new RuntimeException("XXX not yet implemented");
+    }
+
+    /**
+     * What source text was originally lexed or parsed to produce this token?
+     */
+    public Twine getSource() {
+        return mySource;
+    }
+
+    /**
+     * A term is a functor (the above three instance variables) as
+     * parameterized by a list of argument Terms.  These are the arguments.
+     * A term of zero arguments is often refered to as a "functor", so there's
+     * no information beyond the functor-part.
+     */
     public ConstList getArgs() {
         return myArgs;
+    }
+
+    /**
+     *
+     */
+    public Astro withoutArgs() {
+        throw new RuntimeException("XXX not yet implemented");
+    }
+
+    /**
+     *
+     */
+    public Astro withArgs(ConstList args) {
+        throw new RuntimeException("XXX not yet implemented");
+    }
+
+    /**
+     * Lexicographic comparison of, in order:<ul>
+     * <li>the tags</li>
+     * <li>the data</li>
+     * <li>the args</li>
+     * </ul>
+     */
+    public double compareTo(Term other) {
+        double result = myTag.compareTo(other.myTag);
+        if (0.0 != result) {
+            return result;
+        }
+        if (null == myOptData) {
+            if (null == other.myOptData) {
+                //do nothing
+            } else {
+                //null is less than anything else
+                return -1.0;
+            }
+        } else {
+            if (null == other.myOptData) {
+                //everything else is greater than null
+                return 1.0;
+            } else {
+                result = E.asFloat64(E.call(myOptData,
+                                            "compareTo",
+                                            other.myOptData));
+            }
+        }
+        if (0.0 != result) {
+            return result;
+        }
+        return myArgs.compareTo(other.myArgs);
+    }
+
+    /**
+     * What's the longest distance to the bottom?
+     * <p>
+     * A leaf node is height 1.  All other nodes are one more than the height
+     * of their highest child.  This is used for pretty printing.
+     */
+    public int getHeight() {
+        if (myHeight <= 0) {
+            myHeight = 1;
+            for (int i = 0; i < myArgs.size(); i++) {
+                int h = ((Term)myArgs.get(i)).getHeight();
+                myHeight = Math.max(myHeight, h + 1);
+            }
+        }
+        return myHeight;
+    }
+
+    /**
+     *
+     */
+    public void printOn(TextWriter out) throws IOException {
+        out.print("term`");
+        prettyPrintOn(out.indent("     "), true);
+        out.print("`");
+    }
+
+    /**
+     *
+     */
+    public void prettyPrintOn(TextWriter out, boolean quasiFlag)
+      throws IOException {
+        String label = myTag.getTagName();
+        if (null != myOptData) {
+            label = E.toQuote(myOptData).bare();
+            if (quasiFlag) {
+                label = StringHelper.replaceAll(label, "$", "$$");
+                label = StringHelper.replaceAll(label, "@", "@@");
+                label = StringHelper.replaceAll(label, "`", "``");
+            }
+        }
+        out.print(label);
+        int h = getHeight();
+        if (h <= 1) {
+            if (myArgs.size() != 0) {
+                throw new RuntimeException("internal: bad height " + h);
+            }
+            //If it's a leaf, don't show parens either
+            return;
+        }
+        if (h == 2) {
+            //If it only contains leaves, do it on one line
+            out.print("(");
+            ((Term)myArgs.get(0)).prettyPrintOn(out, quasiFlag);
+            for (int i = 1; i < myArgs.size(); i++) {
+                out.print(", ");
+                ((Term)myArgs.get(i)).prettyPrintOn(out, quasiFlag);
+            }
+            out.print(")");
+            return;
+        }
+        //print each child lined up.
+        out.print("(");
+        int reps = label.length() + 1;
+        String spaces = StringHelper.multiply(" ", reps);
+        TextWriter sub = out.indent(spaces);
+
+        ((Term)myArgs.get(0)).prettyPrintOn(sub, quasiFlag);
+        for (int i = 1; i < myArgs.size(); i++) {
+            sub.println(",");
+            ((Term)myArgs.get(i)).prettyPrintOn(sub, quasiFlag);
+        }
+        sub.print(")");
     }
 }



1.11      +46 -33    e/src/jsrc/org/quasiliteral/term/TermBuilder.java

Index: TermBuilder.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/quasiliteral/term/TermBuilder.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- TermBuilder.java	2001/12/05 00:46:11	1.10
+++ TermBuilder.java	2001/12/06 06:25:09	1.11
@@ -7,6 +7,9 @@
 import org.quasiliteral.astro.AstroBuilder;
 import org.quasiliteral.astro.AstroSchema;
 import org.quasiliteral.astro.ASTBuilder;
+import org.quasiliteral.astro.Astro;
+import org.quasiliteral.astro.AstroTag;
+import org.quasiliteral.astro.AstroArg;
 
 //This file is hereby placed in the public domain
 
@@ -52,7 +55,7 @@
      *
      */
     public String toString() {
-        return "<building Term trees for " + mySchema.getName() + ">";
+        return "<building Term trees for " + mySchema.getSchemaName() + ">";
     }
 
     /**
@@ -63,21 +66,23 @@
     }
 
     /**
-     * @return :Functor
+     * @return :Term
      */
-    public Object leafTag(int typeCode, Twine source) {
-        return new Functor(mySchema.getTagForCode(typeCode),
-                           null,
-                           source);
+    public Astro leafTag(AstroTag tag, Twine source) {
+        return new Term(tag,
+                        null,
+                        source,
+                        ConstList.EmptyList);
     }
 
     /**
-     * @return :Functor
+     * @return :Term
      */
-    public Object leafData(Object data, Twine source) {
-        return new Functor(mySchema.getOptDataTag(data),
-                           data,
-                           source);
+    public Astro leafData(Object data, Twine source) {
+        return new Term(mySchema.getTypeTag(data.getClass()),
+                        data,
+                        source,
+                        ConstList.EmptyList);
     }
 
     /**
@@ -86,39 +91,39 @@
      * code, and whose argument represents the data.
      *
      * @return :Term
-     */
-    public Object composite(int typeCode, Object data, Twine source) {
-        return node(leafTag(typeCode, source),
-                    argList(node(leafData(data, source))));
-    }
-
-    /**
-     * @param leaf :Functor
      */
-    public int getCodeOfLeaf(Object leaf) {
-        Functor functor = (Functor)leaf;
-        return functor.getTag().getOptTypeCode();
+    public Astro composite(AstroTag tag, Object data, Twine source) {
+        return node(leafTag(tag, source),
+                    argList(arg(leafData(data, source))));
     }
 
     /**
-     * @param func :(Functor | Term)
+     * @param func :Term with no arguments
      * @return :Term
      */
-    public Object node(Object func) {
-        if (func instanceof Term) {
-            return func;
-        }
-        return new Term(((Functor)func), ConstList.EmptyList);
+    public Astro node(Astro leaf) {
+        Term result = (Term)leaf;
+        E.require(result.getArgs().size() == 0,
+                  "To use as a functor, a Term must not have args: ",
+                  result);
+        return result;
     }
 
     /**
-     * @param func :Functor
+     * @param func :Term with no arguments
      * @param args :(FlexList of(Term))
      * @return :Term
      */
-    public Object node(Object func, Object args) {
+    public Astro node(Astro leaf, Object args) {
+        Term func = (Term)leaf;
+        E.require(func.getArgs().size() == 0,
+                  "To use as a functor, a Term must not have args: ",
+                  func);
         FlexList argList = (FlexList)E.as(args, FlexList.class);
-        return new Term(((Functor)func), argList.snapshot());
+        return new Term(func.getTag(),
+                        func.getOptData(),
+                        func.getSource(),
+                        argList.snapshot());
     }
 
     /**
@@ -137,7 +142,7 @@
      * @param first :Term
      * @return :(FlexList of(Term))
      */
-    public Object argList(Object first) {
+    public Object argList(AstroArg first) {
         FlexList result = FlexList.fromType(Term.class);
         result.push(first);
         return result;
@@ -153,9 +158,17 @@
      * @param next :Term
      * @return :(FlexList of(Term))
      */
-    public Object argList(Object list, Object next) {
+    public Object argList(Object list, AstroArg next) {
         FlexList argList = (FlexList)E.as(list, FlexList.class);
         argList.push(next);
         return argList;
+    }
+
+    /**
+     * @param node :Term
+     * @return :Term
+     */
+    public AstroArg arg(Astro node) {
+        return (Term)node;
     }
 }



1.10      +12 -11    e/src/jsrc/org/quasiliteral/term/TermLexer.java

Index: TermLexer.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/quasiliteral/term/TermLexer.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- TermLexer.java	2001/12/03 03:30:56	1.9
+++ TermLexer.java	2001/12/06 06:25:09	1.10
@@ -24,6 +24,7 @@
 import org.erights.e.elib.tables.EmptyTwine;
 import org.erights.e.elib.tables.Twine;
 import org.quasiliteral.astro.AstroBuilder;
+import org.quasiliteral.astro.Astro;
 import org.quasiliteral.syntax.BaseLexer;
 import org.quasiliteral.syntax.FileFeeder;
 import org.quasiliteral.syntax.LineFeeder;
@@ -99,18 +100,18 @@
     /**
      * Override to skip newlines.
      */
-    public Object nextToken() throws IOException, SyntaxException {
-        Object result;
+    public Astro nextToken() throws IOException, SyntaxException {
+        Astro result;
         do {
             result = super.nextToken();
-        } while (getCodeOfLeaf(result) == TermParser.EOL);
+        } while (result.getOptTagCode() == TermParser.EOL);
         return result;
     }
 
     /**
      *
      */
-    protected Object getNextToken() throws IOException, SyntaxException {
+    protected Astro getNextToken() throws IOException, SyntaxException {
         if (myDelayedNextChar) {
             nextChar();
             myDelayedNextChar = false;
@@ -132,7 +133,7 @@
                 {
                     char c = (char)myChar;
                     nextChar();
-                    return leafTag(c, endToken());
+                    return leafTag((short)c, endToken());
                 }
             case EOFCHAR:
                 {
@@ -194,8 +195,8 @@
                         myContinueFlag = true;
                         skipLine();
                         stopToken();
-                        Object result = getNextToken();
-                        if (getCodeOfLeaf(result) == TermParser.EOFTOK) {
+                        Astro result = getNextToken();
+                        if (result.getOptTagCode() == TermParser.EOFTOK) {
                             needMore("continued line");
                             return null; //make compiler happy
                         } else {
@@ -243,7 +244,7 @@
     /**
      * Called with myChar as the first character of the identifier.
      */
-    protected Object identifier() throws IOException, SyntaxException {
+    protected Astro identifier() throws IOException, SyntaxException {
         do {
             nextChar();
         } while (myChar != EOFCHAR && isIdentifierPart((char)myChar));
@@ -277,17 +278,17 @@
         TermLexer lex = new TermLexer(lr, false, false, false);
         while (true) {
             try {
-                Object t;
+                Astro t;
                 do {
                     t = lex.nextToken();
                     //XXX should print t as a Functor.
                     stdout.println(t);
-                    if (lex.getCodeOfLeaf(t) == TermParser.EOL) {
+                    if (t.getOptTagCode() == TermParser.EOL) {
                         stdout.print("stack: ",
                                      lex.myIndenter.toString(),
                                      "\n");
                     }
-                } while (lex.getCodeOfLeaf(t) != TermParser.EOFTOK);
+                } while (t.getOptTagCode() != TermParser.EOFTOK);
                 return;
             } catch (SyntaxException sex) {
                 TextWriter err = new TextWriter(PrintStreamWriter.err(),



1.12      +48 -45    e/src/jsrc/org/quasiliteral/term/TermParser.java

Index: TermParser.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/quasiliteral/term/TermParser.java,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- TermParser.java	2001/12/05 00:46:11	1.11
+++ TermParser.java	2001/12/06 06:25:09	1.12
@@ -17,12 +17,14 @@
 import org.erights.e.elib.tables.Twine;
 import org.quasiliteral.astro.AstroSchema;
 import org.quasiliteral.astro.BaseSchema;
+import org.quasiliteral.astro.Astro;
+import org.quasiliteral.astro.AstroArg;
 import org.quasiliteral.quasiterm.QuasiBuilder;
 import org.quasiliteral.quasiterm.QuasiBuilderAdaptor;
 import org.quasiliteral.syntax.SyntaxException;
 
 import java.io.IOException;
-//#line 24 "TermParser.java"
+//#line 26 "TermParser.java"
 
 
 
@@ -302,7 +304,7 @@
 "functorHole : '@' '{' LiteralInteger '}'",
 };
 
-//#line 135 "term.y"
+//#line 137 "term.y"
 
 
 /**
@@ -368,23 +370,24 @@
 /**
  *
  */
-private int yylex() {
-    Object token = null;
+private short yylex() {
+    Astro token = null;
     try {
         token = myLexer.nextToken();
     } catch (IOException ex) {
         yyerror("io: " + ex);
     }
     yylval = token;
-    return myLexer.getCodeOfLeaf(token);
+    //Note that yacc uses tag-codes, while Antlr uses type-codes.
+    return token.getOptTagCode();
 }
 
 /**
  *
  */
 private void yyerror(String s) throws SyntaxException {
-    int ttype = myLexer.getCodeOfLeaf(yylval);
-    if (TermParser.EOFTOK == ttype && "syntax error".equals(s)) {
+    short tagCode = ((Astro)yylval).getOptTagCode();
+    if (TermParser.EOFTOK == tagCode && "syntax error".equals(s)) {
         myLexer.syntaxError("Unexpected EOF");
     } else {
         myLexer.syntaxError(s);
@@ -436,7 +439,7 @@
 static public final AstroSchema DEFAULT_SCHEMA =
   new BaseSchema("Term-Tree-Language", ConstList.fromArray(TheTokens));
 
-//#line 388 "TermParser.java"
+//#line 391 "TermParser.java"
 //###############################################################
 // method: yylexdebug : check lexer state
 //###############################################################
@@ -583,90 +586,90 @@
       {
 //########## USER-SUPPLIED ACTIONS ##########
 case 1:
-//#line 72 "term.y"
+//#line 74 "term.y"
 { myOptResult = val_peek(0); }
 break;
 case 2:
-//#line 76 "term.y"
-{ yyval = b.node(val_peek(0)); }
+//#line 78 "term.y"
+{ yyval = b.node((Astro)val_peek(0)); }
 break;
 case 3:
-//#line 77 "term.y"
-{ yyval = b.node(val_peek(3), val_peek(1)); }
+//#line 79 "term.y"
+{ yyval = b.node((Astro)val_peek(3), val_peek(1)); }
 break;
 case 4:
-//#line 78 "term.y"
-{ yyval = b.node(val_peek(3), val_peek(1)); }
+//#line 80 "term.y"
+{ yyval = b.node((Astro)val_peek(3), val_peek(1)); }
 break;
 case 5:
-//#line 80 "term.y"
-{ yyval = b.termHole(null, val_peek(0)); }
+//#line 82 "term.y"
+{ yyval = b.termHole(null,      (Astro)val_peek(0)); }
 break;
 case 6:
-//#line 81 "term.y"
-{ yyval = b.termHole(val_peek(1), val_peek(0));}
+//#line 83 "term.y"
+{ yyval = b.termHole((Astro)val_peek(1), (Astro)val_peek(0)); }
 break;
 case 7:
-//#line 85 "term.y"
+//#line 87 "term.y"
 { yyval = b.argList(); }
 break;
 case 9:
-//#line 90 "term.y"
-{ yyval = b.argList(val_peek(0)); }
+//#line 92 "term.y"
+{ yyval = b.argList((AstroArg)val_peek(0)); }
 break;
 case 10:
-//#line 91 "term.y"
-{ yyval = b.argList(val_peek(2), val_peek(0)); }
+//#line 93 "term.y"
+{ yyval = b.argList(val_peek(2), (AstroArg)val_peek(0)); }
 break;
 case 12:
-//#line 96 "term.y"
-{ yyval = b.alt(val_peek(2), val_peek(0)); }
+//#line 98 "term.y"
+{ yyval = b.alt((AstroArg)val_peek(2), (AstroArg)val_peek(0));}
 break;
 case 13:
-//#line 103 "term.y"
-{ yyval = b.seq(  val_peek(0), "."); }
+//#line 105 "term.y"
+{ yyval = b.arg((Astro)val_peek(0)); }
 break;
 case 14:
-//#line 104 "term.y"
-{ yyval = b.seq(  val_peek(1), (String)val_peek(0)); }
+//#line 106 "term.y"
+{ yyval = b.seq((Astro)val_peek(1), (String)val_peek(0)); }
 break;
 case 15:
-//#line 105 "term.y"
-{ yyval = b.seq(null, (String)val_peek(0)); }
+//#line 107 "term.y"
+{ yyval = b.seq(null,      (String)val_peek(0)); }
 break;
 case 16:
-//#line 106 "term.y"
-{ yyval = b.seq(null, "."); }
+//#line 108 "term.y"
+{ yyval = b.seq(null,      "."); }
 break;
 case 17:
-//#line 107 "term.y"
+//#line 109 "term.y"
 { yyval = b.argGroup(val_peek(2), (String)val_peek(0)); }
 break;
 case 18:
-//#line 108 "term.y"
-{ yyval = b.unpack(val_peek(0)); }
+//#line 110 "term.y"
+{ yyval = b.unpack((Astro)val_peek(0)); }
 break;
 case 19:
-//#line 112 "term.y"
+//#line 114 "term.y"
 { yyval = "?"; }
 break;
 case 20:
-//#line 113 "term.y"
+//#line 115 "term.y"
 { yyval = "+"; }
 break;
 case 21:
-//#line 114 "term.y"
+//#line 116 "term.y"
 { yyval = "*"; }
 break;
 case 27:
-//#line 129 "term.y"
-{ yyval = b.dollarHole(val_peek(1)); }
+//#line 131 "term.y"
+{ yyval = b.dollarHole((Astro)val_peek(1)); }
 break;
 case 28:
-//#line 130 "term.y"
-{ yyval = b.atHole(val_peek(1)); }
+//#line 132 "term.y"
+{ yyval = b.atHole(    (Astro)val_peek(1)); }
 break;
-//#line 615 "TermParser.java"
+//#line 618 "TermParser.java"
 //########## END OF USER-SUPPLIED ACTIONS ##########
     }//switch
     //#### Now let's reduce... ####



1.11      +29 -26    e/src/jsrc/org/quasiliteral/term/term.y

Index: term.y
===================================================================
RCS file: /cvs/e/src/jsrc/org/quasiliteral/term/term.y,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- term.y	2001/12/05 00:46:11	1.10
+++ term.y	2001/12/06 06:25:10	1.11
@@ -12,6 +12,8 @@
 import org.erights.e.elib.tables.Twine;
 import org.quasiliteral.astro.AstroSchema;
 import org.quasiliteral.astro.BaseSchema;
+import org.quasiliteral.astro.Astro;
+import org.quasiliteral.astro.AstroArg;
 import org.quasiliteral.quasiterm.QuasiBuilder;
 import org.quasiliteral.quasiterm.QuasiBuilderAdaptor;
 import org.quasiliteral.syntax.SyntaxException;
@@ -69,49 +71,49 @@
  * </pre>
  */
 start:
-        term                            { myOptResult = $1; }
+        term                         { myOptResult = $1; }
 ;
 
 term:
-        functor                         { $$ = b.node($1); }
- |      functor     '(' argList ')'     { $$ = b.node($1, $3); }
- |      functorHole '(' argList ')'     { $$ = b.node($1, $3); }
+        functor                      { $$ = b.node((Astro)$1); }
+ |      functor     '(' argList ')'  { $$ = b.node((Astro)$1, $3); }
+ |      functorHole '(' argList ')'  { $$ = b.node((Astro)$1, $3); }
 
- |         functorHole                  { $$ = b.termHole(null, $1); }
- |      ID functorHole                  { $$ = b.termHole($1, $2);}
+ |         functorHole               { $$ = b.termHole(null,      (Astro)$1); }
+ |      ID functorHole               { $$ = b.termHole((Astro)$1, (Astro)$2); }
  ;
 
 argList:
-        /* empty */                     { $$ = b.argList(); }
+        /* empty */                  { $$ = b.argList(); }
  |      args
  ;
 
 args:
-        arg                             { $$ = b.argList($1); }
- |      args ',' arg                    { $$ = b.argList($1, $3); }
+        arg                          { $$ = b.argList((AstroArg)$1); }
+ |      args ',' arg                 { $$ = b.argList($1, (AstroArg)$3); }
  ;
 
 arg:
         seq
- |      arg '|' seq                     { $$ = b.alt($1, $3); }
+ |      arg '|' seq                  { $$ = b.alt((AstroArg)$1, (AstroArg)$3);}
  ;
 
 /**
  * Each seq represents some number of Terms
  */
 seq:
-        term                            { $$ = b.seq(  $1, "."); }
- |      term quant                      { $$ = b.seq(  $1, (String)$2); }
- |           quant                      { $$ = b.seq(null, (String)$1); }
- |           '.'                        { $$ = b.seq(null, "."); }
- |      '(' args ')' quant              { $$ = b.argGroup($2, (String)$4); }
- |      '^' LiteralString               { $$ = b.unpack($2); }
+        term                         { $$ = b.arg((Astro)$1); }
+ |      term quant                   { $$ = b.seq((Astro)$1, (String)$2); }
+ |           quant                   { $$ = b.seq(null,      (String)$1); }
+ |           '.'                     { $$ = b.seq(null,      "."); }
+ |      '(' args ')' quant           { $$ = b.argGroup($2, (String)$4); }
+ |      '^' LiteralString            { $$ = b.unpack((Astro)$2); }
  ;
 
 quant:
-        '?'                             { $$ = "?"; }
- |      '+'                             { $$ = "+"; }
- |      '*'                             { $$ = "*"; }
+        '?'                          { $$ = "?"; }
+ |      '+'                          { $$ = "+"; }
+ |      '*'                          { $$ = "*"; }
  ;
 
 functor:
@@ -126,8 +128,8 @@
  * Starts off as a hole for a Functor, but may get promoted.
  */
 functorHole:
-        '$' '{' LiteralInteger '}'      { $$ = b.dollarHole($3); }
- |      '@' '{' LiteralInteger '}'      { $$ = b.atHole($3); }
+        '$' '{' LiteralInteger '}'   { $$ = b.dollarHole((Astro)$3); }
+ |      '@' '{' LiteralInteger '}'   { $$ = b.atHole(    (Astro)$3); }
  ;
 
 
@@ -197,23 +199,24 @@
 /**
  *
  */
-private int yylex() {
-    Object token = null;
+private short yylex() {
+    Astro token = null;
     try {
         token = myLexer.nextToken();
     } catch (IOException ex) {
         yyerror("io: " + ex);
     }
     yylval = token;
-    return myLexer.getCodeOfLeaf(token);
+    //Note that yacc uses tag-codes, while Antlr uses type-codes.
+    return token.getOptTagCode();
 }
 
 /**
  *
  */
 private void yyerror(String s) throws SyntaxException {
-    int ttype = myLexer.getCo