update metagrammar
[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 /**
11  *   A slow, ugly, inefficient, inelegant, ad-hoc parser for TIB files.
12  *
13  *   Despite being inelegant, this parser keeps all internal state on
14  *   the stack (the only heap objects created are those which are
15  *   returned).
16  *
17  *   This was written as an ad-hoc parser to facilitate
18  *   experimentation with the TIB spec.  Once the spec is finalized it
19  *   should probably be rewritten.
20  */
21 public class Tib implements Input<Character> {
22
23     public String showRegion(Region<Character> r) { return ""; }
24
25     public Tib(String s) throws IOException { this(new StringReader(s)); }
26     public Tib(Reader r) throws IOException { this(new BufferedReader(r)); }
27     public Tib(InputStream is) throws IOException { this(new BufferedReader(new InputStreamReader(is))); }
28     public Tib(BufferedReader br) throws IOException {
29         this.br = br;
30         istack.add(-1);
31     }
32     public String getName() { return null; }
33     private String s = "";
34     int pos = 0;
35     int spos = 0;
36
37     int _row = 1;
38     int _col = 0;
39     int _scalar = 0;
40     public Input.Location getLocation() { return new Cartesian.Location(_col, _row, _scalar); }
41     private BufferedReader br;
42
43     char left = CharAtom.left;
44     char right = CharAtom.right;
45
46     boolean waiting = false;
47     char waitingChar = ' ';
48     boolean indenting = true;
49     int indentation = 0;
50     private ArrayList<Integer> istack = new ArrayList<Integer>();
51     private static boolean debug = "true".equals(System.getProperty("tib.debug", "false"));
52     public Character next() throws IOException {
53         Character ret = nextc();
54         if (debug) {
55             if      (ret==null) return null;
56             else if (ret==left)  System.err.print("\033[31m{\033[0m");
57             else if (ret==right) System.err.print("\033[31m}\033[0m");
58             else System.err.print(ret);
59         }
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             _scalar++;
85             if (c=='\n') { _row++; _col=0; }
86             else         _col++;
87         }
88         if (indenting) {
89             if (c==' ') { indentation++; return done(c); }
90             if (c=='\n') { indentation = 0; if (blank) return nextc(); 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 }
136