blob: 077d91e15286f36da04f99571a2e2b86b03f6188 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2004 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
*******************************************************************************/
/*
* Created on Nov 11, 2003
*
* To change the template for this generated file go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
package org.eclipse.wst.common.internal.emf.annotations.core;
/**
* @author Pat Kelley
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public class AnnotationTagParser {
private TagParseEventHandler handler;
private char[] input;
int pos;
int endOfLastGoodAttParse;
public AnnotationTagParser(TagParseEventHandler tp) {
if (tp == null) {
throw new IllegalArgumentException(AnnotationsCoreResources.AnnotationTagParser_0);
}
handler = tp;
}
private boolean eos() {
return pos >= input.length;
}
private boolean isWS(char c) {
return c == ' ' || c == '\n' || c == '\r' || c == '\t';
}
private void skipWS() {
while (pos < input.length && (isWS(input[pos]) || input[pos] == '*')) {
pos++;
}
}
// Caller is expected to make sure the eos has not been reached.
private char peek() {
return input[pos];
}
// Caller is expected to check for EOS.
private char nextChar() {
return input[pos++];
}
private boolean isNextChar(char c) {
if (eos())
return false;
return peek() == c;
}
private boolean isIDChar(char c) {
return !isWS(c) && c != '=' && c != '@' && c != '\"';
}
private Token collectID() {
StringBuffer b = new StringBuffer(16);
Token t = new Token();
t.setBeginning(pos);
while (!eos() && isIDChar(peek())) {
b.append(nextChar());
}
t.setEnd(pos - 1);
t.setText(b.toString());
return t;
}
private Token expectAttribName() {
if (eos()) {
return null;
}
int save = pos;
Token retval = collectID();
if (retval.length() == 0) {
pos = save;
return null;
}
return retval;
}
private Token expectTag() {
if (eos()) {
return null;
}
int savePos = pos;
if (nextChar() != '@') {
return null;
}
if (eos() || isWS(peek())) {
return null;
}
Token retval = expectAttribName();
if (retval.length() == 0) {
pos = savePos + 1;
}
retval.setBeginning(savePos);
// Save end of parse so we can pass it as the end of the parsed tag.
endOfLastGoodAttParse = pos;
return retval;
}
private Token expectQuotedValue() {
skipWS();
if (eos()) {
return null;
}
Token tok = new Token();
tok.setBeginning(pos);
if (peek() != '\"') {
return null;
}
nextChar();
if (eos()) {
return null;
}
StringBuffer b = new StringBuffer(64);
while (!eos() && peek() != '\"') {
b.append(nextChar());
}
if (!eos()) {
nextChar();
}
tok.setEnd(pos - 1);
tok.setText(b.toString());
return tok;
}
private boolean expectAssign() {
if (eos()) {
return false;
}
if (nextChar() == '=') {
return true;
}
pos--;
return false;
}
private Token mkNullToken() {
Token retval = new Token();
retval.setBeginning(pos);
retval.setEnd(pos - 1);
retval.setText(""); //$NON-NLS-1$
return retval;
}
private boolean parseNextAttribute() {
skipWS();
if (eos()) {
return false;
}
Token key = collectID();
if (key == null || key.length() == 0) {
return false;
}
skipWS();
if (eos()) {
// Go ahead and report it, even though it is a partial attribute. (
// we still fail here )
handler.attribute(key, -1, mkNullToken());
return false;
}
int eqPos = pos;
if (!expectAssign()) {
// Even though we won't parse this as a full attribute, go ahead and
// call the handler with it. Some clients want to see partial
// attributes.
handler.attribute(key, -1, mkNullToken());
return false;
}
skipWS();
if (eos()) {
// Same here - we fail on it, but we report it anyway
handler.attribute(key, eqPos, mkNullToken());
return false;
}
Token value = expectQuotedValue();
if (value == null) {
value = collectID();
if (isNextChar('=')) {
pos = value.getBeginning();
value = mkNullToken();
}
}
endOfLastGoodAttParse = pos;
handler.attribute(key, eqPos, value);
return true;
}
private void parseAttributes() {
while (!eos() && parseNextAttribute()) {
// loop while not end of string
}
}
private void skipToTagChar() {
while (!eos() && peek() != '@') {
nextChar();
}
}
public void setParserInput(char[] text) {
input = text;
pos = 0;
endOfLastGoodAttParse = 0;
}
public void setParserInput(String text) {
setParserInput(text.toCharArray());
}
public void parse() {
while (!eos()) {
skipToTagChar();
Token tag = expectTag();
if (tag == null) {
break;
}
handler.annotationTag(tag);
parseAttributes();
handler.endOfTag(endOfLastGoodAttParse);
}
}
}