/*! 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 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); }
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; }
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; }