add Input.getName()
[sbp.git] / src / edu / berkeley / sbp / tib / Tib.java
index 7f9b913..41aab5c 100644 (file)
@@ -1,17 +1,12 @@
-// Copyright 2005 the Contributors, as shown in the revision logs.
-// Licensed under the Apache Public Source License 2.0 ("the License").
-// You may not use this file except in compliance with the License.
+// Copyright 2006 all rights reserved; see LICENSE file for BSD-style license
 
 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.*;
 
-// TODO: multiple {{ }} for superquotation
-// TODO: strings
-// TODO: comments
-
 /**
  *   A slow, ugly, inefficient, inelegant, ad-hoc parser for TIB files.
  *
@@ -23,267 +18,182 @@ 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 String showRegion(Region<Character> r) { return ""; }
+
+    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;
+    public String getName() { return null; }
+    private String s = "";
     int pos = 0;
     int spos = 0;
 
-    int _row = 0;
+    int _row = 1;
     int _col = 0;
-    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, _row, _col);
-            }
-            s = null;
-        }
-        if (pos >= cur.size()) {
-            pos = cur.iip+1;
-            cur = cur.parent;
-            if (cur==null) return null;
-            return CharToken.right(_row, _col);
-        }
-        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(_row, _col);
+    int _scalar = 0;
+    public Input.Location getLocation() { return new Cartesian.Location(_col, _row, _scalar); }
+    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>();
+    private static boolean debug = "true".equals(System.getProperty("tib.debug", "false"));
+    public Character next() throws IOException {
+        Character ret = nextc();
+        if (debug) {
+            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()) {
-                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 = 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 = 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 = top.closeBrace();                 break;
-                    }
-                }
-                top.add(' ');
-                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 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;
+            _scalar++;
+            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);
+    public Character done(char c) {
+        switch(c) {
+            case '{': return left;
+            case '}': return right;
+            default: return c;
+        }
+    }
+    boolean blank = false;
+
+    // Grammar //////////////////////////////////////////////////////////////////////////////
+
+    /*
+    public static class Grammar extends ReflectiveGrammar {
+        private int anon = 0;
+        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)) {
+                Union u = new Union("???");
+                Union u2 = ((PreSequence)walk(tree, 0)).sparse(ws).buildUnion();
+                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);
         }
     }
+    */
 
-    // Testing //////////////////////////////////////////////////////////////////////////////
+    /*
+public class Braces extends Union {
 
-    public static void main(String[] s) throws Exception { System.out.println(parse(new BufferedReader(new InputStreamReader(System.in))).toString(-1)); }
+    private static final Element left  = string("{");
+    private static final Element right = string("}");
     
-    // 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;
+    public static String join(Object[] e) {
         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');
+        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 }));
+    }
+}
+                      */
+
 }