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

markm@eros.cs.jhu.edu markm@eros.cs.jhu.edu
Sat, 3 Nov 2001 22:12:29 -0500


markm       01/11/03 22:12:29

  Modified:    src/jsrc Makefile
               src/jsrc/org/erights/e/develop/exception ExceptionMgr.java
               src/jsrc/org/erights/e/elang/syntax e.y
               src/jsrc/org/erights/e/elib/tables EList.java Twine.java
               src/jsrc/org/quasiliteral/term Functor.java Term.updoc
  Added:       src/jsrc/org/quasiliteral/term Makefile TermBuilder.java
                        TermLexer.java TermParser.java term.y
  Removed:     src/jsrc/org/quasiliteral/quasiterm Makefile
                        TermBuilder.java TermLexer.java TermParser.java
                        term.y
  Log:
  We just parsed our first Term tree!!

Revision  Changes    Path
1.58      +3 -3      e/src/jsrc/Makefile

Index: Makefile
===================================================================
RCS file: /cvs/e/src/jsrc/Makefile,v
retrieving revision 1.57
retrieving revision 1.58
diff -u -r1.57 -r1.58
--- Makefile	2001/11/04 00:38:11	1.57
+++ Makefile	2001/11/04 03:12:28	1.58
@@ -47,10 +47,10 @@
 	find antlr -name '*.java' >> files.tmp
 	$(JCOMPILE) @files.tmp
 
-# optional: remake the parser from yacc, or just use the generated
-# one, which is included.
+# optional: remake the parsers from yacc, or just use the generated
+# ones, which are included.
 elang_parser:
-	(cd $(TOP)/src/jsrc/org/quasiliteral/quasiterm; $(MAKE) all)
+	(cd $(TOP)/src/jsrc/org/quasiliteral/term; $(MAKE) all)
 	(cd $(ER)/elang/syntax; $(MAKE) all)
 
 # space-time-local elang



1.7       +2 -2      e/src/jsrc/org/erights/e/develop/exception/ExceptionMgr.java

Index: ExceptionMgr.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/develop/exception/ExceptionMgr.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- ExceptionMgr.java	2001/09/06 09:55:43	1.6
+++ ExceptionMgr.java	2001/11/04 03:12:28	1.7
@@ -31,9 +31,9 @@
     static private ExceptionNoticer OurNoticer = null;
 
     /**
-     * Returns th as a RuntimeException. <p>
+     * Returns 'th' as a RuntimeException. <p>
      *
-     * Wraps th if necessary so that the caller can to a <pre>
+     * Wraps 'th' if necessary so that the caller can do a <pre>
      *
      *     throw ExceptionMgr.asSafe(th);
      * </pre>



1.91      +0 -1      e/src/jsrc/org/erights/e/elang/syntax/e.y

Index: e.y
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elang/syntax/e.y,v
retrieving revision 1.90
retrieving revision 1.91
diff -u -r1.90 -r1.91
--- e.y	2001/11/04 00:38:11	1.90
+++ e.y	2001/11/04 03:12:28	1.91
@@ -1367,7 +1367,6 @@
     int ttype = ((AstroToken)yylval).getType();
     if (EParser.EOFTOK == ttype && "syntax error".equals(s)) {
         myLexer.needMore("Unexpected EOF");
-        
     } else {
         syntaxError(s);
     }



1.29      +12 -3     e/src/jsrc/org/erights/e/elib/tables/EList.java

Index: EList.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/tables/EList.java,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -r1.28 -r1.29
--- EList.java	2001/09/07 05:49:23	1.28
+++ EList.java	2001/11/04 03:12:28	1.29
@@ -248,11 +248,11 @@
      * Concatenates (snapshots of) this list and other.  XXX If they have a
      * common class, we should use it. <p>
      *
-     * The default implementation here insists that other is an EList, but
-     * this is overridden in the Twine subclass.
+     * The default implementation here insists that other coerces to an
+     * EList, but this is overridden in the Twine subclass.
      */
     public ConstList add(Object other) {
-        EList otherList = (EList)other;
+        EList otherList = (EList)E.as(other, EList.class);
         int len1 = size();
         int len2 = otherList.size();
         if (0 == len1) {
@@ -263,6 +263,15 @@
         FlexList flex = new FlexListImpl(len1 + len2);
         flex.append(this);
         flex.append(otherList);
+        return flex.snapshot();
+    }
+
+    /**
+     * A ConstList equivalent to 'this snapshot() + [value]'
+     */
+    public ConstList with(Object value) {
+        FlexList flex = diverge();
+        flex.push(value);
         return flex.snapshot();
     }
 



1.21      +12 -3     e/src/jsrc/org/erights/e/elib/tables/Twine.java

Index: Twine.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/erights/e/elib/tables/Twine.java,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -r1.20 -r1.21
--- Twine.java	2001/11/04 00:38:12	1.20
+++ Twine.java	2001/11/04 03:12:28	1.21
@@ -241,15 +241,24 @@
     /*package*/ abstract Twine infectOneToOne(String str);
 
     /**
+     * oneToOne defaults to false
+     */
+    public Twine infect(String str) {
+        return infect(str, false);
+    }
+
+    /**
      * Returns a Twine with str as the string part, and the source info from
      * this Twine.
      * <p>
      * @param str The string to annotate with source-span info from this
      *            Twine.
      * @param oneToOne If true, the two strings must be the same size, in
-     *                 which case the new string gets this Twine's
-     *                 optSourceSpan().  If false, then the new string will
-     *                 only get a non-oneToOne form of this source-span
+     *                 which case this Twine's source-span info is mapped
+     *                 one to one onto the new string.  If false, then the
+     *                 new string will only get a non-oneToOne form of this
+     *                 Twine's overall source-span.
+
      */
     public Twine infect(String str, boolean oneToOne) {
         if (oneToOne) {



1.3       +1 -1      e/src/jsrc/org/quasiliteral/term/Functor.java

Index: Functor.java
===================================================================
RCS file: /cvs/e/src/jsrc/org/quasiliteral/term/Functor.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- Functor.java	2001/11/04 00:38:12	1.2
+++ Functor.java	2001/11/04 03:12:28	1.3
@@ -154,7 +154,7 @@
     /**
      *
      */
-    public Object getValue() {
+    public Object getOptValue() {
         return myOptValue;
     }
 



1.2       +16 -1     e/src/jsrc/org/quasiliteral/term/Term.updoc

Index: Term.updoc
===================================================================
RCS file: /cvs/e/src/jsrc/org/quasiliteral/term/Term.updoc,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- Term.updoc	2001/11/03 13:32:51	1.1
+++ Term.updoc	2001/11/04 03:12:28	1.2
@@ -1,6 +1,21 @@
+    ? def term__uriGetter := <unsafe:org.quasiliteral.term.*>
+    # value: <unsafe:org.quasiliteral.term.*>
+    
+    ? def TermParserMaker := <term:TermParser>
+    # value: <unsafe:org.quasiliteral.term.TermParser>
+    
+    ? TermParserMaker(`foo(3, "bar"(3, 'x'), baz)`)
+    # value: term`foo(LiteralInteger:"3"=3,
+    #                 LiteralString:"\"bar\""="bar"(LiteralInteger:"3"=3, LiteralChar:"\'x\'"='x'),
+    #                 baz)`
+    
+    ? 
+
+
+
     ? def astro__uriGetter := <unsafe:org.quasiliteral.astro.*>
     # value: <unsafe:org.quasiliteral.astro.*>
-    
+
     ? def TermTreeMaker := <astro:TermTree>
     # value: <unsafe:org.quasiliteral.astro.TermTree>
     



1.1                  e/src/jsrc/org/quasiliteral/term/Makefile

Index: Makefile
===================================================================

default: all

TOP=../../../../..

include $(TOP)/src/build/makerules.mk

BYACCJ = $(TOP)/dist/bin/$(PLATDIR)/byaccj$(EXE)


# The BYACCJ is assumed to be BYACC/Java, and could originally be
# obtained from "http://www.lincom-asg.com/~rjamison/byacc/".  This is
# standard Berkeley yacc enhanced by Bob Jamison so that it can also
# output Java code.  Both Berkeley yacc and BYACC/Java are covered by
# the standard Berkeley open source license.  This website has since
# disappeared, so the byaccj sources are now included in the E
# sources.


all:
	# The chmod is a horrible kludge to deal with the loss of the
	# execute bit when tar-ing on Windows.
	chmod a+x $(BYACCJ)
	$(BYACCJ) -jv -f TermParser -s Object term.y



1.1                  e/src/jsrc/org/quasiliteral/term/TermBuilder.java

Index: TermBuilder.java
===================================================================
package org.quasiliteral.term;

/**
 * Used by the actions of term.y / TermParser.
 * <p>
 * XXX TermBuilder, TermParser, term.y, and TermLexer are all to be replaced
 * with Antlr-based equivalents.
 *
 * @author <a href="mailto:markm@caplet.com">Mark S Miller</a>
 */
public interface TermBuilder {

    /**
     *
     */
    Object list();

    /**
     *
     */
    Object list(Object elem0);

    /**
     *
     */
    Object with(Object sofar, Object next);

    /**
     *
     */
    Object term(Object fnctr, Object args);

    /**
     *
     */
    Object functor(Object ttype, Object src, Object optValue);

    /**
     *
     */
    Object dollarHole(Object index);

    /**
     *
     */
    Object atHole(Object index);

    /**
     *
     */
    Object repr(Object hole, Object howMany);
}



1.1                  e/src/jsrc/org/quasiliteral/term/TermLexer.java

Index: TermLexer.java
===================================================================
package org.quasiliteral.term;

import org.erights.e.develop.exception.PrintStreamWriter;
import org.erights.e.develop.exception.ThrowableSugar;
import org.erights.e.develop.exception.ExceptionMgr;
import org.erights.e.elib.eio.TextWriter;
import org.erights.e.elib.tables.Twine;
import org.erights.e.elang.syntax.LineFeeder;
import org.erights.e.elang.syntax.Indenter;
import org.erights.e.elang.syntax.TwineFeeder;
import org.erights.e.elang.syntax.SyntaxException;
import org.erights.e.elang.syntax.FileFeeder;
import org.quasiliteral.astro.AstroToken;
import org.quasiliteral.term.TermParser;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.math.BigInteger;

/**
 * Breaks textually input into a stream of tokens according to the Term
 * language's defined grammar.
 * <p>
 * XXX To be replaced with a lexer generated by Antlr
 *
 * @author <a href="mailto:markm@erights.org">Mark S. Miller</a>
 */
public class TermLexer {

    /**
     *
     */
    static public final int EOFCHAR = -1;

    /** contains all lines after the current line */
    private LineFeeder myInput;

    /** the current line, or null at end-of-file */
    public Twine myLTwine = null;

    /** the string part, but as an array for speed */
    public char[] myLData = null;

    /** position in current line of candidate character */
    private int myPos;

    /** the candidate character, or EOFCHAR for end-of-file. */
    private int myChar;

    /**
     * Where on the current line does the current token start?  If the token
     * starts before the current line, or if there is no current token, this
     * is -1.
     */
    private int myOptStartPos = -1;

    /**
     * Accumulates all text of the current token from lines before the
     * current line, or null if no current token or if the current
     * token starts on the current line.  The EOL token itself is not
     * considered to be a line spanning token.
     */
    private Twine myOptStartText = null;

    /**
     * Keeps track of indentation level
     */
    private Indenter myIndenter;

    /**
     * Should the next line get extra indentation as a continuation line?
     */
    private boolean myContinueFlag;

    /**
     *
     */
    public TermLexer(LineFeeder input)
    throws IOException {

        myInput = input;
        myPos = -1;
        myLTwine = myInput.optNextLine(false, 0, 'x', 0);
        if (null == myLTwine) {
            myLData = null;
        } else {
            myLData = myLTwine.bare().toCharArray();
        }
        nextChar();
        myIndenter = new Indenter();
        myContinueFlag = false;
    }

    /**
     * @param sourceCode The source code itself
     */
    static public TermLexer make(Twine sourceCode) {
        LineFeeder lineFeeder = new TwineFeeder(sourceCode);
        try {
            return new TermLexer(lineFeeder);
        } catch (IOException ioe) {
            throw ThrowableSugar.backtrace(ioe, "Parsing a string?");
        }
    }

    /**
     * Skip to the end of this line, so that the next character read will be
     * from the next line, forget any token we may have been in the midst
     * of, and reset our indentation tracker.
     */
    private void reset() {
        if (null != myLTwine) {
            myPos = myLData.length-1;
            myChar = myLData[myPos];
            if ('\n' != myChar) {
                throw new RuntimeException
                  ("internal: must end with newline");
            }
        }
        myOptStartPos = -1;
        myOptStartText = null;
        myIndenter = new Indenter();
        myContinueFlag = false;
    }

    /**
     *
     */
    private void nextLine() throws IOException {
        if (myLTwine == null) {
            myChar = EOFCHAR;
            return;
        }
        if (-1 == myOptStartPos) {
            if (null == myOptStartText) {
                //no current token, do nothing
            } else {
                //current token already started
                myOptStartText = (Twine)myOptStartText.add(myLTwine);
            }
        } else {
            //current token started on this line at myOptStartPos
            myOptStartText = (Twine)myLTwine.run(myOptStartPos,
                                                 myLTwine.size());
            myOptStartPos = -1;
        }
        myPos = -1;

        char closer = myIndenter.getCloser();
        int indent = myIndenter.getIndent();
        if (myContinueFlag) {
            indent += 2;
        }
        myLTwine =
          myInput.optNextLine(('"' == closer || '`' == closer),
                              indent,
                              closer,
                              myIndenter.getCloseIndent());

        if (null == myLTwine) {
            //don't clear myContinueFlag on end-of-file
            myLData = null;
        } else {
            myContinueFlag = false;
            myLData = myLTwine.bare().toCharArray();
        }
        myChar = '\n';
    }

    /**
     *
     */
    private void nextChar() throws IOException {
        while (true) {
            if (null == myLTwine) {
                myChar = EOFCHAR;
                return;
            }
            myPos++;
            int len = myLData.length;
            if (myPos < len) {
                myChar = myLData[myPos];
                return;
            } else {
                nextLine();
            }
        }
    }

    /**
     *
     */
    public AstroToken nextToken() throws IOException, SyntaxException {
        AstroToken result;
        try {
            result = getNextToken();
        } finally {
            myOptStartPos = -1;
            myOptStartText = null;
        }
        if (TermParser.isContinuer(result.getType())) {
            return continuer(result);
        } else {
            return result;
        }
    }

    /**
     * Separated out for use by '>'
     */
    private AstroToken continuer(AstroToken result) throws IOException {
        if (isWhite(myPos, myLData.length)) {
            myContinueFlag = true;
            skipLine();
        }
        return result;
    }

    /**
     *
     */
    /*package*/ void syntaxError(String msg)
    throws SyntaxException {
        int start = myOptStartPos;
        if (-1 == start) {
            start = myPos -1;
        }
        start = Math.max(Math.min(start, myPos -1), 0);
        int bound = Math.max(myPos, start +1);
        SyntaxException sex = new SyntaxException(msg,
                                                  myLTwine,
                                                  start,
                                                  bound);
        reset();
        throw sex;
    }

    /**
     *
     */
    private boolean eatDigit(int radix) throws IOException {
        if (Character.digit((char)myChar, radix) != -1 || myChar == '_') {
            nextChar();
            return true;
        } else {
            return false;
        }
    }

    /**
     *
     */
    private void skipWhiteSpace() throws IOException {
        while (true) {
            if (myChar == EOFCHAR) {
                return;
            }
            if (Character.isWhitespace((char)myChar)) {
                nextChar();
            } else {
                return;
            }
        }
    }

    /**
     * Are all the characters on the current line from start inclusive to
     * bound exclusive whitespace characters?
     */
    private boolean isWhite(int start, int bound) {
        for (int i = start; i < bound; i++) {
            if (! Character.isWhitespace(myLData[i])) {
                return false;
            }
        }
        return true;
    }

    /**
     *
     */
    private AstroToken getNextToken() throws IOException, SyntaxException {
        skipWhiteSpace();
        startToken();

        switch(myChar) {
            case ',':
            case ':':
            case '=':
            case '$':
            case '@':
            case '?':
            case '+':
            case '*': {
                char c = (char)myChar;
                nextChar();
                return new AstroToken(c, endToken());
            } case EOFCHAR: {
                return new AstroToken(TermParser.EOFTOK, Twine.fromString(""));
            } case '(': {
                return openBracket(')');
            } case ')': {
                return closeBracket();
            } case '{': {
                return openBracket('}');
            } case '}': {
                return closeBracket();
            } case '[': {
                return openBracket(']');
            } case ']': {
                return closeBracket();
            } case '#': {
                // Skip comment to end of line (as in "//" case above).
                skipLine();
                stopToken();
                return getNextToken();
            } case '\\': {
                nextChar();
                if (myChar == 'u' || myChar == 'U') {
                    syntaxError("\\u... not yet implemented");
                    return null; //keep compiler happy
                }
                syntaxError("unrecognized escape");
                return null; //keep compiler happy
            } case '\'': {
                return charLiteral();
            } case '"': {
                return stringLiteral();
            } case '`': {
                return twineLiteral();
            }
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9': {
                return numberLiteral();

            } default: {
                if (isIdentifierStart((char)myChar)) {
                    return identifier();
                } else {
                    syntaxError("unrecognized character: '" + (char)myChar +
                                "' code: " + (int)myChar);
                    return null; //keep compiler happy
                }
            }
        }
    }

    /**
     *
     */
    private AstroToken openBracket(char closer) throws IOException {
        int tokenType = myChar;
        nextChar();
        Twine openner = endToken();
        return openBracket(tokenType, openner, closer);
    }

    /**
     *
     */
    private AstroToken openBracket(int tokenType, Twine openner, char closer)
    throws IOException {
        if (isWhite(myPos, myLData.length)) {
            myIndenter.nest(openner, closer);
        } else {
            //Indent the next line to right after the open.
            myIndenter.push(openner, closer, myPos);
        }
        return new AstroToken(tokenType, openner);
    }

    /**
     *
     */
    private AstroToken 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 new AstroToken(closerChar, closer);
    }

    /**
     *
     */
    private char mustEat(char c) throws IOException, SyntaxException {
        nextChar();
        if (myChar != c) {
            syntaxError("" + c + " expected");
        }
        return c;
    }

    /**
     *
     */
    private char charConstant() throws IOException, SyntaxException {
        if (myChar == '\\') {
            nextChar();
            switch(myChar) {
                case 'b': return '\b';
                case 't': return '\t';
                case 'n': return '\n';
                case 'f': return '\f';
                case 'r': return '\r';
                case '"': return '"';
                case '\'': return '\'';
                case '\\': return '\\';
                case '$': return mustEat('$');
                case '@': return mustEat('@');
                case '\n': {
                    //XXX need to move into stringLiteral only
                    //XXX bug: must be accepted at end of string
                    nextChar();
                    return charConstant();
                }
                case EOFCHAR: {
                    syntaxError("End of file in middle of literal");
                }
                case 'u': {
                    syntaxError
                      ("XXX escaped uchar codes not yet implemented");
                }
                default: {
                    if (Character.isDigit((char)myChar)) {
                        syntaxError
                          ("XXX escaped char codes not yet implemented");
                    } else {
                        syntaxError("Unrecognized escaped character");
                    }
                }
            }
        } else if (myChar == '$') {
            return mustEat('$');
        } else if (myChar == '@') {
            return mustEat('@');
        } else if (myChar == '`') {
            return mustEat('`');
        } else if (myChar == EOFCHAR) {
            syntaxError("End of file in middle of literal");
        } else {
            return (char)myChar;
        }
        return 'x'; //keep compiler happy
    }

    /**
     *
     */
    private AstroToken charLiteral() throws IOException, SyntaxException {
        nextChar();
        char value = charConstant();
        nextChar();
        if (myChar != '\'') {
            syntaxError("char constant must end in \"'\"");
        }
        nextChar();
        return new AstroToken(TermParser.LiteralChar,
                             endToken(),
                             new Character(value));
    }

    /**
     * Called with myChar as the first character of the identifier.
     */
    private AstroToken identifier() throws IOException, SyntaxException {
        do {
            nextChar();
        } while (myChar != EOFCHAR && isIdentifierPart((char)myChar));
        return new AstroToken(TermParser.Identifier, endToken());
    }

    /** pretty self explanatory */
    public boolean isEndOfFile() {
        return null == myLTwine;
    }

    /**
     * The first character of an E identifier may be anything accepted
     * as the first character of a Java identifier except '$'.  I.e.,
     * a letter or '_'.
     *
     * @see java.lang.Character#isJavaIdentifierStart
     */
    static public boolean isIdentifierStart(char ch) {
        return Character.isJavaIdentifierStart(ch) && ch != '$';
    }

    /**
     * A non-first character of an E identifier may be anything
     * accepted as a non-first character of a Java identifier except
     * '$'. The ascii subset consists of letters, digits, and '_'.
     * See Character.isJavaIdentifierPart() for the full spec.
     *
     * @see java.lang.Character#isJavaIdentifierPart
     */
    static public boolean isIdentifierPart(char ch) {
        return Character.isJavaIdentifierPart(ch) && ch != '$';
    }

    /**
     *
     */
    private AstroToken numberLiteral()
    throws IOException, SyntaxException {
        // Now handles floating point numbers as well as integers
        boolean floating = false;
        int radix = 10;
        if (myChar == '0') {
            radix = 8;
            nextChar();
            if (myChar == 'x' || myChar == 'X') {
                radix = 16;
                nextChar();
            }
        }
        if (radix == 16) {
            while (eatDigit(16)) {}
        } else {
            //even if radix == 8, we may instead have a floating point literal
            while (eatDigit(10)) {}
            // If we have a decimal point go for the fractional part
            if (myChar == '.' && ! peekChar('.')) {
                nextChar();
                floating = true;
                while (eatDigit(10)) {}
            }

            if ((myChar == 'E') || (myChar == 'e')) {
                nextChar();
                floating = true;
                if (myChar == '-') {
                    nextChar();
                }
                while (eatDigit(10)) {}
            }
        }
        Twine tok = endToken();
        String str = tok.replaceAll("_", "").bare();
        if (floating) {
            return new AstroToken(TermParser.LiteralFloat64,
                                  tok,
                                  Double.valueOf(str));
        } else {
            if (radix == 16) {
                //remove the leading "0x" to make BigInteger happy
                str = str.substring(2);
            }
            return new AstroToken(TermParser.LiteralInteger,
                                  tok,
                                  new BigInteger(str, radix));
        }
    }

    /**
     * XXX Get rid of peekChar/0 or make it work
     */
    private char peekChar() {
        if (myChar == EOFCHAR || myChar == '\n') {
            throw new Error("internal: can't peek here");
        }
        int last = myLData.length -1;

        if (myPos < last) {
            return myLData[myPos +1];
        } else {
            throw new Error("internal: (XXX bug) peek past end");
        }
    }

    /**
     *
     */
    private boolean peekChar(char c) {
        if (myChar == EOFCHAR || myChar == '\n') {
            throw new Error("internal: can't peek here");
        }
        int last = myLData.length -1;

        if (myPos < last) {
            return c == myLData[myPos +1];
        } else {
            return false;
        }
    }

    /**
     *
     */
    private AstroToken twineLiteral() throws IOException, SyntaxException {
        nextChar(); //eat initial '`'
        Twine openner = (Twine)myLTwine.run(myOptStartPos, myPos);
        myIndenter.push(openner, '`', 0);
        Twine value = Twine.fromString("");
        while (true) {
            int startSeg = myPos;
            while ("$@`\n".indexOf(myChar) == -1) {
                if (myChar == EOFCHAR) {
                    syntaxError("File end inside quasi-string literal");
                }
                nextChar();
            }
            value = (Twine)value.add(myLTwine.run(startSeg, myPos));
            //myChar is a '$', '@', '`', or '\n'

            if ('\n' == myChar) {
                value = (Twine)value.add(myLTwine.run(myPos, myPos+1));

            } else if (peekChar((char)myChar)) {
                //A doubled $, @, or ` is uninterpreted, and turns into a
                //single one.
                Twine dbl = (Twine)myLTwine.run(myPos, myPos+2);
                value = (Twine)value.add(dbl.infect(""+(char)myChar,
                                                    false));
                nextChar();
                nextChar();

            } else if (myChar == '`') {
                //terminal backquote is eaten but not added to the
                //value of the resulting QuasiClose token.
                nextChar();
                Twine source = endToken();
                myIndenter.pop('`', source);
                return new AstroToken(TermParser.LiteralTwine,
                                      source,
                                      value);
            } else {
                syntaxError("unexpected: " + (char)myChar);
            }
        }
    }

    /**
     * Skip to the rest of this line.
     */
    private void skipLine() throws IOException {
        if (null != myLTwine) {
            myPos = myLData.length -1;
            myChar = myLData[myPos];
        }
        nextChar();
    }

    /**
     *
     */
    private void startToken() {
        if (-1 != myOptStartPos || null != myOptStartText) {
            throw new Error("internal: token already started");
        }
        myOptStartPos = myPos;
    }

    /**
     * Cancels a started token
     */
    private void stopToken() {
        myOptStartPos = -1;
        myOptStartText = null;
    }

    /**
     *
     */
    private Twine endToken() {
        Twine result;
        int pos = myPos;
        if (-1 == myOptStartPos) {
            if (null == myOptStartText) {
                throw new Error("internal: no current token");
            } else {
                //started on previous line
                result = myOptStartText;
                if (null != myLTwine) {
                    result = (Twine)result.add(myLTwine.run(0, pos));
                }
            }
        } else {
            //starts on this line
            result = (Twine)myLTwine.run(myOptStartPos, pos);
        }
        stopToken();
        return result;
    }

    /**
     *
     */
    private AstroToken stringLiteral() throws IOException, SyntaxException {
        nextChar();
        Twine openner = (Twine)myLTwine.run(myOptStartPos, myPos);
        myIndenter.push(openner, '"', 0);
        StringBuffer value = new StringBuffer();
        while (myChar != '"') {
            if (myChar == EOFCHAR) {
                syntaxError("File ends inside string literal");
            }
            value.append(charConstant());
            nextChar();
        }
        nextChar();
        Twine closer = endToken();
        myIndenter.pop('"', closer);
        return new AstroToken(TermParser.LiteralString,
                             closer,
                             value.toString());
    }

    /**
     * Just for testing.  Reads an input file and prints one token per line
     * to stdout.
     */
    static public void main(String[] args)
    throws IOException, SyntaxException {

        TextWriter stdout = new TextWriter(PrintStreamWriter.out(), true);
        String url;
        BufferedReader ins;
        if (0 == args.length) {
            url = "stdin";
            ins = PrintStreamWriter.in();
        } else if (1 == args.length) {
            url = args[0];
            ins = new BufferedReader(new FileReader(args[0]));
        } else {
            throw new RuntimeException
                ("usage: java org.quasiliteral.term.TermLexer file");
        }
        LineFeeder lr = new FileFeeder(url, ins, stdout);
        TermLexer lex = new TermLexer(lr);
        while (true) {
            try {
                AstroToken t;
                do {
                    t = lex.nextToken();
                    stdout.println(t.asFunctor(TermParser.getTokenNames()));
                } while (t.getType() != TermParser.EOFTOK);
                return;
            } catch (SyntaxException sex) {
                TextWriter err = new TextWriter(PrintStreamWriter.err(),
                                                true);
                err.indent("# ").print("# ", sex);
                err.println();
            }
        }
    }
}



1.1                  e/src/jsrc/org/quasiliteral/term/TermParser.java

Index: TermParser.java
===================================================================
//### This file created by BYACC 1.8(/Java extension  0.92)
//### Java capabilities added 7 Jan 97, Bob Jamison
//### Updated : 27 Nov 97  -- Bob Jamison, Joe Nieten
//###           01 Jan 98  -- Bob Jamison -- fixed generic semantic constructor
//###           01 Jun 99  -- Bob Jamison -- added Runnable support
//### Please send bug reports to rjamison@lincom-asg.com
//### static char yysccsid[] = "@(#)yaccpar	1.8 (Berkeley) 01/20/90";



//#line 7 "term.y"
package org.quasiliteral.term;

import org.erights.e.elang.syntax.SyntaxException;
import org.erights.e.elib.tables.ConstList;
import org.erights.e.elib.tables.Twine;
import org.quasiliteral.astro.AstroToken;

import java.io.IOException;
//#line 19 "TermParser.java"




//#####################################################################
// class: TermParser
// does : encapsulates yacc() parser functionality in a Java
//        class for quick code development
//#####################################################################
public class TermParser
{

boolean yydebug;        //do I want debug output?
int yynerrs;            //number of errors so far
int yyerrflag;          //was there an error?
int yychar;             //the current working character

//########## MESSAGES ##########
//###############################################################
// method: debug
//###############################################################
void debug(String msg)
{
  if (yydebug)
    System.out.println(msg);
}

//########## STATE STACK ##########
final static int YYSTACKSIZE = 500;  //maximum stack size
int statestk[],stateptr;             //state stack
//###############################################################
// methods: state stack push,pop,drop,peek
//###############################################################
void state_push(int state)
{
  if (stateptr>=YYSTACKSIZE)         //overflowed?
    return;
  statestk[++stateptr]=state;
}
int state_pop()
{
  if (stateptr<0)                    //underflowed?
    return -1;
  return statestk[stateptr--];
}
void state_drop(int cnt)
{
int ptr;
  ptr=stateptr-cnt;
  if (ptr<0)
    return;
  stateptr = ptr;
}
int state_peek(int relative)
{
int ptr;
  ptr=stateptr-relative;
  if (ptr<0)
    return -1;
  return statestk[ptr];
}
//###############################################################
// method: init_stacks : allocate and prepare stacks
//###############################################################
boolean init_stacks()
{
  statestk = new int[YYSTACKSIZE];
  stateptr = -1;
  val_init();
  return true;
}
//###############################################################
// method: dump_stacks : show n levels of the stacks
//###############################################################
void dump_stacks(int count)
{
int i;
  System.out.println("=index==state====value=     s:"+stateptr+"  v:"+valptr);
  for (i=0;i<count;i++)
    System.out.println(" "+i+"    "+statestk[i]+"      "+valstk[i]);
  System.out.println("======================");
}


//########## SEMANTIC VALUES ##########
//## **user defined:Object
String   yytext;//user variable to return contextual strings
Object yyval; //used to return semantic vals from action routines
Object yylval;//the 'lval' (result) I got from yylex()
Object valstk[];
int valptr;
//###############################################################
// methods: value stack push,pop,drop,peek.
//###############################################################
void val_init()
{
  valstk=new Object[YYSTACKSIZE];
  yyval=new Object();
  yylval=new Object();
  valptr=-1;
}
void val_push(Object val)
{
  if (valptr>=YYSTACKSIZE)
    return;
  valstk[++valptr]=val;
}
Object val_pop()
{
  if (valptr<0)
    return null;
  return valstk[valptr--];
}
void val_drop(int cnt)
{
int ptr;
  ptr=valptr-cnt;
  if (ptr<0)
    return;
  valptr = ptr;
}
Object val_peek(int relative)
{
int ptr;
  ptr=valptr-relative;
  if (ptr<0)
    return null;
  return valstk[ptr];
}
//#### end semantic value section ####
public final static short Identifier=257;
public final static short LiteralChar=258;
public final static short LiteralInteger=259;
public final static short LiteralFloat64=260;
public final static short LiteralString=261;
public final static short LiteralTwine=262;
public final static short YYERRCODE=256;
final static short yylhs[] = {                           -1,
    0,    1,    1,    1,    3,    3,    4,    4,    4,    2,
    2,    2,    2,    2,    2,    5,    5,    6,    6,    6,
    7,    7,    7,    7,    7,
};
final static short yylen[] = {                            2,
    1,    1,    4,    3,    0,    1,    1,    2,    3,    1,
    3,    3,    5,    1,    1,    4,    4,    1,    1,    1,
    1,    1,    1,    1,    1,
};
final static short yydefred[] = {                         0,
    0,   21,   22,   23,   24,   25,    0,    0,    0,    0,
    1,    0,   15,   14,    0,    0,    7,    0,    0,    0,
    0,    0,    0,    0,   12,    4,    0,   18,   19,   20,
    8,    0,    0,    0,    0,    9,   16,   17,    3,   13,
};
final static short yydgoto[] = {                         10,
   17,   12,   18,   19,   13,   31,   14,
};
final static short yysindex[] = {                       -36,
  -40,    0,    0,    0,    0,    0,  -36, -104, -103,    0,
    0,  -18,    0,    0, -238, -245,    0,  -69,  -15,  -31,
 -233, -229,  -36,  -28,    0,    0,  -36,    0,    0,    0,
    0,  -91,  -90,   -5, -245,    0,    0,    0,    0,    0,
};
final static short yyrindex[] = {                         0,
    1,    0,    0,    0,    0,    0,  -56,    0,    0,    0,
    0,    5,    0,    0,    0,    0,    0,    0,  -39,  -34,
    0,    0,   -3,    3,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
};
final static short yygindex[] = {                         0,
    4,    0,   16,    0,    2,    0,   -8,
};
final static int YYTABLESIZE=226;
final static short yytable[] = {                          8,
   10,    6,   11,   11,    2,   15,   15,   25,   20,   15,
   30,   29,    2,    3,    4,    5,    6,   15,   21,   22,
   16,   23,   24,   26,   20,   32,   40,    9,   27,   33,
   36,   28,   35,   37,   38,   39,    5,    5,   34,    0,
   10,   10,   11,   11,   10,    2,   11,    0,    2,    0,
    0,    0,    0,    6,    7,    0,    0,    0,   15,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,   10,    0,   11,    0,    2,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
    1,    2,    3,    4,    5,    6,
};
final static short yycheck[] = {                         36,
    0,   41,    0,    0,    0,   40,   41,   16,    7,   44,
   42,   43,  258,  259,  260,  261,  262,   58,  123,  123,
   61,   40,  261,   93,   23,  259,   35,   64,   44,  259,
   27,   63,   61,  125,  125,   41,   93,   41,   23,   -1,
   40,   41,   40,   41,   44,   41,   44,   -1,   44,   -1,
   -1,   -1,   -1,   93,   91,   -1,   -1,   -1,   93,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   93,   -1,   93,   -1,   93,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
  257,  258,  259,  260,  261,  262,
};
final static short YYFINAL=10;
final static short YYMAXTOKEN=262;
final static String yyname[] = {
"end-of-file",null,null,null,null,null,null,null,null,null,null,null,null,null,
null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,
null,null,null,null,null,null,"'$'",null,null,null,"'('","')'","'*'","'+'",
"','",null,null,null,null,null,null,null,null,null,null,null,null,null,"':'",
null,null,"'='",null,"'?'","'@'",null,null,null,null,null,null,null,null,null,
null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,
null,"'['",null,"']'",null,null,null,null,null,null,null,null,null,null,null,
null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,
null,null,"'{'",null,"'}'",null,null,null,null,null,null,null,null,null,null,
null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,
null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,
null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,
null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,
null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,
null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,
null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,
null,null,null,null,null,null,null,null,null,"Identifier","LiteralChar",
"LiteralInteger","LiteralFloat64","LiteralString","LiteralTwine",
};
final static String yyrule[] = {
"$accept : start",
"start : term",
"term : functor",
"term : functor '(' argList ')'",
"term : '[' argList ']'",
"argList :",
"argList : args",
"args : term",
"args : hole repr",
"args : args ',' term",
"functor : Identifier",
"functor : Identifier ':' LiteralString",
"functor : Identifier '=' literal",
"functor : Identifier ':' LiteralString '=' literal",
"functor : literal",
"functor : hole",
"hole : '$' '{' LiteralInteger '}'",
"hole : '@' '{' LiteralInteger '}'",
"repr : '?'",
"repr : '+'",
"repr : '*'",
"literal : LiteralChar",
"literal : LiteralInteger",
"literal : LiteralFloat64",
"literal : LiteralString",
"literal : LiteralTwine",
};

//#line 78 "term.y"

/**
 * contains all the tokens after yylval
 */
private TermLexer myLexer;

/**
 *
 */
private TermBuilder b;

/**
 *
 */
private Object myOptResult;

/**
 *
 */
public TermParser(TermLexer lexer, TermBuilder builder) {
    myLexer = lexer;
    b = builder;
    myOptResult = null;
}

/**
 * builder defaults to SimpleTermBuilder
 */
static public Term run(Twine source) {
    return (Term)run(source, SimpleTermBuilder.THE_ONE);
}

/**
 *
 */
static public Object run(Twine source, TermBuilder builder) {
    TermLexer lexer = TermLexer.make(source);
    TermParser parser = new TermParser(lexer, builder);
    return parser.parse();
}

/**
 *
 */
public Object parse() {
    if (yyparse() == 0) {
        return myOptResult;
    } else {
        yyerror("couldn't parse term");
    }
    return null; //keep compiler happy
}
    

/**
 *
 */
private int yylex() {
    AstroToken token = null;
    try {
        token = myLexer.nextToken();
    } catch (IOException ex) {
        yyerror("io: " + ex);
    }
    yytext = token.getText();
    yylval = token;
    return token.getType();
}

/**
 *
 */
private void yyerror(String s) throws SyntaxException {
    int ttype = ((AstroToken)yylval).getType();
    if (TermParser.EOFTOK == ttype && "syntax error".equals(s)) {
        myLexer.syntaxError("Unexpected EOF");
    } else {
        myLexer.syntaxError(s);
    }
}

/**
 *
 */
static /*package*/ boolean isContinuer(int ttype) {
    return false; //for now
}


/*********************************/

/**
 *
 */
static private String[] TheTokens = new String[yyname.length];

/** Not provided for us */
static /*package*/ final short EOFTOK = 0;

static {
    System.arraycopy(yyname, 0, TheTokens, 0, yyname.length);

    /* Since this language has no keywords, it's not a conflict
     * for the names to be identifiers
     */

    TheTokens[EOFTOK]           = "EndOfFile";
}

/**
 *
 */
static /*package*/ ConstList getTokenNames() {
    return ConstList.fromArray(TheTokens);
}
//#line 359 "TermParser.java"
//###############################################################
// method: yylexdebug : check lexer state
//###############################################################
void yylexdebug(int state,int ch)
{
String s=null;
  if (ch < 0) ch=0;
  if (ch <= YYMAXTOKEN) //check index bounds
     s = yyname[ch];    //now get it
  if (s==null)
    s = "illegal-symbol";
  debug("state "+state+", reading "+ch+" ("+s+")");
}



//###############################################################
// method: yyparse : parse input and execute indicated items
//###############################################################
int yyparse()
{
int yyn;       //next next thing to do
int yym;       //
int yystate;   //current parsing state from state table
String yys;    //current token string
boolean doaction;
  init_stacks();
  yynerrs = 0;
  yyerrflag = 0;
  yychar = -1;          //impossible char forces a read
  yystate=0;            //initial state
  state_push(yystate);  //save it
  while (true) //until parsing is done, either correctly, or w/error
    {
    doaction=true;
    if (yydebug) debug("loop"); 
    //#### NEXT ACTION (from reduction table)
    for (yyn=yydefred[yystate];yyn==0;yyn=yydefred[yystate])
      {
      if (yydebug) debug("yyn:"+yyn+"  state:"+yystate+"  char:"+yychar);
      if (yychar < 0)      //we want a char?
        {
        yychar = yylex();  //get next token
        //#### ERROR CHECK ####
        if (yychar < 0)    //it it didn't work/error
          {
          yychar = 0;      //change it to default string (no -1!)
          if (yydebug)
            yylexdebug(yystate,yychar);
          }
        }//yychar<0
      yyn = yysindex[yystate];  //get amount to shift by (shift index)
      if ((yyn != 0) && (yyn += yychar) >= 0 &&
          yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
        {
        if (yydebug)
          debug("state "+yystate+", shifting to state "+yytable[yyn]+"");
        //#### NEXT STATE ####
        yystate = yytable[yyn];//we are in a new state
        state_push(yystate);   //save it
        val_push(yylval);      //push our lval as the input for next rule
        yychar = -1;           //since we have 'eaten' a token, say we need another
        if (yyerrflag > 0)     //have we recovered an error?
           --yyerrflag;        //give ourselves credit
        doaction=false;        //but don't process yet
        break;   //quit the yyn=0 loop
        }

    yyn = yyrindex[yystate];  //reduce
    if ((yyn !=0 ) && (yyn += yychar) >= 0 &&
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
      {   //we reduced!
      if (yydebug) debug("reduce");
      yyn = yytable[yyn];
      doaction=true; //get ready to execute
      break;         //drop down to actions
      }
    else //ERROR RECOVERY
      {
      if (yyerrflag==0)
        {
        yyerror("syntax error");
        yynerrs++;
        }
      if (yyerrflag < 3) //low error count?
        {
        yyerrflag = 3;
        while (true)   //do until break
          {
          if (stateptr<0)   //check for under & overflow here
            {
            yyerror("stack underflow. aborting...");  //note lower case 's'
            return 1;
            }
          yyn = yysindex[state_peek(0)];
          if ((yyn != 0) && (yyn += YYERRCODE) >= 0 &&
                    yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
            {
            if (yydebug)
              debug("state "+state_peek(0)+", error recovery shifting to state "+yytable[yyn]+" ");
            yystate = yytable[yyn];
            state_push(yystate);
            val_push(yylval);
            doaction=false;
            break;
            }
          else
            {
            if (yydebug)
              debug("error recovery discarding state "+state_peek(0)+" ");
            if (stateptr<0)   //check for under & overflow here
              {
              yyerror("Stack underflow. aborting...");  //capital 'S'
              return 1;
              }
            state_pop();
            val_pop();
            }
          }
        }
      else            //discard this token
        {
        if (yychar == 0)
          return 1; //yyabort
        if (yydebug)
          {
          yys = null;
          if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
          if (yys == null) yys = "illegal-symbol";
          debug("state "+yystate+", error recovery discards token "+yychar+" ("+yys+")");
          }
        yychar = -1;  //read another
        }
      }//end error recovery
    }//yyn=0 loop
    if (!doaction)   //any reason not to proceed?
      continue;      //skip action
    yym = yylen[yyn];          //get count of terminals on rhs
    if (yydebug)
      debug("state "+yystate+", reducing "+yym+" by rule "+yyn+" ("+yyrule[yyn]+")");
    if (yym>0)                 //if count of rhs not 'nil'
      yyval = val_peek(yym-1); //get current semantic value
    switch(yyn)
      {
//########## USER-SUPPLIED ACTIONS ##########
case 1:
//#line 28 "term.y"
{ myOptResult = val_peek(0); }
break;
case 2:
//#line 32 "term.y"
{ yyval = b.term(val_peek(0), b.list()); }
break;
case 3:
//#line 33 "term.y"
{ yyval = b.term(val_peek(3), val_peek(1)); }
break;
case 4:
//#line 34 "term.y"
{ yyval = b.term("list", val_peek(1)); }
break;
case 5:
//#line 38 "term.y"
{ yyval = b.list(); }
break;
case 7:
//#line 43 "term.y"
{ yyval = b.list(val_peek(0)); }
break;
case 8:
//#line 44 "term.y"
{ yyval = b.repr(val_peek(1), val_peek(0)); }
break;
case 9:
//#line 45 "term.y"
{ yyval = b.with(val_peek(2), val_peek(0)); }
break;
case 10:
//#line 49 "term.y"
{ yyval = b.functor(val_peek(0), val_peek(0), null); }
break;
case 11:
//#line 50 "term.y"
{ yyval = b.functor(val_peek(2), val_peek(0), null); }
break;
case 12:
//#line 51 "term.y"
{ yyval = b.functor(val_peek(2), val_peek(2), val_peek(0)); }
break;
case 13:
//#line 53 "term.y"
{ yyval = b.functor(val_peek(4), val_peek(3), val_peek(2)); }
break;
case 16:
//#line 59 "term.y"
{ yyval = b.dollarHole(val_peek(1)); }
break;
case 17:
//#line 60 "term.y"
{ yyval = b.atHole(val_peek(1)); }
break;
//#line 558 "TermParser.java"
//########## END OF USER-SUPPLIED ACTIONS ##########
    }//switch
    //#### Now let's reduce... ####
    if (yydebug) debug("reduce");
    state_drop(yym);             //we just reduced yylen states
    yystate = state_peek(0);     //get new state
    val_drop(yym);               //corresponding value drop
    yym = yylhs[yyn];            //select next TERMINAL(on lhs)
    if (yystate == 0 && yym == 0)//done? 'rest' state and at first TERMINAL
      {
      debug("After reduction, shifting from state 0 to state "+YYFINAL+"");
      yystate = YYFINAL;         //explicitly say we're done
      state_push(YYFINAL);       //and save it
      val_push(yyval);           //also save the semantic value of parsing
      if (yychar < 0)            //we want another character?
        {
        yychar = yylex();        //get next character
        if (yychar<0) yychar=0;  //clean, if necessary
        if (yydebug)
          yylexdebug(yystate,yychar);
        }
      if (yychar == 0)          //Good exit (if lex returns 0 ;-)
         break;                 //quit the loop--all DONE
      }//if yystate
    else                        //else not done yet
      {                         //get next state and push, for next yydefred[]
      yyn = yygindex[yym];      //find out where to go
      if ((yyn != 0) && (yyn += yystate) >= 0 &&
            yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
        yystate = yytable[yyn]; //get new state
      else
        yystate = yydgoto[yym]; //else go to new defred
      debug("after reduction, shifting from state "+state_peek(0)+" to state "+yystate+"");
      state_push(yystate);     //going again, so push state & val...
      val_push(yyval);         //for next action
      }
    }//main loop
  return 0;//yyaccept!!
}
//## end of method parse() ######################################



}
//################### END OF CLASS yaccpar ######################



1.1                  e/src/jsrc/org/quasiliteral/term/term.y

Index: term.y
===================================================================

/**
 * XXX To be replaced by a term.g to be processed by Antlr
 */

%{
package org.quasiliteral.term;

import org.erights.e.elang.syntax.SyntaxException;
import org.erights.e.elib.tables.ConstList;
import org.erights.e.elib.tables.Twine;
import org.quasiliteral.astro.AstroToken;

import java.io.IOException;
%}

%token Identifier       //Like E: [0-9a-zA-Z_][a-zA-Z_]*

%token LiteralChar      //like Java & E: unicode
%token LiteralInteger   //like Java & E: precision unlimited
%token LiteralFloat64   //like Java & E: IEEE double precision
%token LiteralString    //like Java & E: double quoted
%token LiteralTwine     //like E: quasi-quoted without holes

%%

start:
        term                            { myOptResult = $1; }
;

term:
        functor                         { $$ = b.term($1, b.list()); }
 |      functor '(' argList ')'         { $$ = b.term($1, $3); }
 |      '[' argList ']'                 { $$ = b.term("list", $2); }
 ;

argList:
        /* empty */                     { $$ = b.list(); }
 |      args
 ;

args:
        term                            { $$ = b.list($1); }
 |      hole repr                       { $$ = b.repr($1, $2); }
 |      args ',' term                   { $$ = b.with($1, $3); }
 ;

functor:
        Identifier                      { $$ = b.functor($1, $1, null); }
 |      Identifier ':' LiteralString    { $$ = b.functor($1, $3, null); }
 |      Identifier '=' literal          { $$ = b.functor($1, $1, $3); }
 |      Identifier ':' LiteralString '=' literal
                                        { $$ = b.functor($1, $2, $3); }
 |      literal
 |      hole
 ;

hole:
        '$' '{' LiteralInteger '}'      { $$ = b.dollarHole($3); }
 |      '@' '{' LiteralInteger '}'      { $$ = b.atHole($3); }
 ;

repr:
        '?'
 |      '+'
 |      '*'
 ;

literal:
        LiteralChar
 |      LiteralInteger
 |      LiteralFloat64
 |      LiteralString
 |      LiteralTwine
 ;

%%

/**
 * contains all the tokens after yylval
 */
private TermLexer myLexer;

/**
 *
 */
private TermBuilder b;

/**
 *
 */
private Object myOptResult;

/**
 *
 */
public TermParser(TermLexer lexer, TermBuilder builder) {
    myLexer = lexer;
    b = builder;
    myOptResult = null;
}

/**
 * builder defaults to SimpleTermBuilder
 */
static public Term run(Twine source) {
    return (Term)run(source, SimpleTermBuilder.THE_ONE);
}

/**
 *
 */
static public Object run(Twine source, TermBuilder builder) {
    TermLexer lexer = TermLexer.make(source);
    TermParser parser = new TermParser(lexer, builder);
    return parser.parse();
}

/**
 *
 */
public Object parse() {
    if (yyparse() == 0) {
        return myOptResult;
    } else {
        yyerror("couldn't parse term");
    }
    return null; //keep compiler happy
}
    

/**
 *
 */
private int yylex() {
    AstroToken token = null;
    try {
        token = myLexer.nextToken();
    } catch (IOException ex) {
        yyerror("io: " + ex);
    }
    yytext = token.getText();
    yylval = token;
    return token.getType();
}

/**
 *
 */
private void yyerror(String s) throws SyntaxException {
    int ttype = ((AstroToken)yylval).getType();
    if (TermParser.EOFTOK == ttype && "syntax error".equals(s)) {
        myLexer.syntaxError("Unexpected EOF");
    } else {
        myLexer.syntaxError(s);
    }
}

/**
 *
 */
static /*package*/ boolean isContinuer(int ttype) {
    return false; //for now
}


/*********************************/

/**
 *
 */
static private String[] TheTokens = new String[yyname.length];

/** Not provided for us */
static /*package*/ final short EOFTOK = 0;

static {
    System.arraycopy(yyname, 0, TheTokens, 0, yyname.length);

    /* Since this language has no keywords, it's not a conflict
     * for the names to be identifiers
     */

    TheTokens[EOFTOK]           = "EndOfFile";
}

/**
 *
 */
static /*package*/ ConstList getTokenNames() {
    return ConstList.fromArray(TheTokens);
}