/*
 * Created on Aug 31, 2005
 * 
 * $Log$
 * Revision 1.1  2005/09/21 22:00:45  dsowen
 * Split out the access stuff into accesslib.
 * New Creator interface off-loads object creation to user.
 *
 */
package ws.fugue88.jpath;

import java.nio.CharBuffer;
import java.text.ParseException;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author dsowen
 */
public class URLPathParser extends PathParser {

	public Path parse(final String path) throws ParseException
	{
		final List parts = new LinkedList();

		CharSequence buff = CharBuffer.wrap(path);
		do {
			final PathPart pp;
			Matcher m;
			if((m = IDENT.matcher(buff)).find()) {
				pp = new Identifier(m.group(1));
			} else if((m = NUM_SEL.matcher(buff)).find()) {
				pp = new NumberSelector(m.group(1));
			} else if((m = STR_SEL.matcher(buff)).find()) {
				pp = new StringSelector(unquote(m.group(1)));
			} else {
				throw new ParseException(
						"Expected identifier or selector, found '"
								+ (buff.length() > 40 ? buff.subSequence(0, 37)
										+ "..." : buff) + "'.", -1);
			}
			parts.add(pp);
			buff = buff.subSequence(m.end(), buff.length());
		} while(buff.length() > 0);

		return new Path(parts);
	}

	private static final String IDENT_START = "A-Za-z_";
	private static final String IDENT_END = IDENT_START + "0-9";
	private static final Pattern IDENT = Pattern.compile("^/([" + IDENT_START
			+ "][" + IDENT_END + "]*)");

	private static final String NUM_LIT = "-?[0-9]+";
	private static final Pattern NUM_SEL = Pattern.compile("^/(" + NUM_LIT
			+ ")");

	private static final String STR_LIT = "'((?:[^']|\\\\')*)'";
	private static final Pattern STR_SEL = Pattern.compile("^/" + STR_LIT);
}