[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);
}