/** the root superclass for all components of the grammar (terminals, nonterminals, literals, etc) */
public abstract class Element {
+ /** if this element always matches exactly one token, return a topology covering exactly those possible tokens, otherwise <tt>null</tt> */
abstract Topology toAtom();
- public Topology noFollow() { return null; }
+
Forest epsilonForm() { throw new Error("no epsilon form: " + this); }
- final boolean possiblyEpsilon(Walk.Cache cache) {
+ final boolean possiblyEpsilon(Walk.Cache cache) {
Boolean ret = cache==null ? null : cache.possiblyEpsilon.get(this);
if (ret != null) return ret.booleanValue();
ret = new Walk.PossiblyEpsilon().walk(this) ? Boolean.TRUE : Boolean.FALSE;
boolean closed = false;
- public Phase(Phase previous, Token token) {
+ private Token.Location location;
+ public Phase(Phase previous, Token token, Token.Location location) {
this.pos = previous==null ? 0 : previous.pos+1;
this.token = token;
+ this.location = location;
}
public boolean isDone() { return token == null; }
throw new Parser.Failed(error, getLocation());
}
- public Token.Location getLocation() { return token==null ? null : token.getLocation(); }
+ public Token.Location getLocation() { return location; }
/** add a new node (merging with existing nodes if possible)
* @param parent the parent of the new node
protected Parser(Union u) { this.pt = new Table(u, top()); }
protected Parser(Table pt) { this.pt = pt; }
- public abstract Forest<R> shiftedToken(T t);
+ public abstract Forest<R> shiftedToken(T t, Token.Location loc);
public abstract Topology<T> top();
/** parse <tt>input</tt>, using the table <tt>pt</tt> to drive the parser */
public Forest<R> parse(Token.Stream<T> input) throws IOException, Failed {
GSS gss = new GSS();
- GSS.Phase current = gss.new Phase(null, input.next());
+ Token.Location loc = input.getLocation();
+ GSS.Phase current = gss.new Phase(null, input.next(), loc);
current.newNode(null, null, pt.start, true, null);
for(;;) {
- GSS.Phase next = gss.new Phase(current, input.next());
+ loc = input.getLocation();
+ GSS.Phase next = gss.new Phase(current, input.next(), loc);
current.reduce();
- Forest forest = current.token==null ? null : shiftedToken((T)current.token);
+ Forest forest = current.token==null ? null : shiftedToken((T)current.token, loc);
current.shift(next, forest);
if (current.isDone()) return (Forest<R>)current.finalResult;
current.checkFailure();
/** this is declared abstract as a way of forcing subclasses to provide a thoughtful implementation */
public abstract String toString();
- public abstract Location getLocation();
-
/** a sequence of input tokens; returns null when EOF is reached */
public static interface Stream<T extends Token> {
public T next() throws IOException;
+ public abstract Location getLocation();
}
/** a location within the input stream */
public static interface Location {
public String toString();
}
-
}
+
public static class CharToStringParser extends Parser<CharToken,String> {
public CharToStringParser(Union u) { super(u); }
public Topology<CharToken> top() { return new IntegerTopology<CharToken>(); }
- public Forest<String> shiftedToken(CharToken ct) {
- return Forest.create(ct.getLocation(), ct.result(), null, null, false, false);
+ public Forest<String> shiftedToken(CharToken ct, Token.Location loc) {
+ return Forest.create(loc, ct.result(), null, null, false, false);
}
}
return new CharRange(new IntegerTopology<CharToken>(new Range.Set(new Range((int)start, (int)end)).complement().intersect(all)));
}
- public static CharToken left(int row, int col) { return new CharToken((char)9998, 0, 0) { public String toString() { return "{"; } }; }
- public static CharToken right(int row, int col) { return new CharToken((char)9999, 0, 0) { public String toString() { return "}"; } }; }
public static final Atom leftBrace = new CharRange(new IntegerTopology<CharToken>(9998)) { public String toString() { return "{"; } };
public static final Atom rightBrace = new CharRange(new IntegerTopology<CharToken>(9999)) { public String toString() { return "}"; } };
+ public static final CharToken left = new CharToken((char)9998);
+ public static final CharToken right = new CharToken((char)9999);
private static final Range.Set all = new Range.Set(new Range(0, Character.MAX_VALUE));
public static final Atom any = new CharRange(new IntegerTopology<CharToken>(all));
// Private //////////////////////////////////////////////////////////////////////////////
public final char c;
- public final Location location;
- public CharToken(char c, int line, int col) { this(c, new CartesianLocation(line, col)); }
- private CharToken(char c, Location loc) { this.c = c; this.location = loc; }
- public String result() { return c+""; }
- public Location getLocation() { return location; }
- public String toString() { return "\'"+StringUtil.escapify(c+"")+"\'"; }
+ public CharToken(char c) { this.c = c; }
+ public String result() { return c+""; }
+ public String toString() { return "\'"+StringUtil.escapify(c+"")+"\'"; }
//////////////////////////////////////////////////////////////////////////////////////////
// Statics //////////////////////////////////////////////////////////////////////////////
- static class CartesianLocation implements Location {
+ public static class CartesianLocation implements Location {
public final int line;
public final int col;
public String toString() { return line + ":" + col; }
public CartesianLocation(int line, int col) { this.line = line; this.col = col; }
- public String getContext() { return ""; }
}
/** an implementation of Token.Stream for sequences of characters */
}
long then = 0;
+ private Token.Location location = new LocWrap(1, 1);
+ public Token.Location getLocation() { return location; }
public Token next() throws IOException {
int i = r.read();
if (i==-1) return null;
char c = (char)i;
- Token ret = new CharToken(c, new LocWrap(line, col));
+ location = new LocWrap(line, col);
+ Token ret = new CharToken(c);
String s = line + "";
while(s.length() < 4) s = " " + s;
s = "line "+s+", col " + col;
int _row = 0;
int _col = 0;
+ public Token.Location getLocation() { return new CharToken.CartesianLocation(_row, _col); }
public CharToken next() throws IOException {
if (cur==null) return null;
if (s != null) {
char c = s.charAt(spos++);
if (c=='\n') { _row++; _col = 0; }
else _col++;
- return new CharToken(c, _row, _col);
+ return new CharToken(c);
}
s = null;
}
pos = cur.iip+1;
cur = cur.parent;
if (cur==null) return null;
- return CharToken.right(_row, _col);
+ return CharToken.right;
}
Object o = cur.child(pos++);
if (o instanceof String) {
}
cur = (Block)o;
pos = 0;
- return CharToken.left(_row, _col);
+ return CharToken.left;
}
public static Block parse(BufferedReader br) throws Invalid, IOException {