lib/citrus.rb in citrus-2.3.4 vs lib/citrus.rb in citrus-2.3.5

- old
+ new

@@ -17,21 +17,19 @@ Infinity = 1.0 / 0 CLOSE = -1 - @cache = {} - # Returns a map of paths of files that have been loaded via #load to the # result of #eval on the code in that file. # # Note: These paths are not absolute unless you pass an absolute path to # #load. That means that if you change the working directory and try to # #require the same file with a different relative path, it will be loaded # twice. def self.cache - @cache + @cache ||= {} end # Evaluates the given Citrus parsing expression grammar +code+ and returns an # array of any grammar modules that are created. Accepts the same +options+ as # GrammarMethods#parse. @@ -69,26 +67,26 @@ # # Citrus.load('mygrammar') # # => [MyGrammar] # def self.load(file, options={}) - file += '.citrus' unless file =~ /\.citrus$/ + file += '.citrus' unless /\.citrus$/ === file force = options.delete(:force) - if force || !@cache[file] + if force || !cache[file] raise LoadError, "Cannot find file #{file}" unless ::File.file?(file) raise LoadError, "Cannot read file #{file}" unless ::File.readable?(file) begin - @cache[file] = eval(::File.read(file), options) + cache[file] = eval(::File.read(file), options) rescue SyntaxError => e e.message.replace("#{::File.expand_path(file)}: #{e.message}") raise e end end - @cache[file] + cache[file] end # Searches the <tt>$LOAD_PATH</tt> for a +file+ with the .citrus suffix and # attempts to load it via #load. Returns the path to the file that was loaded # on success, +nil+ on failure. Accepts the same +options+ as #load. @@ -97,15 +95,17 @@ # # => "/path/to/mygrammar.citrus" # Citrus.cache[path] # # => [MyGrammar] # def self.require(file, options={}) - file += '.citrus' unless file =~ /\.citrus$/ + file += '.citrus' unless /\.citrus$/ === file found = nil - (Pathname.new(file).absolute? ? [''] : $LOAD_PATH).each do |dir| - found = Dir[::File.join(dir, file)].first + paths = [''] + paths += $LOAD_PATH unless Pathname.new(file).absolute? + paths.each do |path| + found = Dir[::File.join(path, file)].first break if found end if found Citrus.load(found, options) @@ -668,10 +668,15 @@ else to_citrus end end + # This alias allows strings to be compared to the string representation of + # Rule objects. It is most useful in assertions in unit tests, e.g.: + # + # assert_equal('"a" | "b"', rule) + # alias_method :to_str, :to_s # Returns the Citrus notation of this rule as a string that is suitable to # be embedded in the string representation of another rule. def to_embedded_s # :nodoc: @@ -1285,24 +1290,27 @@ def to_s @string end + # This alias allows strings to be compared to the string value of Match + # objects. It is most useful in assertions in unit tests, e.g.: + # + # assert_equal("a string", match) + # alias_method :to_str, :to_s # The default value for a match is its string value. This method is # overridden in most cases to be more meaningful according to the desired # interpretation. alias_method :value, :to_s # Returns this match plus all sub #matches in an array. def to_a - [captures[0]] + matches + [self] + matches end - alias_method :to_ary, :to_a - # Returns the capture at the given +key+. If it is an Integer (and an # optional length) or a Range, the result of #to_a with the same arguments # is returned. Otherwise, the value at +key+ in #captures is returned. def [](key, *args) case key @@ -1311,12 +1319,10 @@ else captures[key] end end - alias_method :fetch, :[] - def ==(other) case other when String @string == other when Match @@ -1380,10 +1386,11 @@ def process_events! @captures = captures_hash @matches = [] capture!(@events[0], self) + @captures[0] = self stack = [] offset = 0 close = false index = 0 @@ -1402,11 +1409,14 @@ start = stack.pop match = Match.new(@string.slice(os, event), @events[start..index]) capture!(rule, match) - @matches << match if stack.size == 1 + if stack.size == 1 + @matches << match + @captures[@matches.size] = match + end capture = true end last_length = event unless last_length @@ -1434,16 +1444,9 @@ capture = false if Proxy === event end end index += 1 - end - - # Add numeric indices to @captures. - @captures[0] = self - - @matches.each_with_index do |match, index| - @captures[index + 1] = match end end def capture!(rule, match) # We can lookup matches that were created by proxy by the name of