Commits

Pasberth Usbean committed 99e8e30

GiveStateParser & Proc as parser

  • Participants
  • Parent commits 1e40edc

Comments (0)

Files changed (5)

File examples/string_parser.rb

+$:.unshift File.dirname(__FILE__) + '/../lib'
+require 'regparsec'
+
+StringParser = RegParsec::Regparsers.between('"', '"', /(?:(?:\\\")|[^"])*/)
+p StringParser.parse('"this is a string"')
+# => #<MatchData "this is a string"> 
+p StringParser.parse('"can escape the \" !"')
+# => #<MatchData "can escape the \\\" !"> 
+
+QuoteParser = RegParsec::Regparsers.instance_eval do
+  between(
+    apply('q', update_state(:quotation_mark, apply(/./) { |q| q[0].to_s })),
+    ->(state) { apply( state.quotation_mark ) },
+    ->(state) { apply( /(?:(?:\\#{ Regexp.quote(state.quotation_mark) })|[^#{ Regexp.quote(state.quotation_mark) }])*/ ) { |body| body[0].to_s } }
+  )
+end
+
+p QuoteParser.parse('q"the double quotation!"')
+# => "the double quotation!"
+p QuoteParser.parse('q# the quotation by number marks! #')
+# => " the quotation by number marks! "

File lib/regparsec/parser/primary_parsers.rb

   end
 end
 
+class Proc
+  
+  def to_regparser
+    ::RegParsec::Regparsers::ProcParser.new.curry!(self)
+  end
+end
+
 class RegParsec::Regparsers::StringParser < RegParsec::Regparsers::Base
   
   def self.well_defined_parser_get str
   def __regparse__ state, regexp
     case state.input                                       # case "abc;def;"
     when /\A#{regexp}\z/                                   # when /\A(.*?);\z/
-      md = $~; md[0] =~ /\A#{regexp}/                  #   "abc;def;" =~ /\A(.*?);/
+      md = $~; md[0] =~ /\A#{regexp}/                      #   "abc;def;" =~ /\A(.*?);/
       if $~[0] != md[0]                                    #   if "abc;" != "abc;def;"
         md = $~
         state.input.sub!(md[0], '')
     end
   end
 end
+
+class RegParsec::Regparsers::ProcParser < RegParsec::Regparsers::Base
+  
+  def format_args proc, *args
+    [proc, *args]
+  end
+
+  def __regparse__ state, proc
+    try_convert_into_regparser!( proc.call(state) ).regparse( state )
+  end
+end

File lib/regparsec/parser/state.rb

 
 module RegParsec::Regparsers
 
-  def update_state *regparsers, &result_hook
-    regparser = ::RegParsec::Regparsers::UpdateStateParser.new.curry!(*regparsers)
-    regparser.result_hook! &result_hook if result_hook
-    regparser
+
+  [ [:update_state, :UpdateStateParser],
+    [:give_state, :GiveStateParser]
+  ].each do |method, klass|
+    module_eval(<<-DEF)
+      def #{method}(*args, &result_hook)
+        regparser = ::RegParsec::Regparsers::#{klass}.new.curry!(*args)
+        regparser.result_hook!(&result_hook) if result_hook
+        regparser
+      end
+    DEF
   end
 end
 
   def __regparse__ state, binding_variable, regparser
     case result = regparser.regparse( state )
     when Result::Success
-      state.merge!(binding_variable => result.return_value) # TODO: result procs
+      state.merge!(binding_variable => result.return_value)
       result
     else
       result
     end
   end
 end
+
+class RegParsec::Regparsers::GiveStateParser < RegParsec::Regparsers::Base
+  
+  def format_args *args
+    [ args[0].to_sym,
+      try_convert_into_regparser!(args[1]),
+      *args[2..-1]
+    ]
+  end
+
+  def __regparse__ state, binding_variable, regparser
+    regparser.curry( state[binding_variable] ).regparse( state )
+  end
+end

File lib/regparsec/regparseable.rb

   def format_args *args
     args.map &:try_convert_into_regparser!.in(::RegParsec::RegparserHelpers)
   end
-
-  def curried_args
-    @_curried_args ||= []
-  end
   
   def result_hook &block
     clone.result_hook! &block
   def result_hook! &hook
     result_hooks << hook || raise(ArgumentError, "tried to put a result hook without a block.")
   end
-
-  def result_hooks
-    @_result_hooks ||= []
-  end
-  
-  def curry *args, &block
-    clone.curry! *args, &block
-  end
   
   def curry! *args, &block
     args.each &:push.to(curried_args)
     self
   end
   
+  def curry *args, &block
+    clone.curry! *args, &block
+  end
+  
+  def clone
+    cln = super
+    cln.curried_args = curried_args.clone
+    cln.result_hooks = result_hooks.clone
+    cln
+  end
+  
   def to_regparser
     self
   end
+
+  protected
+
+    def curried_args= a
+      @_curried_args = a
+    end
+
+    def curried_args
+      @_curried_args ||= []
+    end
+  
+    def result_hooks= a
+      @_result_hooks = a
+    end
+
+    def result_hooks
+      @_result_hooks ||= []
+    end
 end

File spec/regparsers/give_state_spec.rb

+require 'spec_helper'
+
+describe ::RegParsec::Regparsers::GiveStateParser do
+  subject { described_class.new.curry(:x, ::RegParsec::Regparsers.apply) }
+
+  example { subject.parse( :input => 'abc', :x => 'abc' ).should == ["abc"] }
+  example { subject.regparse( :input => 'abc', :x => 'abc' ).should == ::RegParsec::Result::Success.new( :return_value => ['abc'], :matching_string => 'abc' ) }
+  example { subject.parse( :input => 'def', :x => 'abc' ).should be_nil }
+  example { subject.regparse( :input => 'def', :x => 'abc' ).should == ::RegParsec::Result::Invalid.new }
+end