[macruby-changes] [2224] MacRuby/branches/experimental

source_changes at macosforge.org source_changes at macosforge.org
Wed Aug 5 13:20:50 PDT 2009


Revision: 2224
          http://trac.macosforge.org/projects/ruby/changeset/2224
Author:   pthomson at apple.com
Date:     2009-08-05 13:20:50 -0700 (Wed, 05 Aug 2009)
Log Message:
-----------
FIrst steps of event-based YAML parsing work.

Modified Paths:
--------------
    MacRuby/branches/experimental/ext/libyaml/rubyext.c
    MacRuby/branches/experimental/lib/yaml.rb

Modified: MacRuby/branches/experimental/ext/libyaml/rubyext.c
===================================================================
--- MacRuby/branches/experimental/ext/libyaml/rubyext.c	2009-08-05 20:20:49 UTC (rev 2223)
+++ MacRuby/branches/experimental/ext/libyaml/rubyext.c	2009-08-05 20:20:50 UTC (rev 2224)
@@ -16,7 +16,8 @@
 #include "yaml.h"
 
 // Ideas to speed this up:
-// none as of yet.
+// embed the yaml_parser_t and yaml_emitter_t into the parser/emitter structs
+// rather than just keep pointers to them; this means fewer mallocs
 
 typedef struct rb_yaml_parser_s {
 	struct RBasic basic;		// holds the class information
@@ -62,13 +63,24 @@
 
 static struct mcache *to_yaml_cache = NULL;
 
+static const int DEFAULT_STACK_SIZE = 5;
+
 static VALUE
 rb_yaml_parser_alloc(VALUE klass, SEL sel)
 {
 	NEWOBJ(parser, struct rb_yaml_parser_s);
 	OBJSETUP(parser, klass, T_OBJECT);
+	
+	GC_WB(&parser->stack, ALLOC_N(VALUE, DEFAULT_STACK_SIZE));	
+	parser->stack_size = DEFAULT_STACK_SIZE;
+	parser->stack_index = -1;
+	parser->stack[0] = Qnil;
+	
+	parser->resolver = rb_oDefaultResolver;
+	
+	parser->event_valid = false;
+	
 	GC_WB(&parser->parser, ALLOC(yaml_parser_t));
-	parser->input = Qnil;
 	yaml_parser_initialize(parser->parser);
 	return (VALUE)parser;
 }
@@ -78,12 +90,8 @@
 {
 	VALUE io = (VALUE)io_ptr;
 	long result = rb_io_primitive_read(ExtractIOStruct(io), (UInt8*)buffer, size);
-	if (result == -1)
-	{
-		return 0;
-	}
 	*size_read = result;
-	return 1;
+	return (result != -1);
 }
 
 #if 0
@@ -113,6 +121,11 @@
 
 #endif
 
+static VALUE
+rb_yaml_parser_input(VALUE self, SEL sel)
+{
+	return RYAMLParser(self)->input;
+}
 
 static VALUE
 rb_yaml_parser_set_input(VALUE self, SEL sel, VALUE input)
@@ -144,10 +157,14 @@
 	return input;
 }
 
+
 static VALUE
-rb_yaml_parser_input(VALUE self, SEL sel)
+rb_yaml_parser_initialize(VALUE self, SEL sel, int argc, VALUE *argv)
 {
-	return RYAMLParser(self)->input;
+	VALUE input = Qnil;
+	rb_scan_args(argc, argv, "01", &input);
+	rb_yaml_parser_set_input(self, 0, input);
+	return self;
 }
 
 static VALUE
@@ -180,19 +197,140 @@
 	return error;
 }
 
-static VALUE
-rb_yaml_parser_initialize(VALUE self, SEL sel, int argc, VALUE *argv)
+static inline void
+delete_event(rb_yaml_parser_t *parser)
 {
-	VALUE input = Qnil;
-	rb_scan_args(argc, argv, "01", &input);
-	rb_yaml_parser_set_input(self, 0, input);
-	return self;
+	if (parser->event_valid)
+	{
+		yaml_event_delete(&parser->event);
+		parser->event_valid = false;
+	}
 }
 
+static inline bool
+next_event(rb_yaml_parser_t *parser)
+{
+	delete_event(parser);
+	if (yaml_parser_parse(parser->parser, &parser->event) == -1)
+	{
+		rb_raise(rb_eRuntimeError, "parsing error"); // XXX: Make this more informative
+		parser->event_valid = false;
+	} else
+	{
+		parser->event_valid = true;
+	}
+	printf("Parsed event\n");
+	return parser->event_valid;
+}
+
+static void
+parse_scalar(rb_yaml_parser_t *parser)
+{
+	VALUE current_item = parser->stack[parser->stack_index];
+	VALUE new_str = rb_str_new2((char*)parser->event.data.scalar.value);
+	if(NIL_P(current_item))
+	{
+		parser->stack[parser->stack_index] = new_str;
+	}
+	else if (TYPE(current_item) == T_ARRAY)
+	{
+		rb_ary_push(current_item, new_str);
+	}
+}
+
+static void
+push(rb_yaml_parser_t *parser, VALUE item)
+{
+	parser->stack_index += 1;
+	if (parser->stack_index >= parser->stack_size)
+	{
+		rb_raise(rb_eRuntimeError, "oh god the stack depth");
+	}
+	parser->stack[parser->stack_index] = item;
+}
+
+static void pop(rb_yaml_parser_t *parser) __attribute__ ((noinline));
+
+static void
+pop(rb_yaml_parser_t *parser)
+{
+	if(parser->stack_index == 0)
+	{
+		return;
+	}
+	
+	printf("something is very wrong here.");
+}
+
+static void
+parse(rb_yaml_parser_t *parser)
+{
+	if(!next_event(parser))
+	{
+		return;
+	}
+	
+	if(parser->event.type != YAML_STREAM_START_EVENT)
+	{
+		rb_raise(rb_eRuntimeError, "expected STREAM_START event");
+	}
+	
+	for(;;) 
+	{
+		if(!next_event(parser))
+		{
+			break;
+		}
+		switch(parser->event.type)
+		{
+			case YAML_DOCUMENT_START_EVENT:
+			break;
+
+			case YAML_MAPPING_START_EVENT:
+			printf("oh god a mapping\n");
+			break;
+
+			case YAML_SEQUENCE_START_EVENT:
+			printf("oh god parsing a sequence");
+			push(parser, rb_ary_new());
+			break;
+
+			case YAML_SCALAR_EVENT:
+			printf("oh god parsing a scalar");
+			parse_scalar(parser);
+			break;
+
+			case YAML_ALIAS_EVENT:
+			printf("oh god an alias i don't even know how to do this\n");
+			break;
+				
+			case YAML_MAPPING_END_EVENT:
+			printf("oh god a mapping ended aaagh\n");
+			break;
+			
+			case YAML_SEQUENCE_END_EVENT:
+			pop(parser);
+			break;
+
+			case YAML_NO_EVENT:
+			rb_raise(rb_eRuntimeError, "expected an event, got nothing");
+			
+			default: break;
+		}
+		if (parser->event.type == YAML_DOCUMENT_END_EVENT)
+		{
+			break;
+		}
+	}
+}
+
+
 static VALUE
 rb_yaml_parser_load(VALUE self, SEL sel)
 {
-	rb_notimplement();
+	rb_yaml_parser_t *parser = RYAMLParser(self);
+	parse(parser);
+	return parser->stack[0];
 }
 
 static IMP rb_yaml_parser_finalize_super = NULL; 
@@ -207,6 +345,10 @@
 		yaml_parser_delete(rbparser->parser);
 		rbparser->parser = NULL;
 	}
+	if((rbparser != NULL) && (rbparser->stack != NULL))
+	{
+		rbparser->stack = NULL;
+	}
 	if (rb_yaml_parser_finalize_super != NULL)
 	{
 		((void(*)(void *, SEL))rb_yaml_parser_finalize_super)(rcv, sel);

Modified: MacRuby/branches/experimental/lib/yaml.rb
===================================================================
--- MacRuby/branches/experimental/lib/yaml.rb	2009-08-05 20:20:49 UTC (rev 2223)
+++ MacRuby/branches/experimental/lib/yaml.rb	2009-08-05 20:20:50 UTC (rev 2224)
@@ -25,7 +25,7 @@
   
   def YAML.load(io)
     parsr = LibYAML::Parser.new(io)
-    LibYAML::DEFAULT_RESOLVER.transfer(parsr.load)
+    parsr.load
   end
   
   def YAML.load_file(path)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090805/c4c49a3d/attachment.html>


More information about the macruby-changes mailing list