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 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     boolean waiting = false;
48     char waitingChar = ' ';
49     boolean indenting = true;
50     int indentation = 0;
51     private ArrayList<Integer> istack = new ArrayList<Integer>();
52     public Character next(int numstates, int resets, int waits) throws IOException {
53         Character ret = nextc(numstates, resets);
54         if      (ret==CharToken.left)  System.out.print("\033[31m{\033[0m");
55         else if (ret==CharToken.right) System.out.print("\033[31m}\033[0m");
56         else if (ret==null) return null;
57         else System.out.print(ret);
58         return ret;
59     }
60
61     Character waitingBrace = null;
62     public Character nextc(int numstates, int resets) throws IOException {
63         char c;
64         if (waitingBrace != null) {
65             Character ret = waitingBrace;
66             waitingBrace = null;
67             return ret;
68         }
69         if (waiting) {
70             waiting = false;
71             c = waitingChar;
72         } else {
73             int i = br.read();
74             if (i==-1) {
75                 if (istack.size() > 1) {
76                     istack.remove(istack.size()-1);
77                     return CharToken.right;
78                 }
79                 return null;
80             }
81             c = (char)i;
82         }
83         if (c=='\n') { _row++; _col=0; }
84         else         _col++;
85         if (indenting) {
86             if (c==' ') { indentation++; return done(c); }
87             if (c=='\n') { indentation = 0; if (blank) return nextc(numstates, resets); blank = true; waiting = true; waitingChar='\n'; return '\n'; }
88             int last = istack.size()==0 ? -1 : istack.get(istack.size()-1);
89             if (indentation==last) {
90                 if (blank) {
91                     indenting = false;
92                     waitingChar = c;
93                     waiting = true;
94                     waitingBrace = CharToken.left;
95                     return CharToken.right;
96                     //return nextc(numstates);
97                 }
98                 blank = false;
99                 indenting = false;
100                 return done(c);
101             }
102             blank = false;
103             waitingChar = c;
104             waiting = true;
105             if (indentation > last) {
106                 indenting = false;
107                 istack.add(indentation);
108                 //System.out.print("\033[31m+"+indentation+"+\033[0m");
109                 return CharToken.left;
110             } else /*if (indentation < last)*/ {
111                 istack.remove(istack.size()-1);
112                 //System.out.print("\033[31m-"+last+"-\033[0m");
113                 blank = true;
114                 return CharToken.right;
115             }
116         } else {
117             blank = false;
118             if (c=='\n') { indenting=true; indentation = 0; }
119             return done(c);
120         }
121     }
122
123     public Character done(char c) {
124         switch(c) {
125             case '{': return CharToken.left;
126             case '}': return CharToken.right;
127             default: return c;
128         }
129     }
130     boolean blank = false;
131
132     // Grammar //////////////////////////////////////////////////////////////////////////////
133
134     public static class Grammar extends MetaGrammar {
135         private int anon = 0;
136         private final Element ws = Repeat.maximal0(nonTerminal("w"));
137         public Grammar() { dropAll.add(ws); }
138         public Object walk(Tree<String> tree) {
139             String head = tree.head();
140             if (tree.numChildren()==0) return super.walk(tree);
141             if ("{".equals(head)) {
142                 String s = "braced"+(anon++);
143                 Union u = nonTerminal(s);
144                 Union u2 = ((PreSequence)walk(tree, 0)).sparse(ws).buildUnion();
145                 u2.add(Sequence.singleton(new Element[] { u }, 0, null, null));
146                 return nonTerminal(s,
147                                    new PreSequence[][] {
148                                        new PreSequence[] {
149                                            new PreSequence(new Element[] { CharToken.leftBrace,
150                                                                            ws,
151                                                                            u2,
152                                                                            ws,
153                                                                            CharToken.rightBrace
154                                            })
155                                        }
156                                    },
157                                    false,
158                                    false);
159             }
160             return super.walk(tree);
161         }
162     }
163
164     /*
165 public class Braces extends Union {
166
167     private static final Element left  = CharToken.string("{");
168     private static final Element right = CharToken.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