Пример #1
0
  private static LambdaN extract_function(final JsContext ctx, String funcname) {
    String func_mRegex =
        String.format("(function %1$s|[\\{;]%1$s\\p{Space}*=\\p{Space}*function)", escape(funcname))
            + "\\((?<args>[a-z,]+)\\)\\{(?<code>[^\\}]+)\\}";
    final Matcher func_m = Pattern.compile(func_mRegex).matcher(ctx.jscode);
    if (!func_m.find()) {
      throw new JsError("Could not find JS function " + funcname);
    }

    final String[] argnames = mscpy(func_m.group("args").split(","));

    return build_function(ctx, argnames, func_m.group("code"));
  }
Пример #2
0
  private static JsObject extract_object(final JsContext ctx, String objname) {
    JsObject obj = new JsObject();
    String obj_mRegex =
        String.format("(var\\p{Space}+)?%1$s\\p{Space}*=\\p{Space}*\\{", escape(objname))
            + "\\p{Space}*(?<fields>([a-zA-Z$0-9]+\\p{Space}*:\\p{Space}*function\\(.*?\\)\\p{Space}*\\{.*?\\})*)\\}\\p{Space}*;";
    final Matcher obj_m = Pattern.compile(obj_mRegex).matcher(ctx.jscode);
    obj_m.find();
    String fields = obj_m.group("fields");
    // Currently, it only supports function definitions
    final Matcher fields_m =
        Pattern.compile(
                "(?<key>[a-zA-Z$0-9]+)\\p{Space}*:\\p{Space}*function\\((?<args>[a-z,]+)\\)\\{(?<code>[^\\}]+)\\}")
            .matcher(fields);

    while (fields_m.find()) {
      final String[] argnames = mscpy(fields_m.group("args").split(","));

      LambdaN f = build_function(ctx, argnames, fields_m.group("code"));

      obj.functions.put(fields_m.group("key"), f);
    }

    return obj;
  }
Пример #3
0
  private static Object interpret_statement(
      final JsContext ctx,
      String stmt,
      final Map<String, Object> local_vars,
      final int allow_recursion) {
    if (allow_recursion < 0) {
      throw new JsError("Recursion limit reached");
    }

    if (stmt.startsWith("var ")) {
      stmt = stmt.substring("var ".length());
    }

    final Matcher ass_m =
        Pattern.compile("^(?<out>[a-z]+)(\\[(?<index>.+?)\\])?=(?<expr>.*)$").matcher(stmt);
    Lambda1 assign;
    String expr;
    if (ass_m.find()) {
      if (ass_m.group("index") != null) {

        final Object lvar = local_vars.get(ass_m.group("out"));
        final Object idx =
            interpret_expression(ctx, ass_m.group("index"), local_vars, allow_recursion);
        assert idx instanceof Integer;

        assign =
            new Lambda1() {
              @SuppressWarnings("unchecked")
              @Override
              public Object eval(Object val) {
                ((List<Object>) lvar).set((Integer) idx, val);
                return val;
              }
            };
        expr = ass_m.group("expr");
      } else {

        final String var = ass_m.group("out");

        assign =
            new Lambda1() {
              @Override
              public Object eval(Object val) {
                local_vars.put(var, val);
                return val;
              }
            };
        expr = ass_m.group("expr");
      }
    } else if (stmt.startsWith("return ")) {
      assign =
          new Lambda1() {
            @Override
            public Object eval(Object v) {
              return v;
            }
          };
      expr = stmt.substring("return ".length());
    } else {
      // Try interpreting it as an expression
      expr = stmt;
      assign =
          new Lambda1() {
            @Override
            public Object eval(Object v) {
              return v;
            }
          };
    }

    Object v = interpret_expression(ctx, expr, local_vars, allow_recursion);
    return assign.eval(v);
  }
Пример #4
0
  @SuppressWarnings("unchecked")
  private static Object interpret_expression(
      final JsContext ctx, String expr, Map<String, Object> local_vars, int allow_recursion) {
    if (isdigit(expr)) {
      return Integer.valueOf(expr);
    }

    if (isalpha(expr)) {
      return local_vars.get(expr);
    }

    //        try:
    //            return json.loads(expr)
    //        except ValueError:
    //            pass
    Object jsl = json_loads(expr);
    if (jsl != null) {
      return jsl;
    }

    Matcher m =
        Pattern.compile("^(?<var>[a-zA-Z0-9_]+)\\.(?<member>[^\\(]+)(\\((?<args>[^\\(\\)]*)\\))?$")
            .matcher(expr);
    if (m.find()) {
      String variable = m.group("var");
      String member = m.group("member");
      String arg_str = m.group("args");

      Object obj = null;
      if (local_vars.containsKey(variable)) {
        obj = local_vars.get(variable);
      } else {
        if (!ctx.objects.containsKey(variable)) {
          ctx.objects.put(variable, extract_object(ctx, variable));
        }
        obj = ctx.objects.get(variable);
      }

      if (arg_str == null) {
        // Member access
        if (member.equals("length")) {
          return len(obj);
        }
        return ((JsObject) obj).functions.get(member).eval(new Object[] {});
      }

      if (!expr.endsWith(")")) {
        throw new JsError("Error parsing js code");
      }
      List<Object> argvals = null;
      if (arg_str.equals("")) {
        argvals = new ArrayList<Object>();
      } else {
        argvals = new ArrayList<Object>();
        for (String v : arg_str.split(",")) {
          argvals.add(interpret_expression(ctx, v, local_vars, 20));
        }
      }

      if (member.equals("split")) {
        // assert argvals == ('',)
        return list(obj);
      }
      if (member.equals("join")) {
        // assert len(argvals) == 1
        return join((List<Object>) obj, argvals.get(0));
      }
      if (member.equals("reverse")) {
        // assert len(argvals) == 0
        reverse(obj);
        return obj;
      }
      if (member.equals("slice")) {
        // assert len(argvals) == 1
        return slice(obj, (Integer) argvals.get(0));
      }
      if (member.equals("splice")) {
        // assert isinstance(obj, list)
        int index = (Integer) argvals.get(0);
        int howMany = (Integer) argvals.get(1);
        List<Object> res = new ArrayList<Object>();
        List<Object> list = (List<Object>) obj;
        for (int i = index; i < Math.min(index + howMany, len(obj)); i++) {
          res.add(list.remove(index));
        }
        return res.toArray();
      }

      return ((JsObject) obj).functions.get(member).eval(argvals.toArray());
    }

    m = Pattern.compile("^(?<in>[a-z]+)\\[(?<idx>.+)\\]$").matcher(expr);
    if (m.find()) {
      Object val = local_vars.get(m.group("in"));
      Object idx = interpret_expression(ctx, m.group("idx"), local_vars, allow_recursion - 1);
      return ((List<?>) val).get((Integer) idx);
    }

    m = Pattern.compile("^(?<a>.+?)(?<op>[%])(?<b>.+?)$").matcher(expr);
    if (m.find()) {
      Object a = interpret_expression(ctx, m.group("a"), local_vars, allow_recursion);
      Object b = interpret_expression(ctx, m.group("b"), local_vars, allow_recursion);
      return (Integer) a % (Integer) b;
    }

    m = Pattern.compile("^(?<func>[a-zA-Z]+)\\((?<args>[a-z0-9,]+)\\)$").matcher(expr);
    if (m.find()) {
      String fname = m.group("func");
      if (!ctx.functions.containsKey(fname) && ctx.jscode.length() > 0) {
        ctx.functions.put(fname, extract_function(ctx, fname));
      }
      List<Object> argvals = new ArrayList<Object>();
      for (String v : m.group("args").split(",")) {
        if (isdigit(v)) {
          argvals.add(Integer.valueOf(v));
        } else {
          argvals.add(local_vars.get(v));
        }
      }
      return ctx.functions.get(fname).eval(argvals.toArray());
    }
    throw new JsError(String.format("Unsupported JS expression %s", expr));
  }