您的位置:首页 > 其它

rex 和 racc (一) 初步安装和使用

2008-12-08 20:02 387 查看
使用ruby的朋友会发现rex/racc这样的应用,他们是纯ruby实现的lex/yacc.

如果你有这样的任务,需要在ruby中解析一些代码.如果你熟悉 lex/yacc,那么首先的想法是,能否用ruby中的rex/racc来实现。

那么首先一点是,如何搭建这样的环境呢?

目前网络上这样的资源比较少,基本上要靠自己摸索之后,才能很好的使用。

首先:安装rex

http://raa.ruby-lang.org/project/rex/ 中下载http://homepage1.nifty.com/arima/ruby/rex-1.0rc1.tar.gz

然后解包,

运行 里面的setup.rb

ruby setup.rb config
ruby setup.rb show
ruby setup.rb setup
ruby setup.rb install

他会安装rex到相应的目录, 默认的会产生rex.cmd.

建议将它删除, 将同目录下的rex 更改成rex.bat 并且将它的头和尾加入下面的代码(完整修改之后的内容如下):

@echo off
@if not "%~d0" == "~d0" goto WinNT
/usr/local/bin/ruby -x "/usr/local/bin/erb.bat" %1 %2 %3 %4 %5 %6 %7 %8 %9
@goto endofruby
:WinNT
"%~dp0ruby" -x "%~f0" %*
@goto endofruby
#!/usr/local/bin/ruby
#
# rex.rb
#
# Copyright (c) 2005-2006 ARIMA Yasuhiro <arima.yasuhiro@nifty.com>
#
# This program is free software.
# You can distribute/modify this program under the terms of
# the GNU LGPL, Lesser General Public License version 2.1.
# For details of LGPL, see the file "COPYING".
#

## ---------------------------------------------------------------------

require 'rex/rexcmd'

RexCmd.new.run

__END__
:endofruby

这样,我们的rex.bat 就类似于 irb.bat等默认的bat。

其次,安装racc

http://i.loveruby.net/en/projects/racc/

下载 上面的 -- Download (.tar.gz)

解压,然后运行:

ruby setup.rb config
ruby setup.rb setup
ruby setup.rb install

就可以了,不建议下载svn 里面的代码然后手工编译,我目前试过编译可以通过,但运行有错误。

在ruby/bin目录下,创建一个racc.bat

内容为:

"%~dp0ruby" "%~dp0racc" %*

当然也可以使用上面的技巧,直接修改racc文件。

最后,运行简单的例子(rex/racc的组合运行)

创建一个text.rex文件

require 'text.rex'

class Text

macro

BLANKS /s+

DIGITS /d+

LETTERS [a-zA-Z]+

rule

{BLANKS}

{LETTERS} { puts :ID , "#{text}"; [ :ID, text] }

{DIGITS} { puts "#{text}"; [ :NUMBER, text.to_i ] }

.|/n { puts "#{text}"; [ text, text ] }

inner

end

创建text.y文件

#

# A simple calculator, version 3.

#

class Text

prechigh

nonassoc UMINUS

left '*' '/'

left '+' '-'

preclow

options no_result_var

rule

target : exp

| /* none */ { 0 }

exp : exp '+' exp { val[0] + val[2] }

| exp '-' exp { val[0] - val[2] }

| exp '*' exp { val[0] * val[2] }

| exp '/' exp { val[0] / val[2] }

| '(' exp ')' { val[1] }

| '-' NUMBER =UMINUS { -(val[1]) }

| NUMBER

end

---- header ----

#

# generated by racc

#

require 'text.rex.rb'

---- inner ----

---- footer ----

puts 'sample calc'

puts '"q" to quit.'

calc = Text.new

while true

print '>>> '; $stdout.flush

str = $stdin.gets.strip

break if /q/i === str

begin

p calc.scan_str(str)

rescue ParseError

puts 'parse error'

end

end

运行:

rex text.rex
上面会产生text.rex.rb
racc text.y
会产生text.tab.rb

运行:
ruby text.tab.rb 就可以了

在命令行输入: 1+2 会输出3 的。

如:

D:/dev_tool/ruby>ruby text.tab.rb
sample calc
"q" to quit.
>>> 1+2
1
+
2
3
>>>

(熟悉lex/yacc的朋友,看上面的代码应该很快,后面我会陆续加入新的文章来描述这一块内容)。

如果查看text.y中,会发现它包含了 text.rex.rb的代码. 呵呵,从而rex/racc就可以组合在一块了.

如果用ruby1.9的,估计会出现这样的错误:

undefined method `collect' for #<String:0xc36cd8> (NoMethodError)

那找到相应的行,将option 从string更改成array就可以了。

比如:C:/ruby-1.9.1/usr/local/lib/ruby/site_ruby/1.9.1/rex/rexcmd.rb

包含:

OPTIONS = <<-EOT

o -o --output-file <outfile> file name of output [<filename>.rb]

o -s --stub - append stub code for debug

o -i --ignorecase - ignore char case

o -C --check-only - syntax check only

o - --independent - independent mode

o -d --debug - print debug information

o -h --help - print this message and quit

o - --version - print version and quit

o - --copyright - print copyright and quit

EOT

而在ruby1.9出错,那么我们可以将上面这块代码修改成:

oldOptions = <<-EOT

o -o --output-file <outfile> file name of output [<filename>.rb]

o -s --stub - append stub code for debug

o -i --ignorecase - ignore char case

o -C --check-only - syntax check only

o - --independent - independent mode

o -d --debug - print debug information

o -h --help - print this message and quit

o - --version - print version and quit

o - --copyright - print copyright and quit

EOT

OPTIONS = []

oldOptions.each_line do |line|

OPTIONS.push(line)

end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: