| /******************************************************************************* |
| * Copyright (c) 2003 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jsp; |
| |
| import java.io.IOException; |
| import java.io.Reader; |
| |
| public abstract class AbstractJspParser { |
| |
| private Reader fReader; |
| private boolean fHasUnread; |
| private int fUnread; |
| private int fPos; |
| protected int fLines= 1; |
| |
| AbstractJspParser() { |
| super(); |
| } |
| |
| private int getc() throws IOException { |
| fPos++; |
| if (fHasUnread) { |
| fHasUnread= false; |
| return fUnread; |
| } |
| |
| int ch= fReader.read(); |
| |
| if (ch == '\n') // LF |
| fLines++; |
| else if (ch == '\r') { // CR |
| int nextCh= getc(); |
| if (nextCh != '\n') |
| fLines++; |
| return nextCh; |
| } |
| return ch; |
| } |
| |
| private void ungetc(int c) { |
| fHasUnread= true; |
| fUnread= c; |
| fPos--; |
| } |
| |
| private void parseDirective() throws IOException { |
| StringBuffer sb= new StringBuffer(); |
| int pos= fPos; |
| while (true) { |
| int c = getc(); |
| if (c == '%') { |
| c= getc(); |
| if (c == '>') { |
| // get attributes |
| parseAttributes(pos, sb.toString()); |
| return; |
| } |
| } |
| sb.append((char)c); |
| } |
| } |
| |
| private void parseTag(boolean endTag) throws IOException { |
| StringBuffer sb= new StringBuffer(); |
| int pos= fPos; |
| while (true) { |
| int c= getc(); |
| if (c == '/') { |
| c= getc(); |
| if (c == '>') { |
| // get attributes |
| parseAttributes(pos, sb.toString()); |
| return; |
| } else { |
| ungetc(c); |
| } |
| } else if (c == '>') { |
| // get attributes |
| parseAttributes(pos, sb.toString()); |
| return; |
| } |
| sb.append((char)c); |
| } |
| } |
| |
| private void parseComment() throws IOException { |
| while (true) { |
| int c = getc(); |
| if (c == '-') { |
| c= getc(); |
| if (c == '-') { |
| c= getc(); |
| if (c == '%') { |
| c= getc(); |
| if (c == '>') { |
| return; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| private void parseJava(char type) throws IOException { |
| StringBuffer sb= new StringBuffer(); |
| int line= fLines; |
| while (true) { |
| int c = getc(); |
| if (c == '%') { |
| c= getc(); |
| if (c == '>') { |
| java(type, sb.toString(), line); |
| return; |
| } |
| } |
| sb.append((char)c); |
| } |
| } |
| |
| protected void java(char tagType, String contents, int line) { |
| // empty implementation |
| } |
| |
| private void parseAttributes(int pos, String s) { |
| |
| boolean hasValue= false; |
| StringBuffer name= new StringBuffer(); |
| StringBuffer value= new StringBuffer(); |
| String startTag= ""; //$NON-NLS-1$ |
| int i= 0; |
| int ix= 0; |
| int startName= 0; |
| int startValue= 0; |
| char c= s.charAt(i++); |
| |
| try { |
| while (true) { |
| |
| // whitespace |
| while (Character.isWhitespace(c)) |
| c= s.charAt(i++); |
| |
| startName= i; |
| while (Character.isLetterOrDigit(c) || c == ':') { |
| name.append(c); |
| c= s.charAt(i++); |
| } |
| |
| // whitespace |
| while (Character.isWhitespace(c)) |
| c= s.charAt(i++); |
| |
| hasValue= false; |
| if (c == '=') { |
| c= s.charAt(i++); |
| |
| // value |
| while (Character.isWhitespace(c)) |
| c= s.charAt(i++); |
| |
| startValue= i; |
| |
| // Special handling for this taglib tag |
| if (startTag.equals("c:out")) { //$NON-NLS-1$ |
| value= value.append(s.substring(startValue, Math.max(startValue, s.length() - 2))); |
| name.setLength(0); |
| tagAttribute(name.toString(), value.toString(), startName+pos, startValue+pos); |
| break; |
| } else if (c == '"') { |
| c= s.charAt(i++); |
| while (c != '"') { |
| value.append(c); |
| c= s.charAt(i++); |
| } |
| c= s.charAt(i++); |
| |
| } else { |
| while (Character.isLetterOrDigit(c)) { |
| value.append(c); |
| c= s.charAt(i++); |
| } |
| } |
| hasValue= true; |
| } |
| |
| if (ix == 0) { |
| startTag= name.toString(); |
| startTag(false, startTag, startName+pos); |
| } else |
| tagAttribute(name.toString(), hasValue ? value.toString() : null, startName+pos, startValue+pos); |
| ix++; |
| |
| name.setLength(0); |
| value.setLength(0); |
| } |
| } catch (StringIndexOutOfBoundsException e) { |
| // we don't log this exception because it is used |
| // as one way to exit the scanning loop |
| } |
| |
| if (name.length() > 0) { |
| if (ix == 0) |
| startTag(false, name.toString(), startName+pos); |
| else |
| tagAttribute(name.toString(), hasValue ? value.toString() : null, startName+pos, startValue+pos); |
| } |
| |
| endTag(false); |
| } |
| |
| protected void startTag(boolean endTag, String name, int startName) { |
| // empty implementation |
| } |
| |
| protected void tagAttribute(String attrName, String value, int startName, int startValue) { |
| // empty implementation |
| } |
| |
| protected void endTag(boolean end) { |
| // empty implementation |
| } |
| |
| protected void text(String t, int line) { |
| // empty implementation |
| } |
| |
| void parse(Reader reader) throws IOException { |
| int c; |
| StringBuffer buffer= new StringBuffer(); |
| fPos= 0; |
| fLines= 1; |
| int line= fLines; |
| fReader= reader; |
| |
| while (true) { |
| c= getc(); |
| switch (c) { |
| case -1: |
| if (buffer.length() > 0) |
| text(buffer.toString(), line); |
| return; |
| case '<': |
| c= getc(); |
| if (c == '%') { |
| // flush buffer |
| if (buffer.length() > 0) { |
| text(buffer.toString(), line); |
| buffer.setLength(0); |
| line= fLines; |
| } |
| c= getc(); |
| switch (c) { |
| case '-': |
| c= getc(); |
| if (c == '-') { |
| parseComment(); |
| } else { |
| ungetc(c); |
| continue; |
| } |
| break; |
| case '@': |
| parseDirective(); |
| break; |
| case ' ': |
| case '!': |
| case '=': |
| parseJava((char)c); |
| break; |
| default: |
| parseComment(); |
| break; |
| } |
| } else if (c == '/') { |
| parseTag(true); |
| } else { |
| ungetc(c); |
| parseTag(false); |
| } |
| break; |
| default: |
| buffer.append((char)c); |
| break; |
| } |
| } |
| } |
| } |