強烈に「何をいまさら」感がありますが (^^; scanner generator `rlex',
paser generator `rpg' をリニューアルしました.
# rlex は lex もどき.rpg は再帰下降パーザをはく.
実際に何をしたかというと,
* オプションで scanner,parser のクラス名を変えられるようにした.
* インラインで scanner,parser を生成できるようにした.
というところです.これを使って後につけたサンプルのような事ができます
(電卓).
コマンドとして入力ファイルから出力ファイルを得る方法は README.* に書い
てありますが,require してインラインで使う方法のドキュメントは全くあり
ません.
http://www.os.xaxon.ne.jp/~kjana/ruby/ruby.html
から拾えるようにしておきます.よろしければ,どうぞ.
# 前に記事を出したのが 3 月 21 日だって (^^;
--
柳川和久 @ 東大阪市 . 大阪府 September 8, 1999
Translaters, traitors.
#!/usr/local/bin/ruby
require "rlex"
require "rpg"
require "mathn"
ss =<<'EOS'
<default>
[_a-zA-Z]\w*
RETURN [:ident, matched, 0]
(?:\d+)?\.?(?:\d+)(?:[eE][+-]?\d+)?
RETURN [:number, matched, 0]
.
# operators, parens, and other single chars
RETURN [matched, matched, 0]
\n
# press return to execute
RETURN [:execute, matched, 0]
EOS
ps =<<'EOS'
calc:
[ <<<@exp = 0>>> exp <<<puts @exp>>> :execute ].
exp:
[];
term <<<e = @term>>> [ ee <<<e += @ee>>>] <<<e>>>.
ee:
"+" term <<<@term>>>;
"-" term <<<- / term>>>.
term:
prim <<<t = @prim>>> [ et <<<t *= @et>>>] <<<t>>>.
et:
"*" prim <<<@prim>>>;
"/" prim <<<1/@prim>>>.
prim:
"-" prim <<<- / prim>>>;
"(" exp ")" <<<@exp>>>;
:ident <<<0 #@token[1]>>>;
:number <<<@token[1].to_f>>>.
EOS
cs = RLEX.new_scanner(ss)
sc = cs.new
cp = RPG.new_parser(ps)
pa = cp.new(sc)
begin
pa.parse
rescue ParseError
tok, val, lno = $!.triple
$stderr.puts "parse error near line #{lno}, token #{val}"
retry
end