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