copyright notices/updates
[sbp.git] / src / edu / berkeley / sbp / tib / Tib.java
1 // Copyright 2006 all rights reserved; see LICENSE file for BSD-style license
2
3 package edu.berkeley.sbp.tib;
4 import edu.berkeley.sbp.*;
5 import edu.berkeley.sbp.misc.*;
6 import edu.berkeley.sbp.chr.*;
7 import java.util.*;
8 import java.io.*;
9
10 // TODO: multiple {{ }} for superquotation
11 // TODO: strings
12 // TODO: comments
13
14 /**
15  *   A slow, ugly, inefficient, inelegant, ad-hoc parser for TIB files.
16  *
17  *   Despite being inelegant, this parser keeps all internal state on
18  *   the stack (the only heap objects created are those which are
19  *   returned).
20  *
21  *   This was written as an ad-hoc parser to facilitate
22  *   experimentation with the TIB spec.  Once the spec is finalized it
23  *   should probably be rewritten.
24  */
25 public class Tib implements Input<Character> {
26
27     public Tib(String s) throws IOException { this(new StringReader(s)); }
28     public Tib(Reader r) throws IOException { this(new BufferedReader(r)); }
29     public Tib(InputStream is) throws IOException { this(new BufferedReader(new InputStreamReader(is))); }
30     public Tib(BufferedReader br) throws IOException {
31         this.br = br;
32         istack.add(-1);
33         //cur = parse(br);
34         //System.out.println("\rparsing: \"" + cur.toString(0, -1) + "\"");
35     }
36
37     private String s = "";
38     int pos = 0;
39     int spos = 0;
40
41     int _row = 1;
42     int _col = 0;
43     public Input.Location getLocation() { return new Cartesian.Location(_col, _row); }
44     private BufferedReader br;
45
46     char left = CharAtom.left;
47     char right = CharAtom.right;
48
49     boolean waiting = false;
50     char waitingChar = ' ';
51     boolean indenting = true;
52     int indentation = 0;
53     private ArrayList<Integer> istack = new ArrayList<Integer>();
54     public Character next() throws IOException {
55         Character ret = nextc();
56         if      (ret==null) return null;
57         else if (ret==left)  System.out.print("\033[31m{\033[0m");
58         else if (ret==right) System.out.print("\033[31m}\033[0m");
59         else System.out.print(ret);
60         return ret;
61     }
62
63     Character waitingBrace = null;
64     public Character nextc() throws IOException {
65         char c;
66         if (waitingBrace != null) {
67             Character ret = waitingBrace;
68             waitingBrace = null;
69             return ret;
70         }
71         if (waiting) {
72             waiting = false;
73             c = waitingChar;
74         } else {
75             int i = br.read();
76             if (i==-1) {
77                 if (istack.size() > 1) {
78                     istack.remove(istack.size()-1);
79                     return right;
80                 }
81                 return null;
82             }
83             c = (char)i;
84             if (c=='\n') { _row++; _col=0; }
85             else         _col++;
86         }
87         if (indenting) {
88             if (c==' ') { indentation++; return done(c); }
89             if (c=='\n') { indentation = 0; if (blank) return nextc(); blank = true; waiting = true; waitingChar='\n'; return '\n'; }
90             int last = istack.size()==0 ? -1 : istack.get(istack.size()-1);
91             if (indentation==last) {
92                 if (blank) {
93                     indenting = false;
94                     waitingChar = c;
95                     waiting = true;
96                     waitingBrace = left;
97                     return right;
98                     //return nextc(numstates);
99                 }
100                 blank = false;
101                 indenting = false;
102                 return done(c);
103             }
104             blank = false;
105             waitingChar = c;
106             waiting = true;
107             if (indentation > last) {
108                 indenting = false;
109                 istack.add(indentation);
110                 //System.out.print("\033[31m+"+indentation+"+\033[0m");
111                 return left;
112             } else /*if (indentation < last)*/ {
113                 istack.remove(istack.size()-1);
114                 //System.out.print("\033[31m-"+last+"-\033[0m");
115                 blank = true;
116                 return right;
117             }
118         } else {
119             blank = false;
120             if (c=='\n') { indenting=true; indentation = 0; }
121             return done(c);
122         }
123     }
124
125     public Character done(char c) {
126         switch(c) {
127             case '{': return left;
128             case '}': return right;
129             default: return c;
130         }
131     }
132     boolean blank = false;
133
134     // Grammar //////////////////////////////////////////////////////////////////////////////
135
136     /*
137     public static class Grammar extends ReflectiveGrammar {
138         private int anon = 0;
139         private final Element ws = Sequence.maximal0(getNonTerminal("w"));
140         public Grammar(Class c) { super(c); dropAll.add(ws); }
141         public Object walk(Tree<String> tree) {
142             String head = tree.head();
143             if (tree.numChildren()==0) return super.walk(tree);
144             if ("{".equals(head)) {
145                 Union u = new Union("???");
146                 Union u2 = ((PreSequence)walk(tree, 0)).sparse(ws).buildUnion();
147                 u2.add(Sequence.singleton(new Element[] { u }, 0));
148                 return anonymousNonTerminal(new Sequence[][] {
149                     new Sequence[] {
150                         Sequence.singleton(new Element[] { CharAtom.leftBrace,
151                                                            ws,
152                                                            u2,
153                                                            ws,
154                                                            CharAtom.rightBrace
155                         }, 2)
156                     }
157                 });
158             }
159             return super.walk(tree);
160         }
161     }
162     */
163
164     /*
165 public class Braces extends Union {
166
167     private static final Element left  = string("{");
168     private static final Element right = string("}");
169     
170     public static String join(Object[] e) {
171         StringBuffer ret = new StringBuffer();
172         for(int i=0; i<e.length; i++) {
173             if (i>0) ret.append(" ");
174             ret.append(e[i]);
175         }
176         return ret.toString();
177     }
178
179     public Braces(Element[] e, Element sep) {
180         super("{"+join(e)+"}");
181         Element[] e2 = new Element[sep == null ? e.length+2 : e.length + 4];
182         e2[0]           = left;
183         e2[e2.length-1] = right;
184         if (sep != null) {
185             e2[1] = sep;
186             e2[e2.length-2] = sep;
187         }
188         for(int i=0; i<e.length; i++) e2[i+(sep==null ? 1 : 2)] = e[i];
189         addAlternative(new Sequence.Singleton(e2));
190         addAlternative(new Sequence.Singleton(sep==null ? new Element[] { left, this, right} : new Element[] { left, sep, this, sep, right }));
191     }
192 }
193                       */
194
195 }
196