jlong/radius

View on GitHub
lib/radius/parser/JavaScanner.rl

Summary

Maintainability
Test Coverage
%%{
    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;
  }
}