Beispiel #1
0
static void
_syx_parser_parse_block_message_pattern (SyxParser *self)
{
  SyxToken token = syx_lexer_get_last_token (self->lexer);
  SyxParserScope *scope = self->_argument_scopes + self->_argument_scopes_top;

  if (! (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, ":")))
    {
      SYX_CODE_ARGUMENTS_COUNT(self->method) = syx_small_integer_new (0);
      return;
    }

  while (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, ":"))
    {
      syx_token_free (token);
      token = syx_lexer_next_token (self->lexer);
      assert (token.type == SYX_TOKEN_NAME_CONST);
      scope->stack[scope->top++] = syx_strdup (token.value.string);
      syx_token_free (token);

      token = syx_lexer_next_token (self->lexer);
    }

  if (! (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, "|")))
    syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected | after block message pattern\n"));

  syx_token_free (token);
  syx_lexer_next_token (self->lexer);

  SYX_CODE_ARGUMENTS_COUNT(self->method) = syx_small_integer_new (scope->top);
  return;
}
Beispiel #2
0
static void
_syx_parser_parse_expression (SyxParser *self)
{
  SyxToken token = syx_lexer_get_last_token (self->lexer);
  syx_string assign_name;
  syx_bool super_term = FALSE;

  if (token.type == SYX_TOKEN_NAME_CONST)
    {
      assign_name = syx_strdup (token.value.string);
      syx_token_free (token);

      token = syx_lexer_next_token (self->lexer);
      if (token.type == SYX_TOKEN_BINARY &&
          (!strcmp (token.value.string, ":=") || !strcmp (token.value.string, "<-")))
        {
          syx_token_free (token);
          syx_lexer_next_token (self->lexer);
          _syx_parser_parse_assignment (self, assign_name);
        }
      else /* Not an assignment, let it be a name term then */
        super_term = _syx_parser_parse_name_term (self, assign_name);

      syx_free (assign_name);
    }
  else
    super_term = _syx_parser_parse_term (self);

  /* After we got the initial object, we can do message continuation on it
     specifying if 'super' has been requested instead of self */
  _syx_parser_do_continuation (self, super_term);
}
Beispiel #3
0
static void
_syx_parser_parse_temporaries (SyxParser *self)
{
  SyxToken token = syx_lexer_get_last_token (self->lexer);
  SyxParserScope scope;
  scope.start = self->_temporary_names_top;
  scope.end = self->_temporary_names_top;

  if (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, "|"))
    {
      syx_token_free (token);
      token = syx_lexer_next_token (self->lexer);
      while (token.type == SYX_TOKEN_NAME_CONST)
        {
          self->_temporary_names[self->_temporary_names_top++] = token.value.string;
          scope.end++;
          token = syx_lexer_next_token (self->lexer);
        }
      if (! (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, "|")))
        syx_signal (SYX_ERROR_INTERP, syx_string_new ("Temporary list not terminated by bar"));
      syx_token_free (token);

      syx_lexer_next_token (self->lexer);
    }

  self->_temporary_scopes.stack[(syx_int32) self->_temporary_scopes.top++] = scope;
}
Beispiel #4
0
static void
_syx_parser_parse_temporaries (SyxParser *self)
{
  SyxToken token = syx_lexer_get_last_token (self->lexer);
  SyxParserScope *scope = self->_temporary_scopes + self->_temporary_scopes_top;

  if (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, "|"))
    {
      syx_token_free (token);
      token = syx_lexer_next_token (self->lexer);
      while (token.type == SYX_TOKEN_NAME_CONST)
        {
          scope->stack[scope->top++] = syx_strdup (token.value.string);
          syx_token_free (token);
          token = syx_lexer_next_token (self->lexer);
        }
      if (! (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, "|")))
        syx_signal (SYX_ERROR_INTERP, syx_string_new ("Temporary list not terminated by bar"));
      syx_token_free (token);

      syx_lexer_next_token (self->lexer);
    }
    
  /* we choose the maximum number so we can hold all the temporaries without forgetting
     previous parsed optimized blocks. */
  if (SYX_IS_NIL (SYX_CODE_TEMPORARIES_COUNT (self->method))
      || scope->top > SYX_SMALL_INTEGER (SYX_CODE_TEMPORARIES_COUNT (self->method)))
    SYX_CODE_TEMPORARIES_COUNT(self->method) = syx_small_integer_new (scope->top);
}
Beispiel #5
0
static void
_syx_parser_parse_method_message_pattern (SyxParser *self)
{
  SyxToken token = syx_lexer_get_last_token (self->lexer);
  syx_char selector[256] = {0};
  SyxParserScope scope;
  scope.start = self->_argument_names_top;
  scope.end = self->_argument_names_top;

  switch (token.type)
    {
    case SYX_TOKEN_NAME_CONST:
      /* Unary message pattern */
      SYX_METHOD_SELECTOR(self->method) = syx_symbol_new (token.value.string);
      syx_token_free (token);

      syx_lexer_next_token (self->lexer);
      break;
    case SYX_TOKEN_BINARY:
      /* Binary message pattern */
      SYX_METHOD_SELECTOR(self->method) = syx_symbol_new (token.value.string);
      syx_token_free (token);

      token = syx_lexer_next_token (self->lexer);
      if (token.type != SYX_TOKEN_NAME_CONST)
        syx_error ("Expected name constant for argument name\n");
      self->_argument_names[self->_argument_names_top++] = token.value.string;
      scope.end++;

      syx_lexer_next_token (self->lexer);
      break;
    case SYX_TOKEN_NAME_COLON:
      /* Keyword message pattern */
      while (token.type == SYX_TOKEN_NAME_COLON)
        {
          strcat (selector, token.value.string);
          syx_token_free (token);

          token = syx_lexer_next_token (self->lexer);
          if (token.type != SYX_TOKEN_NAME_CONST)
            syx_error ("Expected name constant for argument name\n");
          self->_argument_names[self->_argument_names_top++] = token.value.string;
          scope.end++;

          token = syx_lexer_next_token (self->lexer);
        }

      SYX_METHOD_SELECTOR(self->method) = syx_symbol_new (selector);
      break;
    default:
      syx_error ("Invalid message pattern\n");
    }

  self->_argument_scopes.stack[(syx_int32) self->_argument_scopes.top++] = scope;
  SYX_CODE_ARGUMENT_COUNT(self->method) = syx_small_integer_new (scope.end - scope.start);
}
Beispiel #6
0
static void
_syx_parser_parse_method_message_pattern (SyxParser *self)
{
  SyxToken token = syx_lexer_get_last_token (self->lexer);
  syx_char selector[0xFF] = {0};
  SyxParserScope *scope = self->_argument_scopes + self->_argument_scopes_top;

  switch (token.type)
    {
    case SYX_TOKEN_NAME_CONST:
      /* Unary message pattern */
      SYX_METHOD_SELECTOR(self->method) = syx_symbol_new (token.value.string);
      syx_token_free (token);

      syx_lexer_next_token (self->lexer);
      break;
    case SYX_TOKEN_BINARY:
      /* Binary message pattern */
      SYX_METHOD_SELECTOR(self->method) = syx_symbol_new (token.value.string);
      syx_token_free (token);

      token = syx_lexer_next_token (self->lexer);
      if (token.type != SYX_TOKEN_NAME_CONST)
        syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected name constant for argument name\n"));
      scope->stack[scope->top++] = syx_strdup (token.value.string);
      syx_token_free (token);

      syx_lexer_next_token (self->lexer);
      break;
    case SYX_TOKEN_NAME_COLON:
      /* Keyword message pattern */
      while (token.type == SYX_TOKEN_NAME_COLON)
        {
          strcat (selector, token.value.string);
          syx_token_free (token);

          token = syx_lexer_next_token (self->lexer);
          if (token.type != SYX_TOKEN_NAME_CONST)
            syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected name constant for argument name\n"));
          scope->stack[scope->top++] = syx_strdup (token.value.string);
          syx_token_free (token);

          token = syx_lexer_next_token (self->lexer);
        }
      
      SYX_METHOD_SELECTOR(self->method) = syx_symbol_new (selector);
      break;
    default:
      syx_signal (SYX_ERROR_INTERP, syx_string_new ("Invalid message pattern\n"));
    }

  SYX_CODE_ARGUMENTS_COUNT(self->method) = syx_small_integer_new (scope->top);
}
Beispiel #7
0
static SyxOop 
_syx_parser_parse_literal_array (SyxParser *self)
{
  SyxOop elements[256];
  syx_varsize top = 0;
  SyxToken token;

  token = syx_lexer_next_token (self->lexer);
  while (! (token.type == SYX_TOKEN_END || (token.type == SYX_TOKEN_CLOSING && token.value.character == ')')))
    {
      switch (token.type)
        {
        case SYX_TOKEN_ARRAY_BEGIN:
          elements[top++] = _syx_parser_parse_literal_array (self);
          break;
        case SYX_TOKEN_INT_CONST:
          elements[top++] = syx_small_integer_new (token.value.integer);
          break;
        case SYX_TOKEN_BINARY:
          if (!strcmp (token.value.string, "("))
            {
              elements[top++] = _syx_parser_parse_literal_array (self);
              syx_token_free (token);
              break;
            }
        case SYX_TOKEN_NAME_CONST:
        case SYX_TOKEN_NAME_COLON:
        case SYX_TOKEN_SYM_CONST:
          elements[top++] = syx_symbol_new (token.value.string);
          syx_token_free (token);
          break;
        case SYX_TOKEN_STR_CONST:
          elements[top++] = syx_string_new (token.value.string);
          syx_token_free (token);
          break;
        case SYX_TOKEN_CHAR_CONST:
          elements[top++] = syx_character_new (token.value.character);
          break;
        default:
          syx_signal (SYX_ERROR_INTERP, syx_string_new ("Illegal text in literal array\n"));
          break;
        }

      token = syx_lexer_next_token (self->lexer);
    }

  return syx_array_new_ref (top, elements);
}
Beispiel #8
0
static syx_bool
_syx_parser_do_binary_continuation (SyxParser *self, syx_bool super_receiver, syx_bool do_cascade)
{
  syx_string selector;
  SyxToken token;
  syx_bool super_term;

  super_receiver = _syx_parser_do_unary_continuation (self, super_receiver, do_cascade);

  token = syx_lexer_get_last_token (self->lexer);
  while (token.type == SYX_TOKEN_BINARY)
    {
      selector = syx_strdup (token.value.string);
      
      if (do_cascade)
        {
          self->_duplicate_indexes[self->_duplicate_indexes_top - 1] = self->bytecode->code_top;
          do_cascade = FALSE;
        }

      syx_token_free (token);
      syx_lexer_next_token (self->lexer);
      super_term = _syx_parser_parse_term (self);
      _syx_parser_do_unary_continuation (self, super_term, FALSE);
      token = syx_lexer_get_last_token (self->lexer);

      syx_bytecode_gen_message (self->bytecode, super_receiver, 1, selector);
      syx_free (selector);
    }

  return super_receiver;
}
Beispiel #9
0
static void
_syx_parser_parse_block (SyxParser *self)
{
  SyxOop closure;
  SyxOop old_method = self->method;
  SyxBytecode *old_bytecode = self->bytecode;
  syx_bool block_state = self->_in_block;
  syx_token_free (syx_lexer_get_last_token (self->lexer));

  self->method = syx_block_new ();
  self->bytecode = syx_bytecode_new ();
  self->_in_block = TRUE;
  self->_temporary_scopes_top++;
  self->_argument_scopes_top++;

  syx_parser_parse (self, FALSE);

  closure = syx_block_closure_new (self->method);
  self->method = old_method;
  syx_bytecode_free (self->bytecode);
  self->bytecode = old_bytecode;
  self->_in_block = block_state;
  self->_temporary_scopes_top--;
  self->_argument_scopes_top--;

  syx_bytecode_push_block_closure (self->bytecode, closure);
}
Beispiel #10
0
/*!
  Parse simple declarations like classes and methods.

  \return TRUE if no error has occurred
*/
syx_bool
syx_cold_parse (SyxLexer *lexer)
{
  SyxToken token;
  syx_bool parseOk = TRUE;

  token = syx_lexer_next_token (lexer);
  while (parseOk && token.type != SYX_TOKEN_END)
    {
      if (_IS_EXL_MARK (token))
        parseOk = syx_cold_parse_methods (lexer);
      else
        parseOk = _syx_cold_parse_class (lexer);

      syx_token_free (token);
      token = syx_lexer_next_token (lexer);
    }
  
  syx_token_free (token);
  return parseOk;
}
Beispiel #11
0
static SyxOop
_syx_cold_parse_vars (SyxLexer *lexer, syx_bool capitalized)
{
  SyxOop vars;
  SyxOop vars_raw[256];
  syx_varsize vars_size;
  SyxToken token;

  /* Fetch variable names using the lexer */
  token = syx_lexer_next_token (lexer);
  for (vars_size=0; token.type != SYX_TOKEN_END; vars_size++)
    {
      if (token.type != SYX_TOKEN_NAME_CONST)
        {
          syx_token_free (token);
          syx_error ("Expected names for variables\n");
        }

      if (capitalized && !isupper (token.value.string[0]))
        {
          syx_token_free (token);
          syx_error ("First letter must be uppercase\n");
        }

      vars_raw[vars_size] = syx_symbol_new (token.value.string);
      syx_token_free (token);
      token = syx_lexer_next_token (lexer);
    }

  /* Create the array */
  vars = syx_array_new_size (vars_size);
  /* Copy out of the stack */
  memcpy (SYX_OBJECT_DATA (vars), vars_raw, sizeof (SyxOop ) * vars_size);

  return vars;
}
Beispiel #12
0
static void
_syx_parser_parse_block_message_pattern (SyxParser *self)
{
  SyxToken token = syx_lexer_get_last_token (self->lexer);
  SyxParserScope scope;
  scope.start = self->_argument_names_top;
  scope.end = self->_argument_names_top;

  if (! (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, ":")))
    {
      self->_argument_scopes.stack[(syx_int32) self->_argument_scopes.top++] = scope;
      SYX_CODE_ARGUMENT_COUNT(self->method) = syx_small_integer_new (0);
      return;
    }

  while (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, ":"))
    {
      syx_token_free (token);
      token = syx_lexer_next_token (self->lexer);
      assert (token.type == SYX_TOKEN_NAME_CONST);
      self->_argument_names[self->_argument_names_top++] = token.value.string;
      scope.end++;

      token = syx_lexer_next_token (self->lexer);
    }

  if (! (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, "|")))
    syx_error ("Expected | after block message pattern\n");

  syx_token_free (token);
  syx_lexer_next_token (self->lexer);

  self->_argument_scopes.stack[(syx_int32) self->_argument_scopes.top++] = scope;
  SYX_CODE_ARGUMENT_COUNT(self->method) = syx_small_integer_new (scope.end - scope.start);
  return;
}
Beispiel #13
0
static void
_syx_parser_parse_statement (SyxParser *self)
{
  SyxToken token = syx_lexer_get_last_token (self->lexer);

  if (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, "^"))
    {
      syx_token_free (token);
      syx_lexer_next_token (self->lexer);
      _syx_parser_parse_expression (self);
      syx_bytecode_do_special (self->bytecode, SYX_BYTECODE_STACK_RETURN);
    }
  else
    _syx_parser_parse_expression (self);
}
Beispiel #14
0
static syx_varsize
_syx_parser_parse_optimized_block (SyxParser *self, SyxBytecodeSpecial branch_type, syx_bool do_pop)
{
  syx_int8 scope_top;
  syx_uint16 jump;
  syx_bool block_state;
  SyxToken token;
  syx_int32 i;

  syx_bytecode_do_special (self->bytecode, branch_type);
  syx_bytecode_gen_code (self->bytecode, 0);
  jump = self->bytecode->code_top - 1;

  if (do_pop)
    syx_bytecode_pop_top (self->bytecode);
  
  block_state = self->_in_block;
  self->_in_block = TRUE;

  token = syx_lexer_get_last_token (self->lexer);
  if (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, "["))
    {
      syx_token_free (token);
      syx_lexer_next_token (self->lexer);
      /* we need to restore the current scope after the optimized block has been parsed */
      scope_top = self->_temporary_scopes[self->_temporary_scopes_top].top;
      _syx_parser_parse_temporaries (self);
      _syx_parser_parse_body (self);
      for (i=scope_top; i < self->_temporary_scopes[self->_temporary_scopes_top].top; i++)
        syx_free (self->_temporary_scopes[self->_temporary_scopes_top].stack[i]);
      self->_temporary_scopes[self->_temporary_scopes_top].top = scope_top;
      token = syx_lexer_next_token (self->lexer);
    }
  else
    {
      /* a variable or such has been used, like ifTrue: trueBlock */
      _syx_parser_do_binary_continuation (self, _syx_parser_parse_term (self), FALSE);
      syx_bytecode_gen_message (self->bytecode, FALSE, 0, "value");
    }

  self->_in_block = block_state;
  self->bytecode->code[jump] = SYX_COMPAT_SWAP_16 (self->bytecode->code_top);
  return jump;
}
Beispiel #15
0
static void
_syx_parser_parse_array (SyxParser *self)
{
  syx_varsize num_elements = 0;
  SyxToken token = syx_lexer_get_last_token (self->lexer);

  syx_token_free (token);
  token = syx_lexer_next_token (self->lexer);
  while (! (token.type == SYX_TOKEN_END || (token.type == SYX_TOKEN_CLOSING && token.value.character == '}')))
    {
      _syx_parser_parse_expression (self);
      num_elements++;
      token = syx_lexer_get_last_token (self->lexer);
      if (token.type == SYX_TOKEN_CLOSING && token.value.character == '.')
        token = syx_lexer_next_token (self->lexer);
    }

  syx_bytecode_push_array (self->bytecode, num_elements);
}
Beispiel #16
0
static syx_bool
_syx_parser_do_unary_continuation (SyxParser *self, syx_bool super_receiver, syx_bool do_cascade)
{
  SyxToken token = syx_lexer_get_last_token (self->lexer);

  while (token.type == SYX_TOKEN_NAME_CONST)
    {
      if (do_cascade)
        self->_duplicate_indexes[self->_duplicate_indexes_top - 1] = self->bytecode->code_top;

      syx_bytecode_gen_message (self->bytecode, super_receiver,
                                0, token.value.string);
      syx_token_free (token);

      token = syx_lexer_next_token (self->lexer);
      super_receiver = FALSE;
    }

  return super_receiver;
}
Beispiel #17
0
static void
_syx_parser_do_continuation (SyxParser *self, syx_bool super_receiver)
{
  SyxToken token;
  self->_duplicate_indexes_top++;

  super_receiver = _syx_parser_do_key_continuation (self, super_receiver);
  
  token = syx_lexer_get_last_token (self->lexer);
  while (token.type == SYX_TOKEN_CLOSING && token.value.character == ';')
    {
      syx_bytecode_duplicate_at (self->bytecode, self->_duplicate_indexes[self->_duplicate_indexes_top - 1]);
      syx_bytecode_pop_top (self->bytecode);
      syx_token_free (token);
      syx_lexer_next_token (self->lexer);
      _syx_parser_do_key_continuation (self, super_receiver);
      token = syx_lexer_get_last_token (self->lexer);
    }

  self->_duplicate_indexes_top--;
}
Beispiel #18
0
static syx_varsize
_syx_parser_parse_optimized_block (SyxParser *self, SyxBytecodeSpecial branch_type, syx_bool do_pop)
{
  syx_uint16 jump;
  syx_bool block_state;
  SyxToken token;

  syx_bytecode_do_special (self->bytecode, branch_type);
  syx_bytecode_gen_code (self->bytecode, 0);
  jump = self->bytecode->code_top - 1;

  if (do_pop)
    syx_bytecode_pop_top (self->bytecode);
  
  block_state = self->_in_block;
  self->_in_block = TRUE;

  token = syx_lexer_get_last_token (self->lexer);
  if (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, "["))
    {
      syx_token_free (token);
      syx_lexer_next_token (self->lexer);
      _syx_parser_parse_temporaries (self);
      _syx_parser_parse_body (self);
      self->_temporary_scopes.top--;
      token = syx_lexer_next_token (self->lexer);
    }
  else
    {
      _syx_parser_do_binary_continuation (self, _syx_parser_parse_term (self), FALSE);
      syx_bytecode_gen_message (self->bytecode, FALSE, 0, "value");
    }

  self->_in_block = block_state;
  self->bytecode->code[jump] = SYX_COMPAT_SWAP_16 (self->bytecode->code_top);
  return jump;
}
Beispiel #19
0
int SYX_CDECL
main (int argc, char *argv[])
{
  SyxLexer *lexer;
  SyxToken token;

  syx_init (0, NULL, "..");

#ifdef HAVE_LIBGMP
  lexer = syx_lexer_new ("nameconst 123 16r123 16rFFFFFFFF 123.321 1e2 1.3e-2 $c $  #symbol #(aaa) \"comment\" 'string' + := -> !!");
#else
  lexer = syx_lexer_new ("nameconst 123 16r123 123.321 1e2 1.3e-2 $c $  #symbol #(aaa) \"comment\" 'string' + := -> !!");
#endif

  token = syx_lexer_next_token (lexer);
  assert (token.type == SYX_TOKEN_NAME_CONST);
  assert (!strcmp (token.value.string, "nameconst"));
  syx_token_free (token);

  token = syx_lexer_next_token (lexer);
  assert (token.type == SYX_TOKEN_INT_CONST);
  assert (token.value.integer == 123);
  syx_token_free (token);

  token = syx_lexer_next_token (lexer);
  assert (token.type == SYX_TOKEN_INT_CONST);
  assert (token.value.integer == 0x123);

#ifdef HAVE_LIBGMP
  token = syx_lexer_next_token (lexer);
  assert (token.type == SYX_TOKEN_LARGE_INT_CONST);
  assert (mpz_cmp_si (*token.value.large_integer, 0xFFFFFFFF) == 0);
#endif

  token = syx_lexer_next_token (lexer);
  assert (token.type == SYX_TOKEN_FLOAT_CONST);
  assert (token.value.floating == 123.321);
  syx_token_free (token);

  token = syx_lexer_next_token (lexer);
  assert (token.type == SYX_TOKEN_FLOAT_CONST);
  assert (token.value.floating == 100.0);
  syx_token_free (token);

  token = syx_lexer_next_token (lexer);
  assert (token.type == SYX_TOKEN_FLOAT_CONST);
  assert (token.value.floating == 0.013);
  syx_token_free (token);

  token = syx_lexer_next_token (lexer);
  assert (token.type == SYX_TOKEN_CHAR_CONST);
  assert (token.value.character == 'c');
  syx_token_free (token);

  token = syx_lexer_next_token (lexer);
  assert (token.type == SYX_TOKEN_CHAR_CONST);
  assert (token.value.character == ' ');
  syx_token_free (token);

  token = syx_lexer_next_token (lexer);
  assert (token.type == SYX_TOKEN_SYM_CONST);
  assert (!strcmp (token.value.string, "symbol"));
  syx_token_free (token);

  token = syx_lexer_next_token (lexer);
  assert (token.type == SYX_TOKEN_ARRAY_BEGIN);
  syx_token_free (token);

  token = syx_lexer_next_token (lexer);
  assert (token.type == SYX_TOKEN_NAME_CONST);
  assert (!strcmp (token.value.string, "aaa"));
  syx_token_free (token);
  
  token = syx_lexer_next_token (lexer);
  assert (token.type == SYX_TOKEN_CLOSING);
  assert (token.value.character == ')');
  syx_token_free (token);

  token = syx_lexer_next_token (lexer);
  assert (token.type == SYX_TOKEN_STR_CONST);
  assert (!strcmp (token.value.string, "string"));
  syx_token_free (token);

  token = syx_lexer_next_token (lexer);
  assert (token.type == SYX_TOKEN_BINARY);
  assert (!strcmp (token.value.string, "+"));
  syx_token_free (token);

  token = syx_lexer_next_token (lexer);
  assert (token.type == SYX_TOKEN_BINARY);
  assert (!strcmp (token.value.string, ":="));
  syx_token_free (token);

  token = syx_lexer_next_token (lexer);
  assert (token.type == SYX_TOKEN_BINARY);
  assert (!strcmp (token.value.string, "->"));
  syx_token_free (token);

  token = syx_lexer_next_token (lexer);
  assert (token.type == SYX_TOKEN_BINARY);
  assert (!strcmp (token.value.string, "!"));
  syx_token_free (token);

  token = syx_lexer_next_token (lexer);
  assert (token.type == SYX_TOKEN_BINARY);
  assert (!strcmp (token.value.string, "!"));
  syx_token_free (token);

  syx_lexer_free (lexer, FALSE);

  return 0;
}
Beispiel #20
0
static syx_bool
_syx_cold_parse_class (SyxLexer *lexer)
{
  SyxToken token = syx_lexer_get_last_token (lexer);
  SyxOop superclass, subclass;
  syx_string subclass_name;
  syx_bool existing_class = TRUE;

  SyxOop inst_vars, class_vars;
  SyxLexer *inst_vars_lexer, *class_vars_lexer;
  syx_varsize super_inst_vars_size;
  syx_int32 i;

  if (token.type != SYX_TOKEN_NAME_CONST)
    {
      syx_error ("Expected a name constant\n");
      syx_token_free (token);
      return FALSE;
    }

  if (!strcmp (token.value.string, "nil"))
    superclass = syx_nil;
  else
    superclass = syx_globals_at (token.value.string);
  
  token = syx_lexer_next_token (lexer);
  if (!(token.type == SYX_TOKEN_NAME_COLON && !strcmp (token.value.string, "subclass:")))
    {
      syx_token_free (token);
      syx_error ("Expected #subclass:\n");
      return FALSE;
    }
  syx_token_free (token);

  token = syx_lexer_next_token (lexer);
  if (token.type != SYX_TOKEN_SYM_CONST)
    {
      syx_token_free (token);
      syx_error ("Expected a symbol constant\n");
      return FALSE;
    }

  subclass_name = syx_strdup (token.value.string);
  syx_token_free (token);
  subclass = syx_globals_at_if_absent (subclass_name, syx_nil);

  if (strcmp (subclass_name, "Object"))
    {
      if (SYX_IS_NIL (subclass))
        existing_class = FALSE;
      else
        {
          existing_class = TRUE;
          if (SYX_OOP_NE (SYX_CLASS_SUPERCLASS(subclass), superclass))
            {
              syx_array_remove (SYX_CLASS_SUBCLASSES (SYX_CLASS_SUPERCLASS (subclass)),
                                subclass);
              SYX_CLASS_SUPERCLASS(subclass) = superclass;
              syx_array_add (SYX_CLASS_SUBCLASSES (superclass), subclass, TRUE);

              syx_array_remove (SYX_CLASS_SUBCLASSES (SYX_CLASS_SUPERCLASS(syx_object_get_class (subclass))),
                                syx_object_get_class (subclass));
              SYX_CLASS_SUPERCLASS(syx_object_get_class (subclass)) = syx_object_get_class (superclass);
              syx_array_add (SYX_CLASS_SUBCLASSES (syx_object_get_class (superclass)),
                             syx_object_get_class (subclass), TRUE);
            }
        }
    }

  token = syx_lexer_next_token (lexer);
  if (token.type != SYX_TOKEN_NAME_COLON)
    {
      syx_token_free (token);
      syx_error ("Expected #instanceVariableNames:\n");
      return FALSE;
    }
  syx_token_free (token);

  token = syx_lexer_next_token (lexer);
  if (token.type != SYX_TOKEN_STR_CONST)
    {
      syx_token_free (token);
      syx_error ("Expected a string as argument for #instanceVariableNames:\n");
      return FALSE;
    }
  inst_vars_lexer = syx_lexer_new (token.value.string);

  token = syx_lexer_next_token (lexer);
  if (token.type != SYX_TOKEN_NAME_COLON)
    {
      syx_token_free (token);
      syx_error ("Expected #classVariableNames:\n");
      return FALSE;
    }
  syx_token_free (token);

  token = syx_lexer_next_token (lexer);
  if (token.type != SYX_TOKEN_STR_CONST)
    {
      syx_token_free (token);
      syx_error ("Expected a string as argument for #classVariableNames:\n");
      return FALSE;
    }
  class_vars_lexer = syx_lexer_new (token.value.string);

  token = syx_lexer_next_token (lexer);
  if (!_IS_EXL_MARK (token))
    {
      syx_token_free (token);
      syx_error ("Class definition must terminate with an exlamation mark\n");
      return FALSE;
    }
  syx_token_free (token);

  if (!existing_class)
    {
      subclass = syx_class_new (superclass);
      SYX_CLASS_NAME(subclass) = syx_symbol_new (subclass_name);
      syx_globals_at_put (SYX_CLASS_NAME(subclass), subclass);
    }
  syx_free (subclass_name);

  /* Parse instance variables */
  inst_vars = _syx_cold_parse_vars (inst_vars_lexer, FALSE);
  syx_lexer_free (inst_vars_lexer, TRUE);

  /* Fetch superclass instanceSize */
  if (SYX_IS_NIL (superclass))
    super_inst_vars_size = 0;
  else
    super_inst_vars_size = SYX_SMALL_INTEGER (SYX_CLASS_INSTANCE_SIZE (superclass));

  SYX_CLASS_INSTANCE_VARIABLES(subclass) = inst_vars;
  SYX_CLASS_INSTANCE_SIZE(subclass) = syx_small_integer_new (super_inst_vars_size
                                                             + SYX_OBJECT_DATA_SIZE (inst_vars));

  /* Now parse class variables */
  class_vars = _syx_cold_parse_vars (class_vars_lexer, TRUE);
  syx_lexer_free (class_vars_lexer, TRUE);

  SYX_CLASS_CLASS_VARIABLES(subclass) = syx_dictionary_new (SYX_OBJECT_DATA_SIZE (class_vars) + 10); 

  /* translate from array to dictionary */
  for (i=0; i < SYX_OBJECT_DATA_SIZE(class_vars); i++)
    syx_dictionary_at_symbol_put (SYX_CLASS_CLASS_VARIABLES(subclass),
                                  SYX_OBJECT_DATA(class_vars)[i], syx_nil);
  /* get rid of this */
  syx_object_free (class_vars);

  return TRUE;
}
Beispiel #21
0
syx_bool
syx_cold_parse_methods (SyxLexer *lexer)
{
  SyxToken token;
  SyxOop klass;
  SyxParser *parser;
  SyxLexer *method_lexer;
  /*syx_symbol category; */
  syx_string chunk;
  SyxLexer saved_lexer = *lexer;

  token = syx_lexer_next_token (lexer);
  if (token.type != SYX_TOKEN_NAME_CONST)
    {
      *lexer = saved_lexer;
      return FALSE;
    }

  klass = syx_globals_at (token.value.string);
  syx_token_free (token);

  if (SYX_IS_NIL (klass))
    return FALSE;

  token = syx_lexer_next_token (lexer);
  if (token.type == SYX_TOKEN_NAME_CONST && !strcmp (token.value.string, "class"))
    {
      klass = syx_object_get_class (klass);
      syx_token_free (token);
      token = syx_lexer_next_token (lexer);
    }

  if (! (token.type == SYX_TOKEN_NAME_COLON && !strcmp (token.value.string, "methodsFor:")))
    {
      *lexer = saved_lexer;
      return FALSE;
    }
  syx_token_free (token);

  token = syx_lexer_next_token (lexer);
  if (token.type != SYX_TOKEN_STR_CONST)
    {
      *lexer = saved_lexer;
      return FALSE;
    }

  /*  category = syx_strdup (token.value.string); */
  syx_token_free (token);

  token = syx_lexer_next_token (lexer);
  if (!_IS_EXL_MARK (token))
    {
      *lexer = saved_lexer;
      return FALSE;
    }
  syx_token_free (token);

  if (SYX_IS_NIL (SYX_CLASS_METHODS (klass)))
    {
      SYX_CLASS_METHODS(klass) = syx_dictionary_new (50);
    }

  while (TRUE)
    {
      chunk = syx_lexer_next_chunk (lexer);
      method_lexer = syx_lexer_new (chunk);
      if (!method_lexer)
        break;

      parser = syx_parser_new (method_lexer, syx_method_new (), klass);
      syx_parser_parse (parser, FALSE);

      syx_dictionary_at_symbol_put (SYX_CLASS_METHODS(klass),
                                    SYX_METHOD_SELECTOR(parser->method),
                                    parser->method);

      syx_parser_free (parser, TRUE);
    }
  
  return TRUE;
}
Beispiel #22
0
static syx_bool
_syx_parser_do_key_continuation (SyxParser *self, syx_bool super_receiver)
{
  SyxToken token;
  syx_char selector[256] = {0};
  syx_int8 num_args;
  syx_bool super_term;
  syx_uint16 jump, conditionJump, loopJump;
  SyxBytecodeSpecial branchType;

  super_receiver = _syx_parser_do_binary_continuation (self, super_receiver, TRUE);

  token = syx_lexer_get_last_token (self->lexer);
  if (token.type == SYX_TOKEN_NAME_COLON)
    {
      self->_duplicate_indexes[self->_duplicate_indexes_top - 1] = self->bytecode->code_top;
      
      if (!strcmp (token.value.string, "ifTrue:"))
        {
          syx_token_free (token);
          token = syx_lexer_next_token (self->lexer);
          jump = _syx_parser_parse_optimized_block (self, SYX_BYTECODE_BRANCH_IF_TRUE, FALSE);

          token = syx_lexer_get_last_token (self->lexer);
          if (token.type == SYX_TOKEN_NAME_COLON && !strcmp (token.value.string, "ifFalse:"))
            {
              syx_token_free (token);
              token = syx_lexer_next_token (self->lexer);
              
              /* skip ifFalse: block if condition is true */
              syx_bytecode_do_special (self->bytecode, SYX_BYTECODE_BRANCH);
              syx_bytecode_gen_code (self->bytecode, 0);
              conditionJump = self->bytecode->code_top - 1;

              /* jump here if condition is false */
              self->bytecode->code[jump] = SYX_COMPAT_SWAP_16 (self->bytecode->code_top);
              jump = _syx_parser_parse_optimized_block (self, SYX_BYTECODE_BRANCH, TRUE);
              /* We don't need any jump after ifFalse: */
              self->bytecode->code[jump] = 0;

              /* jump here if condition was true */
              self->bytecode->code[conditionJump] = SYX_COMPAT_SWAP_16 (self->bytecode->code_top);
            }

          return FALSE;
        }
      else if (!strcmp (token.value.string, "ifFalse:"))
        {
          syx_token_free (token);
          token = syx_lexer_next_token (self->lexer);
          jump = _syx_parser_parse_optimized_block (self, SYX_BYTECODE_BRANCH_IF_FALSE, FALSE);

          token = syx_lexer_get_last_token (self->lexer);
          if (token.type == SYX_TOKEN_NAME_COLON && !strcmp (token.value.string, "ifTrue:"))
            {
              syx_token_free (token);
              token = syx_lexer_next_token (self->lexer);

              /* skip ifTrue: block if condition is false */
              syx_bytecode_do_special (self->bytecode, SYX_BYTECODE_BRANCH);
              syx_bytecode_gen_code (self->bytecode, 0);
              conditionJump = self->bytecode->code_top - 1;

              /* jump here if condition is true */
              self->bytecode->code[jump] = SYX_COMPAT_SWAP_16 (self->bytecode->code_top);
              jump = _syx_parser_parse_optimized_block (self, SYX_BYTECODE_BRANCH, TRUE);
              /* We don't need any jump after ifFalse: */
              self->bytecode->code[jump] = 0;

              /* jump here if condition was false */
              self->bytecode->code[conditionJump] = SYX_COMPAT_SWAP_16 (self->bytecode->code_top);
            }

          return FALSE;
        }
      else if (!strcmp (token.value.string, "whileTrue:") || !strcmp (token.value.string, "whileFalse:"))
        {
          if (!strcmp (token.value.string, "whileTrue:"))
            branchType = SYX_BYTECODE_BRANCH_IF_TRUE;
          else
            branchType = SYX_BYTECODE_BRANCH_IF_FALSE;

          syx_token_free (token);
          token = syx_lexer_next_token (self->lexer);
          loopJump = self->bytecode->code_top;
          syx_bytecode_do_special (self->bytecode, SYX_BYTECODE_DUPLICATE);
          syx_bytecode_gen_message (self->bytecode, FALSE, 0, "value");
          conditionJump = _syx_parser_parse_optimized_block (self, branchType, FALSE);
          syx_bytecode_pop_top (self->bytecode);
          syx_bytecode_do_special (self->bytecode, SYX_BYTECODE_BRANCH);
          syx_bytecode_gen_code (self->bytecode, loopJump);
          self->bytecode->code[conditionJump] = SYX_COMPAT_SWAP_16 (self->bytecode->code_top);
          syx_bytecode_pop_top (self->bytecode);

          return FALSE;
        }

      num_args = 0;
      while (token.type == SYX_TOKEN_NAME_COLON)
        {
          strcat (selector, token.value.string);
          num_args++;
          syx_token_free (token);
          syx_lexer_next_token (self->lexer);

          super_term = _syx_parser_parse_term (self);
          _syx_parser_do_binary_continuation (self, super_term, FALSE);

          token = syx_lexer_get_last_token (self->lexer);
        }

      syx_bytecode_gen_message (self->bytecode, super_receiver, num_args, selector);

      return FALSE;
    }
  return super_receiver;
}
Beispiel #23
0
static syx_bool
_syx_parser_parse_term (SyxParser *self)
{
  SyxToken token = syx_lexer_get_last_token (self->lexer);
  syx_bool super_term = FALSE;
  switch (token.type)
    {
    case SYX_TOKEN_NAME_CONST:
      super_term = _syx_parser_parse_name_term (self, token.value.string);
      syx_token_free (token);
      break;
    case SYX_TOKEN_STR_CONST:
      syx_bytecode_push_literal (self->bytecode, syx_string_new (token.value.string));
      syx_token_free (token);
      break;
    case SYX_TOKEN_INT_CONST:
      syx_bytecode_push_literal (self->bytecode, syx_small_integer_new (token.value.integer));
      syx_token_free (token);
      break;
#ifdef HAVE_LIBGMP
    case SYX_TOKEN_LARGE_INT_CONST:
      syx_bytecode_push_literal (self->bytecode,
                                 syx_large_integer_new_mpz (token.value.large_integer));
      syx_token_free (token);
      break;
#endif
    case SYX_TOKEN_FLOAT_CONST:
      syx_bytecode_push_literal (self->bytecode, syx_float_new (token.value.floating));
      syx_token_free (token);
      break;
    case SYX_TOKEN_SYM_CONST:
      syx_bytecode_push_literal (self->bytecode, syx_symbol_new (token.value.string));
      syx_token_free (token);
      break;
    case SYX_TOKEN_CHAR_CONST:
      syx_bytecode_push_literal (self->bytecode, syx_character_new (token.value.character));
      syx_token_free (token);
      break;
    case SYX_TOKEN_ARRAY_BEGIN:
      syx_bytecode_push_literal (self->bytecode, _syx_parser_parse_literal_array (self));
      syx_token_free (token);
      break;
    case SYX_TOKEN_BINARY:
      if (!strcmp (token.value.string, "("))
        {
          syx_token_free (token);
          token = syx_lexer_next_token (self->lexer);
          _syx_parser_parse_expression (self);
          token = syx_lexer_get_last_token (self->lexer);
          if (! (token.type == SYX_TOKEN_CLOSING && token.value.character == ')'))
            syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected ) after sub expression"));
          break;
        }
      else if (!strcmp (token.value.string, "["))
        {
          _syx_parser_parse_block (self);
          break;
        }
      else if (!strcmp (token.value.string, "{"))
        {
          _syx_parser_parse_array (self);
          break;
        }
      else if (!strcmp (token.value.string, "-"))
        {
          syx_token_free (token);
          token = syx_lexer_next_token (self->lexer);
          if (token.type == SYX_TOKEN_INT_CONST)
            syx_bytecode_push_literal (self->bytecode, syx_small_integer_new (-token.value.integer));

#ifdef HAVE_LIBGMP
          else if (token.type == SYX_TOKEN_LARGE_INT_CONST)
            {
              mpz_neg (*token.value.large_integer, *token.value.large_integer);
              syx_bytecode_push_literal (self->bytecode,
                                         syx_large_integer_new_mpz (token.value.large_integer));
            }
#endif /* HAVE_LIBGMP */

          else if (token.type == SYX_TOKEN_FLOAT_CONST)
            syx_bytecode_push_literal (self->bytecode, syx_float_new (-token.value.floating));
          else
            syx_signal(SYX_ERROR_INTERP, syx_string_new ("Negation not followed by number"));

          syx_token_free (token);
          break;
        }
      /* We continue here because of weird binary token used as expression start */

    default:
      switch (token.type)
        {
        case SYX_TOKEN_END:
          syx_signal (SYX_ERROR_INTERP, syx_string_new ("Unexpected end of input"));
          break;
        case SYX_TOKEN_STRING_ENTRY:
          syx_signal (SYX_ERROR_INTERP, syx_string_new ("Invalid expression start: %s", token.value.string));
          syx_token_free (token);
          break;
        case SYX_TOKEN_CLOSING:
          syx_signal (SYX_ERROR_INTERP, syx_string_new ("Unexpected closing: %c", token.value.character));
          break;
        default:
          syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected expression"));
          break;
        }
    }

  syx_lexer_next_token (self->lexer);
  return super_term;
}
Beispiel #24
0
static void
_syx_parser_parse_primitive (SyxParser *self)
{
  SyxToken token = syx_lexer_get_last_token (self->lexer);
  syx_int32 prim_index;

  SYX_METHOD_PRIMITIVE(self->method) = syx_small_integer_new (-1);

  if (! (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, "<")))
    return;
  syx_token_free (token);

  token = syx_lexer_next_token (self->lexer);
  if (token.type != SYX_TOKEN_NAME_COLON)
    syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected name colon"));

  if (!strcmp (token.value.string, "primitive:"))
    {
      syx_token_free (token);

      token = syx_lexer_next_token (self->lexer);
      if (token.type != SYX_TOKEN_STR_CONST)
        syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected a string containing the primitive to be called"));
      
      prim_index = syx_primitive_get_index (token.value.string);
      if (prim_index < 0)
        syx_signal (SYX_ERROR_INTERP, syx_string_new ("Unknown primitive named", token.value.string));
      syx_token_free (token);
      
      token = syx_lexer_next_token (self->lexer);
      if (! (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, ">")))
        syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected >"));
      syx_token_free (token);
      
      SYX_METHOD_PRIMITIVE (self->method) = syx_small_integer_new (prim_index);
      
      syx_lexer_next_token (self->lexer);
    }
  else if (!strcmp (token.value.string, "cCall:"))
    {
      syx_token_free (token);
      
      token = syx_lexer_next_token (self->lexer);

      if (token.type != SYX_TOKEN_STR_CONST)
        syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected a string containing the primitive to be called"));
      syx_bytecode_gen_literal (self->bytecode, syx_symbol_new (token.value.string));
      syx_token_free (token);

      token = syx_lexer_next_token (self->lexer);
      if (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, ">"))
        {
          syx_token_free (token);
          syx_bytecode_gen_literal (self->bytecode, syx_nil);
          SYX_METHOD_PRIMITIVE (self->method) = syx_small_integer_new (-2);
          syx_lexer_next_token (self->lexer);
          return;
        }

      if (! (token.type == SYX_TOKEN_NAME_COLON && !strcmp (token.value.string, "plugin:")))
        syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected plugin:"));
      syx_token_free (token);

      token = syx_lexer_next_token (self->lexer);
      if (token.type != SYX_TOKEN_STR_CONST)
        syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected a string containing the plugin name"));
      syx_bytecode_gen_literal (self->bytecode, syx_symbol_new (token.value.string));
      syx_token_free (token);

      token = syx_lexer_next_token (self->lexer);
      if (! (token.type == SYX_TOKEN_BINARY && !strcmp (token.value.string, ">")))
        syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected >"));
      syx_token_free (token);

      syx_lexer_next_token (self->lexer);

      SYX_METHOD_PRIMITIVE(self->method) = syx_small_integer_new (-2);
    }
  else
    syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected primitive or cCall"));

  return;
}