You can try the following too.  It has general purpose use like
yacc/lex (and ruby equivalent) and antlr, but you specify
syntax in Ruby (like your class does).

http://www.ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/138450

I'm still working on it.

Eric

--- Andreas Habel <mail / exceptionfault.de> wrote:
> Hi,
> 
> I`ve written a short class for parsing and interpreting
> simple 'command 
> strings'. I`m thinking about commands used in email based
> role playing 
> games like Eressea (if someone knows)
> 
> Maybe the commands could look like this
> 
>
-------------------------------------------------------------------
> code = <<EOF
>      BEGIN
>          NAME="myName"
>          VALUE = "noValue"
>      END
> EOF
>
-------------------------------------------------------------------
> 
> My class now parses this code and in the same action it has
> to extract 
> the values.
> 
>
-------------------------------------------------------------------
> class Literal
> 
>      attr_reader     :expr
>      attr_accessor   :childs,    :code
> 
>      def initialize( expr, code = Proc.new{} )
>          @expr, @code = expr, code
>          @childs = []
>          yield self if block_given?
>      end
> 
>      def <<( child )
>          @childs << child
>      end
> 
>      def exec( str )
>          res = @expr.match( str )
>          @code.call( res )
>          return if @childs.size <= 0
>          found = false
>          @childs.each do |chld|
>              if chld.expr.match( res.post_match )
>                  found = true
>                  chld.exec( res.post_match )
>                  break
>              end
>          end
>    raise "Error in Code:\n#{res.post_match.split("\n")[0]}"
> unless found
>      end
> 
> end
>
-------------------------------------------------------------------
> 
> Now I need to define the grammar of my language like this
> (sorry for 
> awful linebreaks):
> 
>
-------------------------------------------------------------------
> syntax['root'] = Literal.new( //, Proc.new{|*i|})
> syntax['begin'] = Literal.new( /\A\s*BEGIN\s/i, Proc.new{|m|
> p "found 
> BEGIN" } ) do |me|
>                      syntax['root'] << me
>                    end
> 
> syntax['name'] = Literal.new(
> /\A\s*NAME\s*=\s*"([a-zA-Z]*)"\s/i, 
> Proc.new{|m| p "found NAME with value #{m[1]}" } ) do |me|
>                      syntax['begin'] << me
>                    end
> 
> syntax['value'] = Literal.new(
> /\A\s*VALUE\s*=\s*"([a-zA-Z]*)"\s/i, 
> Proc.new{|m| p "found VALUE with value #{m[1]}" } ) do |me|
>                      syntax['begin'] << me
>                      syntax['name'] << me
>                      me << syntax['name']
>                    end
> 
> syntax['end'] = Literal.new( /\A\s*END/i, Proc.new{|m| p
> "found END" } ) 
> do |me|
>                      syntax['begin'] << me
>                      syntax['name'] << me
>                      syntax['value'] << me
>                    end
> 
>
-------------------------------------------------------------------
> 
> And at least the parsing starts with
> 
>
-------------------------------------------------------------------
> p syntax['root'].exec( code )
>
-------------------------------------------------------------------
> 
> It produces something like
> "found BEGIN"
> "found NAME with value myName"
> "found VALUE with value noValue"
> "found END"
> 
> on success, and
> 
> "found BEGIN"
> syntax.rb:37:in `exec': Error in Code: (RuntimeError)
>          WronName="myName"       from syntax.rb:33:in `exec'
>          from syntax.rb:30:in `each'
>          from syntax.rb:30:in `exec'
>          from syntax.rb:64
> 
> on failure.
> 
> So far so good *g*.
> This was my first try and I`m not sure if this is roughly the
> ruby way.
> I think this gets very complicated with complex commands, so
> feel free 
> to annotate!
> 
> Thanks,
> Andreas
> 
> 


		
__________________________________ 
Yahoo! Mail Mobile 
Take Yahoo! Mail with you! Check email on your mobile phone. 
http://mobile.yahoo.com/learn/mail