/*******************************************************************************
* Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
* 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:
* The Chisel Group, University of Victoria
*******************************************************************************/
package net.sourceforge.tagsea.c.waypoints.parser;
import java.io.IOException;
import java.util.Collection;
import java.util.LinkedList;
import org.eclipse.jface.text.Region;
/**
* Parses a string to find java waypoint info.
* @author Del Myers
*/
@Deprecated
public class NewCWaypointParser implements ICWaypointParser {
private int position;
private int wordPosition;
/* (non-Javadoc)
* @see net.sourceforge.tagsea.java.waypoints.parser.IJavaWaypointParser#parse(java.lang.String)
*/
public IParsedCWaypointInfo parse(String waypointDefinition, int offset) {
//read ahead until we get to a "
position = 0;
waypointDefinition = chomp(waypointDefinition);
ParsedCWaypointInfo info = new ParsedCWaypointInfo(waypointDefinition, offset);
try {
readToTag(waypointDefinition);
Region[] words = getWords(waypointDefinition);
interpretWords(words, waypointDefinition, info);
} catch (MalformedWaypointException e) {
info.caughtException(e);
} catch (IOException e) {
info.caughtException(new MalformedWaypointException(MalformedWaypointException.READ_ERROR, 0, waypointDefinition.length()));
}
String comment = "";
if (position < waypointDefinition.length()) {
comment = waypointDefinition.substring(position).trim();
}
info.setDescription(comment, new Region(position, comment.length()));
return info;
}
/**
* @param waypointDefinition
* @return
*/
private String chomp(String waypointDefinition) {
int index = waypointDefinition.length()-1;
while (Character.isWhitespace(waypointDefinition.charAt(index)) && index >= 0) {
index--;
}
if (index >= -1) {
waypointDefinition = waypointDefinition.substring(0, index+1);
}
return waypointDefinition;
}
/**
* @param words
* @param waypointDefinition
* @param info
* @throws MalformedWaypointException
*/
private void interpretWords(Region[] words, String waypointDefinition, ParsedCWaypointInfo info) throws MalformedWaypointException {
for (Region region : words) {
String word = waypointDefinition.substring(region.getOffset(), region.getOffset()+region.getLength());
if (word.startsWith("-")) {
interpretMetaData(word, region, info);
} else {
try {
interpretTag(word, region, info);
} catch (IOException e) {
}
}
}
}
/**
* @param word
* @param region
* @param info
* @throws MalformedWaypointException
* @throws IOException
*/
private void interpretTag(String word, Region region, ParsedCWaypointInfo info) throws MalformedWaypointException, IOException {
int open = word.indexOf('(');
int close = word.lastIndexOf(')');
int dot = word.indexOf('.');
if (dot != -1 && (open != -1 || close != -1)) {
throw new MalformedWaypointException(MalformedWaypointException.BAD_TAG_SYNTAX, region.getOffset(), region.getLength());
}
if (close != -1 && close != word.length()-1) {
throw new MalformedWaypointException(MalformedWaypointException.MISPLACED_PARENS, region.getOffset(), region.getLength());
}
if (open != -1) {
interpretParenTag(word, region, info);
} else {
info.putTag(word, region);
}
}
/**
* @param word
* @param region
* @param info
* @throws IOException
* @throws MalformedWaypointException
*/
private void interpretParenTag(String word, Region region, ParsedCWaypointInfo info) throws IOException, MalformedWaypointException {
LinkedList<String> tags = new LinkedList<String>();
wordPosition = 0;
tags.addAll(findTags(word,region.getOffset()));
for (String s : tags) {
info.putTag(s, region);
}
}
/**
* @param word
* @param start where to start reading the word.
* @param offset the offset into the tag data at which the word occurs.
* @return
* @throws IOException
* @throws MalformedWaypointException
*/
private Collection<? extends String> findTags(String reader, int localOffset) throws IOException, MalformedWaypointException {
char c;
String currentWord = "";
LinkedList<String> words = new LinkedList<String>();
while (wordPosition < reader.length()) {
c = reader.charAt(wordPosition);
if (Character.isWhitespace(c)) {
if (!"".equals(currentWord))
words.add(currentWord);
currentWord = "";
} else {
if (c == '(') {
if ("".equals(currentWord))
throw new MalformedWaypointException(MalformedWaypointException.EXPECTED_WORD, wordPosition+localOffset, 1);
wordPosition++;
Collection<? extends String> nextWords = findTags(reader, localOffset);
for (String s : nextWords) {
words.add(currentWord+'.'+s);
}
currentWord = "";
} else if (c == ')') {
if (!"".equals(currentWord))
words.add(currentWord);
else if (words.size() == 0) {
throw new MalformedWaypointException(MalformedWaypointException.EXPECTED_WORD, wordPosition+localOffset, 1);
}
return words;
} else
currentWord += c;
}
wordPosition++;
}
return words;
}
/**
* @param word
* @param region
* @param info
* @throws MalformedWaypointException
*/
private void interpretMetaData(String word, Region region, ParsedCWaypointInfo info) throws MalformedWaypointException {
int equals = word.indexOf('=');
if (equals < 0) {
throw new MalformedWaypointException(MalformedWaypointException.EXPECTED_EQUALS, region.getOffset(), region.getLength());
} else if (equals == 0) {
throw new MalformedWaypointException(MalformedWaypointException.EXPECTED_LVALUE, region.getOffset(), 1);
} else if (equals == word.length()-1) {
throw new MalformedWaypointException(MalformedWaypointException.EXPECTED_RVALUE, region.getOffset()+word.length()-1, 1);
}
String key = word.substring(1, equals);
String value = word.substring(equals+1, word.length());
if (value.startsWith("\"")) {
value = value.substring(1, value.length()-1);
}
info.putAttribute(key, value, region);
}
/**
* @param reader
* @return
* @throws IOException
* @throws MalformedWaypointException
*/
private Region[] getWords(String reader) throws IOException, MalformedWaypointException {
LinkedList<Region> words = new LinkedList<Region>();
char c = 0;
String currentWord = "";
int wordStart = position;
boolean inQuotes =false;
int parensCount = 0;
boolean isMetaData = false;
char lastCharacter = ' ';
boolean hasPeriod = false;
while (position < reader.length()) {
lastCharacter = c;
c = (char)reader.charAt(position);
position++;
if (Character.isWhitespace(c)) {
if (!"".equals(currentWord)) {
if (isMetaData) {
if (!inQuotes) {
words.add(new Region(wordStart, currentWord.length()));
isMetaData = false;
currentWord = "";
wordStart = position;
hasPeriod = false;
parensCount = 0;
} else {
currentWord += c;
}
} else {
if (parensCount == 0) {
if (currentWord.endsWith(".")) {
//trailing period is bad.
throw new MalformedWaypointException(MalformedWaypointException.ILLEGAL_CHARACTER + ": '.'", wordStart+currentWord.length()-1, 1);
}
words.add(new Region(wordStart, currentWord.length()));
isMetaData = false;
currentWord = "";
hasPeriod = false;
wordStart = position;
} else {
currentWord += c;
}
}
} else {
wordStart = position;
}
} else {
if (c == '-' && Character.isWhitespace(lastCharacter)) {
isMetaData = true;
} else if (c == '(' && !isMetaData) {
parensCount++;
if (hasPeriod) {
throw new MalformedWaypointException(MalformedWaypointException.ILLEGAL_CHARACTER + ": \'"+c+"\'", position-1, 1);
}
} else if (c == ')' && !isMetaData) {
parensCount--;
if (hasPeriod) {
throw new MalformedWaypointException(MalformedWaypointException.ILLEGAL_CHARACTER + ": \'"+c+"\'", position-1, 1);
}
}
if (c == '"' && !isMetaData) {
throw new MalformedWaypointException(MalformedWaypointException.ILLEGAL_CHARACTER + ": \'"+c+"\'", position-1, 1);
}
if (isMetaData && c == '\"') {
inQuotes = !inQuotes;
if (position < reader.length() && !inQuotes) {
if (!Character.isWhitespace(reader.charAt(position))) {
throw new MalformedWaypointException(MalformedWaypointException.EXPECTED_SPACE, position-1, 1);
}
}
} else if (c == ':' && parensCount != 0) {
throw new MalformedWaypointException(MalformedWaypointException.ILLEGAL_CHARACTER + ": \'"+c+"\'", position-1, 1);
} else if (c=='.' && !isMetaData) {
if (parensCount != 0) {
throw new MalformedWaypointException(MalformedWaypointException.ILLEGAL_CHARACTER + ": \'"+c+"\'", position-1, 1);
}
hasPeriod = true;
} else if (c == ':' && !inQuotes) {
//quit, we have reached the end.
break;
}
currentWord += c;
}
}
if (inQuotes) {
throw new MalformedWaypointException(MalformedWaypointException.EXPECTED_EQUALS, wordStart, currentWord.length());
} else if (parensCount != 0) {
throw new MalformedWaypointException(MalformedWaypointException.UNMATCHED_PAREN, wordStart, currentWord.length());
} else if (!"".equals(currentWord)) {
words.add(new Region(wordStart, currentWord.length()));
}
return (Region[])words.toArray(new Region[words.size()]);
}
/**
* @param reader
* @throws IOException
*/
private void readToTag(String reader) throws IOException {
String target = TAG_SEQUENCE;
String currentWord = "";
position = 0;
while (position < reader.length()) {
char c = reader.charAt(position);
position++;
if (Character.isWhitespace(c)) {
currentWord = "";
continue;
} else {
currentWord = currentWord + c;
if (currentWord.equals(target)) {
if (position < reader.length() && Character.isWhitespace(reader.charAt(position)))
break;
else
currentWord = "";
}
}
}
}
}