39
©2014 Shintaro Hosoai Xtext & Xtend Documents 細細 細細細 2022/06/12 SEA 細 細細細細細細細 西

Xtext&Xtend documents

Embed Size (px)

DESCRIPTION

第56回SEA関西プロセス分科会で用いた言語仕様ドキュメントです. Xtext, Xtendの言語仕様について解説しています.Xtendは仕様がかなり大きく,すべては扱いきれておりません.詳しくは本家ドキュメントを参照ください. Xtext: http://www.eclipse.org/Xtext/documentation.html Xtend: https://www.eclipse.org/xtend/documentation.html

Citation preview

Page 1: Xtext&Xtend documents

©2014 Shintaro Hosoai

Xtext & Xtend Documents

細合 晋太郎

2023/04/11 SEA 関西プロセス分科会

Page 2: Xtext&Xtend documents

©2014 Shintaro Hosoai 2

Xtext

04/11/2023 SEA 関西プロセス分科会

Page 3: Xtext&Xtend documents

©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; .

..

Page 4: Xtext&Xtend documents

©2014 Shintaro Hosoai

DSL Mixin

• DSL Mixin を行うには With 句に DSL 名を指定する.grammar DSL 名 with  ベース DSL 名• デフォルトの DSLorg.eclipse.xtext.common.TerminalsID や INT,STRING 等の Terminal が定義されている.• Xbase

org.eclipse.xtext.xbase.XbaseJvm 統合に必要な各種要素が定義されている.• 自前 DSL を Mixin するには,以下のように with 句に DSL

名を指定

404/11/2023 SEA 関西プロセス分科会

grammar my.SuperGrammargenerate super "http://my.org/super"...RuleA : "a" stuff=RuleB;RuleB : "{" name=ID "}"; grammar my.SubGrammar with my.SuperGrammar...

ベース DSL

子 DSL

Page 5: Xtext&Xtend documents

©2014 Shintaro Hosoai 5

Parser Rules

• 定義名:~‘;’までが一つのルールとなる.• この定義名のモデルが生成される( Returns を

指定しない場合, Returns で指定したモデルを割り当てることも出来る.)

04/11/2023 SEA 関西プロセス分科会

State:   'state' name=ID   ('actions' '{' actions+=[Command]+ '}')?   transitions+=Transition*   'end';Transition:   event=[Event] '=>' state=[State];

DSL 定義

Page 6: Xtext&Xtend documents

©2014 Shintaro Hosoai

語彙

• ’’ で区切った部分は語彙として定義される

604/11/2023 SEA 関西プロセス分科会

State:   'state' name=ID   ('actions' '{' actions+=[Command]+ '}')?   transitions+=Transition*   'end';

DSL 定義

state myState actions { myCommand1 myCommand2 } event2 => myState2 event3 => myState3end

DSL 例

Page 7: Xtext&Xtend documents

©2014 Shintaro Hosoai

変数

• 変数は,属性として生成される.• 割り当てに応じて

= :単体,+= : EList• として生成される

704/11/2023 SEA 関西プロセス分科会

State:   'state' name=ID   ('actions' '{' actions+=[Command]+ '}')?   transitions+=Transition*   'end';Transition:   event=[Event] '=>' state=[State];

DSL 定義

Statename : ID

actions : List<Command>transitions:List<Transition>

Transitionevent : Eventstate : State

Page 8: Xtext&Xtend documents

©2014 Shintaro Hosoai

数量子• () :グループ• * :0回以上• + :1回以上• ? :0または1

• Terminal 限定• . :任意の一文字• ! :否定. !(‘A’|’B’|’C’) なら ABC 以外の文字がマッチ.• -> : Until, ‘/*’ -> ‘*/’ なら */ が来るまでスキップされる• .. :範囲値.‘ A’..’D’ なら ABCD ,数値も可

     Unicode の並びで範囲指定しているらしい.    このため日本語を指定することも可能.

804/11/2023 SEA 関西プロセス分科会

Page 9: Xtext&Xtend documents

©2014 Shintaro Hosoai

Type Reference

State:   'state' name=ID   ('actions' '{' actions+=[Command]+ '}')?   transitions+=Transition*   'end';

state myState actions { myCommand1 myCommand2 } event2 => myState2 event3 => myState3end

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] )

Page 10: Xtext&Xtend documents

©2014 Shintaro Hosoai

Terminal

• 任意の語彙の作成• terminal 語彙名 :

定義;• 例えば,アルファベットから始まる英数字の羅

列• terminal MyID :

(‘a’..’z’|’A’..’Z’)(‘a’..’z’|’A’..’Z’|’0’..’9’)*;

1004/11/2023 SEA 関西プロセス分科会

Page 11: Xtext&Xtend documents

©2014 Shintaro Hosoai 11

Xtend

04/11/2023 SEA 関西プロセス分科会

Page 12: Xtext&Xtend documents

©2014 Shintaro Hosoai

こんにちは Xtend!

• Xtend の記法は Java によく似ています.• メソッド定義は def キーワードで行います.

• class HelloWorld {

def static void main(String[] args) { println("Hello World") }}

// Generated Java Source Codeimport 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 コードに変換されます.

Page 13: Xtext&Xtend documents

©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)

Page 14: Xtext&Xtend documents

©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 と同じ

Page 15: Xtext&Xtend documents

©2014 Shintaro Hosoai

Field(1)

• 変数宣言の方法は3つ• Java と同じ型名 変数名

メソッド内の定義には使えない. var/val を利用すること

• var 変数名 :動的型.型推論で適切な型が振られる

• val 定数名 :定数宣言.こちらも明確な型指定は行わず,初回代入時の型に応じて決まる.

• アクセス指示子はデフォルトで Private

Page 16: Xtext&Xtend documents

©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 が生成される

1604/11/2023 SEA 関西プロセス分科会

Page 17: Xtext&Xtend documents

©2014 Shintaro Hosoai

Field(3)

• this• Java と同じ.省略可

• it :省略可能になる変数, Lambda と組合わせるといいらしい• val it = new Person• name = “Horst” : it.setName() が呼ばれる

• クラス変数,クラスメソッドへのアクセス• MyClass::myField• MyClass::myMethod()

1704/11/2023 SEA 関西プロセス分科会

Page 18: Xtext&Xtend documents

©2014 Shintaro Hosoai

Expression

• Xtend の構文はすべて式です.メソッド呼び出しはもちろん,ブロック,各種制御構文,メソッド定義もすべて値を返します.• 関数型もあります• val toUpperCaseFunction = [String s |

s.toUpperCase] ↑String.toUpperCase メソッドをtoUpperCaseFunction という変数に代入

1804/11/2023 SEA 関西プロセス分科会

Page 19: Xtext&Xtend documents

©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’ が代入される1904/11/2023 SEA 関西プロセス分科会

Page 20: Xtext&Xtend documents

©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

2004/11/2023 SEA 関西プロセス分科会

Page 21: Xtext&Xtend documents

©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 が返る)

2104/11/2023 SEA 関西プロセス分科会

Page 22: Xtext&Xtend documents

©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 の比較が行えます.

2204/11/2023 SEA 関西プロセス分科会

Page 23: Xtext&Xtend documents

©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 されています.

2304/11/2023 SEA 関西プロセス分科会

この O は Integer にCast されている

この O は String にCast されている

Page 24: Xtext&Xtend documents

©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

2404/11/2023 SEA 関西プロセス分科会

Page 25: Xtext&Xtend documents

©2014 Shintaro Hosoai

制御構文: for   Range との組み合わせ• 1 ~ 10 までループしたい場合どうするの?for (i : 1 ..10) print i10..1 で逆順も可能

Range Operations• 0..10 → 012345678910• 0..<10 → 0123456789• 10>..0 → 9876543210• 0 .. hoge.length といった表記も可

2504/11/2023 SEA 関西プロセス分科会

Page 26: Xtext&Xtend documents

©2014 Shintaro Hosoai

Methods(1)

• メソッド宣言は def で行う.デフォルトのアクセス指示子は public. protected, package, private指定可.• 返り値の型は省略可能.また Return も省略可

能,一番最後の式の値が返る.• static でクラスメソッドとすることも出来る

( Java と同じ)• 抽象メソッド

• 抽象クラスやインターフェイス内で, Body の無いメソッド定義は,抽象メソッドとなる.

abstract class MyAbstractClass() {  def String abstractMethod() // no body}

Page 27: Xtext&Xtend documents

©2014 Shintaro Hosoai

Methods(2)

• オーバーライドは def の代わりに override キーワードを用いて明示する.

• Exception• Java と同様

• Generic• Java と同様

• Method Call• Java と同様.引数がない場合は()省略可能

override String second(List<String> elements) {  elements.get(1)}

Page 28: Xtext&Xtend documents

©2014 Shintaro Hosoai

Lambda(1)

• [ Type variable | expression]• 以下, Java と Xtend の Lambda の実装比較Javafinal JTextField textField = new JTextField();textFeild.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ textField.text=“Something happend”); }});Xtendval textField = new JTextFieldtextField.addActionListener([ActionEvent e | textField.text = “Something happned”])

2804/11/2023 SEA 関西プロセス分科会

これも省略可

Page 29: Xtext&Xtend documents

©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• などなど.

2904/11/2023 SEA 関西プロセス分科会

Page 30: Xtext&Xtend documents

©2014 Shintaro Hosoai

Dispatch Methods(1)

• Java はコンパイル時の型に基づいて,メソッド呼び出しを決定する.このため,動的に Dispatch できない

  左図のような構造で, Dispatcher に          MyInterface a = MyClass1();  Dispatcher.dispatch(a);          とすると,呼び出しは不定となる          (コンパイルできない)

• 言語 AST(Abstract Syntax Tree) へのアクセスは,このような Dispatch Method が多用される

MyInterface

MyClass1 MyClass2

Dispatcherdispatch(MyClass1 a)dispatch(MyClass2 b)

Page 31: Xtext&Xtend documents

©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

Page 32: Xtext&Xtend documents

©2014 Shintaro Hosoai

Extension Methods

• クラスにメソッドを(仮想的に)付け加える• たとえば. String に toFirstUpper() メソッドを加えた

•第一引数を対象の型にしたメソッドは Extension Method として呼び出せる

• def extensionCall(String str, Hoge any){• str.doSomething()• }• “hello”.extensionCall(hogeAny) ← 呼び出す時は左辺の

オブジェクトが第一引数として渡される.

Page 33: Xtext&Xtend documents

©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)

Page 34: Xtext&Xtend documents

©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, 属性設定を行うコンストラクタ等を生成

Page 35: Xtext&Xtend documents

©2014 Shintaro Hosoai

Annotation Type Declaration

annotation MyAnnotation {  String[] value  boolean isTricky = false  int[] lotteryNumbers = #[ 42, 137 ]}

Page 36: Xtext&Xtend documents

©2014 Shintaro Hosoai

Enum Type Declaration

• Java と同じ?enum MyColor {  GREEN,  BLUE,  RED}

Page 37: Xtext&Xtend documents

©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が左辺,引数が右辺.ここでは自身と同じ型を引数に取っているが,異なる型でも可能.オーバーロードも可.

+二項演算子の呼び出し

Page 38: Xtext&Xtend documents

©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)

Page 39: Xtext&Xtend documents

©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)