PHP 関西勉強会 (2009/3/14)




PHP でメタプログラミング
 カスタム DSL 作成入門


               株式会社アイテマン
               Piece Project
          ...
メタプログラミングとは?




「他のプログラムや自分自身を記述し
たり、操作するプログラムを記述す
る」
-- 「ジェネレーティブプログラミング」より




             Copyright © 2009 ITEMAN, In...
メタプログラムとは?




「他のプログラムを記述したり操作し
たりするプログラム」
-- 「ジェネレーティブプログラミング」より




                Copyright © 2009 ITEMAN, Inc. All r...
メタプログラミング/メタプログラムの例

プログラムジェネレータ
コンパイラ
インタプリタ
リフレクション
アスペクト指向プログラミング
(Aspect Oriented Programming)
言語指向プログラミング
(Language O...
言語指向プログラミング




「言語指向プログラミングとは、ドメ
イン特化言語を使ってソフトウェア構
築を行う一般的な開発スタイルのこと
です。」
- http://capsctrl.que.jp/kdmsnr/wiki/bliki/?Lan...
ドメイン特化言語




「ドメイン特化言語(DSL:Domain
Specific Language)とは、ある特
定の種類の問題に特化したコンピュー
タ言語のことです。」
- http://capsctrl.que.jp/kdmsnr/wi...
ドメイン特化言語の例

TeX
SQL
Yacc
Lex
アクティブデータモデル
XML 設定ファイル
GUI ビルダ

                 Copyright © 2009 ITEMAN, Inc. All rights res...
言語指向プログラミング

Intentional Software
 (Intentional Software)
MPS (JetBrains)
Software Factories (Microsoft)
Generative Progra...
次期 Piece Framework のアーキテクチャ

 Eclipse

                                抽象形
   PHP
                                abstract...
PHP でカスタム DSL を作成する



1. DSL の設計と Lexer および
Parser の実装
2. セマンティックモデル (ドメイン
モデル) の設計・実装
3. (オプション) Eclipse 上の DSL
エディタの設計・...
トランスフォーメーション


                              セマンティックモデル
DSL スクリプト                                                    PHP ス...
DSL の設計と Lexer および Parser の実装

1. 具体的な DSL スクリプトを書き
ながら、
2. 同時に Parser を定義し、
3. 必要に応じて Lexer に手を加え
て、
4. テストプログラムを実行する。
5....
Lexer Generator と Parser Generator



Lexer Generator
 - PHP_LexerGenerator
Parser Generator
 - PHP_ParserGenerator
 - kmy...
カスタム DSL の例
Employees.mapper - Piece_ORM マッパー DSL

association skills {
    table skills
    type manyToMany
    property ...
Lexer 定義の例
MapperLexer.plex - Piece_ORM マッパー DSL の Lexer 定義

...
/*!lex2php
%input $this->_input
%counter $this->_counter
...
Lexer 定義の例
MapperLexer.plex - Piece_ORM マッパー DSL の Lexer 定義

...
/*!lex2php
%statename INITIAL

METHOD {
    if ($this->_d...
Parser 定義の例
MapperParser.y - Piece_ORM マッパー DSL の Parser 定義

...
start ::= topStatementList.

topStatementList ::= topStat...
DSL ローダの実装
DSL ローダの制御フロー

...
public function load()
{
    $this->_initializeAST();
    $this->_loadAST();
    $this->_loa...
DSL ローダの実装
AST (Abstract Syntax Tree) の初期化

...
private function _initializeAST()
{
    $this->_ast = new Ast();

      fo...
DSL ローダの実装
Lexer と Parser を実行し、DSL を AST に変換する

...
private function _loadAST()
{
    $mapperLexer = new MapperLexer(file_...
DSL ローダの実装
シンボルテーブルの作成とセマンティックモデルの作成

...
private function _loadSymbols()
{
    try {
        $this->_loadMethods();
    }...
セマンティックモデル
Operational Interface と Population Interface

...
// A operational interface
public function executeQueryWithCr...
AST クラスの実装
AST extends DOMDocument

...
class AST extends DOMDocument
{
    public function addMethod($name, $query = null...
トランスフォーメーション


                              セマンティックモデル
DSL スクリプト                                                    PHP ス...
Eclipse 上の DSL エディタの設計・実装

1. TMF (Textual Modeling Framework) にDSL
グラマーを移植する。 (グラマー言語は選択可能)
2. 補完、バリデーション、リファクタリングなどを
実装す...
Eclipse 上の DSL エディタの設計・実装


3. ページフローやワークフローのように可視化が効
果的であればグラフィカルエディタも実装、TMF と
統合する。




   2 Way モデリングの完成



           ...
Eclipse 上の DSL エディタの設計・実装


4. PDT, Aptana など他のプラグインと協調できる
ように拡張する。




       双方向の変更の反映



                Copyright © 20...
おわりに




          Copyright © 2009 ITEMAN, Inc. All rights reserved.
- 28 -
参考文献
Krzysztof Czarnecki, Ulrich Eisenecker, Generative Programming:
Methods, Tools, and Applications, Addison-Wesley Pub ...
Upcoming SlideShare
Loading in …5
×

How To Create Custom DSLs By PHP

2,741 views
2,631 views

Published on

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
2,741
On SlideShare
0
From Embeds
0
Number of Embeds
177
Actions
Shares
0
Downloads
6
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

How To Create Custom DSLs By PHP

  1. 1. PHP 関西勉強会 (2009/3/14) PHP でメタプログラミング カスタム DSL 作成入門 株式会社アイテマン Piece Project 久保敦啓 <kubo@iteman.jp> Copyright © 2009 ITEMAN, Inc. All rights reserved. -1-
  2. 2. メタプログラミングとは? 「他のプログラムや自分自身を記述し たり、操作するプログラムを記述す る」 -- 「ジェネレーティブプログラミング」より Copyright © 2009 ITEMAN, Inc. All rights reserved. -2-
  3. 3. メタプログラムとは? 「他のプログラムを記述したり操作し たりするプログラム」 -- 「ジェネレーティブプログラミング」より Copyright © 2009 ITEMAN, Inc. All rights reserved. -3-
  4. 4. メタプログラミング/メタプログラムの例 プログラムジェネレータ コンパイラ インタプリタ リフレクション アスペクト指向プログラミング (Aspect Oriented Programming) 言語指向プログラミング (Language Oriented Programming) Copyright © 2009 ITEMAN, Inc. All rights reserved. -4-
  5. 5. 言語指向プログラミング 「言語指向プログラミングとは、ドメ イン特化言語を使ってソフトウェア構 築を行う一般的な開発スタイルのこと です。」 - http://capsctrl.que.jp/kdmsnr/wiki/bliki/?LanguageWorkbench より Copyright © 2009 ITEMAN, Inc. All rights reserved. -5-
  6. 6. ドメイン特化言語 「ドメイン特化言語(DSL:Domain Specific Language)とは、ある特 定の種類の問題に特化したコンピュー タ言語のことです。」 - http://capsctrl.que.jp/kdmsnr/wiki/bliki/?LanguageWorkbench より Copyright © 2009 ITEMAN, Inc. All rights reserved. -6-
  7. 7. ドメイン特化言語の例 TeX SQL Yacc Lex アクティブデータモデル XML 設定ファイル GUI ビルダ Copyright © 2009 ITEMAN, Inc. All rights reserved. -7-
  8. 8. 言語指向プログラミング Intentional Software (Intentional Software) MPS (JetBrains) Software Factories (Microsoft) Generative Programming Language Workbenches (Martin Fowler) Oslo (Microsoft) Copyright © 2009 ITEMAN, Inc. All rights reserved. -8-
  9. 9. 次期 Piece Framework のアーキテクチャ Eclipse 抽象形 PHP abstract representation DSL スクリプト 保存 store 保存形 stored representation 復元 DSLの参照・編集 Piece_IDE with TMF 生成 generation ツリービュー 投影 projection PDT, The Language Toolkit, ... Piece Framework Webサービス Piece Framework ランタイムオブジェクト エディター 双方向の変更の反映 グラフィカルエディター 実行可能形 executable representation ソースコード、HTML ファイル、データベーススキーマ、... 編集可能形 editable representation Copyright © 2009 ITEMAN, Inc. All rights reserved. -9-
  10. 10. PHP でカスタム DSL を作成する 1. DSL の設計と Lexer および Parser の実装 2. セマンティックモデル (ドメイン モデル) の設計・実装 3. (オプション) Eclipse 上の DSL エディタの設計・実装 Copyright © 2009 ITEMAN, Inc. All rights reserved. - 10 -
  11. 11. トランスフォーメーション セマンティックモデル DSL スクリプト PHP スクリプト ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ------ ------ Generate オプション Parse Populate AST Copyright © 2009 ITEMAN, Inc. All rights reserved. - 11 -
  12. 12. DSL の設計と Lexer および Parser の実装 1. 具体的な DSL スクリプトを書き ながら、 2. 同時に Parser を定義し、 3. 必要に応じて Lexer に手を加え て、 4. テストプログラムを実行する。 5. 以上を繰り返す Copyright © 2009 ITEMAN, Inc. All rights reserved. - 12 -
  13. 13. Lexer Generator と Parser Generator Lexer Generator - PHP_LexerGenerator Parser Generator - PHP_ParserGenerator - kmyacc + PHP 対応パッチ Copyright © 2009 ITEMAN, Inc. All rights reserved. - 13 -
  14. 14. カスタム DSL の例 Employees.mapper - Piece_ORM マッパー DSL association skills { table skills type manyToMany property skills } association computer { table computers type oneToOne property computer } method findByIdAndNote { query quot;SELECT * FROM $__table WHERE id = $id AND note = $notequot; } method findAllWithSkills1 { association skills } ... Copyright © 2009 ITEMAN, Inc. All rights reserved. - 14 -
  15. 15. Lexer 定義の例 MapperLexer.plex - Piece_ORM マッパー DSL の Lexer 定義 ... /*!lex2php %input $this->_input %counter $this->_counter %token $this->token %value $this->value %line $this->line ID = /[a-zA-Z_][a-zA-Z_0-9]*/ WS = /[ trn]+/ STRING = /quot;[^[quot;]+quot;/ LCURLY = quot;{quot; RCURLY = quot;}quot; METHOD = quot;methodquot; ... SL_COMMENT = !//[^nr]*r?n! ML_COMMENT = !/*[^*]**+([^*/][^*]**+)*/! */ /*!lex2php %statename INITIAL ... Copyright © 2009 ITEMAN, Inc. All rights reserved. - 15 -
  16. 16. Lexer 定義の例 MapperLexer.plex - Piece_ORM マッパー DSL の Lexer 定義 ... /*!lex2php %statename INITIAL METHOD { if ($this->_debug) echo quot;found METHOD [ {$this->value} ]nquot;; $this->token = MapperParser::METHOD; } QUERY { if ($this->_debug) echo quot;found QUERY [ {$this->value} ]nquot;; $this->token = MapperParser::QUERY; } ORDER_BY { if ($this->_debug) echo quot;found ORDER_BY [ {$this->value} ]nquot;; $this->token = MapperParser::ORDER_BY; } ... Copyright © 2009 ITEMAN, Inc. All rights reserved. - 16 -
  17. 17. Parser 定義の例 MapperParser.y - Piece_ORM マッパー DSL の Parser 定義 ... start ::= topStatementList. topStatementList ::= topStatementList topStatement. topStatementList ::= . topStatement ::= method. topStatement ::= association. method ::= METHOD ID(A) LCURLY methodStatementList(B) RCURLY. { if (array_key_exists(strtolower(A), $this->_methodDeclarations)) { throw new Exception(quot;Cannot redeclare the method [ {A} ] (previously declared on line quot; . $this->_methodDeclarations[ strtolower(A) ] . ')' ); } $this->_methodDeclarations[ strtolower(A) ] = $this->_mapperLexer->line; $this->_ast->addMethod(A, @B['query'], @B['orderBy'], @B['associations']); } ... Copyright © 2009 ITEMAN, Inc. All rights reserved. - 17 -
  18. 18. DSL ローダの実装 DSL ローダの制御フロー ... public function load() { $this->_initializeAST(); $this->_loadAST(); $this->_loadSymbols(); $this->_createMapper(); } ... Copyright © 2009 ITEMAN, Inc. All rights reserved. - 18 -
  19. 19. DSL ローダの実装 AST (Abstract Syntax Tree) の初期化 ... private function _initializeAST() { $this->_ast = new Ast(); foreach ($this->_metadata->getFieldNames() as $fieldName) { ... } $this->_ast->addMethod('findAll', 'SELECT * FROM $__table'); $this->_ast->addMethod('insert'); $this->_ast->addMethod('update'); $this->_ast->addMethod('delete'); } ... Copyright © 2009 ITEMAN, Inc. All rights reserved. - 19 -
  20. 20. DSL ローダの実装 Lexer と Parser を実行し、DSL を AST に変換する ... private function _loadAST() { $mapperLexer = new MapperLexer(file_get_contents($this->_configFile)); $mapperParser = new MapperParser($mapperLexer, $this->_ast, $this- >_configFile); try { while ($mapperLexer->yylex()) { $mapperParser->doParse($mapperLexer->token, $mapperLexer->value); } } catch (Exception $e) { throw new Exception($e->getMessage() . quot; in {$this->_configFile} on line {$mapperLexer- >line}quot; ); } $mapperParser->doParse(0, 0); } ... Copyright © 2009 ITEMAN, Inc. All rights reserved. - 20 -
  21. 21. DSL ローダの実装 シンボルテーブルの作成とセマンティックモデルの作成 ... private function _loadSymbols() { try { $this->_loadMethods(); } catch (Exception $e) { throw new Exception($e->getMessage() . quot; in {$this->_configFile}quot;); } } private function _createMapper() { $this->_mapper = new Mapper($this->_mapperID); foreach ($this->_methods as $method) { $this->_mapper->addMethod($method); } } ... Copyright © 2009 ITEMAN, Inc. All rights reserved. - 21 -
  22. 22. セマンティックモデル Operational Interface と Population Interface ... // A operational interface public function executeQueryWithCriteria($methodName, $criteria, $isManip = false) { if (!$this->hasMethod($methodName)) { throw new Exception(quot;The method [ $methodName ] was not definedquot;); } $queryExecutor = new QueryExecutor($this, $isManip); return $queryExecutor->executeWithCriteria($this- >_getMethod($methodName)->getName(), $criteria); } // A population interface public function addMethod(Method $method) { $this->_methods[ strtolower($method->getName()) ] = $method; } ... Copyright © 2009 ITEMAN, Inc. All rights reserved. - 22 -
  23. 23. AST クラスの実装 AST extends DOMDocument ... class AST extends DOMDocument { public function addMethod($name, $query = null, $orderBy = null, $associations = null) { $id = strtolower($name); $xpath = new DOMXPath($this); $methodNodeList = $xpath->query(quot;//method[@id='$id']quot;); if (!$methodNodeList->length) { $methodElement = $this->appendChild(new DOMElement('method')); $methodElement->setAttribute('id', $id); $methodElement->setAttribute('name', $name); } else { $methodElement = $methodNodeList->item(0); } ... } ... Copyright © 2009 ITEMAN, Inc. All rights reserved. - 23 -
  24. 24. トランスフォーメーション セマンティックモデル DSL スクリプト PHP スクリプト ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ------ ------ Generate オプション Parse Populate AST Copyright © 2009 ITEMAN, Inc. All rights reserved. - 24 -
  25. 25. Eclipse 上の DSL エディタの設計・実装 1. TMF (Textual Modeling Framework) にDSL グラマーを移植する。 (グラマー言語は選択可能) 2. 補完、バリデーション、リファクタリングなどを 実装する。 DSL エディタとツリービューの完成 Copyright © 2009 ITEMAN, Inc. All rights reserved. - 25 -
  26. 26. Eclipse 上の DSL エディタの設計・実装 3. ページフローやワークフローのように可視化が効 果的であればグラフィカルエディタも実装、TMF と 統合する。 2 Way モデリングの完成 Copyright © 2009 ITEMAN, Inc. All rights reserved. - 26 -
  27. 27. Eclipse 上の DSL エディタの設計・実装 4. PDT, Aptana など他のプラグインと協調できる ように拡張する。 双方向の変更の反映 Copyright © 2009 ITEMAN, Inc. All rights reserved. - 27 -
  28. 28. おわりに Copyright © 2009 ITEMAN, Inc. All rights reserved. - 28 -
  29. 29. 参考文献 Krzysztof Czarnecki, Ulrich Eisenecker, Generative Programming: Methods, Tools, and Applications, Addison-Wesley Pub (Sd), 2000, ISBN 978-0201309775 津田 義史、今関 剛、朝比奈 勲訳、『ジェネレーティブプロ グラミング』、翔泳社、2008年、ISBN 978-4798113319 http://capsctrl.que.jp/kdmsnr/wiki/bliki/?DomainSpecificLanguage http://www.martinfowler.com/articles/languageWorkbench.html http://capsctrl.que.jp/kdmsnr/wiki/bliki/?LanguageWorkbench http://martinfowler.com/dslwip/index.html Copyright © 2009 ITEMAN, Inc. All rights reserved. - 29 -

×