Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
CROSS 2014
言語CROSS

Smalltalkによる

四則演算パーサ別解解説

2014 SoftUmeYa, LLC
Masashi Umezawa
四則演算パーサ課題
数式のパース、計算処理を実装する
間違った入力が行われた場合も、単なるエラーとせず、
なんらかの形で構文に謝りがある事をユーザーに伝
えるようにして下さい。

入力例:(1*2+(3*4)
出力例:数式が不正です

文字列の...
どう解く?
PetitParser
PEGパーサコンビネータ
http://scg.unibe.ch/research/helvetia/petitparser

OMeta
パーサ定義・パターンマッチDSL
http://tinlizzi...
PetitParser
オブジェクトにasParserと送るとパーサ
ができる
あとはそれらをメッセージ送信で組み合
わせる
できあがったコードはほぼBNFと同じよ
うに見える
例: SQLiteのselect-core

 http://www.sqlite.org/syntaxdiagrams.html#select-core
PetitParserでの表現
シンタックスグラフをメッセージ送信に
selectCore
^ select , (distinct / all) optional ,
(resultColumn separatedBy: $, asPars...
四則演算パーサの定義
 クラスを導入しないパターン
number := #digit asParser plus token trim
数値パーサ作成
==> [ :token | token inputValue asNumber ].
t...
ワークスペースで実行
parser parse: '1+2*(3+4)'
"=> 15"
parser parse: '(1+2*(3+4)'
"=> $) expected at 10"
四則演算パーサの定義(2)
 クラスを導入するパターン
 PPCompositeParserのサブクラスとして
ArithmeticParser定義

PPCompositeParser subclass: #ArithmeticParse...
クラス導入の利点
 ツールの恩恵
対話的デバッグ、ビジュアライズ等が可能
ワークスペースで実行(2)
ArithmeticParser parse: '1+2*(3+4)'
"=> 15"
ArithmeticParser parse: '(1+2*(3+4)'
"=> $) expected at 10"
Upcoming SlideShare
Loading in …5
×

Smalltalkで四則演算パーサ

3,108 views

Published on

CROSS 2014 「言語CROSS」での四則演算パーサ作成課題の解答です

Published in: Technology, Education
  • Be the first to comment

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"

×