0,0 → 1,224 |
package ak.zpath; |
|
import java.util.List; |
import java.util.ArrayList; |
|
public class PathParser |
{ |
public List parse(String path) |
throws PathParseException |
{ |
char c; |
int startPos; |
int pos = 0; |
int endPos = path.length(); |
String token; |
List tokens = new ArrayList(); |
|
while(pos < endPos) { |
c = path.charAt(pos); |
|
while(Character.isWhitespace(c) && pos < endPos - 1) { |
c = path.charAt(++pos); |
} |
if(pos >= endPos) break; |
|
switch(c) { |
case '/': |
addToken(tokens, pos, Token.TOKEN_SLASH, null); |
pos++; |
break; |
|
case '[': |
addToken(tokens, pos, Token.TOKEN_OPEN_BRACKET, null); |
pos++; |
break; |
|
case ']': |
addToken(tokens, pos, Token.TOKEN_CLOSE_BRACKET, null); |
pos++; |
break; |
|
case '@': |
addToken(tokens, pos, Token.TOKEN_AT, null); |
pos++; |
break; |
|
case '#': |
addToken(tokens, pos, Token.TOKEN_SHARP, null); |
pos++; |
break; |
|
case '"': |
case '\'': |
startPos = pos+1; |
pos = findStringEnd(path, c, startPos); |
addToken(tokens, startPos-1, Token.TOKEN_STRING, |
path.substring(startPos, pos)); |
pos++; |
break; |
|
case '=': |
addToken(tokens, pos, Token.TOKEN_EQUAL, null); |
pos++; |
break; |
|
case '$': |
if(++pos >= endPos) |
throw new PathParseException("variable name expected", pos); |
c = path.charAt(pos); |
if(c == '{') { |
startPos = ++pos; |
pos = findVariableEnd(path, c, startPos); |
addToken(tokens, startPos-2, |
Token.TOKEN_VARIABLE, path.substring(startPos, pos)); |
} |
else if(Character.isLetter(c)) { |
startPos = pos; |
pos = findVariableEnd(path, '\u0000', pos); |
addToken(tokens, startPos-1, |
Token.TOKEN_VARIABLE, path.substring(startPos, pos)); |
} |
else |
throw new PathParseException("variable name expected", pos); |
pos++; |
break; |
|
case ':': |
if(++pos >= endPos) |
throw new PathParseException("'=' expected", pos); |
c = path.charAt(pos); |
if(c == '=') |
addToken(tokens, pos-1, Token.TOKEN_ASSIGN, null); |
else |
throw new PathParseException("'=' expected", pos); |
pos++; |
break; |
|
case '.': |
if(++pos >= endPos) |
throw new PathParseException("'=' or '.' expected", pos); |
c = path.charAt(pos); |
if(c == '=') |
addToken(tokens, pos-1, Token.TOKEN_APPEND, null); |
else if(c == '.') |
addToken(tokens, pos-1, Token.TOKEN_NAME, ".."); |
else |
throw new PathParseException("'=' expected", pos); |
pos++; |
break; |
|
case '*': |
if(pos < endPos-1 && path.charAt(pos+1) == '*') { |
addToken(tokens, pos, Token.TOKEN_NAME, "**"); |
pos += 2; |
} |
else { |
addToken(tokens, pos, Token.TOKEN_NAME, "*"); |
pos++; |
} |
break; |
|
default: |
if(Character.isLetter(c) || c == '_') { |
startPos = pos; |
pos = findTokenEnd(path, pos); |
token = path.substring(startPos, pos); |
if("and".equals(token)) |
addToken(tokens, startPos, Token.TOKEN_AND, null); |
else if("or".equals(token)) |
addToken(tokens, startPos, Token.TOKEN_OR, null); |
else if("new".equals(token)) |
addToken(tokens, startPos, Token.TOKEN_NEW, null); |
else |
addToken(tokens, startPos, Token.TOKEN_NAME, token); |
} |
else |
throw new PathParseException( |
"unexpected character '" + c + "'", pos); |
} |
} |
|
return tokens; |
} |
|
private int findStringEnd(String path, char c, int pos) |
throws PathParseException |
{ |
int endPos = path.length(); |
|
if(pos >= endPos - 1) |
throw new PathParseException( |
"unclosed string, '" + c + "' expected", pos); |
|
while(path.charAt(++pos) != c) { |
if(pos >= endPos - 1) |
throw new PathParseException( |
"unclosed string, '" + c + "' expected", pos); |
} |
|
return pos; |
} |
|
private int findVariableEnd(String path, char c, int pos) |
throws PathParseException |
{ |
int endPos = path.length(); |
|
if(pos >= endPos) |
throw new PathParseException("unexpected end of variable name", pos); |
|
char c2 = path.charAt(pos); |
|
if(c == '{' && c2 == '}') |
throw new PathParseException("empty variable name", pos); |
else if(!Character.isLetter(c2) && c2 != '_') |
throw new PathParseException("variable name expected", pos); |
|
while(true) { |
if(pos >= endPos - 1) |
throw new PathParseException("unexpected end of variable name", pos); |
|
c2 = path.charAt(++pos); |
|
if(c == '{') { |
if(c2 == '}') break; |
if(!Character.isLetter(c2) && !Character.isDigit(c2) && c2 != '_') |
throw new PathParseException("unexpected character '" + c2 |
+ "' in variable name is occured instead of '}'", pos); |
} |
else { |
if(!Character.isLetter(c2) && !Character.isDigit(c2) && c2 != '_') |
break; |
if(pos >= endPos - 1) { |
pos++; |
break; |
} |
} |
} |
|
return pos; |
} |
|
private int findTokenEnd(String path, int pos) |
throws PathParseException |
{ |
int endPos = path.length(); |
char c; |
|
while(true) { |
pos++; |
if(pos >= endPos) break; |
|
c = path.charAt(pos); |
if(!Character.isLetter(c) && !Character.isDigit(c) && c != '_') break; |
} |
|
return pos; |
} |
|
private void addToken(List tokens, int pos, int type, String value) |
{ |
tokens.add(new Token(type, pos, value)); |
} |
} |