/*! Parse a declaration file. \return TRUE if no error has occurred */ syx_bool syx_cold_file_in (syx_symbol filename) { SyxLexer *lexer; syx_string buffer; syx_int32 fd, count; syx_size size; #ifdef HAVE_FSTAT struct stat statbuf; #endif if ((fd = open (filename, O_RDONLY)) < 0) { syx_error ("can't open %s\n", filename); return FALSE; } #ifdef HAVE_FSTAT if ((fstat (fd, &statbuf)) < 0) { syx_error ("can't obtain size of %s\n", filename); return FALSE; } size = statbuf.st_size; #else size = 1000000; #endif buffer = (syx_string) syx_malloc (size + 1); count = read (fd, buffer, size); buffer[count - 1] = '\0'; close (fd); lexer = syx_lexer_new (buffer); if (!lexer) { syx_free (buffer); return FALSE; } if (!syx_cold_parse (lexer)) { syx_lexer_free (lexer, TRUE); return FALSE; } syx_lexer_free (lexer, TRUE); return TRUE; }
/*! Free all memory used by the parser. \param free_segment TRUE frees the instance_names (not its contents) and the lexer */ void syx_parser_free (SyxParser *self, syx_bool free_segment) { syx_bytecode_free (self->bytecode); if (free_segment) { if (self->instance_names) syx_free (self->instance_names); syx_lexer_free (self->lexer, TRUE); } syx_free (self); }
/*! Free all memory used by the parser. \param free_segment TRUE frees the instance_names (not its contents) and the lexer */ void syx_parser_free (SyxParser *self, syx_bool free_segment) { syx_size i; syx_bytecode_free (self->bytecode); for (i=0; i < self->_temporary_names_top; i++) syx_free (self->_temporary_names[i]); for (i=0; i < self->_argument_names_top; i++) syx_free (self->_argument_names[i]); if (free_segment) { if (self->instance_names) syx_free (self->instance_names); syx_lexer_free (self->lexer, TRUE); } syx_free (self); }
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; }
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; }