Example #1
0
File: v7.c Project: di3online/v7
//  number      =   { digit }
static enum v7_err parse_num(struct v7 *v7) {
  double value = 0;
  int is_negative = 0;

  if (*v7->cursor == '-') {
    is_negative = 1;
    TRY(match(v7, *v7->cursor));
  }

  CHECK(is_digit(*v7->cursor), V7_SYNTAX_ERROR);
  v7->tok = v7->cursor;
  while (is_digit(*v7->cursor)) {
    value *= 10;
    value += *v7->cursor++ - '0';
  }

  if (is_negative) {
    value = -value;
  }

  v7->tok_len = (unsigned long) (v7->cursor - v7->tok);
  skip_whitespaces_and_comments(v7);

  if (!v7->no_exec) {
    TRY(v7_make_and_push(v7, V7_NUM));
    v7_top(v7)[-1]->v.num = value;
  }

  return V7_OK;
}
Example #2
0
File: string.c Project: amihwan/v7
V7_PRIVATE enum v7_err Str_match(struct v7_c_func_arg *cfa) {
#define v7 (cfa->v7) /* Needed for TRY() macro below */
  struct v7_val *arg = cfa->args[0];
  struct Resub sub;
  struct v7_val *arr = NULL;
  unsigned long shift = 0;

  if (cfa->num_args > 0) {
    TRY(check_str_re_conv(v7, &arg, 1));
    TRY(regex_check_prog(arg));
    do {
      if (!re_exec(arg->v.str.prog, arg->fl.fl,
                   cfa->this_obj->v.str.buf + shift, &sub)) {
        if (NULL == arr) {
          arr = v7_push_new_object(v7);
          v7_set_class(arr, V7_CLASS_ARRAY);
        }
        shift = sub.sub[0].end - cfa->this_obj->v.str.buf;
        v7_append(v7, arr, v7_mkv(v7, V7_TYPE_STR, sub.sub[0].start,
                                  sub.sub[0].end - sub.sub[0].start, 1));
      }
    } while (arg->fl.fl.re_g && shift < cfa->this_obj->v.str.len);
  }
  if (0 == shift) TRY(v7_make_and_push(v7, V7_TYPE_NULL));
  return V7_OK;
#undef v7
}
Example #3
0
File: v7.c Project: di3online/v7
//  factor  =   number | string_literal | "(" expression ")" |
//              variable | "this" | "null" | "true" | "false" |
//              "{" object_literal "}" |
//              "[" array_literal "]" |
//              function_definition |
//              function_call
static enum v7_err parse_factor(struct v7 *v7) {
  int old_sp = v7_sp(v7);

  if (*v7->cursor == '(') {
    TRY(match(v7, '('));
    TRY(parse_expression(v7));
    TRY(match(v7, ')'));
  } else if (*v7->cursor == '\'' || *v7->cursor == '"') {
    TRY(parse_string_literal(v7));
  } else if (*v7->cursor == '{') {
    TRY(parse_object_literal(v7));
  } else if (is_alpha(*v7->cursor) || *v7->cursor == '_') {
    TRY(parse_identifier(v7));
    if (test_token(v7, "this", 4)) {
      inc_stack(v7, 1);
      v7_top(v7)[-1] = &v7->scopes[v7->current_scope];
    } else if (test_token(v7, "null", 4)) {
      TRY(v7_make_and_push(v7, V7_NULL));
    } else if (test_token(v7, "true", 4)) {
      TRY(v7_make_and_push(v7, V7_BOOL));
      v7_top(v7)[-1]->v.num = 1;
    } else if (test_token(v7, "false", 5)) {
      TRY(v7_make_and_push(v7, V7_BOOL));
      v7_top(v7)[-1]->v.num = 0;
    } else if (test_token(v7, "function", 8)) {
      TRY(parse_function_definition(v7, NULL, 0));
    } else if (test_token(v7, "delete", 6)) {
      TRY(parse_delete(v7));
    } else {
      TRY(parse_variable(v7));
    }
  } else {
    TRY(parse_num(v7));
  }

  if (*v7->cursor == '(') {
    TRY(parse_function_call(v7));
  }

  // Don't leave anything on stack if no execution flag is set
  if (v7->no_exec) {
    inc_stack(v7, old_sp - v7->sp);
  }

  return V7_OK;
}
Example #4
0
File: v7.c Project: di3online/v7
static enum v7_err parse_return_statement(struct v7 *v7) {
  if (*v7->cursor == ';' || *v7->cursor == '}') {
    if (!v7->no_exec) TRY(v7_make_and_push(v7, V7_UNDEF));
  } else {
    TRY(parse_expression(v7));
  }
  return V7_OK;
}
Example #5
0
File: v7.c Project: di3online/v7
static enum v7_err v7_make_and_push_string(struct v7 *v7, const char *s,
                                           unsigned long len, int do_copy) {
  struct v7_val **v = v7_top(v7);
  TRY(v7_make_and_push(v7, V7_STR));
  v[0]->v.str.len = len;
  v[0]->v.str.buf = do_copy ? v7_strdup(s, len) : (char *) s;
  v[0]->flags = do_copy ? 0 : STR_RO;
  return V7_OK;
}
Example #6
0
File: v7.c Project: di3online/v7
// function_defition = "function" "(" func_params ")" "{" func_body "}"
static enum v7_err parse_function_definition(struct v7 *v7, struct v7_val **v,
                                             int num_params) {
  int i = 0, old_no_exec = v7->no_exec, old_sp = v7->sp;
  const char *src = v7->cursor;

  // If 'v' (func to call) is NULL, that means we're just parsing function
  // definition to save it's body.
  v7->no_exec = v == NULL;
  TRY(match(v7, '('));

  // Initialize new scope
  if (!v7->no_exec) {
    v7->current_scope++;
    CHECK(v7->current_scope < (int) ARRAY_SIZE(v7->scopes),
          V7_RECURSION_TOO_DEEP);
    CHECK(v7->scopes[v7->current_scope].v.props == NULL, V7_INTERNAL_ERROR);
    CHECK(v7->scopes[v7->current_scope].type == V7_OBJ, V7_INTERNAL_ERROR);
  }

  while (*v7->cursor != ')') {
    TRY(parse_identifier(v7));
    if (!v7->no_exec) {
      struct v7_val *key = v7_mkval_str(v7, v7->tok, v7->tok_len);
      struct v7_val *val = i < num_params ? v[i + 1] : v7_mkval(v7, V7_UNDEF);
      v7_set(v7, &v7->scopes[v7->current_scope], key, val);
    }
    i++;
    if (!test_and_skip_char(v7, ',')) break;
  }
  TRY(match(v7, ')'));
  TRY(match(v7, '{'));

  while (*v7->cursor != '}') {
    int is_return_statement = 0;
    inc_stack(v7, old_sp - v7->sp);   // Clean up the stack from prev stmt
    TRY(parse_statement(v7, &is_return_statement));
    if (is_return_statement) break;   // Leave statement value on stack
  }

  if (v7->no_exec) {
    TRY(v7_make_and_push(v7, V7_FUNC));
    v7_top(v7)[-1]->v.func = v7_strdup(src, (v7->cursor + 1) - src);
  }
  TRY(match(v7, '}'));

  // Deinitialize scope
  if (!v7->no_exec) {
    v7->scopes[v7->current_scope].ref_count = 1;  // Force free_val() below
    free_val(v7, &v7->scopes[v7->current_scope]);
    v7->current_scope--;
    assert(v7->current_scope >= 0);
  }

  v7->no_exec = old_no_exec;
  return V7_OK;
}
Example #7
0
static void call_handler(struct ns_connection *nc, const char *name) {
  struct v7_val *js_srv = (struct v7_val *) nc->server->server_data;
  struct v7_val *v, *options = v7_lookup(js_srv, "options");
  if ((v = v7_lookup(options, name)) != NULL) {
    v7_push(s_v7, v);
    v7_make_and_push(s_v7, V7_OBJ);
    make_js_conn(v7_top(s_v7)[-1], nc);
    v7_call(s_v7, 1);
  }
}
Example #8
0
File: v7.c Project: di3online/v7
//  declaration =   "var" identifier [ "=" expression ] [ "," { i [ "=" e ] } ]
static enum v7_err parse_declaration(struct v7 *v7) {
  int sp = v7_sp(v7);

  do {
    inc_stack(v7, sp - v7_sp(v7));  // Clean up the stack after prev decl
    TRY(parse_identifier(v7));
    if (*v7->cursor == '=') {
      if (!v7->no_exec) v7_make_and_push(v7, V7_UNDEF);
      TRY(parse_assignment(v7, &v7->scopes[v7->current_scope]));
    }
  } while (test_and_skip_char(v7, ','));

  return V7_OK;
}
Example #9
0
File: v7.c Project: di3online/v7
// variable = identifier { '.' identifier | '[' expression ']' }
static enum v7_err parse_variable(struct v7 *v7) {
  struct v7_val **v = NULL, key = str_to_val(v7->tok, v7->tok_len);
  struct v7_val *ns = find(v7, &key), ro_prop;

  if (!v7->no_exec) {
    TRY(v7_make_and_push(v7, V7_UNDEF));
    v = v7_top(v7);
  }

  while (*v7->cursor == '.' || *v7->cursor == '[') {
    int ch = *v7->cursor;

    TRY(match(v7, ch));
    CHECK(v7->no_exec || ns != NULL, V7_SYNTAX_ERROR);
    v7->cur_obj = ns;

    if (ch == '.') {
      TRY(parse_identifier(v7));
      if (!v7->no_exec) {
        key = str_to_val(v7->tok, v7->tok_len);
        ns = get2(ns, &key);
        if (ns != NULL && ns->type == V7_RO_PROP) {
          ns->v.prop_func(v7->cur_obj, &ro_prop);
          ns = &ro_prop;
        }
      }
    } else {
      TRY(parse_expression(v7));
      TRY(match(v7, ']'));
      if (!v7->no_exec) {
        ns = get2(ns, v7_top(v7)[-1]);
        if (ns != NULL && ns->type == V7_RO_PROP) {
          ns->v.prop_func(v7->cur_obj, &ro_prop);
          ns = &ro_prop;
        }
        TRY(inc_stack(v7, -1));
      }
    }
  }

  if (v != NULL && ns != NULL) {
    free_val(v7, v[-1]);
    v[-1] = ns;
    v[-1]->ref_count++;
  }

  return V7_OK;
}
Example #10
0
File: v7.c Project: di3online/v7
static enum v7_err parse_object_literal(struct v7 *v7) {
  TRY(v7_make_and_push(v7, V7_OBJ));
  TRY(match(v7, '{'));
  while (*v7->cursor != '}') {
    if (*v7->cursor == '\'' || *v7->cursor == '"') {
      TRY(parse_string_literal(v7));
    } else {
      TRY(parse_identifier(v7));
      TRY(v7_make_and_push_string(v7, v7->tok, v7->tok_len, 1));
    }
    TRY(match(v7, ':'));
    TRY(parse_expression(v7));
    if (!v7->no_exec) {
      struct v7_val **v = v7_top(v7) - 3;
      CHECK(v[0]->type == V7_OBJ, V7_TYPE_MISMATCH);
      v7_set(v7, v[0], v[1], v[2]);
      inc_stack(v7, -2);
    }
    test_and_skip_char(v7, ',');
  }
  TRY(match(v7, '}'));
  return V7_OK;
}
Example #11
0
File: v7.c Project: di3online/v7
static enum v7_err do_arithmetic_op(struct v7 *v7, int op) {
  struct v7_val **v = v7_top(v7) - 2;
  double a, b, res = 0;

  if (v7->no_exec) return V7_OK;
  CHECK(v7->sp >= 2, V7_STACK_UNDERFLOW);
  CHECK(v[0]->type == V7_NUM && v[1]->type == V7_NUM, V7_TYPE_MISMATCH);
  a = v[0]->v.num;
  b = v[1]->v.num;

  switch (op) {
    case '+': res = a + b; break;
    case '-': res = a - b; break;
    case '*': res = a * b; break;
    case '/': res = a / b; break;
  }

  TRY(inc_stack(v7, -2));
  TRY(v7_make_and_push(v7, V7_NUM));
  v7_top(v7)[-1]->v.num = res;

  return V7_OK;
}
Example #12
0
File: v7.c Project: di3online/v7
static enum v7_err parse_string_literal(struct v7 *v7) {
  char buf[MAX_STRING_LITERAL_LENGTH];
  const char *begin = v7->cursor++;
  struct v7_val *v;
  size_t i = 0;

  TRY(v7_make_and_push(v7, V7_STR));
  v = v7_top(v7)[-1];

  // Scan string literal into the buffer, handle escape sequences
  while (*v7->cursor != *begin && *v7->cursor != '\0') {
    switch (*v7->cursor) {
      case '\\':
        v7->cursor++;
        switch (*v7->cursor) {
          case 'n': buf[i++] = '\n'; break;
          case 't': buf[i++] = '\t'; break;
          case '\\': buf[i++] = '\\'; break;
          default: if (*v7->cursor == *begin) buf[i++] = *begin; break;
        }
        break;
      default:
        buf[i++] = *v7->cursor;
        break;
    }
    if (i >= sizeof(buf) - 1) i = sizeof(buf) - 1;
    v7->cursor++;
  }

  v->v.str.len = v7->no_exec ? 0 : i;
  v->v.str.buf = v7->no_exec ? NULL : v7_strdup(buf, v->v.str.len);
  TRY(match(v7, *begin));
  skip_whitespaces_and_comments(v7);

  return V7_OK;
}