[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Newbie Question: - Parse my commands...

paytonrules

9/12/2006 6:14:00 PM

Okay I'm trying to take our old scripting software and quickly move it
up in the world. We have a program that takes as a parameter a script
file, parses it and runs it for unit testing purposes. There are
several problems:

1) Each script file requires setting up a large database.
2) No way to debug a file short of setting breakpoints in C++ on the
parser itself.
3) No way - this is the big one - to just run an individual command
and get instant feedback.

Now in the meantime I've been playing with Ruby and ROR and I think I
should be able to use the irb command to create this pretty quickly,
but I'm not quite sure how. Our commands in the .scr file currently
look like this

ObjectName.Make(param1, param2, param3, param4)

The first step, which I'm doing now, is to take our executable program
and break the parsing engine into a DLL. That's easy. I can then
create a quick ruby program so I could do this:

irb
load 'rubyProg'

parse ObjectName.Make(param1, param2, param3, param4)


The rubyProg could work this way - but I'm pretty sure I can go one
step farther with ruby and just type:

ObjectName.Make(param1, param2, param3, param4)

through ruby extensions. The question is - how do I have the
interpreter pass on any code to the parser ruby can't handle it?

3 Answers

vidar

9/12/2006 11:09:00 PM

0


paytonrules wrote:

> The first step, which I'm doing now, is to take our executable program
> and break the parsing engine into a DLL. That's easy. I can then
> create a quick ruby program so I could do this:
>
> irb
> load 'rubyProg'
>
> parse ObjectName.Make(param1, param2, param3, param4)
>
>
> The rubyProg could work this way - but I'm pretty sure I can go one
> step farther with ruby and just type:
>
> ObjectName.Make(param1, param2, param3, param4)
>
> through ruby extensions. The question is - how do I have the
> interpreter pass on any code to the parser ruby can't handle it?

method_missing() can be used for this to some extent. It depends on how
exact you want the syntax. If you can get away with changing the object
names so that they start with a lowercase letter it's cleaner. In Ruby,
a capital first letter of a name indicates a constant, which means you
need some extra uglyness to handle that.

With a lowercase first letter in your object names you can do:

class MissingProxy
def initialize ob
@ob = ob
end

def method_missing(sym,*args)
# Call your script processor here.
puts "PROCESS: #{@ob.to_s}.#{sym.to_s}(#{args.join(',')})"
end
end

def method_missing(sym,*args)
MissingProxy.new(sym)
end

myObject.Make('test',123)


If, on the other hand you don't want to rewrite anything, you can wrap
the statements like this:

begin
MyObject.Make('test',123)
rescue NameError => n
eval("#{n.name} = MissingProxy.new(:#{n.name})")
retry
end

I'd consider both of these methods fairly ugly. They make trapping
errors in your Ruby code tricky, as any misspelled object/class names
will trigger your script interpreter instead of giving an error, but it
does give a lot of flexibility.

An alternative that is less intrusive is to wrap the latter method
missing in a module:

module Script
def method_missing(sym,*args)
MissingProxy.new(sym)
end
end

And add the module name to any script command:

Script.MyObject.Make('test',123)

If you do it this way at least misspellings etc. in your Ruby code is
less likely to trigger your script processing, but then I guess you
could just as well do it the way you suggested in the first place.

Vidar.

Logan Capaldo

9/12/2006 11:35:00 PM

0

On Wed, Sep 13, 2006 at 08:10:35AM +0900, Vidar Hokstad wrote:
>
> paytonrules wrote:
>
> > The first step, which I'm doing now, is to take our executable program
> > and break the parsing engine into a DLL. That's easy. I can then
> > create a quick ruby program so I could do this:
> >
> > irb
> > load 'rubyProg'
> >
> > parse ObjectName.Make(param1, param2, param3, param4)
> >
> >
> > The rubyProg could work this way - but I'm pretty sure I can go one
> > step farther with ruby and just type:
> >
> > ObjectName.Make(param1, param2, param3, param4)
> >
> > through ruby extensions. The question is - how do I have the
> > interpreter pass on any code to the parser ruby can't handle it?
>
> method_missing() can be used for this to some extent. It depends on how
> exact you want the syntax. If you can get away with changing the object
> names so that they start with a lowercase letter it's cleaner. In Ruby,
> a capital first letter of a name indicates a constant, which means you
> need some extra uglyness to handle that.
>
> With a lowercase first letter in your object names you can do:
>
> class MissingProxy
> def initialize ob
> @ob = ob
> end
>
> def method_missing(sym,*args)
> # Call your script processor here.
> puts "PROCESS: #{@ob.to_s}.#{sym.to_s}(#{args.join(',')})"
> end
> end
>
> def method_missing(sym,*args)
> MissingProxy.new(sym)
> end
>
> myObject.Make('test',123)
>
>
> If, on the other hand you don't want to rewrite anything, you can wrap
> the statements like this:
>
> begin
> MyObject.Make('test',123)
> rescue NameError => n
> eval("#{n.name} = MissingProxy.new(:#{n.name})")
> retry
> end
To handle the MyObject case, you needs simply define const_missing
instead of method_missing, no need to rescue name error.
>
> I'd consider both of these methods fairly ugly. They make trapping
> errors in your Ruby code tricky, as any misspelled object/class names
> will trigger your script interpreter instead of giving an error, but it
> does give a lot of flexibility.
>
Agreed.

paytonrules

9/13/2006 6:38:00 PM

0


Logan Capaldo wrote:
> On Wed, Sep 13, 2006 at 08:10:35AM +0900, Vidar Hokstad wrote:
> >
> > paytonrules wrote:
> >
> > > The first step, which I'm doing now, is to take our executable program
> > > and break the parsing engine into a DLL. That's easy. I can then
> > > create a quick ruby program so I could do this:
> > >
> > > irb
> > > load 'rubyProg'
> > >
> > > parse ObjectName.Make(param1, param2, param3, param4)
> > >
> > >
> > > The rubyProg could work this way - but I'm pretty sure I can go one
> > > step farther with ruby and just type:
> > >
> > > ObjectName.Make(param1, param2, param3, param4)
> > >
> > > through ruby extensions. The question is - how do I have the
> > > interpreter pass on any code to the parser ruby can't handle it?
> >
> > method_missing() can be used for this to some extent. It depends on how
> > exact you want the syntax. If you can get away with changing the object
> > names so that they start with a lowercase letter it's cleaner. In Ruby,
> > a capital first letter of a name indicates a constant, which means you
> > need some extra uglyness to handle that.
> >
> > With a lowercase first letter in your object names you can do:
> >
> > class MissingProxy
> > def initialize ob
> > @ob = ob
> > end
> >
> > def method_missing(sym,*args)
> > # Call your script processor here.
> > puts "PROCESS: #{@ob.to_s}.#{sym.to_s}(#{args.join(',')})"
> > end
> > end
> >
> > def method_missing(sym,*args)
> > MissingProxy.new(sym)
> > end
> >
> > myObject.Make('test',123)
> >
> >
> > If, on the other hand you don't want to rewrite anything, you can wrap
> > the statements like this:
> >
> > begin
> > MyObject.Make('test',123)
> > rescue NameError => n
> > eval("#{n.name} = MissingProxy.new(:#{n.name})")
> > retry
> > end
> To handle the MyObject case, you needs simply define const_missing
> instead of method_missing, no need to rescue name error.
> >
> > I'd consider both of these methods fairly ugly. They make trapping
> > errors in your Ruby code tricky, as any misspelled object/class names
> > will trigger your script interpreter instead of giving an error, but it
> > does give a lot of flexibility.
> >
> Agreed.

> > I'd consider both of these methods fairly ugly. They make trapping
> > errors in your Ruby code tricky, as any misspelled object/class names
> > will trigger your script interpreter instead of giving an error, but it
> > does give a lot of flexibility.

I agree - but the C++ parser is allowed to return errors no?

To put it another way - lets assume I do the const_missing. Parse will
return errors - couldn't I use the parse errors to deterimine "is this
a parse error or is this a Ruby error"?

I realize I'm not explaining myself well - perhaps because I'm really
just experiementing with this to make sure I've got a good idea. We've
already got an old parser executable that parses script files. I just
want to use irb and ruby to glue this and make a statement-by-statement
runtime interpreter. Would a better design be to include the irb in my
application and work the other way around?