Xtext&Xtend documents

889 views

Published on

第56回SEA関西プロセス分科会で用いた言語仕様ドキュメントです.

Xtext, Xtendの言語仕様について解説しています.Xtendは仕様がかなり大きく,すべては扱いきれておりません.詳しくは本家ドキュメントを参照ください.
Xtext:
http://www.eclipse.org/Xtext/documentation.html
Xtend:
https://www.eclipse.org/xtend/documentation.html

Published in: Engineering
  • Be the first to comment

Xtext&Xtend documents

  1. 1. ©2014 Shintaro Hosoai Xtext & Xtend Documents 細合 晋太郎 2014/3/31 SEA関西プロセス分科会
  2. 2. ©2014 Shintaro Hosoai Xtext 2014/3/31 SEA関西プロセス分科会 2
  3. 3. ©2014 Shintaro Hosoai Xtext構造 grammar org.eclipse.xtext.example.fowlerdsl.Statemachine with org.eclipse.xtext.common.Terminals generate statemachine "http://www.eclipse.org/xtext/example/fowlerdsl/Statemachine" Statemachine : {Statemachine} ('events' events+=Event+ 'end')? ('resetEvents' resetEvents+=[Event]+ 'end')? ('commands' commands+=Command+ 'end')? states+=State*; terminal MYID: 'A''0'..'9'; 言語名宣言と言語Mixin 言語モデル宣言 Parser Rule/言語構造定義 lexis/語彙定義 初めのうちは,上二つは自動生成ままで利用するのがよい Event: name=ID; ...
  4. 4. ©2014 Shintaro Hosoai DSL Mixin • DSL Mixinを行うにはWith句にDSL名を指定する. grammar DSL名 with ベースDSL名 • デフォルトのDSL org.eclipse.xtext.common.Terminals IDやINT,STRING等のTerminalが定義されている. • Xbase org.eclipse.xtext.xbase.Xbase Jvm統合に必要な各種要素が定義されている. • 自前DSLをMixinするには,以下のようにwith句にDSL名を 指定 42014/3/31 SEA関西プロセス分科会 grammar my.SuperGrammar generate super "http://my.org/super" ... RuleA : "a" stuff=RuleB; RuleB : "{" name=ID "}"; grammar my.SubGrammar with my.SuperGrammar ... ベースDSL 子DSL
  5. 5. ©2014 Shintaro Hosoai Parser Rules • 定義名:~‘;’までが一つのルールとなる. • この定義名のモデルが生成される(Returnsを 指定しない場合,Returnsで指定したモデルを 割り当てることも出来る.) 52014/3/31 SEA関西プロセス分科会 State: 'state' name=ID ('actions' '{' actions+=[Command]+ '}')? transitions+=Transition* 'end'; Transition: event=[Event] '=>' state=[State]; DSL定義
  6. 6. ©2014 Shintaro Hosoai 語彙 • ’’で区切った部分は語彙として定義される 62014/3/31 SEA関西プロセス分科会 State: 'state' name=ID ('actions' '{' actions+=[Command]+ '}')? transitions+=Transition* 'end'; DSL定義 state myState actions { myCommand1 myCommand2 } event2 => myState2 event3 => myState3 end DSL例
  7. 7. ©2014 Shintaro Hosoai 変数 • 変数は,属性として生成される. • 割り当てに応じて =:単体, +=:EList • として生成される 72014/3/31 SEA関西プロセス分科会 State: 'state' name=ID ('actions' '{' actions+=[Command]+ '}')? transitions+=Transition* 'end'; Transition: event=[Event] '=>' state=[State]; DSL定義 State name : ID actions : List<Command> transitions:List<Transition> Transition event : Event state : State
  8. 8. ©2014 Shintaro Hosoai 数量子 • ():グループ • * :0回以上 • + :1回以上 • ? :0または1 • Terminal 限定 • . :任意の一文字 • ! :否定.!(‘A’|’B’|’C’)なら ABC以外の文字が マッチ. • -> : Until, ‘/*’ -> ‘*/’ なら*/が来るまでスキップさ れる • .. :範囲値.‘A’..’D’ ならABCD,数値も可 Unicodeの並びで範囲指定しているらし い. このため日本語を指定することも可能. 82014/3/31 SEA関西プロセス分科会
  9. 9. ©2014 Shintaro Hosoai Type Reference State: 'state' name=ID ('actions' '{' actions+=[Command]+ '}')? transitions+=Transition* 'end'; state myState actions { myCommand1 myCommand2 } event2 => myState2 event3 => myState3 end Transition: event=[Event] '=>' state=[State]; DSL定義 DSL例 []で指定した要素はnameによりで インスタンスを参照する. このため参照されるRuleにはname=ID を持つ必要がある. 例ではState,Event,Commandは参照可 Transitionはname=IDを持たないので, 参照出来ない. 割り当てに用いることが出来るのは, ・Terminal Rule (ex: ID) ・Parser Rule (ex: Transition) ・Parser Ruleの実体への参照(ex: [Command])
  10. 10. ©2014 Shintaro Hosoai Terminal • 任意の語彙の作成 • terminal 語彙名 : 定義; • 例えば,アルファベットから始まる英数字の羅 列 • terminal MyID : (‘a’..’z’|’A’..’Z’)(‘a’..’z’|’A’..’Z’|’0’..’9’)*; 102014/3/31 SEA関西プロセス分科会
  11. 11. ©2014 Shintaro Hosoai Xtend 2014/3/31 SEA関西プロセス分科会 11
  12. 12. ©2014 Shintaro Hosoai こんにちはXtend! • Xtendの記法はJavaによく似ています. • メソッド定義はdefキーワードで行います. •class HelloWorld { def static void main(String[] args) { println("Hello World") } } // Generated Java Source Code import org.eclipse.xtext.xbase.lib.InputOutput; public class HelloWorld { public static void main(final String[] args) { InputOutput.<String>println("Hello World"); } } 自動生成 生成されたJavaコード Xtendコード 記述したXtendコードはセーブ タイミングで自動的にJavaコー に変換されます.
  13. 13. ©2014 Shintaro Hosoai Xtendの特徴 • Extension methods • Lambda Expression • Active Annotations • Operator overloading • Powerful switch expressions • Multiple dispatch • Template expressions • No statement • Properties • Type inference • Full support for Java generics • Translate to Java (not bytecode)
  14. 14. ©2014 Shintaro Hosoai Classes and Members package com.acme import java.util.List class MyClass { String name new(String name) { this.name = name } def String first(List<String> elements) { elements.get(0) } } セミコロンは不要(あってもよ い) コンストラクタはnewキーワードで定義 クラス内で自身のコンストラクタ呼び出しは this(). 親コンストラクタはsuper() (Javaと同じ) メソッドはdefキー ワードで定義 デフォルトはpublic. protected, package, privateを指定可能 extends, implementsの使い方は Javaと同じ
  15. 15. ©2014 Shintaro Hosoai Field(1) • 変数宣言の方法は3つ • Javaと同じ型名 変数名 メソッド内の定義には使えない.var/valを利用する こと • var 変数名 :動的型.型推論で適切な型が振られ る • val 定数名 :定数宣言.こちらも明確な型指定は 行わず,初回代入時の型に応じて決まる. • アクセス指示子はデフォルトでPrivate
  16. 16. ©2014 Shintaro Hosoai Field(2) • getter/setterの自動呼出し • FooクラスにsetHoge(), getHoge()定義されている場 合. • val foo = new Foo • foo.hoge : getHoge()が呼ばれる • foo.hoge = “aaa”:setHoge(“aaa”)が呼ばれる • getter/setterの自動生成 • @Property • Type variable • とすることで,自動的にGetter/Setterが生成される 162014/3/31 SEA関西プロセス分科会
  17. 17. ©2014 Shintaro Hosoai Field(3) • this • Javaと同じ.省略可 • it: 省略可能になる変数,Lambdaと組合わせるといいら しい • val it = new Person • name = “Horst” : it.setName()が呼ばれる • クラス変数,クラスメソッドへのアクセス • MyClass::myField • MyClass::myMethod() 172014/3/31 SEA関西プロセス分科会
  18. 18. ©2014 Shintaro Hosoai Expression • Xtendの構文はすべて式です.メソッド呼び出 しはもちろん,ブロック,各種制御構文,メ ソッド定義もすべて値を返します. • 関数型もあります • val toUpperCaseFunction = [String s | s.toUpperCase] ↑String.toUpperCaseメソッドを toUpperCaseFunctionという変数に代入 182014/3/31 SEA関西プロセス分科会
  19. 19. ©2014 Shintaro Hosoai Operators(1) • 一覧は演算子とオーバーライド章を参照 • 等価・比較演算子 • ==, != : equals()で比較.文字列比較はこれ で • ===, !== : 従来のJavaの比較演算子.Reference • >, <, >=, <= : Javaと同じ.Comparable • 算術演算: +, -, *, /, %, **.Javaと同じだが,Primitive Type以外に もオーバーライドして利用可 • Elvis Operator: null-safe feature call • val salutation = person.firstName ?: ‘Sir/Madam’ • personがNullでもぬるぽにならない.’Sir/Madam’が 代入される 192014/3/31 SEA関西プロセス分科会
  20. 20. ©2014 Shintaro Hosoai Operators(2) • With Operator:オブジェクトの属性に簡単代入 • var person = new Person => [ firstName = “Shintaro” lastName = “Hosoai” address = new Address => [ city = “Fukuoka” ] ] • Range Operator : 範囲値作成 • 0..10 → 012345678910 • Pair Operator : ペア値作成(簡易Hash?) • val nameAndAge = ‘Homer’ -> 42 202014/3/31 SEA関西プロセス分科会
  21. 21. ©2014 Shintaro Hosoai 制御構文:IF • if (cond) { • expression • }else{ • elseExpression • } • ifも式として用いる事ができます. • var name = if (firstName!=null) firstName+’ ’+lastName else lastName • var name = if (str.length>1) str : elseを省略する とelse nullと見なされます(nullが返る) 212014/3/31 SEA関西プロセス分科会
  22. 22. ©2014 Shintaro Hosoai 制御構文:switch switch myString { case myString.length > 5 : “a long string” case ‘some’ : “It’s some string”. default : “It’s another short string” } • caseに条件文が使えます.break句は不要です. Stringの比較が行えます. 222014/3/31 SEA関西プロセス分科会
  23. 23. ©2014 Shintaro Hosoai 制御構文:switch:Type Guard def something(Object o){ switch o { String : o.substring(3) Integer case o > 10 : o.toString default : “not match” } } 型で条件分岐できます.(instanceof) 型にマッチした後にさらにCaseで条件を加える 事ができます.マッチした時点で自動的にCast されています. 232014/3/31 SEA関西プロセス分科会 このOはIntegerに Castされている このOはStringに Castされている
  24. 24. ©2014 Shintaro Hosoai 制御構文:for • Xtendのforはjava5の拡張Forのみです.従来の for(int a=0; a<10;a++)といった書き方はできませ ん. (Range記法と組み合わせる事で同様の事はで きます) for ( Type variable : arrayOrIterable){ expressions. } 型宣言や{}は省略可です.適切な型が選択さ れます.ex) List<String>ならStringの変数となる. for(variable : arrayOrIterable) expression 242014/3/31 SEA関西プロセス分科会
  25. 25. ©2014 Shintaro Hosoai 制御構文:for Rangeとの組み合わ せ • 1~10までループしたい場合どうするの? for (i : 1 ..10) print i 10..1で逆順も可能 Range Operations • 0..10 → 012345678910 • 0..<10 → 0123456789 • 10>..0 → 9876543210 • 0 .. hoge.length といった表記も可 252014/3/31 SEA関西プロセス分科会
  26. 26. ©2014 Shintaro Hosoai Methods(1) • メソッド宣言はdefで行う.デフォルトのアク セス指示子はpublic. protected, package, private指 定可. • 返り値の型は省略可能.またReturnも省略可 能,一番最後の式の値が返る. • staticでクラスメソッドとすることも出来る (Javaと同じ) • 抽象メソッド • 抽象クラスやインターフェイス内で,Bodyの 無いメソッド定義は,抽象メソッドとなる. abstract class MyAbstractClass() { def String abstractMethod() // no body }
  27. 27. ©2014 Shintaro Hosoai Methods(2) • オーバーライドはdefの代わりにoverrideキー ワードを用いて明示する. • Exception • Javaと同様 • Generic • Javaと同様 • Method Call • Javaと同様.引数がない場合は()省略可能 override String second(List<String> elements) { elements.get(1) }
  28. 28. ©2014 Shintaro Hosoai Lambda(1) • [ Type variable | expression] • 以下,JavaとXtendのLambdaの実装比較 Java final JTextField textField = new JTextField(); textFeild.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ textField.text=“Something happend”); }}); Xtend val textField = new JTextField textField.addActionListener([ActionEvent e | textField.text = “Something happned” ]) 282014/3/31 SEA関西プロセス分科会 これも省略可
  29. 29. ©2014 Shintaro Hosoai Lambda(2) • [a, b | a.length – b.length] <二引数の関数の場合 • 変数への代入も可能 • val myFunction = [Type a | a.doAnything()] • コレクションにももちろん利用可能 • 予め便利なメソッド群がExtension Methodとして追 加されている • forEach((T)=>void Procedure) : void • map((T)=>R Transformation) : List<R> • filter((T)=> Boolean Predicate) : Iteratable<T> • findFirst((T)=>Boolean Predicate): T • reduce((T,T)=> T function): T • などなど. 292014/3/31 SEA関西プロセス分科会
  30. 30. ©2014 Shintaro Hosoai Dispatch Methods(1) • Javaはコンパイル時の型に基づいて,メソッド 呼び出しを決定する.このため,動的に Dispatchできない 左図のような構造で,Dispatcher に MyInterface a = MyClass1(); Dispatcher.dispatch(a); とすると,呼び出しは不 定となる (コンパイルできない) • 言語AST(Abstract Syntax Tree)へのアクセスは, このようなDispatch Methodが多用される MyInterface MyClass1 MyClass2 Dispatcher dispatch(MyClass1 a) dispatch(MyClass2 b)
  31. 31. ©2014 Shintaro Hosoai Dispatch Methods(2) • Xtendではdispatch キーワードを付与する ことで,Dispatch Method として定義できる • 次のようなXtext定義を 行った際などは,dispatch を指定するとよい class DispatchSample { def doGenerate(){ val expressions = new ArrayList<Expression> expressions.add(new Add) expressions.add(new Sub) expressions.add(new Mul) expressions.add(new Div) for(e : expressions){ genExpression(e); } } dispatch def genExpression(Add a)'''''' dispatch def genExpression(Sub a)'''''' dispatch def genExpression(Mul a)'''''' dispatch def genExpression(Div a)'''''' } interface Expression{} class Add implements Expression{} class Sub implements Expression{} class Mul implements Expression{} class Div implements Expression{} Expression : Add | Sub | Mul | Div; Add : ...; Sub : ...; Mul : ...; Div : ...; 実際にはDSL のパーサがこ のようにモデ ルを詰めて渡 してくる Xtextで 生成 される AST
  32. 32. ©2014 Shintaro Hosoai Extension Methods • クラスにメソッドを(仮想的に)付け加える • たとえば.StringにtoFirstUpper()メソッドを加 えたり • 第一引数を対象の型にしたメソッドはExtension Methodとして呼び出せる • def extensionCall(String str, Hoge any){ • str.doSomething() • } • “hello”.extensionCall(hogeAny) ←呼び出す時は左 辺のオブジェクトが第一引数として渡される.
  33. 33. ©2014 Shintaro Hosoai Extension Imports/Provider • Xtendには,モデル操作等の便利なユーティリ ティメソッドがExtension Methodのライブラリ として提供されている • ObjectExtensions (src) • IterableExtensions (src) • MapExtensions (src) • ListExtensions (src) • CollectionExtensions (src) • BooleanExtensions (src) • IntegerExtensions (src) • FunctionExtensions (src)
  34. 34. ©2014 Shintaro Hosoai Active Annotation • @Property • 属性に付与することで,private変数とgetter/setter を生成する • @Property String name • -> private String _name; String getName(){return _name;} void setName(String name){this._name=name;} • @Data • クラスに付与することで,含まれる属性の getter/setter, 属性設定を行うコンストラクタ等を生 成
  35. 35. ©2014 Shintaro Hosoai Annotation Type Declaration annotation MyAnnotation { String[] value boolean isTricky = false int[] lotteryNumbers = #[ 42, 137 ] }
  36. 36. ©2014 Shintaro Hosoai Enum Type Declaration • Javaと同じ? enum MyColor { GREEN, BLUE, RED }
  37. 37. ©2014 Shintaro Hosoai 演算子とオーバーライド(1) • Xtendでは,演算子のオーバーライドが可能 • 演算子に対応するメソッドを定義すると,その 演算子が使われた際に対応するメソッドが呼ば れる. class OperatorOverwrite { String name = “hoge” def operator_plus(OperatorOverwrite e2){ this.name+"::"+e2.name } def static void main(String[] args) { var op1 = new OperatorOverwrite; var op2 = new OperatorOverwrite; print(op1+op2) } } +二項演算子の定義. オーバーライドではある がoverrideではなくdefで 定義する. thisが左辺,引数が右辺. ここでは自身と同じ型を 引数に取っているが,異 なる型でも可能.オー バーロードも可. +二項演算子の呼び出し
  38. 38. ©2014 Shintaro Hosoai 演算子とオーバーライド(2) 演算子 対応メソッド名 演算子 対応メソッド名 ! e1 e1.operator_not() e1 == e2 e1.operator_equals(e2) - e1 e1.operator_minus() e1 != e2 e1.operator_notEquals(e2) + e1 e1.operator_plus() e1 === e2 e1.operator_tripleEquals(e2) e1 + e2 e1.operator_plus(e2) e1 !== e2 e1.operator_tripleNotEquals(e2) e1 – e2 e1.operator_minus(e2) e1 < e2 e1.operator_lessThan(e2) e1 * e2 e1.operator_multiply(e2) e1 > e2 e1.operator_greaterThan(e2) e1 / e2 e1.operator_divide(e2) e1 <= e2 e1.operator_lessEqualsThan(e2) e1 % e2 e1.operator_modulo(e2) e1 >= e2 e1.operator_greaterEqualsThan(e2) e1 ** e2 e1.operator_power(e2) e1 -> e2 e1.operator_mappedTo(e2) e1 += e2 e1.operator_add(e2) e1 .. e2 e1.operator_upTo(e2) e1 –= e2 e1.operator_remove(e2) e1 >.. e2 e1.operator_greaterThanDoubleDot( e2) e1 || e2 e1.operator_or(e2) e1 ..<e2 e1.operator_doubleDotLessThan(e2) e1 && e2 e1.operator_and(e2)
  39. 39. ©2014 Shintaro Hosoai 演算子とオーバーライド(3) 演算子 対応メソッド名 演算子 対応メソッド名 e1 => e2 e1.operator_equals(e2) e1 <= e2 e1.operator_notEquals(e2) e1 >>> e2 e1.operator_greaterThan(e2) e1 << e2 e1.operator_tripleEquals(e2) e1 <> e2 e1.operator_lessEqualsThan(e2) e1 >> e2 e1.operator_tripleNotEquals( e2) e1 ?: e2 e1.operator_greaterEqualsThan( e2) e1 <<< e2 e1.operator_lessThan(e2) e1 <=> e2 e1.operator_mappedTo(e2)

×