人気ブログランキング | 話題のタグを見る

pegc.rb 用サンプルソース arithc.rb

PEG コンパイラコンパイラ pegc.rb 用のソースリスト arithc.rb を作った。概要は次の通り

1.pegc.rb 用ソースリスト arithc.rb の概要

require 'pegc.rb'

parser = Peg.new

parser.mkhead('Parse') # オブジェクトプログラムの先頭部分の作成。

#文法の記述
# program <- spacing expr ルートの非終端記号を program にしておくと後で便利
# expr <- term ('+' term / '-' term)* / term
# term <- factor ('*' factor / '/' factor)* / factor
# factor <- number / '(' expr ')'
# scanner

parser.mkend # クラスの締めくくり

# create parser object

puts 'parser = Parse.new' # 自動作成した Parse クラスのオブジェクトを生成

# make main loop

parser.mkconsole 

# 文法のルートの非終端記号を program にして、パーサオブジェクトの名前を parser にしておくと、コンソールが自動作成できる。 parser.mkconsole の代わりに、parser.mkcheck とすると一行だけ Ruby の命令を実行するコンソールを自動作成するのでデバッグに便利。

(ソースリスト終わり)

pegc.rb は完成品というより、再帰下降構文分析ルーチンの骨組みだけを作る。中途半端な機能だが、単純なので中身を知りながら使えるのが便利だ。

しっかりと構築してあるプログラムは中身が見えないので学習するのに気力がいる。ひとの作ったプログラムは、そのひとのロジックが分るまでは理解しづらいものだ。pegc.rb の場合、本体自体もそう難しいことはしていないのですぐに理解できると思う。

2.整数四則演算計算機用ソースリスト arithc.rb

require 'pegc.rb'

parser = Peg.new

# make hedder list

parser.mkhead('Parse')

# program <- spacing expr

parser.mkseq('program', 'spacing and expr', 'puts pop')


# expr <- term ('+' term / '-' term)* / term

parser.mkslash('expr', 'term and add_sub_term_star', 'term')
parser.mkstar('add_sub_term_star', 'add_sub_term')
parser.mkslash('add_sub_term', 'add_term', 'sub_term')
parser.mkseq('add_term', 'add and term', 'push(pop + pop)')
parser.mkseq('sub_term', 'sub and term', 'a = pop; b = pop; push(b - a)')


# term <- factor ('*' factor / '/' factor)* / factor

parser.mkslash('term', 'factor and mul_div_factor_star', 'factor')
parser.mkstar('mul_div_factor_star', 'mul_div_factor')
parser.mkslash('mul_div_factor', 'mul_factor', 'div_factor')
parser.mkseq('mul_factor', 'mul and factor', 'push(pop * pop)')
parser.mkseq('div_factor', 'div and factor', 'a = pop; b = pop; push(b / a)')


# factor <- number / '(' expr ')'

parser.mkslash('factor','number', 'open and expr and close')


# scanner

parser.mkterm('spacing', '/\A\s*/')
parser.mkterm('number', '/\A[-]?[1-9][0-9]*\s*/', 'push(@match.to_i)')
parser.mkterm('add', '/\A\+\s*/')
parser.mkterm('sub', '/\A-\s*/')
parser.mkterm('mul', '/\A\*\s*/')
parser.mkterm('div', '/\A\/\s*/')
parser.mkterm('open', '/\A\(\s*/')
parser.mkterm('close', '/\A\)\s*/')

# make end line

parser.mkend

# create parser object

puts 'parser = Parse.new'

# make main loop

parser.mkconsole
by tnomura9 | 2008-05-04 17:31 | Ruby | Comments(0)
<< PEG パーサジェネレータ p... PEG コンパイラ・コンパイラ... >>