Perlのパーサジェネレータを触ってみた [Perl]

| コメント(0) | トラックバック(1)

最近、仕事でDSLの機能拡張をする機会があったのですが、構文解析とかその辺の話はあんましよく知らない(EBNFは適当に書けるし、 boost::spirit も触ったことはあるけど、本格的なのは初めて。ちなみに仕事のはRubyの Racc が使われてる)ので、手習いにPerlで使えるパーサジェネレータで逆ポーランド記法の電卓を書いてみようと思い立った。

EBNF は超有名な

expr: expr expr '+'
    | expr expr '-'
    | expr expr '*'
    | expr expr '/'
    | NUM

です。

とりあえず、Perlのパーサジェネレータで有名だと思っているのは Parse::RecDescent なので、早速

...

...

動いてくれないので色々調べてみたら P::RD が使ってる再帰下降法は 逆ポーランド記法の様な 最左再帰 の構文を処理できないということでした。ションボリ

気を取り直して LR法を使っているパーサジェネレータということで、 Parse::Eyapp を試してみた

use strict;
use warnings;

use Parse::Eyapp;
use Regexp::Common;

my $grammer = q<
%%
expr: expr expr '+' { $_[1] + $_[2] }
    | expr expr '-' { $_[1] - $_[2] }
    | expr expr '*' { $_[1] * $_[2] }
    | expr expr '/' { $_[1] / $_[2] }
    | NUM
    ;
%%
>;

Parse::Eyapp->new_grammar(
  input => $grammer,
  classname => "RPCalc",
  firstline => 1,
);
{ no strict 'refs';
  no warnings 'once';

  # 字句解析 (yylex)
  *{RPCalc::_Lexer} = sub {
    my ($p) = shift;

    for ($p->YYData->{INPUT}) {
      m/\G\s+/gc;
      $_ eq ''                      and return ('', undef);
      m/\G$RE{num}{real}{-keep}/gc  and return ('NUM', $1);
      m/\G(.)/gcs                   and return ($1,$1)
    }
    return ('',undef);
  };

  # エラーハンドラ
  *{RPCalc::_Error} = sub {
    die "Syntax error near " . 
    ($_[0]->YYCurval?$_[0]->YYCurval:"end of file") .
    "\n"
  };

  # メインルーチン
  *{RPCalc::Run} = sub {
    my ($self) = shift;
    $self->YYParse( yylex => \&RPCalc::_Lexer, yyerror => \&RPCalc::_Error, );
  };
};

my $parser = RPCalc->new;
print "? ";
while (<>) {
  last if m{^q(?:uit)?};
  $parser->YYData->{INPUT} = $_;
  my $ret;
  eval { $ret = $parser->Run };
  warn $@ if $@;
  print $ret,$/ if defined $ret;
  print "? ";
}

字句解析器 _Lexer、エラーハンドラ _Error そしてパーサのメイン Run$grammer の中に書けるんだけど、エディタの構文強調が利かなくなるので外に出してます。後、演算子の優先順位とかは今回は関係ないので省略。

次は中置記法の四則演算に挑戦だー

トラックバック(1)

トラックバックURL: http://floralcompany.jp/mt/mt-tb.cgi/58

前回 の続き。四則演算のパースに挑戦。 括弧が使えるようになるのと、単項+- に... 続きを読む

コメントする

AUTHOR

  • turugina (虎王 剱奈)
  • E-mail: turugina {at} floralcompany.jp
  • pixiv
  • PiXA

2012年5月

    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    

アーカイブ

OpenID対応しています OpenIDについて
Powered by Movable Type 5.13-ja

- 警 告 -

本サイトにはいわゆる「18禁画像」(イラスト)へのリンクが存在します。 未成年の方や、その手の画像に不快感を覚える方は、 該当記事(「えちぃの」及び「ちょっとえちぃの」カテゴリ) をご覧にならないようお願いいたします。

上記を理解した上で非表示のブログパーツを表示する
あわせて読みたいブログパーツ
ついった
drawr/pixiv/twitpic