package edu.berkeley.sbp.tib;
import edu.berkeley.sbp.*;
import edu.berkeley.sbp.misc.*;
+import edu.berkeley.sbp.chr.*;
import java.util.*;
import java.io.*;
* experimentation with the TIB spec. Once the spec is finalized it
* should probably be rewritten.
*/
-public class Tib implements Token.Stream<CharToken> {
-
- public Tib(String s) throws IOException, Invalid { this(new StringReader(s)); }
- public Tib(Reader r) throws IOException, Invalid { this(new BufferedReader(r)); }
- public Tib(InputStream is) throws IOException, Invalid { this(new BufferedReader(new InputStreamReader(is))); }
- public Tib(BufferedReader br) throws IOException, Invalid {
- cur = parse(br);
- System.out.println("\rparsing: \"" + cur.toString(0, -1) + "\"");
+public class Tib implements Input<Character> {
+
+ 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))); }
+ public Tib(BufferedReader br) throws IOException {
+ this.br = br;
+ istack.add(-1);
+ //cur = parse(br);
+ //System.out.println("\rparsing: \"" + cur.toString(0, -1) + "\"");
}
- private Block cur;
- private String s = null;
+ private String s = "";
int pos = 0;
int spos = 0;
- int _row = 0;
+ int _row = 1;
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) {
- if (spos < s.length()) {
- char c = s.charAt(spos++);
- if (c=='\n') { _row++; _col = 0; }
- else _col++;
- return new CharToken(c);
- }
- s = null;
- }
- if (pos >= cur.size()) {
- pos = cur.iip+1;
- _row = cur.endrow;
- _col = cur.endcol;
- cur = cur.parent;
- if (cur==null) return null;
- return CharToken.right;
- }
- Object o = cur.child(pos++);
- if (o instanceof String) {
- spos = 0;
- s = (String)o;
- return next();
- }
- if (o instanceof Block) {
- Block b = (Block)o;
- _row = b.row;
- _col = b.col;
- }
- if (((Block)o).isLiteral()) {
- spos = 0;
- s = ((Block.Literal)o).text();
- return next();
- }
- cur = (Block)o;
- pos = 0;
- return CharToken.left;
+ public Input.Location getLocation() { return new Cartesian.Location(_col, _row); }
+ private BufferedReader br;
+
+ char left = CharAtom.left;
+ char right = CharAtom.right;
+
+ boolean waiting = false;
+ char waitingChar = ' ';
+ boolean indenting = true;
+ int indentation = 0;
+ private ArrayList<Integer> istack = new ArrayList<Integer>();
+ public Character next() throws IOException {
+ Character ret = nextc();
+ if (ret==null) return null;
+ else if (ret==left) System.out.print("\033[31m{\033[0m");
+ else if (ret==right) System.out.print("\033[31m}\033[0m");
+ else System.out.print(ret);
+ return ret;
}
- public static Block parse(BufferedReader br) throws Invalid, IOException {
- int row=0, col=0;
- try {
- boolean blankLine = false;
- Block top = new Block.Root();
- for(String s = br.readLine(); s != null; s = br.readLine()) {
- row++;
- col=0;
- while (s.length() > 0 &&
- s.charAt(0) == ' ' &&
- (!(top instanceof Block.Literal) || col < top.col)) { col++; s = s.substring(1); }
- if ((top instanceof Block.Literal) && col >= top.col) { top.add(s); continue; }
- if (s.length()==0) { blankLine = true; continue; }
- while (col < top.col) {
- if (s.startsWith("{}") && top instanceof Block.Literal && ((Block.Literal)top).braceCol == col) break;
- blankLine = false;
- top.endrow = row;
- top.endcol = col;
- top = top.closeIndent();
- }
- if (s.startsWith("{}")) {
- int bc = col;
- boolean append = top instanceof Block.Literal && ((Block.Literal)top).braceCol == bc;
- s = s.substring(2);
- col += 2;
- while (s.length() > 0 && s.charAt(0) == ' ' && !(append && col >= top.col) ) { col++; s = s.substring(1); }
- if (append) top.add(s); else (top = new Block.Literal(top, row, col, bc)).add(s);
- continue;
- }
- while (s.length() > 0 && s.charAt(s.length()-1)==' ') { s = s.substring(0, s.length()-1); }
- if (col > top.col) top = new Block.Indent(top, row, col);
- else if (blankLine) { top.endrow=row; top.endcol=col; top = top.closeIndent(); top = new Block.Indent(top, row, col); }
- blankLine = false;
- for(int i=0; i<s.length(); i++) {
- top.add(s.charAt(i));
- switch(s.charAt(i)) {
- case '{': top = new Block.Brace(top, row, col); break;
- case '}': top.endrow=row; top.endcol=col; top = top.closeBrace(); break;
- }
- }
- top.add('\n');
- top.finishWord();
- }
- // FIXME
- Block ret = top;
- while (ret.parent != null) ret = ret.parent;
+ Character waitingBrace = null;
+ public Character nextc() throws IOException {
+ char c;
+ if (waitingBrace != null) {
+ Character ret = waitingBrace;
+ waitingBrace = null;
return ret;
- } catch (InternalException ie) {
- throw new Invalid(ie, row, col);
- }
- }
-
- public static class Block {
- Block parent;
- public final int row;
- public final int col;
- public int endrow;
- public int endcol;
- public final int iip;
- private final Vector children = new Vector();
- private String pending = "";
-
- public int size() { return children.size(); }
- public Object child(int i) { return children.elementAt(i); }
- public boolean isLiteral() { return false; }
-
- protected Block(int row, int col) {
- this.row=row;
- this.col=col;
- this.iip = -1;
- parent = null;
- }
- public Block(Block parent, int row, int col) {
- this.row=row;
- this.col=col;
- this.iip = parent.size();
- (this.parent = parent).add(this);
- }
-
- public void add(String s) { children.addElement(s); }
- public void add(char c) {
- if (c == '{' || c == '}') { finishWord(); return; }
- if (c != ' ') { pending += c; return; }
- if (pending.length() > 0) { finishWord(); add(" "); return; }
- if (size()==0) return;
- if (child(size()-1).equals(" ")) return;
- add(" ");
- return;
- }
-
- public void add(Block b) { children.addElement(b); }
- public Block promote() { parent.parent.replaceLast(this); return close(); }
- public Object lastChild() { return children.lastElement(); }
- public Block lastChildAsBlock() { return (Block)lastChild(); }
- public void replaceLast(Block b) { children.setElementAt(b, children.size()-1); b.parent = this; }
-
- public void finishWord() { if (pending.length() > 0) { add(pending); pending = ""; } }
-
- public Block closeBrace() { throw new InternalException("attempt to closeBrace() a "+getClass().getName()); }
- public Block closeIndent() { throw new InternalException("attempt to closeIndent() a "+getClass().getName()); }
- public Block close() {
- while(size() > 0 && child(size()-1).equals(" ")) children.setSize(children.size()-1);
- if (size()==0) throw new InternalException("PARSER BUG: attempt to close an empty block (should never happen)");
- if (size() > 1 || !(lastChild() instanceof Block)) return parent;
- return lastChildAsBlock().promote();
}
- public String toString() { return toString(80); }
- public String toString(int justificationLimit) { return toString(0, 80); }
- protected String toString(int indent, int justificationLimit) {
- StringBuffer ret = new StringBuffer();
- StringBuffer line = new StringBuffer();
- for(int i=0; i<children.size(); i++) {
- Object o = children.elementAt(i);
- if (i>0 && children.elementAt(i-1) instanceof Block && justificationLimit!=-1) ret.append("\n");
- if (o instanceof Block) {
- ret.append(justify(line.toString(), indent, justificationLimit));
- line.setLength(0);
- if (justificationLimit==-1) {
- ret.append("{");
- ret.append(((Block)o).toString(indent+2, justificationLimit));
- ret.append("}");
- } else {
- ret.append(((Block)o).toString(indent+2, justificationLimit));
- }
- } else {
- line.append(o.toString());
+ if (waiting) {
+ waiting = false;
+ c = waitingChar;
+ } else {
+ int i = br.read();
+ if (i==-1) {
+ if (istack.size() > 1) {
+ istack.remove(istack.size()-1);
+ return right;
}
+ return null;
}
- ret.append(justify(line.toString(), indent, justificationLimit));
- return ret.toString();
- }
-
- private static class Root extends Block {
- public Root() { super(0, Integer.MIN_VALUE); }
- public Block close() { throw new InternalException("attempted to close top block"); }
- public String toString(int justificationLimit) { return toString(-2, justificationLimit); }
- }
-
- private static class Brace extends Block {
- public Brace(Block parent, int row, int col) { super(parent, row, col); }
- public Block closeBrace() { return super.close(); }
- }
-
- private static class Indent extends Block {
- public Indent(Block parent, int row, int col) { super(parent, row, col); }
- public Block closeIndent() { return super.close(); }
- }
-
- private static class Literal extends Block {
- private StringBuffer content = new StringBuffer();
- public final int braceCol;
- public Literal(Block parent, int row, int col, int braceCol) { super(parent,row,col); this.braceCol = braceCol; }
- public boolean isLiteral() { return true; }
- public int size() { return 1; }
- public Object child(int i) { return i==0 ? content.toString() : null; }
- public Block close() { return parent; }
- public Block closeIndent() { return close(); }
- public void add(String s) { if (content.length()>0) content.append('\n'); content.append(s); }
- public String text() { return content.toString(); }
- protected String toString(int indent, int justificationLimit) {
- StringBuffer ret = new StringBuffer();
- String s = content.toString();
- while(s.length() > 0) {
- int nl = s.indexOf('\n');
- if (nl==-1) nl = s.length();
- ret.append(spaces(indent));
- ret.append("{} ");
- ret.append(s.substring(0, nl));
- s = s.substring(Math.min(s.length(),nl+1));
- ret.append('\n');
+ c = (char)i;
+ if (c=='\n') { _row++; _col=0; }
+ else _col++;
+ }
+ if (indenting) {
+ if (c==' ') { indentation++; return done(c); }
+ if (c=='\n') { indentation = 0; if (blank) return nextc(); blank = true; waiting = true; waitingChar='\n'; return '\n'; }
+ int last = istack.size()==0 ? -1 : istack.get(istack.size()-1);
+ if (indentation==last) {
+ if (blank) {
+ indenting = false;
+ waitingChar = c;
+ waiting = true;
+ waitingBrace = left;
+ return right;
+ //return nextc(numstates);
}
- return ret.toString();
+ blank = false;
+ indenting = false;
+ return done(c);
}
+ blank = false;
+ waitingChar = c;
+ waiting = true;
+ if (indentation > last) {
+ indenting = false;
+ istack.add(indentation);
+ //System.out.print("\033[31m+"+indentation+"+\033[0m");
+ return left;
+ } else /*if (indentation < last)*/ {
+ istack.remove(istack.size()-1);
+ //System.out.print("\033[31m-"+last+"-\033[0m");
+ blank = true;
+ return right;
+ }
+ } else {
+ blank = false;
+ if (c=='\n') { indenting=true; indentation = 0; }
+ return done(c);
}
}
-
- // Exceptions //////////////////////////////////////////////////////////////////////////////
-
- private static class InternalException extends RuntimeException { public InternalException(String s) { super(s); } }
- public static class Invalid extends /*IOException*/RuntimeException {
- public Invalid(InternalException ie, int row, int col) {
- super(ie.getMessage() + " at " + row + ":" + col);
- }
- }
-
- // Testing //////////////////////////////////////////////////////////////////////////////
-
- public static void main(String[] s) throws Exception {
- System.out.println(parse(new BufferedReader(new InputStreamReader(System.in))).toString(-1)); }
-
- // Utilities //////////////////////////////////////////////////////////////////////////////
-
- public static String spaces(int i) { if (i<=0) return ""; return " " + spaces(i-1); }
-
- private static String justify(String s, int indent, int justificationLimit) {
- if (s.length() == 0) return "";
- if (justificationLimit==-1) return s;
- StringBuffer ret = new StringBuffer();
- while(s.length() > 0) {
- if (s.charAt(0) == ' ') { s = s.substring(1); continue; }
- ret.append(spaces(indent));
- int i = s.indexOf(' ');
- if (i==-1) i = s.length();
- while(s.indexOf(' ', i+1) != -1 && s.indexOf(' ', i+1) < justificationLimit-indent) i = s.indexOf(' ', i+1);
- if (s.length() + indent < justificationLimit) i = s.length();
- ret.append(s.substring(0, i));
- s = s.substring(i);
- ret.append('\n');
+ public Character done(char c) {
+ switch(c) {
+ case '{': return left;
+ case '}': return right;
+ default: return c;
}
- return ret.toString();
}
+ boolean blank = false;
// Grammar //////////////////////////////////////////////////////////////////////////////
- public static class Grammar extends MetaGrammar {
+ /*
+ public static class Grammar extends ReflectiveGrammar {
private int anon = 0;
- private final Element ws = Repeat.maximal0(nonTerminal("w"));
- public Grammar() { dropAll.add(ws); }
+ private final Element ws = Sequence.maximal0(getNonTerminal("w"));
+ public Grammar(Class c) { super(c); dropAll.add(ws); }
public Object walk(Tree<String> tree) {
String head = tree.head();
if (tree.numChildren()==0) return super.walk(tree);
if ("{".equals(head)) {
- String s = "braced"+(anon++);
- Union u = nonTerminal(s);
+ Union u = new Union("???");
Union u2 = ((PreSequence)walk(tree, 0)).sparse(ws).buildUnion();
- u2.add(Sequence.singleton(new Element[] { u }, 0, null, null));
- return nonTerminal(s,
- new PreSequence[][] {
- new PreSequence[] {
- new PreSequence(new Element[] { CharToken.leftBrace,
- ws,
- u2,
- ws,
- CharToken.rightBrace
- })
- }
- },
- false,
- false);
+ u2.add(Sequence.singleton(new Element[] { u }, 0));
+ return anonymousNonTerminal(new Sequence[][] {
+ new Sequence[] {
+ Sequence.singleton(new Element[] { CharAtom.leftBrace,
+ ws,
+ u2,
+ ws,
+ CharAtom.rightBrace
+ }, 2)
+ }
+ });
}
return super.walk(tree);
}
}
+ */
+
+ /*
+public class Braces extends Union {
+
+ private static final Element left = string("{");
+ private static final Element right = string("}");
+
+ public static String join(Object[] e) {
+ StringBuffer ret = new StringBuffer();
+ for(int i=0; i<e.length; i++) {
+ if (i>0) ret.append(" ");
+ ret.append(e[i]);
+ }
+ return ret.toString();
+ }
+
+ public Braces(Element[] e, Element sep) {
+ super("{"+join(e)+"}");
+ Element[] e2 = new Element[sep == null ? e.length+2 : e.length + 4];
+ e2[0] = left;
+ e2[e2.length-1] = right;
+ if (sep != null) {
+ e2[1] = sep;
+ e2[e2.length-2] = sep;
+ }
+ for(int i=0; i<e.length; i++) e2[i+(sep==null ? 1 : 2)] = e[i];
+ addAlternative(new Sequence.Singleton(e2));
+ addAlternative(new Sequence.Singleton(sep==null ? new Element[] { left, this, right} : new Element[] { left, sep, this, sep, right }));
+ }
+}
+ */
}