%%{ 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 %starttag; Prefix = PrefixChar+ >_prefix %prefix; Open = "<"; Sep = ":" >_check_prefix; End = "/"; Close = ">"; Name = Prefix Sep TagName; NameAttr = NameChar+ >_nameattr %nameattr; 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; } }