Support for IO inputs in the lexer.

Using IO/StringIO objects one can parse large XML files without first having to
read the entire file into memory. This can potentially save a lot of memory at
the cost of a slightly slower runtime.

For IO like instances the lexer will consume the input line by line. If a
String is given it's consumed as a whole instead. A small side effect of
reading the input line by line is that text such as "foo\nbar" will be lexed as
two tokens instead of one.

Fixes #19.
This commit is contained in:
Yorick Peterse committed 2014-05-26 00:30:39 +02:00
1 parent 6b9d65923a
commit 629dcd3fe6
5 files changed
+133 -33

No files matched your search

+21 -6
View File
@@ -11,6 +11,7 @@ import org.jruby.RubyModule;
import org.jruby.RubyClass;
import org.jruby.RubyObject;
import org.jruby.RubyString;
import org.jruby.RubyFixnum;
import org.jruby.util.ByteList;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
@@ -36,6 +37,10 @@ public class Lexer extends RubyObject
%% write data;
/* Used by Ragel to keep track of the current state. */
int act;
int cs;
/**
* Sets up the current class in the Ruby runtime.
*/
@@ -79,28 +84,35 @@ public class Lexer extends RubyObject
* This method always returns nil.
*/
@JRubyMethod
public IRubyObject advance_native(ThreadContext context)
public IRubyObject advance_native(ThreadContext context, RubyString rb_str)
{
// Pull the data in from Ruby land.
RubyString rb_str = (RubyString) this.callMethod(context, "read_data");
Encoding encoding = rb_str.getEncoding();
byte[] data = rb_str.getBytes();
int act = 0;
int cs = 0;
int ts = 0;
int te = 0;
int p = 0;
int pe = data.length;
int eof = data.length;
%% write init;
%% write exec;
return context.nil;
}
/**
* Resets the internal state of the lexer.
*/
@JRubyMethod
public IRubyObject reset_native(ThreadContext context)
{
this.act = 0;
this.cs = java_lexer_start;
return context.nil;
}
/**
* Calls back in to Ruby land passing the current token value along.
*
@@ -131,5 +143,8 @@ public class Lexer extends RubyObject
}
%%{
variable act this.act;
variable cs this.cs;
include base_lexer "base_lexer.rl";
}%%