rsyntaxtree 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ pkg/
2
+ tmp/
3
+ doc/
4
+ .DS_Store
5
+ Gemfile.lock
6
+
7
+ *.bak
8
+ *.~
9
+
10
+
11
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in rsyntaxtree.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # RSyntaxTree: yet another syntax tree generator in Ruby
2
+
3
+ RSyntaxTree is a graphical syntax tree generator written in the Ruby programming language. It is basically a port of [phpSyntaxTree](http://ironcreek.net/phpsyntaxtree/) created by André Eisenbach.
4
+
5
+ While phpSyntaxTree does not accept **multi-byte characters** as those in Chinese, Japanese, and Korean, RSyntaxTree handles text of any language as long as encoded in UTF-8 and fonts have been installed. Additionally, RSyntaxTree can output **symmetrized** tree diagrams, a functionality that is not implemented in phpSyntaxTree.
6
+
7
+ RSyntaxTree consists of an easy-to-use command-line app and a web-based interfaces made with [Sinatra](http://www.sinatrarb.com) web framework.
8
+
9
+ ### Web Interface
10
+
11
+ Working web interface of a previous version of RSyntaxTree is available at http://yohasebe.com/rsyntaxtree . New version will be deployed soon.
12
+
13
+ ### Installation
14
+
15
+ `# gem install rsyntaxtree`
16
+
17
+ ### Usage
18
+
19
+ For the web interface, see Usage section in http://yohasebe.com/rsyntaxtree .
20
+
21
+ For the command-line interface, type `$rsyntaxtree -h` after installation. Here's what you get:
22
+
23
+ RSyntaxTree, (linguistic) syntax tree generator written in Ruby.
24
+
25
+ Usage:
26
+ rsyntaxtree [options] "[NP [N bracket] [NP notation]]]"
27
+ where [options] are:
28
+ --outdir, -o <s>: Output directory (default: present working directory) (default: ./)
29
+ --format, -f <s>: Output format: png or svg (default: png)
30
+ --leafstyle, -l <s>: visual style of tree leaves: triangle, bar, or nothing (default: triangle)
31
+ --fontstyle, -n <s>: Font style: sans-serif, serif, jp-gothic, jp-mincho, cjk (default: cjk)
32
+ --font, -t <s>: Path to a ttf font used to generate tree
33
+ --fontsize, -s <i>: Font size: 8-20 (default: 16)
34
+ --color, -c <s>: Color text and bars: on or off (default: on)
35
+ --symmetrize, -y <s>: Generate symmetrical, balanced tree: on or off (default: on)
36
+ --autosub, -a <s>: Put subscript numbers to nodes: on or off (default: off)
37
+ --version, -v: Print version and exit
38
+ --help, -h: Show this message
39
+
40
+ ### Development
41
+
42
+ For the latest updates and downloads please visit http://github.com/yohasebe/rsyntaxtree
43
+
44
+ ### Author
45
+
46
+ Yoichiro Hasebe yohasebe@gmail.com
47
+
48
+ ### License
49
+
50
+ RSyntaxTree is distributed under the [MIT License](http://www.opensource.org/licenses/mit-license.php).
51
+
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/app.rb ADDED
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ require 'sinatra'
5
+ require 'haml'
6
+ require 'base64'
7
+ require './helpers/helpers'
8
+ require './lib/rsyntaxtree'
9
+
10
+ include Helpers
11
+
12
+ configure do
13
+ enable :sessions
14
+ end
15
+
16
+ get '/' do #
17
+ haml :index
18
+ end
19
+
20
+ post '/check' do
21
+ data = params["data"]
22
+ result = RSGenerator.check_data(data)
23
+ return result ? "true" : "false"
24
+ end
25
+
26
+ get '/draw_png' do
27
+ rs_generator = RSGenerator.new(params)
28
+ content_type "image/png"
29
+ rs_generator.draw_tree
30
+ end
31
+
32
+ post '/draw_png' do
33
+ basename = "syntree.png"
34
+ rs_generator = RSGenerator.new(params)
35
+ png_blob = rs_generator.draw_png
36
+ response.headers['content_type'] = "image/png"
37
+ response.headers['content_length'] = png_blob.size.to_s
38
+ response.headers['content_disposition'] = "inline" + %(; filename="#{basename}")
39
+ Base64.encode64(png_blob)
40
+ end
41
+
42
+ post '/download_svg' do
43
+ content_type 'image/svg+xml'
44
+ attachment 'syntree.svg'
45
+ rs_generator = RSGenerator.new(params)
46
+ rs_generator.draw_svg
47
+ end
48
+
49
+ post '/download_pdf' do
50
+ content_type 'applcation/pdf'
51
+ attachment 'syntree.pdf'
52
+ rs_generator = RSGenerator.new(params)
53
+ rs_generator.draw_pdf
54
+ end
55
+
data/bin/rsyntaxtree ADDED
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ $LOAD_PATH << File.join( File.dirname(__FILE__), '../lib')
5
+
6
+ require 'rsyntaxtree'
7
+ require 'trollop'
8
+
9
+ opts = Trollop::options do
10
+ version "RSyntaxTree #{RSyntaxTree::VERSION} (c) 2012 Yoichiro Hasebe"
11
+ banner <<-EOS
12
+ RSyntaxTree, (linguistic) syntax tree generator written in Ruby.
13
+
14
+ Usage:
15
+ rsyntaxtree [options] "[NP [N bracket] [NP notation]]]"
16
+ where [options] are:
17
+ EOS
18
+
19
+ opt :outdir, "Output directory (default: present working directory)",
20
+ :default => "./"
21
+ opt :format, "Output format: png, pdf, or svg",
22
+ :default => "png"
23
+ opt :leafstyle, "visual style of tree leaves: triangle, bar, or nothing",
24
+ :default => "triangle"
25
+ opt :fontstyle, "Font style: sans-serif, serif, jp-gothic, jp-mincho, cjk",
26
+ :default => "cjk"
27
+ opt :font, "Path to a ttf font used to generate tree", :type => String
28
+ opt :fontsize, "Font size: 8-20",
29
+ :default => 16
30
+ opt :color, "Color text and bars: on or off",
31
+ :default => "on"
32
+ opt :symmetrize, "Generate symmetrical, balanced tree: on or off",
33
+ :default => "on"
34
+ opt :autosub, "Put subscript numbers to nodes: on or off",
35
+ :default => "off"
36
+ end
37
+
38
+ Trollop::die :outdir, "must be an exsting directory path" unless FileTest::directory?(opts[:outdir])
39
+ Trollop::die :format, "must be png or svg" unless /\A(png|pdf|svg)\z/ =~ opts[:format]
40
+ Trollop::die :leafstyle, "must be triangle, bar, or nothing" unless /\A(triangle|bar|nothing)\z/ =~ opts[:leafstyle]
41
+ Trollop::die :fontstyle, "must be sans-serif, serif, jp-gothic, jp-mincho, or cjk" unless /\A(sans\-serif|serif|jp\-gothic|jp\-mincho|cjk)\z/ =~ opts[:fontstyle]
42
+ Trollop::die :font, "must be path to an existing ttf font" if opts[:font] && !File::exists?(opts[:font])
43
+ Trollop::die :fontsize, "must be in the range 8-20" unless opts[:fontsize] >= 8 && opts[:fontsize] <= 20
44
+ Trollop::die :color, "must be either on or off" unless /\A(on|off)\z/ =~ opts[:color]
45
+ Trollop::die :symmetrize, "must be either on or off" unless /\A(on|off)\z/ =~ opts[:symmetrize]
46
+ Trollop::die :autosub, "must be either on or off" unless /\A(on|off)\z/ =~ opts[:autosub]
47
+
48
+ string_opts = {}
49
+ opts.each do |key, value|
50
+ string_opts[key.to_s] = value unless key == :font && !value
51
+ end
52
+
53
+ data = ARGV[0]
54
+
55
+ unless data && RSGenerator.check_data(data)
56
+ puts "bracket notation given is invalid"
57
+ exit
58
+ end
59
+
60
+ string_opts["data"] = data
61
+
62
+ rsg = RSGenerator.new(string_opts)
63
+ ext = string_opts["format"]
64
+ outfile = File.new(File.expand_path(string_opts["outdir"]) + "/syntree." + ext, "wb")
65
+ case ext
66
+ when "png"
67
+ outfile.write rsg.draw_png
68
+ when "pdf"
69
+ outfile.write rsg.draw_pdf
70
+ when "svg"
71
+ outfile.write rsg.draw_svg
72
+ end
73
+ outfile.close
data/config.ru ADDED
@@ -0,0 +1,7 @@
1
+ path = File.expand_path("../", __FILE__)
2
+
3
+ require 'rubygems'
4
+ require 'sinatra'
5
+ require "#{path}/app"
6
+
7
+ run Sinatra::Application
Binary file
Binary file
data/fonts/ipagp.ttf ADDED
Binary file
data/fonts/ipamp.ttf ADDED
Binary file
Binary file
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ module Helpers
5
+ def link_to(name, location, alternative = false)
6
+ if alternative and alternative[:condition]
7
+ "<a href=#{alternative[:location]}>#{alternative[:name]}</a>"
8
+ else
9
+ "<a href=#{location}>#{name}</a>"
10
+ end
11
+ end
12
+
13
+ def multibyte?(text)
14
+ result = false
15
+ text.strip.split(//).each do |chr|
16
+ unless /([!-~]|\s)/ =~ chr
17
+ result = true; break
18
+ end
19
+ end
20
+ return result
21
+ end
22
+ end
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #==========================
5
+ # rsyntaxtree.rb
6
+ #==========================
7
+ #
8
+ # Facade of rsyntaxtree library. When loaded by a driver script, it does all
9
+ # the necessary 'require' to use the library.
10
+ #
11
+ # This file is part of RSyntaxTree, which is a ruby port of Andre Eisenbach's
12
+ # excellent program phpSyntaxTree.
13
+ # Copyright (c) 2007-2009 Yoichiro Hasebe <yohasebe@gmail.com>
14
+ # Copyright (c) 2003-2004 Andre Eisenbach <andre@ironcreek.net>
15
+ #
16
+ # This program is free software; you can redistribute it and/or modify
17
+ # it under the terms of the GNU General Public License as published by
18
+ # the Free Software Foundation; either version 2 of the License, or
19
+ # (at your option) any later version.
20
+ #
21
+ # This program is distributed in the hope that it will be useful,
22
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
23
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24
+ # GNU General Public License for more details.
25
+ #
26
+ # You should have received a copy of the GNU General Public License
27
+ # along with this program; if not, write to the Free Software
28
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29
+
30
+ $LOAD_PATH << File.join( File.dirname(__FILE__), 'rsyntaxtree')
31
+ $LOAD_PATH << File.join( File.dirname(__FILE__), '../helpers')
32
+
33
+ require 'uri'
34
+ require 'imgutils'
35
+ require 'element'
36
+ require 'elementlist'
37
+ require 'string_parser'
38
+ require 'tree_graph'
39
+ require 'svg_graph'
40
+ require 'error_message'
41
+ require 'helpers'
42
+ require 'version'
43
+
44
+ FONT_DIR = File.expand_path(File.dirname(__FILE__) + "/../fonts")
45
+
46
+ class RSGenerator
47
+ include Helpers
48
+ def initialize(params = {})
49
+ new_params = {}
50
+ params.each do |key, value|
51
+ case key
52
+ when "data"
53
+ data = URI.unescape(value)
54
+ data = data.gsub('-AMP-', '&').gsub('-PRIME-', "'").gsub('-SCOLON-', ';')
55
+ new_params[key] = data
56
+ when "symmetrize", "color", "autosub"
57
+ new_params[key] = value == "on"? true : false
58
+ when "fontsize"
59
+ new_params[key] = value.to_i
60
+ when "fontstyle"
61
+ if value == "sans-serif"
62
+ new_params["font"] = FONT_DIR + "/DroidSans.ttf"
63
+ elsif value == "serif"
64
+ new_params["font"] = FONT_DIR + "/DroidSerif-Regular.ttf"
65
+ elsif value == "jp-gothic"
66
+ new_params["font"] = FONT_DIR + "/ipagp.ttf"
67
+ elsif value == "jp-mincho"
68
+ new_params["font"] = FONT_DIR + "/ipamp.ttf"
69
+ elsif value == "cjk"
70
+ new_params["font"] = FONT_DIR + "/wqy-zenhei.ttf"
71
+ end
72
+ else
73
+ new_params[key] = value
74
+ end
75
+ end
76
+
77
+
78
+ @params = {
79
+ "symmetrize" => true,
80
+ "color" => true,
81
+ "autosub" => false,
82
+ "fontsize" => 18,
83
+ "format" => "png",
84
+ "leafstyle" => "triangle",
85
+ "font" => FONT_DIR + "/ipagp.ttf",
86
+ "filename" => "syntree",
87
+ "data" => "",
88
+ }
89
+
90
+ @params.merge! new_params
91
+ end
92
+
93
+ def self.check_data(text)
94
+ # StringParser.validate_text(text)
95
+ sp = StringParser.new(text)
96
+ sp.valid?
97
+ end
98
+
99
+ def draw_png
100
+ @params["format"] = "png"
101
+ draw_tree
102
+ end
103
+
104
+ def draw_pdf
105
+ @params["format"] = "pdf"
106
+ draw_tree
107
+ end
108
+
109
+ def draw_svg
110
+ @params["format"] = "svg"
111
+ draw_svg
112
+ end
113
+
114
+ def draw_tree
115
+ sp = StringParser.new(@params["data"])
116
+ sp.parse
117
+ sp.auto_subscript if @params["autosub"]
118
+ elist = sp.get_elementlist
119
+ graph = TreeGraph.new(elist,
120
+ @params["symmetrize"], @params["color"], @params["leafstyle"], @params["font"], @params["fontsize"], @params["format"])
121
+ graph.to_blob(@params["format"])
122
+ end
123
+
124
+ def draw_svg
125
+ sp = StringParser.new(@params["data"].gsub('&', '&amp;'))
126
+ sp.parse
127
+ sp.auto_subscript if @params["autosub"]
128
+ elist = sp.get_elementlist
129
+ graph = SVGGraph.new(elist,
130
+ @params["symmetrize"], @params["color"], @params["leafstyle"], @params["font"], @params["fontsize"])
131
+ graph.svg_data
132
+ end
133
+ end
134
+
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #==========================
5
+ # element.rb
6
+ #==========================
7
+ #
8
+ # Aa class that represents a basic tree element, either node or leaf.
9
+ #
10
+ # This file is part of RSyntaxTree, which is a ruby port of Andre Eisenbach's
11
+ # excellent program phpSyntaxTree.
12
+ #
13
+ # Copyright (c) 2007-2009 Yoichiro Hasebe <yohasebe@gmail.com>
14
+ # Copyright (c) 2003-2004 Andre Eisenbach <andre@ironcreek.net>
15
+ #
16
+ # This program is free software; you can redistribute it and/or modify
17
+ # it under the terms of the GNU General Public License as published by
18
+ # the Free Software Foundation; either version 2 of the License, or
19
+ # (at your option) any later version.
20
+ #
21
+ # This program is distributed in the hope that it will be useful,
22
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
23
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24
+ # GNU General Public License for more details.
25
+ #
26
+ # You should have received a copy of the GNU General Public License
27
+ # along with this program; if not, write to the Free Software
28
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29
+
30
+ ETYPE_UNDEFINED = 0
31
+ ETYPE_NODE = 1
32
+ ETYPE_LEAF = 2
33
+
34
+ class Element
35
+
36
+ attr_accessor :id, :parent, :type, :content, :level, :width, :indent
37
+ def initialize(id = 0, parent = 0, content = NULL, level = 0, type = ETYPE_LEAF)
38
+ @id = id # Unique element id
39
+ @parent = parent # Parent element id
40
+ @type = type # Element type
41
+ @content = content.strip # The actual element content
42
+ @level = level # Element level in the tree (0=top etc...)
43
+ @width = 0 # Width of the element in pixels
44
+ @indent = 0 # Drawing offset
45
+ end
46
+
47
+ # Debug helper function
48
+ def dump
49
+ printf( "ID : %d\n", @id );
50
+ printf( "Parent : %d\n", @parent );
51
+ printf( "Level : %d\n", @level );
52
+ printf( "Type : %d\n", @type );
53
+ printf( "Width : %d\n", @width );
54
+ printf( "Indent : %d\n", @indent );
55
+ printf( "Content : %s\n\n", @content );
56
+ end
57
+
58
+ end
@@ -0,0 +1,137 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #==========================
5
+ # elementlist.rb
6
+ #==========================
7
+ #
8
+ # Contains a list of unordered tree elements with a defined parent
9
+ #
10
+ # This file is part of RSyntaxTree, which is a ruby port of Andre Eisenbach's
11
+ # excellent program phpSyntaxTree.
12
+ #
13
+ # Copyright (c) 2007-2009 Yoichiro Hasebe <yohasebe@gmail.com>
14
+ # Copyright (c) 2003-2004 Andre Eisenbach <andre@ironcreek.net>
15
+ #
16
+ # This program is free software; you can redistribute it and/or modify
17
+ # it under the terms of the GNU General Public License as published by
18
+ # the Free Software Foundation; either version 2 of the License, or
19
+ # (at your option) any later version.
20
+ #
21
+ # This program is distributed in the hope that it will be useful,
22
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
23
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24
+ # GNU General Public License for more details.
25
+ #
26
+ # You should have received a copy of the GNU General Public License
27
+ # along with this program; if not, write to the Free Software
28
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29
+
30
+ require 'element'
31
+
32
+ class ElementList
33
+
34
+ attr_accessor :elements, :iterator
35
+ def initialize
36
+ @elements = Array.new # The element array
37
+ @iterator = -1 # Iterator index (used for get_first / get_next)
38
+ end
39
+
40
+ def add(element)
41
+ @elements << element
42
+ if(element.parent != 0)
43
+ parent = get_id(element.parent)
44
+ parent.type = ETYPE_NODE
45
+ end
46
+ end
47
+
48
+ def get_first
49
+ if(@elements.length == 0)
50
+ return nil
51
+ else
52
+ @iterator = 0
53
+ return @elements[@iterator]
54
+ end
55
+ end
56
+
57
+ def get_next
58
+ @iterator += 1
59
+ if @elements[@iterator]
60
+ return @elements[@iterator]
61
+ else
62
+ return nil
63
+ end
64
+ end
65
+
66
+ def get_id(id)
67
+ @elements.each do |element|
68
+ if(element.id == id)
69
+ return element
70
+ end
71
+ end
72
+ return nil;
73
+ end
74
+
75
+ def get_elements
76
+ @elements
77
+ end
78
+
79
+ def get_child_count(id)
80
+ get_children(id).length
81
+ end
82
+
83
+ def get_children(id)
84
+ children = Array.new
85
+ @elements.each do |element|
86
+ if(element.parent == id)
87
+ children << element.id
88
+ end
89
+ end
90
+ children
91
+ end
92
+
93
+ def get_element_width(id)
94
+ element = get_id(id)
95
+ if element
96
+ return element.width
97
+ else
98
+ return -1;
99
+ end
100
+ end
101
+
102
+ def set_element_width(id, width)
103
+ element = get_id(id)
104
+ if element
105
+ element.width = width
106
+ end
107
+ end
108
+
109
+ def get_indent(id)
110
+ element = get_id(id)
111
+ if element
112
+ return element.indent
113
+ else
114
+ return -1
115
+ end
116
+ end
117
+
118
+ def set_indent(id, indent)
119
+ element = get_id(id)
120
+ if element
121
+ element.indent = indent
122
+ end
123
+ end
124
+
125
+ def get_level_height
126
+ maxlevel = 0
127
+ @elements.each do |element|
128
+ level = element.level
129
+ if(level > maxlevel)
130
+ maxlevel = level
131
+ end
132
+ end
133
+ return maxlevel + 1;
134
+ end
135
+
136
+ end
137
+