Ejemplo n.º 1
0
static void
_syx_parser_parse_body (SyxParser *self)
{
  SyxToken token = syx_lexer_get_last_token (self->lexer);

  while (TRUE)
    {
      while (token.type == SYX_TOKEN_CLOSING)
        {
          if (self->_in_block && token.value.character == ']')
            return;
          
          if (token.value.character == '.')
            {
              token = syx_lexer_next_token (self->lexer);
              /* Do not pop from the stack multiple times */
              if (token.type != SYX_TOKEN_CLOSING && token.type != SYX_TOKEN_END)
                syx_bytecode_pop_top (self->bytecode);
            }
          else
            token = syx_lexer_next_token (self->lexer);
        }

      if (token.type == SYX_TOKEN_END)
        break;

      _syx_parser_parse_statement (self);
      token = syx_lexer_get_last_token (self->lexer);
    }

  if (self->_in_block)
    syx_signal (SYX_ERROR_INTERP, syx_string_new ("Expected ] after block body"));
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
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--;
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
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;
}