rsyntaxtree 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+