Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

BNF-like grammar specified DIRECTLY in Ruby

20 views
Skip to first unread message

Eric Mahurin

unread,
Apr 16, 2005, 12:25:29 AM4/16/05
to
Here is my first contribution to Ruby:

http://raa.ruby-lang.org/project/syntax/

There is still plenty missing in here and it is a work in
progress, but I think it is ready for some of you to try it out
if you like it.

To get an idea of what this is, there is a simple expression
evaluator example below. This is pure Ruby code - no yacc type
compiling necessary. That's what I love about it.

Eric


#!/usr/bin/ruby -d

require "syntax"

NULL = Syntax::NULL
INF = +1.0/0
LOOP0 = (0..INF)
LOOP1 = (1..INF)

int = (("0".."9")*LOOP1).qualify { |m| m.to_s.to_i }

number = (
int +
(("."+int)|NULL) +
((("e"|"E")+("+"|"-"|NULL)+int)|NULL)
).qualify { |m|
if (m.length>1)
m.to_s.to_f
else
m[0]
end
}

ws = ((" "|"\t"|"\n")*LOOP0).qualify { TRUE } # skipped with
TRUE

expr = Syntax::Pass.new # need to predefine object for
recursion

atom =
(number+ws).qualify{|m|m[0]} |
("(" + expr + ")" + ws).qualify{|m|m[1]}

term = (
atom + ( ("*"|"/"|"%") + ws + atom )*LOOP0
).qualify { |m|
product = m[0]
m[1].each { |m|
case m[0]
when "*" then product *= m[1]
when "/" then product /= m[1]
when "%" then product %= m[1]
end
}
product
}

expr << (
ws + term + ( ("+"|"-") + ws + term )*LOOP0
).qualify { |m|
sum = m[0]
m[1].each { |m|
case m[0]
when "+" then sum += m[1]
when "-" then sum -= m[1]
end
}
sum
}

while (gets)
p(expr===RandomAccessStream.new($_))
end


__________________________________
Do you Yahoo!?
Make Yahoo! your home page
http://www.yahoo.com/r/hs


Jamis Buck

unread,
Apr 16, 2005, 12:39:22 AM4/16/05
to
Very nice! One quibble: any chance you could change the name?

http://rubyforge.org/projects/syntax

:) Might get confusing if someone wants to install both libs.

- Jamis

Eric Mahurin

unread,
Apr 16, 2005, 10:23:26 AM4/16/05
to
Would it be better to put it on rubyforge after renaming?

Also, is it best rubygems? Is this the ruby equivalent of cpan
for perl?


__________________________________
Do you Yahoo!?
Plan great trips with Yahoo! Travel: Now over 17,000 guides!
http://travel.yahoo.com/p-travelguide


Takaaki Tateishi

unread,
Apr 16, 2005, 11:14:28 AM4/16/05
to
Eric Mahurin wrote:
> Here is my first contribution to Ruby:
> http://raa.ruby-lang.org/project/syntax/

Let me inform you that I'm also developing similar library TDP4R. :-)
http://rubyforge.org/projects/tdp4r
Some examples are available at:
http://rubyforge.org/cgi-bin/viewcvs.cgi/tdp4r/samples/?cvsroot=tdp4r

Thanks,
--
Takaaki Tateishi <tt...@ttsky.net>

Jamis Buck

unread,
Apr 16, 2005, 11:54:51 AM4/16/05
to
On Apr 16, 2005, at 8:23 AM, Eric Mahurin wrote:

> Would it be better to put it on rubyforge after renaming?
>

That's not necessary, but it's nice if you need a CVS repository, or a
home page, or a wiki for your project. It also gives you bug and
feature request tracking, mailing lists, forums, and more. If any of
that sounds appealing, you may want to apply for a new project there.
If you have those things all hosted elsewhere, or you don't want/need
them, then you probably won't gain anything by a RubyForge project
(except, perhaps, better project visibility).

> Also, is it best rubygems? Is this the ruby equivalent of cpan
> for perl?

Currently RubyGems is the de facto standard for Ruby libraries. There
really isn't a CPAN equivalent for Ruby, yet--we've got RAA and
RubyForge, with RubyGems as the package manager. (Another nice thing
about RubyForge--when you add a gem file to your project file list, it
will automatically be added to the RubyGems package list.)

- Jamis

Eric Mahurin

unread,
Apr 16, 2005, 2:25:40 PM4/16/05
to
That is similar to what I'm doing. A primary difference
between what you are doing and I am is that for yours a rule is
a proc/method and for mine a rule is an object. I think the
way I did it is cleaner, but having a rule as a proc does make
it easier to have local variables in a rule. I have to pass
variables in a rule around in the parse tree (preferred) or via
globals (yuck).

The samples you show parse strings. Can you parse files
without reading the whole thing in? Can you do things with or
without a lexer? The way I have it set up a lexer is optional
and a lexer can be built out of the same parse classes.

We could collaborate off-line if you wish...

Eric

--- Takaaki Tateishi <tt...@ttsky.net> wrote:
> Eric Mahurin wrote:
> > Here is my first contribution to Ruby:
> > http://raa.ruby-lang.org/project/syntax/
>

> Let me inform you that I'm also developing similar library
> TDP4R. :-)
> http://rubyforge.org/projects/tdp4r
> Some examples are available at:
>
>
http://rubyforge.org/cgi-bin/viewcvs.cgi/tdp4r/samples/?cvsroot=tdp4r
>
> Thanks,
> --
> Takaaki Tateishi <tt...@ttsky.net>
>
>
>

Takaaki Tateishi

unread,
Apr 18, 2005, 11:05:47 AM4/18/05
to
Eric Mahurin wrote:
> That is similar to what I'm doing. A primary difference
> between what you are doing and I am is that for yours a rule is
> a proc/method and for mine a rule is an object. I think the
> way I did it is cleaner, but having a rule as a proc does make
> it easier to have local variables in a rule.

A rule of tdp4r is an instance of Rule, which consists of Proc objects and methods.
In order to handle a recursive rule easily, tdp4r uses methods.

> The samples you show parse strings. Can you parse files
> without reading the whole thing in?

It's possible if you define methods shift and unshift.
A parser read a token using shift and push it back using unshift.

> Can you do things with or without a lexer?

tdp4r doesn't provide a function of a lexer.

Takaaki Tateishi

unread,
Apr 18, 2005, 5:40:23 PM4/18/05
to
Takaaki Tateishi wrote:
> It's possible if you define methods shift and unshift.
> A parser read a token using shift and push it back using unshift.

Sorry, that is not correct.
--
Takaaki Tateishi <tt...@ttsky.net>

0 new messages