| 1 package gnu.q2.lang; 2 import gnu.kawa.lispexpr.*; 3 import gnu.expr.QuoteExp; 4 import gnu.text.*; 5 import gnu.mapping.*; 6 import gnu.lists.*; 7 import gnu.expr.Keyword; 8 import gnu.kawa.xml.MakeAttribute; 9 10 11 12 public class Q2Read extends LispReader 13 { 14 void init() 15 { 16 initialColonIsKeyword = false; 17 ((InPort) port).readState = ' '; 18 } 19 20 public Q2Read(InPort port) 21 { 22 super(port); 23 init(); 24 } 25 26 public Q2Read(InPort port, SourceMessages messages) 27 { 28 super(port, messages); 29 init(); 30 } 31 32 int skipIndentation () 33 throws java.io.IOException , SyntaxException 34 { 35 int numTabs = 0, numSpaces = 0; 36 int ch = port.read(); 37 while (ch == '\t') 38 { 39 numTabs++; 40 ch = port.read(); 41 } 42 while (ch == ' ') 43 { 44 numSpaces++; 45 ch = port.read(); 46 } 47 if (ch < 0) 48 return -1; 49 port.unread(); 50 return (numTabs << 16) + numSpaces; 51 } 52 53 boolean singleLine() 54 { 55 return interactive && nesting == 0; 56 } 57 58 public Object readCommand () 59 throws java.io.IOException , SyntaxException 60 { 61 return readCommand(false); 62 } 63 64 public Object readCommand (boolean forceList) 65 throws java.io.IOException , SyntaxException 66 { 67 int line = port.getLineNumber(); 68 int startColumn = port.getColumnNumber(); 69 int lastColumn = startColumn; 70 Object obj = LList.Empty; 71 PairWithPosition pair = null, last = null; 72 for (;;) 73 { 74 int ch = read(); 75 if (ch < 0) 76 break; 77 if (ch == ' ' || ch == '\t') 78 continue; 79 unread(); 80 if (ch == ')') 81 break; 82 line = port.getLineNumber(); 83 int column = port.getColumnNumber(); 84 while (ch == '\r' || ch == '\n') 85 { 86 if (singleLine()) 87 return obj; 88 ch = read(); 89 skipIndentation(); column = port.getColumnNumber(); 91 ch = peek(); 92 if (column <= startColumn) 93 break; 94 } 95 if (column <= startColumn && last != null) 96 break; 97 Object next; 98 if (column == lastColumn && last != null) 99 next = readCommand(); 100 else if (column < lastColumn && last != null) 101 { 102 PairWithPosition p = pair; 103 for (;;) 104 { 105 Object n = p.cdr; 106 if (n == LList.Empty) 107 break; 108 PairWithPosition np = (PairWithPosition) n; 109 int pColumn = np.getColumnNumber()-1; 110 if (pColumn >= column) 111 { 112 if (pColumn > column) 113 error('e', "some tokens on previous line indented more than current line"); 114 n = np.cdr; 115 if (n != LList.Empty) 116 { 117 if (((PairWithPosition) n).getColumnNumber()-1==column) 118 { 119 p = (PairWithPosition) n; 120 continue; 121 } 122 last = (PairWithPosition) 123 makePair(np, port.getLineNumber(), column); 124 p.cdr = last; 125 } 126 break; 127 } 128 p = np; 129 } 130 next = readCommand(); 131 } 132 else 133 next = readObject(); 134 if (next == Sequence.eofValue) 135 break; 136 lastColumn = column; 137 String filename = port.getName(); 138 PairWithPosition cur = PairWithPosition.make(next, LList.Empty, 139 filename, line+1, column+1); 140 if (last == null) 141 { 142 pair = cur; 143 obj = cur; 144 } 145 else if (last.car instanceof Keyword) 146 { 147 Object name = new QuoteExp(((Keyword) last.car).getName()); 148 last.car 149 = new PairWithPosition(last, MakeAttribute.makeAttribute, 150 new PairWithPosition(last, name, cur)); 151 continue; 152 } 153 else 154 last.cdr = cur; 155 last = cur; 156 } 157 if (! forceList) 158 { 159 if (obj == last) 160 obj = last.car; 161 else if (last == null) 162 obj = QuoteExp.voidExp; 163 } 164 return obj; 165 } 166 167 public static Object readObject(InPort port) 168 throws java.io.IOException , SyntaxException 169 { 170 return (new Q2Read(port)).readObject(); 171 } 172 173 174 String expressionStartFile; 175 int expressionStartLine; 176 int expressionStartColumn; 177 178 void saveExpressionStartPosition() 179 { 180 expressionStartFile = port.getName(); 181 expressionStartLine = port.getLineNumber(); 182 expressionStartColumn = port.getColumnNumber(); 183 } 184 } 185 186 class Q2ReaderParens extends ReaderDispatchMisc 187 { 188 public Object read (Lexer in, int ch, int count) 189 throws java.io.IOException , SyntaxException 190 { 191 Q2Read reader = (Q2Read) in; 192 char saveReadState = reader.pushNesting('('); 193 try 194 { 195 Object result = reader.readCommand(true); 196 197 LineBufferedReader port = reader.getPort(); 198 if (port.read() != ')') 199 reader.error("missing ')'"); 200 return result; 201 } 202 finally 203 { 204 reader.popNesting(saveReadState); 205 } 206 } 207 208 } 209 | Popular Tags |