1 16 package org.apache.cocoon.components.language.markup.xsp; 17 18 import org.xml.sax.SAXException ; 19 20 38 public class XSPExpressionParser { 39 40 44 public static interface Handler { 45 public void handleText(char[] chars, int start, int length) throws SAXException ; 46 47 public void handleExpression(char[] chars, int start, int length) throws SAXException ; 48 } 49 50 53 protected static abstract class State { 54 61 public abstract void consume(XSPExpressionParser parser, char ch) throws SAXException ; 62 63 70 public void done(XSPExpressionParser parser) throws SAXException { 71 throw new SAXException ("Incomplete XSP expression {#"+parser.getExpression()); 72 } 73 } 74 75 78 protected static class QuotedState extends State { 79 private final char quote; 80 81 86 public QuotedState(char quote) { 87 this.quote = quote; 88 } 89 90 97 public void consume(XSPExpressionParser parser, char ch) throws SAXException { 98 parser.append(ch); 99 if (ch == quote && !parser.isEscaped()) 100 parser.setState(EXPRESSION_STATE); 101 else if (ch == '\\') 102 parser.setEscaped(!parser.isEscaped()); 103 else 104 parser.setEscaped(false); 105 } 106 } 107 108 111 protected static final State TEXT_STATE = new State() { 112 public void consume(XSPExpressionParser parser, char ch) throws SAXException { 113 switch (ch) { 114 case '{': 115 parser.setState(LBRACE_STATE); 116 break; 117 118 default: 119 parser.append(ch); 120 } 121 } 122 123 128 public void done(XSPExpressionParser parser) throws SAXException { 129 parser.handleText(); 130 } 131 }; 132 133 136 protected static final State LBRACE_STATE = new State() { 137 public void consume(XSPExpressionParser parser, char ch) throws SAXException { 138 switch (ch) { 139 case '#': 140 parser.setState(TEXT_HASH_STATE); 141 break; 142 143 default: 144 parser.append('{'); 145 parser.append(ch); 146 parser.setState(TEXT_STATE); 147 } 148 } 149 150 155 public void done(XSPExpressionParser parser) throws SAXException { 156 parser.append('{'); 158 parser.handleText(); 159 } 160 }; 161 162 165 protected static final State TEXT_HASH_STATE = new State() { 166 public void consume(XSPExpressionParser parser, char ch) throws SAXException { 167 switch (ch) { 168 case '#': 169 parser.append('{'); 170 parser.append('#'); 171 parser.setState(TEXT_STATE); 172 break; 173 174 default: 175 parser.handleText(); 176 parser.initExpression(); 177 parser.setState(EXPRESSION_STATE); 178 EXPRESSION_STATE.consume(parser, ch); 179 } 180 } 181 }; 182 183 186 protected static final State EXPRESSION_STATE = new State() { 187 public void consume(XSPExpressionParser parser, char ch) throws SAXException { 188 switch (ch) { 189 case '{': 190 parser.incrNesting(); 191 parser.append(ch); 192 break; 193 194 case '}': 195 if (parser.decrNesting() > 0) { 196 parser.append(ch); 197 } 198 else { 199 parser.handleExpression(); 200 parser.setState(TEXT_STATE); 201 } 202 break; 203 204 case '"': 205 parser.append(ch); 206 parser.setState(EXPRESSION_STRING_STATE); 207 break; 208 209 case '\'': 210 parser.append(ch); 211 parser.setState(EXPRESSION_CHAR_STATE); 212 break; 213 214 case '\u00B4': 215 parser.append(ch); 216 parser.setState(EXPRESSION_SHELL_STATE); 217 break; 218 219 default: 220 parser.append(ch); 221 } 222 } 223 }; 224 225 229 protected static final State EXPRESSION_STRING_STATE = new QuotedState('"'); 230 231 235 protected static final State EXPRESSION_CHAR_STATE = new QuotedState('\''); 236 237 241 protected static final State EXPRESSION_SHELL_STATE = new QuotedState('`'); 242 243 246 private State state = TEXT_STATE; 247 248 251 private int nesting = 0; 252 253 256 private boolean escaped = false; 257 258 261 private Handler handler; 262 263 267 private char[] buf = new char[256]; 268 269 272 private int bufSize; 273 274 277 private int bufGrow = 256; 278 279 284 public XSPExpressionParser(Handler handler) { 285 this.handler = handler; 286 } 287 288 294 public void consume(String chars) throws SAXException { 295 int end = chars.length(); 296 297 for (int i = 0; i < end; ++i) { 298 char ch = chars.charAt(i); 299 state.consume(this, ch); 300 } 301 } 302 303 311 public void consume(char[] chars, int start, int length) throws SAXException { 312 int end = start + length; 313 314 for (int i = start; i < end; ++i) { 315 char ch = chars[i]; 316 state.consume(this, ch); 317 } 318 } 319 320 325 public void flush() throws SAXException { 326 state.done(this); 327 bufSize = 0; 328 state = TEXT_STATE; 329 } 330 331 protected State getState() { 332 return state; 333 } 334 335 protected void setState(State state) { 336 this.state = state; 337 } 338 339 protected void initExpression() { 340 nesting = 1; 341 escaped = false; 342 } 343 344 protected void incrNesting() { 345 nesting++; 346 } 347 348 protected int decrNesting() { 349 return --nesting; 350 } 351 352 protected void setEscaped(boolean escaped) { 353 this.escaped = escaped; 354 } 355 356 protected boolean isEscaped() { 357 return escaped; 358 } 359 360 protected String getExpression() { 361 return new String (buf, 0, bufSize); 362 } 363 364 protected void handleText() throws SAXException { 365 if (bufSize > 0) { 366 handler.handleText(buf, 0, bufSize); 367 bufSize = 0; 368 } 369 } 370 371 protected void handleExpression() throws SAXException { 372 if (bufSize == 0) { 373 throw new SAXException ("Illegal empty expression."); 374 } 375 376 handler.handleExpression(buf, 0, bufSize); 377 378 bufSize = 0; 379 } 380 381 protected void append(char ch) { 382 if (bufSize + 1 >= buf.length) { 383 char[] newBuf = new char[buf.length + bufGrow]; 384 System.arraycopy(buf, 0, newBuf, 0, buf.length); 385 buf = newBuf; 386 } 387 388 buf[bufSize] = ch; 389 ++bufSize; 390 } 391 } 392 | Popular Tags |