%%{
machine parser; action _prefix { mark_pfx = p; } action prefix { prefix = input.substring(mark_pfx, p); } action _check_prefix { if ( !prefix.equals(tag_prefix) ) { // have to manually add ':' / Sep // pass the text through & reset state pass_through(input.substring(tagstart, p) + ":"); prefix = ""; fgoto main; } } action _starttag { mark_stg = p; } action starttag { name = input.substring(mark_stg, p); } action _attr { mark_attr = p; } action attr { attributes.op_aset( runtime.getCurrentContext(), RubyString.newString(runtime, nat), RubyString.newString(runtime, vat) ); } action _nameattr { mark_nat = p; } action nameattr { nat = input.substring(mark_nat, p); } action _valattr { mark_vat = p; } action valattr { vat = input.substring(mark_vat, p); } action opentag { flavor = RubySymbol.newSymbol(runtime, "open".intern()); } action selftag { flavor = RubySymbol.newSymbol(runtime, "self".intern()); } action closetag { flavor = RubySymbol.newSymbol(runtime, "close".intern()); } Closeout := empty; # words PrefixChar = [\-A-Za-z0-9._?] ; NameChar = [\-A-Za-z0-9._:] ; TagName = NameChar+ >_starttag %sarttag; Prefix = PrefixChar+ >_prefix %refix; Open = "<"; Sep = ":" >_check_prefix; End = "/"; Close = ">"; Name = Prefix Sep TagName; NameAttr = NameChar+ >_nameattr %ameattr; Q1Char = ( "\\\'" | [^'] ) ; Q1Attr = Q1Char* >_valattr %valattr; Q2Char = ( "\\"" | [^"] ) ; Q2Attr = Q2Char* >_valattr %valattr; Attr = NameAttr space* "=" space* ('"' Q2Attr '"' | "'" Q1Attr "'") space* >_attr %attr; Attrs = (space+ Attr* | empty); CloseTrailer = End Close %selftag; OpenTrailer = Close %opentag; Trailer = (OpenTrailer | CloseTrailer); OpenOrSelfTag = Name Attrs? Trailer; CloseTag = End Name space* Close %closetag; SomeTag = Open (OpenOrSelfTag | CloseTag); main := |* SomeTag => { tag(prefix, name, attributes, flavor); prefix = ""; name = ""; attributes = RubyHash.newHash(runtime); flavor = RubySymbol.newSymbol(runtime, "tasteless".intern()); }; any => { pass_through(input.substring(p, p + 1)); tagstart = p + 1; }; *|;
}%%
package radius.parser;
import java.util.HashMap; import java.util.LinkedList; import org.jruby.Ruby; // runtime import org.jruby.RubyObject; import org.jruby.runtime.builtin.IRubyObject; import org.jruby.RubyArray; import org.jruby.RubyString; import org.jruby.RubyHash; import org.jruby.RubySymbol;
public class JavaScanner {
Ruby runtime = null;
RubyArray rv = null;
void pass_through(String str) {
RubyObject last = ((RubyObject)rv.last());
if ( rv.size() > 0 && last != null && (last instanceof RubyString) ){
// XXX concat changes for ruby 1.9
((RubyString) last).concat(RubyString.newString(runtime, str));
} else {
rv.append(RubyString.newString(runtime, str));
}
}
void tag(String prefix, String name, RubyHash attr, RubySymbol flavor) {
RubyHash tag = RubyHash.newHash(runtime);
tag.op_aset(
runtime.getCurrentContext(),
RubySymbol.newSymbol(runtime, "prefix"),
RubyString.newString(runtime, prefix)
);
tag.op_aset(
runtime.getCurrentContext(),
RubySymbol.newSymbol(runtime, "name"),
RubyString.newString(runtime, name)
);
tag.op_aset(
runtime.getCurrentContext(),
RubySymbol.newSymbol(runtime, "attrs"),
attr
);
tag.op_aset(
runtime.getCurrentContext(),
RubySymbol.newSymbol(runtime, "flavor"),
flavor
);
rv.append(tag);
}
public JavaScanner(Ruby runtime) {
this.runtime = runtime;
}
%% write data;
public RubyArray operate(String tag_prefix, String input) {
char[] data = input.toCharArray();
String disposable_string;
String name = "";
String prefix = "";
RubySymbol flavor = RubySymbol.newSymbol(runtime, "tasteless".intern());
RubyHash attributes = RubyHash.newHash(runtime);
int tagstart = 0;
int mark_pfx = 0;
int mark_stg = 0;
int mark_attr = 0;
int mark_nat = 0;
int mark_vat = 0;
String nat = "";
String vat = "";
int cs;
int p = 0;
int pe = data.length;
int eof = pe;
int act;
int ts;
int te;
rv = RubyArray.newArray(runtime);
char[] remainder = data;
%% write init;
%% write exec;
return rv;
}
}