_____________________________________________________________________________
Immediately
- - evil problems with: (x y? z /ws)
- - it gets even more evil than that
+ - foo.add(x)
+ foo.add(y.andnot(x)) ==> this is broken
- Annotation Tutorial
+ - Get at least *some* sort of moderate improvement in the error messages
+
+ ..................................................
+
+ - evil problems with: (x y? z /ws)
+ - it gets even more evil than that
+ - basically, follow restrictions are not honored when the element
+ matches against the empty string
______________________________________________________________________________
v1.1
+ - precedes restrictions ("<-")
+
- MUST HAVE BETTER ERROR MESSAGES
- use for developing java15.g
+
- java15.g
+ - once this is ready, do big announcement
+
- topology no longer needed as an arg to parser?
- broader regression testing (for stuff like error messages, etc)
______________________________________________________________________________
-v1.1
+v1.2
- finalize metagrammar and rdp-op's
- write some grammars
/** if ambiguity checking is enabled, this exception is thrown to signal that the parse was ambiguous */
public class Ambiguous extends Exception {
+
final Forest<?> ambiguity;
private final HashSet<Tree<?>> ht;
+
+ /**
+ * @param ht a specially-constructed set of trees with shared nodes replaced by '*'
+ */
Ambiguous(Forest<?> ambiguity, HashSet<Tree<?>> ht) {
this.ambiguity = ambiguity;
this.ht = ht;
public Forest<?> getAmbiguity() { return ambiguity; }
+ /** WARNING: this method is not considered part of the "stable API"; it may be removed in the future */
+ public Input.Region getRegion() { return ambiguity.getRegion(); }
+
public String toString() {
- // FIXME: print the input region that was ambiguously matched
StringBuffer sb = new StringBuffer();
sb.append("unresolved ambiguity at "+ambiguity.getRegion()+"; shared subtrees are shown as \"*\" ");
- //sb.append("\noffending text: ");
for(Tree<?> result : ht) {
- sb.append("\n possibility: ");
+ sb.append("\n possibility: ");
StringBuffer sb2 = new StringBuffer();
result.toPrettyString(sb2);
sb.append(StringUtil.indent(sb2.toString(), 15));
int resets = 0;
int waits = 0;
- public GSS() { }
+ Input input;
+
+ public GSS(Input input) { this.input = input; }
private Phase.Node[] reducing_list = null;
private Phase prev;
private Input.Location location;
private Input.Location nextLocation;
+ private Input.Location prevLocation;
+
public final Parser parser;
private Forest forest;
- public Phase(Phase prev, Parser parser, Phase previous, Tok token, Input.Location location, Input.Location nextLocation, Forest forest) throws ParseFailed {
+ public Phase(Phase prev, Parser parser, Phase previous, Tok token, Input.Location location,
+ Input.Location nextLocation, Forest forest) throws ParseFailed {
+ this.prevLocation = prev==null ? location : prev.getLocation();
this.prev = prev;
this.forest = forest;
this.parser = parser;
public boolean isDone() throws ParseFailed {
if (token != null) return false;
if (token==null && finalResult==null)
- throw new ParseFailed(ParseFailed.error(ANSI.red("unexpected end of file\n"), token, hash.values()), getLocation());
+ throw new ParseFailed(ParseFailed.error(("unexpected end of file\n"),
+ token, hash.values()),
+ getLocation().createRegion(getLocation()), input);
return true;
}
+ public Input.Location getPrevLocation() { return prevLocation; }
public Input.Location getLocation() { return location; }
+ public Input.Region getRegion() { return getPrevLocation().createRegion(getLocation()); }
public Input.Location getNextLocation() { return nextLocation; }
/** add a new node (merging with existing nodes if possible)
}
if (!good && token!=null)
- throw new ParseFailed(ParseFailed.error(ANSI.red("unexpected character ")+" \'"+
+ throw new ParseFailed(ParseFailed.error(("unexpected character ")+" \'"+
ANSI.purple(StringUtil.escapify(token+"", "\\\'\r\n"))+
"\' encountered at "+
- ANSI.green(getLocation())+"\n", token, hash.values()),
- getLocation());
+ ANSI.green(next.getRegion())+"\n", token, hash.values()),
+ next.getRegion(), input);
if (token==null && finalResult==null)
- throw new ParseFailed(ParseFailed.error(ANSI.red("unexpected end of file\n"), token, hash.values()),
- getLocation());
+ throw new ParseFailed(ParseFailed.error(("unexpected end of file at "+getLocation()+"\n"), token, hash.values()),
+ getLocation().createRegion(getLocation()), input);
}
for(Node child : ((Forest.Many<?>)result).parents) {
if (only != null && child!=only) continue;
holder[pos] = result;
- if (pos==0) child.finish(r, r.rewrite(child.phase().getNextLocation().createRegion(target.getLocation())), target);
+ if (pos==0) child.finish(r, r.rewrite(child.phase().getLocation().createRegion(target.getLocation())), target);
else child.reduce(r, pos-1, target, null);
}
/** returns the location the input stream is currently at */
public Location<Token> getLocation();
+ /**
+ * <b>Optional:</b> <i>If possible</i>, this method will return a
+ * <60 char long rendering of the input region (for example, if
+ * the input is a region of characters, it would be those
+ * characters, possibly with ellipses in the middle to truncate
+ * the length) -- otherwise, returns null.
+ */
+ public abstract String showRegion(Region<Token> r);
+
/** <font color=purple>a location (position) in the input stream -- <i>between tokens</i></font> */
public static interface Location<Token> extends Comparable<Location> {
public Region<Token> createRegion(Location<Token> loc);
public String toString();
+
+ /** the location following this one */
+ public Location next();
+
+ /** the location preceding this one */
+ public Location prev();
}
/** <font color=purple>a contiguous set of <tt>Location</tt>s</font> */
public static interface Region<Token> /* implements Topology<Location<Tok>> */ {
+
+ /**
+ * the toString() method of Region should return a <80char
+ * "rendition" of the input region, if possible
+ */
+ public abstract String toString();
+
+ /** The location of the start of this region */
+ public abstract Location<Token> getStart();
+
+ /** The location of the end of this region */
+ public abstract Location<Token> getEnd();
+
}
}
public class ParseFailed extends Exception {
private final Input.Location location;
+ private final Input.Region region;
+ private final Input input;
private final String message;
- ParseFailed() { this("", null); }
- ParseFailed(String message, Input.Location loc) { this.location = loc; this.message = message; }
+ ParseFailed() { this("", null, null); }
+ ParseFailed(String message, Input.Region region, Input input) {
+ this.region = region;
+ this.location = region.getStart();
+ this.message = message;
+ this.input = input;
+ }
public Input.Location getLocation() { return location; }
- public String toString() { return message/* + (location==null ? "" : (" at " + location))*/; }
+ private Input.Region getRegion() { return region; }
+ public String toString() {
+ Input.Location before = getRegion().getStart();
+ for(int i=0; i<10; i++) before = before.prev() == null ? before : before.prev();
+ Input.Location after = getRegion().getEnd();
+ for(int i=0; i<10; i++) after = after.next() == null ? after : after.next();
+ StringBuilder ret = new StringBuilder();
+ ret.append(message);
+ ret.append('\n');
+ ret.append(" at: ");
+ ret.append(getRegion()+"");
+ if (input != null) {
+ ret.append('\n');
+ ret.append(" text: ");
+ String first = input.showRegion(before.createRegion(getRegion().getStart()));
+ ret.append(first);
+ String second = input.showRegion(getRegion());
+ ret.append(ANSI.red(second));
+ ret.append(input.showRegion(getRegion().getEnd().createRegion(after)));
+ ret.append('\n');
+ ret.append(" ");
+ for(int i=0; i<first.length(); i++) ret.append(' ');
+ for(int i=0; i<second.length(); i++) ret.append(ANSI.red("^"));
+ }
+ return ret.toString();
+ }
// FIXME
private static HashSet<GSS.Phase.Node> touched = new HashSet<GSS.Phase.Node>();
/** parse <tt>input</tt>, and return the shared packed parse forest (or throw an exception) */
public Forest<NodeType> parse(Input<Token> input) throws IOException, ParseFailed {
- GSS gss = new GSS();
+ GSS gss = new GSS(input);
Input.Location loc = input.getLocation();
Token tok = input.next();
GSS.Phase current = gss.new Phase<Token>(null, this, null, tok, loc, input.getLocation(), null);
boolean cr = false;
private int count = 0;
+ private StringBuilder cache = new StringBuilder();
+
+ public void setCacheEnabled(boolean enabled) {
+ if (!enabled) cache = null;
+ else if (cache == null) cache = new StringBuilder();
+ }
+
public boolean isCR() { return cr; }
public Character _next() throws IOException {
cr = false;
int i = r.read();
- if (i==-1) { System.err.print("\r...done \r"); return null; }
+ if (i==-1) { /*System.err.print("\r...done \r"); */return null; }
char c = (char)i;
+ if (cache != null) cache.append(c);
cr = c=='\n';
+ /*
if ((count++) % 100 == 0)
System.err.print(" " + count + "\r");
+ */
return c;
}
+
+ public String showRegion(Region<Character> rc) {
+ if (cache == null) return null;
+ Cartesian.Region r = (Cartesian.Region)rc;
+ int start = r.getStart().getScalar()+1;
+ int end = r.getEnd().getScalar()+1;
+ if (end > cache.length()) end = cache.length();
+ String ret;
+ if (end-start < 60) ret = cache.substring(start, end);
+ else ret = cache.substring(start, start+25) +
+ "..." +
+ cache.substring(end-25, end);
+ return StringUtil.escapify(ret, "\n\r");
+ }
+
}
public abstract boolean isCR();
long then = 0;
- private Cartesian.Location location = new Cartesian.Location(0, 1);
+ private Cartesian.Location location = new Cartesian.Location();
public edu.berkeley.sbp.Input.Location getLocation() { return location; }
public Token next() throws IOException {
- int line = location.getRow();
- int col = location.getCol();
+ int line = location.getRow();
+ int col = location.getCol();
+ int scalar = location.getScalar();
Token t = _next();
if (t==null) return null;
String s = " line "+line+", col " + col;
} else {
col++;
}
- location = new Cartesian.Location(col, line);
+ location.next = new Cartesian.Location(col, line, scalar+1);
+ location.next.prev = location;
+ location = location.next;
return t;
}
+
+ public String showRegion(Input.Region<Token> region) {
+ return null;
+ }
}
/** an implementation of Location for a cartesian grid (row, col) */
public static class Location<Tok> implements Input.Location<Tok>, Comparable<Input.Location> {
protected final int row;
protected final int col;
+ protected final int scalar;
+ Location<Tok> next = null;
+ Location<Tok> prev = null;
+ public Location<Tok> next() { return next; }
+ public Location<Tok> prev() { return prev; }
public String toString() { return row+":"+col; }
public int getCol() { return col; }
public int getRow() { return row; }
- public Location(int col, int row) { this.row = row; this.col = col; }
+ public int getScalar() { return scalar; }
+ public Location() { this(-1, 1, 0); }
+ public Location(int col, int row, int scalar) { this.row = row; this.col = col; this.scalar = scalar; }
public int compareTo(Input.Location loc) throws ClassCastException {
if (!(loc instanceof Cartesian.Location)) throw new ClassCastException(loc.getClass().getName());
Location<Tok> c = (Location<Tok>)loc;
public static class Region<Tok> implements Input.Region<Tok> {
public final Location<Tok> start;
public final Location<Tok> end;
+ public Location<Tok> getStart() { return start; }
+ public Location<Tok> getEnd() { return end; }
public String toString() {
+ if (start.row==end.row && start.col==end.col) return start+"";
if (start.row==end.row) return start.row+":"+(start.col+"-"+end.col);
return start+"-"+end;
}
expr.add(multSequence);
expr.add(Sequence.create(atom('0', '9')));
- String input = "(1+3*8)*7";
+ edu.berkeley.sbp.chr.CharInput input = new edu.berkeley.sbp.chr.CharInput("(1+3*8)*7");
System.out.println("input: \""+input+"\"");
System.out.println("grammar: \n"+sb);
Forest f = new edu.berkeley.sbp.chr.CharParser(expr).parse(input);
- System.out.println("output: "+f.expand1().toPrettyString());
+ try {
+ System.out.println("output: "+f.expand1().toPrettyString());
+ } catch (Ambiguous a) {
+ System.err.println(a.toString());
+ System.err.println(" ambiguous text: " + input.showRegion(a.getRegion()));
+ }
}
}
*/
public class Tib implements Input<Character> {
+ public String showRegion(Region<Character> r) { return null; }
+
public Tib(String s) throws IOException { this(new StringReader(s)); }
public Tib(Reader r) throws IOException { this(new BufferedReader(r)); }
public Tib(InputStream is) throws IOException { this(new BufferedReader(new InputStreamReader(is))); }
int _row = 1;
int _col = 0;
- public Input.Location getLocation() { return new Cartesian.Location(_col, _row); }
+ int _scalar = 0;
+ public Input.Location getLocation() { return new Cartesian.Location(_col, _row, _scalar); }
private BufferedReader br;
char left = CharAtom.left;
return null;
}
c = (char)i;
+ _scalar++;
if (c=='\n') { _row++; _col=0; }
else _col++;
}
public class ANSI {
//public static String black(Object o) { return "\033[30m"+o+"\033[0m"; }
public static String black(Object o) { return o+""; }
- //public static String red(Object o) { return "\033[31m"+o+"\033[0m"; }
- public static String red(Object o) { return o+""; }
+ public static String red(Object o) { return "\033[31m"+o+"\033[0m"; }
+ //public static String red(Object o) { return o+""; }
//public static String green(Object o) { return "\033[32m"+o+"\033[0m"; }
public static String green(Object o) { return o+""; }
//public static String yellow(Object o) { return "\033[33m"+o+"\033[0m"; }
}
protected abstract int bar(int c);
- protected abstract int bop( );
+ protected abstract int bop( );
-}
+}
\ No newline at end of file