lib/sexpr/grammar.rb in sexpr-0.2.0 vs lib/sexpr/grammar.rb in sexpr-0.3.0

- old
+ new

@@ -1,82 +1,26 @@ +require_relative 'grammar/options' +require_relative 'grammar/matching' +require_relative 'grammar/parsing' +require_relative 'grammar/tagging' module Sexpr - class Grammar + module Grammar + include Options + include Matching + include Parsing + include Tagging - attr_reader :rules, :options - - def initialize(rules = {}, options = {}) - @rules = compile_rules(rules) - @options = options - end - - def [](rule_name) - @rules[rule_name] - end - - def root - @root ||= begin - root = options[:root] || rules.keys.first - root = self[root] if root.is_a?(Symbol) + def self.new(options = {}) + unless options.is_a?(Hash) + raise ArgumentError, "Invalid grammar definition: #{options.inspect}" end + Module.new.tap{|g| + g.instance_eval{ + include(Grammar) + extend(self) + install_options(options) + } + } end - def parser - options[:parser] - end - - def parse(input) - case input - when lambda{|x| x.respond_to?(:to_path)} - parse(File.read(input.to_path)) - when IO - parse(input.read) - when String - unless p = parser - raise NoParserError, "No parser set.", caller - end - p.parse(input).value - end - end - - def match?(sexp) - root.match?(sexp) - end - alias :=== :match? - - private - - def compile_rules(rules) - Hash[rules.map{|k,v| - [k.to_sym, compile_rule(k.to_sym, v)] - }] - end - - def compile_rule(name, defn) - case rule = compile_rule_defn(defn) - when Terminal, Alternative - rule - else - Rule.new(name, rule) - end - end - - def compile_rule_defn(arg) - case arg - when Element - arg - when Regexp, TrueClass, FalseClass, NilClass - Terminal.new arg - when lambda{|x| x.is_a?(Array) && x.size == 1 && x.first.is_a?(Array)} - Sequence.new arg.first.map{|s| compile_rule_defn(s) } - when Array - Alternative.new arg.map{|s| compile_rule_defn(s)} - when /([\?\+\*])$/ - Many.new compile_rule_defn($`), $1 - when /^[a-z][a-z_]+$/ - Reference.new arg.to_sym, self - else - raise ArgumentError, "Invalid rule definition: #{arg.inspect}", caller - end - end - - end # class Grammar + end # module Grammar end # module Sexpr \ No newline at end of file