/*******************************************************************************
* Copyright (c) 2009-2013 CWI
* 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:
* * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI
* * Tijs van der Storm - Tijs.van.der.Storm@cwi.nl
*******************************************************************************/
package org.rascalmpl.interpreter.utils;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public final class StringUtils {
public static String unescapeSingleQuoteAndBackslash(String str) { //TODO not Unicode safe!
char[] chars = str.toCharArray();
StringBuffer result = new StringBuffer();
for (int i = 0; i < chars.length; i++) {
char b = chars[i];
switch (b) {
case '\\':
if(i >= chars.length - 1){
b = '\\';
} else {
switch (chars[++i]) {
case '\\':
b = '\\';
break;
case '\'':
b = '\'';
break;
}
}
}
result.append(b);
}
return result.toString();
}
public static String unquote(String str) {
return str.substring(1, str.length() - 1);
}
public static String unescapeBase(String str) {
char[] chars = str.toCharArray();
StringBuffer result = new StringBuffer();
for (int i = 0; i < chars.length; i++) {
char b = chars[i];
switch (b) {
case '\\':
switch (chars[++i]) {
case '\\':
result.append('\\');
b = '\\';
break;
case 'n':
b = '\n';
break;
case '"':
b = '"';
break;
case '\'':
result.append('\\');
b = '\'';
break;
case 't':
b = '\t';
break;
case 'b':
b = '\b';
break;
case 'f':
b = '\f';
break;
case 'r':
b = '\r';
break;
case '<':
b = '<';
break;
case '>':
b = '>';
break;
case 'a':
StringBuilder a = new StringBuilder();
a.append(chars[++i]);
a.append(chars[++i]);
b = (char) Integer.parseInt(a.toString(), 16);
break;
case 'u':
StringBuilder u = new StringBuilder();
u.append(chars[++i]);
u.append(chars[++i]);
u.append(chars[++i]);
u.append(chars[++i]);
b = (char) Integer.parseInt(u.toString(), 16);
break;
case 'U':
StringBuilder U = new StringBuilder();
U.append(chars[++i]);
U.append(chars[++i]);
U.append(chars[++i]);
U.append(chars[++i]);
U.append(chars[++i]);
U.append(chars[++i]);
int cp = Integer.parseInt(U.toString(), 16);
result.appendCodePoint(cp);
continue;
default:
b = '\\';
}
}
result.append(b);
}
return result.toString();
}
private final static Pattern getLastIdentifier = Pattern.compile(".*?([\\\\]?[_a-zA-Z]([\\-_a-zA-Z0-9]|::[\\\\]?)*)\\s*$");
public static class OffsetLengthTerm {
public OffsetLengthTerm(int offset, int length, String term) {
this.offset = offset;
this.length = length;
this.term = term;
}
public final int offset;
public final int length;
public final String term;
}
public static OffsetLengthTerm findRascalIdentifierAtOffset(String buffer, int offset) {
Matcher m = getLastIdentifier.matcher(buffer);
int split = findSplitPoint(offset, buffer);
if (split > 0) {
m.region(0, split + 1);
}
if (m.matches()) {
String originalTerm = m.group(1);
return new OffsetLengthTerm( m.start(1), originalTerm.length(), originalTerm);
}
return null;
}
private static boolean validRascalIdentifier(char c) {
return (c >= 'A' && c <= 'Z')
|| (c >= 'a' && c <= 'z')
|| (c >= '0' && c <= '9')
|| c == '_' || c == '-'
|| c == '\\'
;
}
private static int findSplitPoint(int currentCursorPosition, String currentConsoleInput) {
for (int i = currentCursorPosition; i < currentConsoleInput.length(); i++) {
char currentChar = currentConsoleInput.charAt(i);
if (currentChar == ':' && i + 1 < currentConsoleInput.length() && currentConsoleInput.charAt(i + 1) == ':') {
i++;
continue;
}
if (!validRascalIdentifier(currentChar))
return i - 1;
}
return -1;
}
public static String[] splitQualifiedName(String name) {
int splitPoint = name.lastIndexOf("::");
if (splitPoint >= 0) {
return new String[] {
name.substring(0, splitPoint),
name.substring(splitPoint + 2)
};
}
return new String[] {name};
}
private static boolean validRascalLocation(char c) {
return ('\t' < c || c > '\n')
&& (c != '\r')
&& (c != ' ')
&& (c != '<')
&& (c != '>')
;
}
public static int findRascalLocationStart(String line, int cursor) {
for (int pos = Math.min(cursor, line.length() - 1); pos >= 0; pos--) {
char c = line.charAt(pos);
if (c == '|') {
return pos;
}
else if (!validRascalLocation(c)) {
return -1;
}
}
return -1;
}
public static int findRascalLocationEnd(String line, int locationStart) {
assert line.charAt(locationStart) == '|';
for (int pos = locationStart + 1; pos < line.length(); pos++) {
char c = line.charAt(pos);
if (c == '|') {
return pos - 1;
}
if (!validRascalLocation(c)) {
return pos;
}
}
return line.length() - 1;
}
}