use of com.google.refine.grel.ast.VariableExpr in project OpenRefine by OpenRefine.
the class Parser method parseFactor.
/**
* <term> := <term-start> ( <path-segment> )*
* <term-start> :=
* <string> | <number> | - <number> | <regex> | <identifier> |
* <identifier> ( <expression-list> )
*
* <path-segment> := "[" <expression-list> "]"
* | "." <identifier>
* | "." <identifier> "(" <expression-list> ")"
*
*/
protected Evaluable parseFactor() throws ParsingException {
if (_token == null) {
throw makeException("Expecting something more at end of expression");
}
Evaluable eval = null;
if (_token.type == TokenType.String) {
eval = new LiteralExpr(_token.text);
next(false);
} else if (_token.type == TokenType.Regex) {
RegexToken t = (RegexToken) _token;
try {
Pattern pattern = Pattern.compile(_token.text, t.caseInsensitive ? Pattern.CASE_INSENSITIVE : 0);
eval = new LiteralExpr(pattern);
next(false);
} catch (Exception e) {
throw makeException("Bad regular expression (" + e.getMessage() + ")");
}
} else if (_token.type == TokenType.Number) {
eval = new LiteralExpr(((NumberToken) _token).value);
next(false);
} else if (_token.type == TokenType.Operator && _token.text.equals("-")) {
// unary minus?
next(true);
if (_token != null && _token.type == TokenType.Number) {
Number n = ((NumberToken) _token).value;
eval = new LiteralExpr(n instanceof Long ? -n.longValue() : -n.doubleValue());
next(false);
} else {
throw makeException("Bad negative number");
}
} else if (_token.type == TokenType.Identifier) {
String text = _token.text;
next(false);
if (_token == null || _token.type != TokenType.Delimiter || !_token.text.equals("(")) {
eval = "null".equals(text) ? new LiteralExpr(null) : new VariableExpr(text);
} else if ("PI".equals(text)) {
eval = new LiteralExpr(Math.PI);
next(false);
} else {
Function f = ControlFunctionRegistry.getFunction(text);
Control c = ControlFunctionRegistry.getControl(text);
if (f == null && c == null) {
throw makeException("Unknown function or control named " + text);
}
// swallow (
next(true);
List<Evaluable> args = parseExpressionList(")");
if (c != null) {
Evaluable[] argsA = makeArray(args);
String errorMessage = c.checkArguments(argsA);
if (errorMessage != null) {
throw makeException(errorMessage);
}
eval = new ControlCallExpr(argsA, c);
} else {
eval = new FunctionCallExpr(makeArray(args), f);
}
}
} else if (_token.type == TokenType.Delimiter && _token.text.equals("(")) {
next(true);
eval = parseExpression();
if (_token != null && _token.type == TokenType.Delimiter && _token.text.equals(")")) {
next(false);
} else {
throw makeException("Missing )");
}
} else if (_token.type == TokenType.Delimiter && _token.text.equals("[")) {
// [ ... ] array
// swallow [
next(true);
List<Evaluable> args = parseExpressionList("]");
eval = new FunctionCallExpr(makeArray(args), new ArgsToArray());
} else {
throw makeException("Missing number, string, identifier, regex, or parenthesized expression");
}
while (_token != null) {
if (_token.type == TokenType.Operator && _token.text.equals(".")) {
// swallow .
next(false);
if (_token == null || _token.type != TokenType.Identifier) {
throw makeException("Missing function name");
}
String identifier = _token.text;
next(false);
if (_token != null && _token.type == TokenType.Delimiter && _token.text.equals("(")) {
// swallow (
next(true);
Function f = ControlFunctionRegistry.getFunction(identifier);
if (f == null) {
throw makeException("Unknown function " + identifier);
}
List<Evaluable> args = parseExpressionList(")");
args.add(0, eval);
eval = new FunctionCallExpr(makeArray(args), f);
} else {
eval = new FieldAccessorExpr(eval, identifier);
}
} else if (_token.type == TokenType.Delimiter && _token.text.equals("[")) {
// swallow [
next(true);
List<Evaluable> args = parseExpressionList("]");
args.add(0, eval);
eval = new FunctionCallExpr(makeArray(args), ControlFunctionRegistry.getFunction("get"));
} else {
break;
}
}
return eval;
}
use of com.google.refine.grel.ast.VariableExpr in project OpenRefine by OpenRefine.
the class Filter method call.
@Override
public Object call(Properties bindings, Evaluable[] args) {
Object o = args[0].evaluate(bindings);
if (ExpressionUtils.isError(o)) {
return o;
} else if (!ExpressionUtils.isArrayOrCollection(o) && !(o instanceof JSONArray)) {
return new EvalError("First argument is not an array");
}
String name = ((VariableExpr) args[1]).getName();
Object oldValue = bindings.get(name);
try {
List<Object> results = null;
if (o.getClass().isArray()) {
Object[] values = (Object[]) o;
results = new ArrayList<Object>(values.length);
for (Object v : values) {
if (v != null) {
bindings.put(name, v);
} else {
bindings.remove(name);
}
Object r = args[2].evaluate(bindings);
if (r instanceof Boolean && ((Boolean) r).booleanValue()) {
results.add(v);
}
}
} else if (o instanceof JSONArray) {
JSONArray a = (JSONArray) o;
int l = a.length();
results = new ArrayList<Object>(l);
for (int i = 0; i < l; i++) {
try {
Object v = a.get(i);
if (v != null) {
bindings.put(name, v);
} else {
bindings.remove(name);
}
Object r = args[2].evaluate(bindings);
if (r instanceof Boolean && ((Boolean) r).booleanValue()) {
results.add(v);
}
} catch (JSONException e) {
results.add(new EvalError(e.getMessage()));
}
}
} else {
Collection<Object> collection = ExpressionUtils.toObjectCollection(o);
results = new ArrayList<Object>(collection.size());
for (Object v : collection) {
if (v != null) {
bindings.put(name, v);
} else {
bindings.remove(name);
}
Object r = args[2].evaluate(bindings);
if (r instanceof Boolean && ((Boolean) r).booleanValue()) {
results.add(v);
}
}
}
return results.toArray();
} finally {
/*
* Restore the old value bound to the variable, if any.
*/
if (oldValue != null) {
bindings.put(name, oldValue);
} else {
bindings.remove(name);
}
}
}
use of com.google.refine.grel.ast.VariableExpr in project OpenRefine by OpenRefine.
the class ForEach method call.
@Override
public Object call(Properties bindings, Evaluable[] args) {
Object o = args[0].evaluate(bindings);
if (ExpressionUtils.isError(o)) {
return o;
} else if (!ExpressionUtils.isArrayOrCollection(o) && !(o instanceof JSONArray)) {
return new EvalError("First argument to forEach is not an array");
}
String name = ((VariableExpr) args[1]).getName();
Object oldValue = bindings.get(name);
try {
List<Object> results = null;
if (o.getClass().isArray()) {
Object[] values = (Object[]) o;
results = new ArrayList<Object>(values.length);
for (Object v : values) {
if (v != null) {
bindings.put(name, v);
} else {
bindings.remove(name);
}
Object r = args[2].evaluate(bindings);
results.add(r);
}
} else if (o instanceof JSONArray) {
JSONArray a = (JSONArray) o;
int l = a.length();
results = new ArrayList<Object>(l);
for (int i = 0; i < l; i++) {
try {
Object v = a.get(i);
if (v != null) {
bindings.put(name, v);
} else {
bindings.remove(name);
}
Object r = args[2].evaluate(bindings);
results.add(r);
} catch (JSONException e) {
results.add(new EvalError(e.getMessage()));
}
}
} else {
Collection<Object> collection = ExpressionUtils.toObjectCollection(o);
results = new ArrayList<Object>(collection.size());
for (Object v : collection) {
if (v != null) {
bindings.put(name, v);
} else {
bindings.remove(name);
}
Object r = args[2].evaluate(bindings);
results.add(r);
}
}
return results.toArray();
} finally {
/*
* Restore the old value bound to the variable, if any.
*/
if (oldValue != null) {
bindings.put(name, oldValue);
} else {
bindings.remove(name);
}
}
}
use of com.google.refine.grel.ast.VariableExpr in project OpenRefine by OpenRefine.
the class ForNonBlank method call.
@Override
public Object call(Properties bindings, Evaluable[] args) {
Object o = args[0].evaluate(bindings);
Evaluable var = args[1];
String name = ((VariableExpr) var).getName();
if (ExpressionUtils.isNonBlankData(o)) {
Object oldValue = bindings.get(name);
bindings.put(name, o);
try {
return args[2].evaluate(bindings);
} finally {
/*
* Restore the old value bound to the variable, if any.
*/
if (oldValue != null) {
bindings.put(name, oldValue);
} else {
bindings.remove(name);
}
}
} else {
return args[3].evaluate(bindings);
}
}
use of com.google.refine.grel.ast.VariableExpr in project OpenRefine by OpenRefine.
the class Parser method parse.
public static Template parse(String s) throws ParsingException {
List<Fragment> fragments = new ArrayList<Fragment>();
int start = 0, current = 0;
while (current < s.length() - 1) {
char c = s.charAt(current);
char c2 = s.charAt(current + 1);
if (c == '\\') {
if (c2 == '\\' || c2 == '{' || c2 == '$') {
fragments.add(new StaticFragment(s.substring(start, current).concat(Character.toString(c2))));
start = current += 2;
} else {
// Invalid escape - just leave it in the template
current += 1;
}
continue;
}
if (c == '$' && c2 == '{') {
int closeBrace = s.indexOf('}', current + 2);
if (closeBrace > current + 1) {
String columnName = s.substring(current + 2, closeBrace);
if (current > start) {
fragments.add(new StaticFragment(s.substring(start, current)));
}
start = current = closeBrace + 1;
fragments.add(new DynamicFragment(new FieldAccessorExpr(new FieldAccessorExpr(new VariableExpr("cells"), columnName), "value")));
continue;
}
} else if (c == '{' && c2 == '{') {
int closeBrace = s.indexOf('}', current + 2);
if (closeBrace > current + 1 && closeBrace < s.length() - 1 && s.charAt(closeBrace + 1) == '}') {
String expression = s.substring(current + 2, closeBrace);
if (current > start) {
fragments.add(new StaticFragment(s.substring(start, current)));
}
start = current = closeBrace + 2;
fragments.add(new DynamicFragment(MetaParser.parse(expression)));
continue;
}
}
current++;
}
if (start < s.length()) {
fragments.add(new StaticFragment(s.substring(start)));
}
return new Template(fragments);
}
Aggregations