package org.libll;
import java.util.HashMap; import java.util.ArrayList;
import org.jruby.Ruby; import org.jruby.RubyModule; import org.jruby.RubyClass; import org.jruby.RubyObject; import org.jruby.RubySymbol; import org.jruby.RubyArray; import org.jruby.RubyFixnum;
import org.jruby.anno.JRubyClass; import org.jruby.anno.JRubyMethod; import org.jruby.runtime.ThreadContext; import org.jruby.runtime.ObjectAllocator; import org.jruby.runtime.builtin.IRubyObject;
/**
* Class used for storing the configuration (e.g. the rules and the lookup * table) of a parser driver. This class mimics its C equivalent (also called * "DriverConfig"). */
@JRubyClass(name=“LL::DriverConfig”, parent=“Object”) public class DriverConfig extends RubyObject {
/** * The current Ruby runtime. */ private Ruby runtime; /** * Hash mapping Ruby Symbols with their indexes. */ public HashMap<RubySymbol, Long> terminals = new HashMap<RubySymbol, Long>(); /** * 2-dimensional array containing the rules and their steps. */ public ArrayList<ArrayList<Long>> rules = new ArrayList<ArrayList<Long>>(); /** * 2-dimensional array used as the lookup table. */ public ArrayList<ArrayList<Long>> table = new ArrayList<ArrayList<Long>>(); /** * Array containing the callback names. */ public ArrayList<RubySymbol> action_names = new ArrayList<RubySymbol>(); /** * Array containing the arities of every callback. */ public ArrayList<Integer> action_arg_amounts = new ArrayList<Integer>(); /** * Sets up the class in the Ruby runtime. */ public static void load(Ruby runtime) { RubyModule ll = (RubyModule) runtime.getModule("LL"); RubyClass config = ll.defineClassUnder( "DriverConfig", runtime.getObject(), ALLOCATOR ); config.defineAnnotatedMethods(DriverConfig.class); } private static final ObjectAllocator ALLOCATOR = new ObjectAllocator() { public IRubyObject allocate(Ruby runtime, RubyClass klass) { return new org.libll.DriverConfig(runtime, klass); } }; /** * @param runtime The current Ruby runtime. * @param klass The DriverConfig class. */ public DriverConfig(Ruby runtime, RubyClass klass) { super(runtime, klass); this.runtime = runtime; } /** * Stores the terminals of the parser in the current DriverConfig instance. * * @param arg Array of terminals to store. */ @JRubyMethod(name="terminals_native=") public IRubyObject set_terminals_native(ThreadContext context, IRubyObject arg) { RubyArray array = arg.convertToArray(); for ( long index = 0; index < array.size(); index++ ) { RubySymbol sym = (RubySymbol) array.entry(index); this.terminals.put(sym, index); } return context.nil; } /** * Stores the rules in the current DriverConfig instance. * * @param arg Array of rules to store. */ @JRubyMethod(name="rules_native=") public IRubyObject set_rules_native(ThreadContext context, IRubyObject arg) { RubyArray array = arg.convertToArray(); for ( long rindex = 0; rindex < array.size(); rindex++ ) { RubyArray ruby_row = (RubyArray) array.entry(rindex); ArrayList<Long> row = new ArrayList<Long>(); for ( long cindex = 0; cindex < ruby_row.size(); cindex++ ) { RubyFixnum column = (RubyFixnum) ruby_row.entry(cindex); row.add(column.getLongValue()); } this.rules.add(row); } return context.nil; } /** * Stores the lookup table in the current DriverConfig instance. * * @param arg Array containing the rows/columns of the lookup table. */ @JRubyMethod(name="table_native=") public IRubyObject set_table_native(ThreadContext context, IRubyObject arg) { RubyArray array = arg.convertToArray(); for ( long rindex = 0; rindex < array.size(); rindex++ ) { RubyArray ruby_row = (RubyArray) array.entry(rindex); ArrayList<Long> row = new ArrayList<Long>(); for ( long cindex = 0; cindex < ruby_row.size(); cindex++ ) { RubyFixnum column = (RubyFixnum) ruby_row.entry(cindex); row.add(column.getLongValue()); } this.table.add(row); } return context.nil; } /** * Stores the callback actions and their arities in the current DriverConfig * instance. * * @param arg Array containing the callback names and their arguments. */ @JRubyMethod(name="actions_native=") public IRubyObject set_actions_native(ThreadContext context, IRubyObject arg) { RubyArray array = arg.convertToArray(); for ( long rindex = 0; rindex < array.size(); rindex++ ) { RubyArray row = (RubyArray) array.entry(rindex); RubySymbol name = (RubySymbol) row.entry(0); RubyFixnum arity = (RubyFixnum) row.entry(1); this.action_names.add(name); this.action_arg_amounts.add((int) arity.getLongValue()); } return context.nil; }
}