Successfully reported this slideshow.
Your SlideShare is downloading. ×

Smalltalkで四則演算パーサ

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Loading in …3
×

Check these out next

1 of 11 Ad
Advertisement

More Related Content

More from Masashi Umezawa (20)

Recently uploaded (20)

Advertisement

Smalltalkで四則演算パーサ

  1. 1. CROSS 2014 言語CROSS Smalltalkによる 四則演算パーサ別解解説 2014 SoftUmeYa, LLC Masashi Umezawa
  2. 2. 四則演算パーサ課題 数式のパース、計算処理を実装する 間違った入力が行われた場合も、単なるエラーとせず、 なんらかの形で構文に謝りがある事をユーザーに伝 えるようにして下さい。 入力例:(1*2+(3*4) 出力例:数式が不正です 文字列のパース処理の比較が主なポイントなので、eval のような機能や、上記のような機能を持ったライブラリを そのまま使う事は禁止とします。
  3. 3. どう解く? PetitParser PEGパーサコンビネータ http://scg.unibe.ch/research/helvetia/petitparser OMeta パーサ定義・パターンマッチDSL http://tinlizzie.org/ometa/ OMetaは以前紹介したのでPetitParserに 参考: 「OMetaの紹介」 • ftp://swikis.ddo.jp/SqueakDevJa/events/ScalaOff2008/OMetaIntro.pdf
  4. 4. PetitParser オブジェクトにasParserと送るとパーサ ができる あとはそれらをメッセージ送信で組み合 わせる できあがったコードはほぼBNFと同じよ うに見える
  5. 5. 例: SQLiteのselect-core  http://www.sqlite.org/syntaxdiagrams.html#select-core
  6. 6. PetitParserでの表現 シンタックスグラフをメッセージ送信に selectCore ^ select , (distinct / all) optional , (resultColumn separatedBy: $, asParser trim) , (from , joinSource) optional , (where , expression ) optional , (groupBy , (orderingTerm separatedBy: $, asParser trim), ('HAVING' asParser caseInsensitive trim , expression) optional ) optional
  7. 7. 四則演算パーサの定義  クラスを導入しないパターン number := #digit asParser plus token trim 数値パーサ作成 ==> [ :token | token inputValue asNumber ]. terms := PPUnresolvedParser new. primary := PPUnresolvedParser new. それ以外のパーサ作成 parenthesis := PPUnresolvedParser new. (def: で後から定義) addition := PPUnresolvedParser new. multiplication := PPUnresolvedParser new. multiplication def: ((primary separatedBy: ($* asParser / $/ asParser) trim) foldLeft: [ :a :op :b | a perform: op asSymbol with: b ]). addition def: ((multiplication separatedBy: ($+ asParser / $- asParser) trim) foldLeft: [ :a :op :b | a perform: op asSymbol with: b ]). parenthesis def: ($( asParser trim , terms , $) asParser trim ==> [ :nodes | nodes second ]). 乗除、加減、括弧の順で primary def: number / parenthesis. パーサ定義 terms def: addition / multiplication. parser := terms end. 終端を定義して完成!
  8. 8. ワークスペースで実行 parser parse: '1+2*(3+4)' "=> 15" parser parse: '(1+2*(3+4)' "=> $) expected at 10"
  9. 9. 四則演算パーサの定義(2)  クラスを導入するパターン  PPCompositeParserのサブクラスとして ArithmeticParser定義 PPCompositeParser subclass: #ArithmeticParser instanceVariableNames: 'terms addition multiplication primary number parentheses'  パース要素ごとにメソッドを定義 parentheses ^ $( asParser trim , terms , $) asParser trim ==> [ :nodes | nodes second ]
  10. 10. クラス導入の利点  ツールの恩恵 対話的デバッグ、ビジュアライズ等が可能
  11. 11. ワークスペースで実行(2) ArithmeticParser parse: '1+2*(3+4)' "=> 15" ArithmeticParser parse: '(1+2*(3+4)' "=> $) expected at 10"

×