[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Please help with my string parser

Andreas Habel

5/18/2005 7:56:00 PM

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