radius-ts 1.1.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +22 -17
- data/LICENSE +19 -0
- data/README.rdoc +7 -25
- data/Rakefile +8 -34
- data/VERSION +1 -0
- data/lib/radius/parser.rb +17 -6
- data/lib/radius/parser/JavaScanner$Flavor.class +0 -0
- data/lib/radius/parser/JavaScanner$Tag.class +0 -0
- data/lib/radius/parser/JavaScanner.class +0 -0
- data/lib/radius/parser/JavaScanner.java +634 -0
- data/lib/radius/parser/JavaScanner.rl +179 -0
- data/lib/radius/parser/java_scanner.jar +0 -0
- data/lib/radius/parser/scanner.rb +63 -62
- data/lib/radius/parser/scanner.rl +2 -1
- data/lib/radius/parser/squiggle_scanner.rl +125 -0
- data/lib/radius/utility.rb +10 -0
- data/lib/radius/version.rb +5 -11
- data/tasks/jeweler.rake +23 -0
- data/tasks/rdoc.rake +13 -0
- data/tasks/rubinius.rake +4 -0
- data/tasks/scan.rake +25 -2
- data/tasks/test.rake +7 -0
- data/test/benchmarks.rb +35 -0
- data/test/context_test.rb +1 -1
- data/test/multithreaded_test.rb +41 -10
- data/test/parser_test.rb +6 -1
- data/test/quickstart_test.rb +2 -2
- data/test/squiggle_test.rb +6 -1
- data/test/test_helper.rb +5 -1
- data/test/utility_test.rb +30 -0
- metadata +35 -26
- data/Manifest.txt +0 -22
@@ -0,0 +1,125 @@
|
|
1
|
+
%%{
|
2
|
+
machine parser;
|
3
|
+
|
4
|
+
|
5
|
+
# action _prefix { mark_pfx = p }
|
6
|
+
# action prefix {
|
7
|
+
# if data[mark_pfx..p-1] != @prefix
|
8
|
+
# @nodes.last << data[mark_pfx-1..p]
|
9
|
+
# fbreak;
|
10
|
+
# end
|
11
|
+
# }
|
12
|
+
action _starttag { mark_stg = p }
|
13
|
+
action starttag { @starttag = data[mark_stg..p-1] }
|
14
|
+
action _attr { mark_attr = p }
|
15
|
+
action attr {
|
16
|
+
@attrs[@nat] = @vat
|
17
|
+
}
|
18
|
+
|
19
|
+
action prematch {
|
20
|
+
@prematch_end = p
|
21
|
+
@prematch = data[0..p] if p > 0
|
22
|
+
}
|
23
|
+
|
24
|
+
action _nameattr { mark_nat = p }
|
25
|
+
action nameattr { @nat = data[mark_nat..p-1] }
|
26
|
+
action _valattr { mark_vat = p }
|
27
|
+
action valattr { @vat = data[mark_vat..p-1] }
|
28
|
+
|
29
|
+
action opentag { @flavor = :open }
|
30
|
+
action selftag { @flavor = :self }
|
31
|
+
action closetag { @flavor = :close }
|
32
|
+
|
33
|
+
action stopparse {
|
34
|
+
@cursor = p;
|
35
|
+
fbreak;
|
36
|
+
}
|
37
|
+
|
38
|
+
|
39
|
+
Closeout := empty;
|
40
|
+
|
41
|
+
# words
|
42
|
+
# PrefixChar = [\-A-Za-z0-9._?] ;
|
43
|
+
NameChar = [\-A-Za-z0-9._:?] ;
|
44
|
+
TagName = NameChar+ >_starttag %starttag;
|
45
|
+
# Prefix = PrefixChar+ >_prefix %prefix;
|
46
|
+
|
47
|
+
# Name = Prefix ":" TagName;
|
48
|
+
|
49
|
+
NameAttr = NameChar+ >_nameattr %nameattr;
|
50
|
+
Q1Char = ( "\\\'" | [^'] ) ;
|
51
|
+
Q1Attr = Q1Char* >_valattr %valattr;
|
52
|
+
Q2Char = ( "\\\"" | [^"] ) ;
|
53
|
+
Q2Attr = Q2Char* >_valattr %valattr;
|
54
|
+
|
55
|
+
Attr = NameAttr space* "=" space* ('"' Q2Attr '"' | "'" Q1Attr "'") space* >_attr %attr;
|
56
|
+
Attrs = (space+ Attr* | empty);
|
57
|
+
|
58
|
+
CloseTrailer = "/}" %selftag;
|
59
|
+
OpenTrailer = "}" %opentag;
|
60
|
+
|
61
|
+
Trailer = (OpenTrailer | CloseTrailer);
|
62
|
+
|
63
|
+
# OpenOrSelfTag = Name Attrs? Trailer;
|
64
|
+
OpenOrSelfTag = TagName Attrs? Trailer;
|
65
|
+
# CloseTag = "/" Name space* "}" %closetag;
|
66
|
+
CloseTag = "/" TagName space* "}" %closetag;
|
67
|
+
|
68
|
+
SomeTag = '{' space* (OpenOrSelfTag | CloseTag);
|
69
|
+
|
70
|
+
main := |*
|
71
|
+
SomeTag => {
|
72
|
+
tag = {:prefix=>@prefix, :name=>@starttag, :flavor => @flavor, :attrs => @attrs}
|
73
|
+
@prefix = nil
|
74
|
+
@name = nil
|
75
|
+
@flavor = :tasteless
|
76
|
+
@attrs = {}
|
77
|
+
@nodes << tag << ''
|
78
|
+
fbreak;
|
79
|
+
};
|
80
|
+
any => {
|
81
|
+
@nodes.last << data[p]
|
82
|
+
@tagstart = p
|
83
|
+
};
|
84
|
+
*|;
|
85
|
+
}%%
|
86
|
+
|
87
|
+
module Radius
|
88
|
+
class SquiggleScanner
|
89
|
+
def operate(prefix, data)
|
90
|
+
buf = ""
|
91
|
+
csel = ""
|
92
|
+
@prematch = ''
|
93
|
+
@starttag = nil
|
94
|
+
@attrs = {}
|
95
|
+
@flavor = :tasteless
|
96
|
+
@cursor = 0
|
97
|
+
@tagstart = 0
|
98
|
+
@nodes = ['']
|
99
|
+
remainder = data.dup
|
100
|
+
|
101
|
+
until remainder.length == 0
|
102
|
+
p = perform_parse(prefix, remainder)
|
103
|
+
remainder = remainder[p..-1]
|
104
|
+
end
|
105
|
+
|
106
|
+
return @nodes
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
def perform_parse(prefix, data)
|
111
|
+
stack = []
|
112
|
+
p = 0
|
113
|
+
ts = 0
|
114
|
+
te = 0
|
115
|
+
act = 0
|
116
|
+
eof = data.length
|
117
|
+
|
118
|
+
@prefix = prefix
|
119
|
+
%% write data;
|
120
|
+
%% write init;
|
121
|
+
%% write exec;
|
122
|
+
return p
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
data/lib/radius/utility.rb
CHANGED
@@ -26,5 +26,15 @@ module Radius
|
|
26
26
|
underscored_string.split('_').each { |part| string << part.capitalize }
|
27
27
|
string
|
28
28
|
end
|
29
|
+
|
30
|
+
if RUBY_VERSION[0,3] == '1.8'
|
31
|
+
def self.array_to_s(c)
|
32
|
+
c.to_s
|
33
|
+
end
|
34
|
+
else
|
35
|
+
def self.array_to_s(c)
|
36
|
+
c.map{|x| x.is_a?(Array) ? array_to_s(x) : x.to_s }.join
|
37
|
+
end
|
38
|
+
end
|
29
39
|
end
|
30
40
|
end
|
data/lib/radius/version.rb
CHANGED
@@ -1,14 +1,8 @@
|
|
1
|
-
module Radius
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
class << self
|
8
|
-
def to_s
|
9
|
-
[Major, Minor, Tiny].join('.')
|
10
|
-
end
|
11
|
-
alias :to_str :to_s
|
1
|
+
module Radius #:nodoc:
|
2
|
+
def self.version
|
3
|
+
@version ||= begin
|
4
|
+
filename = File.join(File.dirname(__FILE__), '..', '..', 'VERSION')
|
5
|
+
IO.read(filename).strip
|
12
6
|
end
|
13
7
|
end
|
14
8
|
end
|
data/tasks/jeweler.rake
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
begin
|
2
|
+
require 'jeweler'
|
3
|
+
Jeweler::Tasks.new do |gem|
|
4
|
+
gem.name = "radius-ts"
|
5
|
+
gem.summary = "A tag-based templating language for Ruby. (JRuby Extensions)"
|
6
|
+
gem.description = "Radius is a powerful tag-based template language for Ruby inspired by the template languages used in MovableType and TextPattern. It uses tags similar to XML, but can be used to generate any form of plain text (HTML, e-mail, etc...). This is likely the last release before merging back upstream to jlong/radius."
|
7
|
+
gem.email = "todd@rubidine.com"
|
8
|
+
gem.homepage = "http://github.com/xtoddx/radius-ts"
|
9
|
+
gem.authors = [
|
10
|
+
"John W. Long (me@johnwlong.com)",
|
11
|
+
"David Chelimsky (dchelimsky@gmail.com)",
|
12
|
+
"Bryce Kerley (bkerley@brycekerley.net)",
|
13
|
+
"Todd Willey <todd@rubidine.com>"
|
14
|
+
]
|
15
|
+
gem.files = FileList["[A-Z]*", "{bin,lib,tasks,test}/**/*"].exclude("tmp")
|
16
|
+
gem.extra_rdoc_files = ['README.rdoc', 'QUICKSTART.rdoc', 'LICENSE', 'CHANGELOG']
|
17
|
+
gem.add_development_dependency('RedCloth')
|
18
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
19
|
+
end
|
20
|
+
Jeweler::GemcutterTasks.new
|
21
|
+
rescue LoadError
|
22
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
23
|
+
end
|
data/tasks/rdoc.rake
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rake/rdoctask'
|
2
|
+
Rake::RDocTask.new do |rdoc|
|
3
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
4
|
+
|
5
|
+
rdoc.rdoc_dir = 'rdoc'
|
6
|
+
rdoc.title = "Radius #{version}"
|
7
|
+
rdoc.main = "README.rdoc"
|
8
|
+
rdoc.rdoc_files.include('*.rdoc')
|
9
|
+
rdoc.rdoc_files.include('LICENSE')
|
10
|
+
rdoc.rdoc_files.include('CHANGELOG')
|
11
|
+
rdoc.rdoc_files.include('QUICKSTART.rdoc')
|
12
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
13
|
+
end
|
data/tasks/rubinius.rake
ADDED
data/tasks/scan.rake
CHANGED
@@ -2,11 +2,12 @@ namespace :scan do
|
|
2
2
|
desc 'Generate the parsers'
|
3
3
|
task 'build' => [
|
4
4
|
'lib/radius/parser/scanner.rb',
|
5
|
-
'lib/radius/parser/squiggle_scanner.rb'
|
5
|
+
'lib/radius/parser/squiggle_scanner.rb',
|
6
|
+
'lib/radius/parser/java_scanner.jar'
|
6
7
|
]
|
7
8
|
|
8
9
|
desc 'Generate a PDF state graph from the parsers'
|
9
|
-
task 'graph' => ['doc/scanner.pdf', 'doc/squiggle_scanner.
|
10
|
+
task 'graph' => ['doc/scanner.pdf', 'doc/squiggle_scanner.pdf']
|
10
11
|
|
11
12
|
desc 'turn the scanner.rl file into a ruby file'
|
12
13
|
file 'lib/radius/parser/scanner.rb' => 'lib/radius/parser/scanner.rl' do |t|
|
@@ -24,6 +25,28 @@ namespace :scan do
|
|
24
25
|
end
|
25
26
|
end
|
26
27
|
|
28
|
+
desc 'package JavaScanner into a jar file'
|
29
|
+
file 'lib/radius/parser/java_scanner.jar' => 'lib/radius/parser/JavaScanner.class' do
|
30
|
+
cd 'lib' do
|
31
|
+
sh "jar -cf radius/parser/java_scanner.jar radius/parser/*.class"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
desc 'turn the JavaScanner.java file into a java class file'
|
36
|
+
file 'lib/radius/parser/JavaScanner.class' => 'lib/radius/parser/JavaScanner.java' do |t|
|
37
|
+
cd 'lib' do
|
38
|
+
jruby_path = ENV['JRUBY_HOME'] || '/usr/local/jruby/current'
|
39
|
+
sh "javac -cp #{jruby_path}/lib/jruby.jar radius/parser/JavaScanner.java"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
desc 'turn the JavaScanner.rl file into a java source file'
|
44
|
+
file 'lib/radius/parser/JavaScanner.java' => 'lib/radius/parser/JavaScanner.rl' do |t|
|
45
|
+
cd 'lib/radius/parser' do
|
46
|
+
sh "ragel -J -F1 JavaScanner.rl"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
27
50
|
desc 'pdf of the ragel scanner'
|
28
51
|
file 'doc/scanner.pdf' => 'lib/radius/parser/scanner.dot' do |t|
|
29
52
|
cd 'lib/radius/parser' do
|
data/tasks/test.rake
ADDED
data/test/benchmarks.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
$: << File.join(File.dirname(__FILE__), '..', 'lib')
|
2
|
+
require 'radius'
|
3
|
+
|
4
|
+
if RUBY_PLATFORM == 'java'
|
5
|
+
require 'java'
|
6
|
+
require 'radius/parser/jscanner'
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'benchmark'
|
10
|
+
|
11
|
+
document = <<EOF
|
12
|
+
Before it all
|
13
|
+
<r:foo>
|
14
|
+
Middle Top
|
15
|
+
<r:bar />
|
16
|
+
Middle Bottom
|
17
|
+
</r:foo>
|
18
|
+
After it all
|
19
|
+
EOF
|
20
|
+
|
21
|
+
amount = 1000
|
22
|
+
|
23
|
+
Benchmark.bmbm do |bm|
|
24
|
+
bm.report('vanilla') do
|
25
|
+
scanner = Radius::Scanner.new(:scanner => Radius::Scanner)
|
26
|
+
amount.times { scanner.operate('r', document) }
|
27
|
+
end
|
28
|
+
|
29
|
+
if RUBY_PLATFORM == 'java'
|
30
|
+
bm.report('JavaScanner') do
|
31
|
+
scanner = Radius::JavaScanner.new(JRuby.runtime)
|
32
|
+
amount.times { scanner.operate('r', document) }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/test/context_test.rb
CHANGED
data/test/multithreaded_test.rb
CHANGED
@@ -12,18 +12,49 @@ class MultithreadTest < Test::Unit::TestCase
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
15
|
+
if RUBY_PLATFORM == 'java'
|
16
|
+
require 'java'
|
17
|
+
def test_runs_multithreaded
|
18
|
+
lock = java.lang.String.new("lock")
|
19
|
+
threads = []
|
20
|
+
1000.times do |t|
|
21
|
+
thread = Thread.new do
|
22
|
+
parser = Radius::Parser.new(@context, :tag_prefix => 'r')
|
23
|
+
parser.context.globals.thread_id = Thread.current.object_id
|
24
|
+
expected = "#{Thread.current.object_id} / "+
|
25
|
+
"#{parser.context.globals.object_id}"
|
26
|
+
actual = parser.parse('<r:thread />')
|
27
|
+
assert_equal expected, actual
|
28
|
+
end
|
29
|
+
lock.synchronized do
|
30
|
+
threads << thread
|
31
|
+
end
|
32
|
+
end
|
33
|
+
lock.synchronized do
|
34
|
+
threads.each{|t| t.join }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
else
|
38
|
+
def test_runs_multithreaded
|
39
|
+
threads = []
|
40
|
+
mute = Mutex.new
|
41
|
+
1000.times do |t|
|
42
|
+
thread = Thread.new do
|
43
|
+
parser = Radius::Parser.new(@context, :tag_prefix => 'r')
|
44
|
+
parser.context.globals.thread_id = Thread.current.object_id
|
45
|
+
expected = "#{Thread.current.object_id} / "+
|
46
|
+
"#{parser.context.globals.object_id}"
|
47
|
+
actual = parser.parse('<r:thread />')
|
48
|
+
assert_equal expected, actual
|
49
|
+
end
|
50
|
+
mute.synchronize do
|
51
|
+
threads << thread
|
52
|
+
end
|
53
|
+
end
|
54
|
+
mute.synchronize do
|
55
|
+
threads.each{|t| t.join }
|
24
56
|
end
|
25
57
|
end
|
26
|
-
threads.each{|t| t.join }
|
27
58
|
end
|
28
59
|
|
29
60
|
end
|
data/test/parser_test.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require File.
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/test_helper')
|
2
2
|
|
3
3
|
class RadiusParserTest < Test::Unit::TestCase
|
4
4
|
include RadiusTestHelper
|
@@ -261,6 +261,11 @@ class RadiusParserTest < Test::Unit::TestCase
|
|
261
261
|
assert_equal 'bar', @context.globals.foo
|
262
262
|
end
|
263
263
|
|
264
|
+
def test_parse_with_other_namespaces
|
265
|
+
@parser = Radius::Parser.new(@context, :tag_prefix => 'r')
|
266
|
+
assert_equal "<fb:test>hello world</fb:test>", @parser.parse("<fb:test>hello world</fb:test>")
|
267
|
+
end
|
268
|
+
|
264
269
|
protected
|
265
270
|
|
266
271
|
def assert_parse_output(output, input, message = nil)
|
data/test/quickstart_test.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require File.
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/test_helper')
|
2
2
|
|
3
3
|
class QuickstartTest < Test::Unit::TestCase
|
4
4
|
|
@@ -20,7 +20,7 @@ class QuickstartTest < Test::Unit::TestCase
|
|
20
20
|
RedCloth.new(contents).to_html
|
21
21
|
end
|
22
22
|
parser = Radius::Parser.new(context)
|
23
|
-
assert_equal "<
|
23
|
+
assert_equal "<p>Hello <b>World</b>!</p>", parser.parse('<radius:textile>Hello **World**!</radius:textile>')
|
24
24
|
end
|
25
25
|
|
26
26
|
def test_nested_example
|
data/test/squiggle_test.rb
CHANGED
@@ -10,7 +10,7 @@ class RadiusSquiggleTest < Test::Unit::TestCase
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def test_sane_scanner_default
|
13
|
-
|
13
|
+
assert !Radius::Parser.new.scanner.is_a?(Radius::SquiggleScanner)
|
14
14
|
end
|
15
15
|
|
16
16
|
def test_initialize_with_params
|
@@ -235,6 +235,11 @@ class RadiusSquiggleTest < Test::Unit::TestCase
|
|
235
235
|
assert_equal 'bar', @context.globals.foo
|
236
236
|
end
|
237
237
|
|
238
|
+
def test_parse_with_other_namespaces
|
239
|
+
@parser = Radius::Parser.new(@context, :tag_prefix => 'r')
|
240
|
+
assert_equal "{fb:test}hello world{/fb:test}", @parser.parse("{fb:test}hello world{/fb:test}")
|
241
|
+
end
|
242
|
+
|
238
243
|
protected
|
239
244
|
|
240
245
|
def assert_parse_output(output, input, message = nil)
|
data/test/test_helper.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'rubygems'
|
1
2
|
require 'timeout'
|
2
3
|
|
3
4
|
unless defined? RADIUS_LIB
|
@@ -15,9 +16,12 @@ unless defined? RADIUS_LIB
|
|
15
16
|
Radius::Context.new do |c|
|
16
17
|
c.define_tag("reverse" ) { |tag| tag.expand.reverse }
|
17
18
|
c.define_tag("capitalize") { |tag| tag.expand.upcase }
|
18
|
-
c.define_tag("attr" ) { |tag| tag.attr.inspect }
|
19
19
|
c.define_tag("echo" ) { |tag| tag.attr['value'] }
|
20
20
|
c.define_tag("wrap" ) { |tag| "[#{tag.expand}]" }
|
21
|
+
c.define_tag("attr") do |tag|
|
22
|
+
kv = tag.attr.keys.sort.collect{|k| "#{k.inspect}=>#{tag[k].inspect}"}
|
23
|
+
"{#{kv.join(', ')}}"
|
24
|
+
end
|
21
25
|
end
|
22
26
|
end
|
23
27
|
|