ANTLR4で生成したファイルをjrubyから触ってみる
ANTLR4でパーサまでを生成してクラスをjarにして、扱うときはJRubyからアクセスしてみます。
あまり、ANTLR4には詳しく説明しません。まだよくわからいので。
準備
Java JDK7準備
以下のページからJDKを落とします。
http://www.oracle.com/technetwork/java/javase/downloads/index.html
Linuxならば、たとえば jdk-7u25-linux-x64.tar.gz を以下のように配置します。
% sudo mkdir /opt % cd /opt % sudo tar xzf ~/Download/jdk-7u25-linux-x64.tar.gz % cd % vi ~/.bashrc ... PATH=$PATH:/opt/jdk1.7.0_25/bin export PATH ... % source ~/.bashrc
javaとjavacとjarのコマンドがあることを確認します。(ex. % which javac)
JRubyの準備
http://jruby.org/
ここでは、jruby-1.7.4 が最新です。
antlr4の準備
まずは、antlr4をダウンロードします。
http://www.antlr4.org/download/
antlr-4.1-complete.jar
Hello.g4 記述
まずは、antlr4用のファイルを用意します。
手始めに、次に記載されているものをそのまま使います。
http://www.antlr.org/wiki/display/ANTLR4/Getting+Started+with+ANTLR+v4
- Hello.g4
// Define a grammar called Hello grammar Hello; r : 'hello' ID ; ID : [a-z]+ ; WS : [ \t\r\n]+ -> skip ;
コンパイル&jar化
- Javaコード生成
% java -jar ./antlr-4.1-complete.jar Hello.g4
Hello.tokens
HelloBaseListener.java
HelloLexer.java
HelloLexer.tokens
HelloListener.java
HelloParser.java
% javac -cp ./antlr-4.1-complete.jar Hello*.java
HelloBaseListener.class
HelloLexer.class
HelloListener.class
HelloParser$RContext.class
HelloParser.class
- Jar化
% mkdir Hello % mv *.class Hello % jar cf Hello.jar -C Hello .
Hello.jar
ここからRubyになります。
hello.rbでListenerコードを書く
同じディレクトリに、以下のファイルがあることを確認してください。
- antlr-4.1-complete.jar
- Hello.jar (作成したjarファイル)
- hello.rb
$:.unshift File.dirname(__FILE__) require 'java' require 'antlr-4.1-complete.jar' require 'Hello.jar' java_import "org.antlr.v4.runtime.ANTLRInputStream" java_import "org.antlr.v4.runtime.CommonTokenStream" class TestHelloListener include Java::Default::HelloListener def enterR(ctx) puts "enterR" end def exitR(ctx) puts "exitR" puts ctx.ID end def enterEveryRule(ctx) end def exitEveryRule(ctx) end def visitTerminal(node) end def visitErrorNode(node) end end input = ANTLRInputStream.new("hello aaa") lexer = Java::Default::HelloLexer.new(input) tokens = CommonTokenStream.new(lexer) parser = Java::Default::HelloParser.new(tokens) parser.addParseListener(TestHelloListener.new) parser.r
JRubyで実行
% jruby hello.rb enterR exitR aaa
JRuby+LWJGLでGLSLを試してみる
はじめてということで、手始めに動くかどうかだけ試します。
GLSLのfragment側で色を緑にしてみます。
$:.unshift File.dirname(__FILE__) require 'java' require 'lwjgl.jar' import org.lwjgl.opengl.Display import org.lwjgl.opengl.DisplayMode GL11 = org.lwjgl.opengl.GL11 GL20 = org.lwjgl.opengl.GL20 Display.setDisplayMode DisplayMode.new(300, 200) Display.setTitle "sample" Display.create v_str = <<VERT void main(void) { gl_Position = ftransform(); } VERT f_str = <<FRAG void main(void) { gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); } FRAG vid = GL20.glCreateShader(GL20::GL_VERTEX_SHADER) GL20.glShaderSource(vid, v_str) GL20.glCompileShader(vid) fid = GL20.glCreateShader(GL20::GL_FRAGMENT_SHADER) GL20.glShaderSource(fid, f_str) GL20.glCompileShader(fid) pid = GL20.glCreateProgram GL20.glAttachShader(pid, vid) GL20.glAttachShader(pid, fid) GL20.glLinkProgram(pid) linked = GL20.glGetProgram(pid, GL20::GL_LINK_STATUS) puts "linked err." if linked==GL11::GL_FALSE GL20.glUseProgram(pid) GL11.glClearColor 0.1,0.1,0.1,1 while !Display.isCloseRequested GL11.glClear GL11::GL_COLOR_BUFFER_BIT #GL11.glColor3d(1,0,0) GL11.glBegin GL11::GL_POLYGON GL11.glVertex2d(-0.5,-0.5) GL11.glVertex2d( 0.5,-0.5) GL11.glVertex2d( 0.5, 0.5) GL11.glVertex2d(-0.5, 0.5) GL11.glEnd Display.update end
とくに難しいことなく動きました。
めでたしめでたし。
とりあえず、ここまで。
JRubyFXでボタンを押してラベルに表示するのを試してみた
jrubyfxのsampleをいろいろあさって、ボタンを押したらラベル表示を更新する簡単な実装を試してみました。
- hello2.rb
require 'jrubyfx' class Hello < JRubyFX::Application def start(stage) with(stage, title: "sample", width: 200, height: 100) do layout_scene do vbox do label("hello", id: 'view') button("push") do set_on_action do stage["#view"].text = "pushed!!!" end end end end show end end end Hello.launch
「ボタンを押した」というアクションはset_on_actionで取得。
動作はそのブロック内に記述します。
ハッシュが使えるので、labelにidを振っておいて、ハッシュでラベルのテキストを更新します。
実行してみる
% jruby hello2.rb
swingよりもいい感じに書けます。とくにハッシュが使えるところが。
swingの知識がちょっとあればとりあえずなんとなく作れちゃいますね。
だんだん惚れてきました。
JRubyFXでまずは簡単なラベル表示をしてみた
まだ、JavaFXもよく理解していないですが、適当に実装してみます。
とりあえず、ラベルを使って文字列を表示するところから。
stage上に、まずはsceneを作って、その上にlabelとか貼っていけばよさそうです。
- hello.rb
require 'jrubyfx' class Hello < JRubyFX::Application def start(stage) with(stage) do layout_scene(200, 100) do label("hello") end show end end end Hello.launch
実行してみる
% jruby hello.rb
rubyっぽくブロックで書けるように工夫されているみたい。
慣れるまでがちょい時間かかりそう、
でも簡潔に書けるのは好ましい。
JRubyFX+FXMLのデモを動かしてみた
今日試した限りでは、JRubyFXがrubygemsに登録されているものは動かなくて、直接githubから持ってきて、ようやく動きました。
2003/05/20にjrubyfxのバージョン1.0.0なるものがrubygemsにアップされたようです。
おそらく、FXMLローダあたりのバグが解消されています。
準備
JRE7インストール先に、jfxrt.jar があることを確認しました。
C:\Program Files (x86)\Java\jre7\lib\jfxrt.jar
にあれば大丈夫だと思います。
次に、
- jrubyfx (1.0.0 以上)
- jrubyfx-fxmlloader
をインストール
% jruby -S gem install jrubyfx jrubyfx-fxmlloader
次に、JRubyFXのサンプルをgithubから落とします。
https://github.com/jruby/jrubyfx
Windowsならzipデータをダウンロードしてローカル環境に展開すればよいです。
Jruby+LWJGL+RubeusでOpenGLしてみる
$:.unshift File.dirname(__FILE__) require 'lwjgl.jar' require 'rubeus' Rubeus::Swing.irb import org.lwjgl.opengl.AWTGLCanvas GL = org.lwjgl.opengl.GL11 class MyCanvas < AWTGLCanvas def initialize end def initGL GL.glClearColor 0.0,0.0,0.0,1 GL.glViewport(0, 0, width, height) end def paintGL GL.glClear(GL::GL_COLOR_BUFFER_BIT) GL.glColor3d(1,1,0) GL.glBegin GL::GL_POLYGON GL.glVertex2d(-0.5,-0.5) GL.glVertex2d( 0.5,-0.5) GL.glVertex2d( 0.5, 0.5) GL.glVertex2d(-0.5, 0.5) GL.glEnd swapBuffers repaint end end JFrame.new do |f| f.layout = BorderLayout.new canvas = MyCanvas.new f.size = "400x300" f.visible = true end