/*! Do parse. \return TRUE if parsing was successful, otherwise FALSE */ syx_bool syx_parser_parse (SyxParser *self, syx_bool skip_message_pattern) { SyxToken token; SyxParserScope scope; token = syx_lexer_next_token (self->lexer); if (token.type == SYX_TOKEN_END) return TRUE; if (skip_message_pattern) { scope.start = self->_argument_names_top; scope.end = self->_argument_names_top; self->_argument_scopes.stack[(syx_int32) self->_argument_scopes.top++] = scope; } else _syx_parser_parse_message_pattern (self); if (!self->_in_block) _syx_parser_parse_primitive (self); _syx_parser_parse_temporaries (self); if (self->_in_block) syx_bytecode_push_constant (self->bytecode, SYX_BYTECODE_CONST_NIL); _syx_parser_parse_body (self); syx_bytecode_do_special (self->bytecode, SYX_BYTECODE_SELF_RETURN); SYX_CODE_BYTECODES(self->method) = syx_byte_array_new_ref (self->bytecode->code_top * sizeof (syx_uint16), (syx_uint8 *)self->bytecode->code); SYX_CODE_LITERALS(self->method) = syx_array_new_ref (self->bytecode->literals_top, self->bytecode->literals); if (self->_in_block) SYX_BLOCK_ARGUMENT_STACK_TOP(self->method) = syx_small_integer_new (self->_argument_scopes.stack[self->_argument_scopes.top-1].start); else { SYX_METHOD_ARGUMENT_STACK_SIZE(self->method) = syx_small_integer_new (self->_argument_names_top); SYX_METHOD_TEMPORARY_STACK_SIZE(self->method) = syx_small_integer_new (self->_temporary_names_top); } SYX_CODE_STACK_SIZE(self->method) = syx_small_integer_new (self->bytecode->stack_size + 1); SYX_CODE_TEXT(self->method) = syx_string_new (self->lexer->text + syx_find_first_non_whitespace (self->lexer->text)); SYX_CODE_CLASS(self->method) = self->klass; return TRUE; }
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; }
/*! Do parse. \return TRUE if parsing was successful, otherwise FALSE */ syx_bool syx_parser_parse (SyxParser *self, syx_bool skip_message_pattern) { SyxToken token; token = syx_lexer_next_token (self->lexer); if (token.type == SYX_TOKEN_END) return TRUE; self->_temporary_scopes[self->_temporary_scopes_top].top = 0; self->_argument_scopes[self->_argument_scopes_top].top = 0; if (!skip_message_pattern) _syx_parser_parse_message_pattern (self); if (!self->_in_block) _syx_parser_parse_primitive (self); _syx_parser_parse_temporaries (self); if (self->_in_block) syx_bytecode_push_constant (self->bytecode, SYX_BYTECODE_CONST_NIL); _syx_parser_parse_body (self); syx_bytecode_do_special (self->bytecode, SYX_BYTECODE_SELF_RETURN); SYX_CODE_BYTECODES(self->method) = syx_byte_array_new_ref (self->bytecode->code_top * sizeof (syx_uint16), (syx_uint8 *)self->bytecode->code); SYX_CODE_LITERALS(self->method) = syx_array_new_ref (self->bytecode->literals_top, self->bytecode->literals); SYX_CODE_STACK_SIZE(self->method) = syx_small_integer_new (self->bytecode->stack_size + 1); SYX_CODE_TEXT(self->method) = syx_string_new (self->lexer->text + syx_find_first_non_whitespace (self->lexer->text)); SYX_CODE_CLASS(self->method) = self->klass; /* Free arguments and temporaries of this scope */ _syx_parser_free_arguments (self); _syx_parser_free_temporaries (self); return TRUE; }
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; }