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