Spectre 0.0.1
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/CHANGELOG +1 -0
- data/LICENSE +23 -0
- data/README +20 -0
- data/Rakefile +112 -0
- data/lib/spectre/base.rb +44 -0
- data/lib/spectre/base/closure.rb +96 -0
- data/lib/spectre/base/directive.rb +148 -0
- data/lib/spectre/base/grammar.rb +269 -0
- data/lib/spectre/base/inputiterator.rb +276 -0
- data/lib/spectre/base/node.rb +393 -0
- data/lib/spectre/base/operators.rb +342 -0
- data/lib/spectre/base/parser.rb +110 -0
- data/lib/spectre/generic.rb +115 -0
- data/lib/spectre/generic/directives.rb +246 -0
- data/lib/spectre/generic/negations.rb +68 -0
- data/lib/spectre/generic/primitives.rb +172 -0
- data/lib/spectre/generic/semanticaction.rb +43 -0
- data/lib/spectre/string.rb +57 -0
- data/lib/spectre/string/additionals.rb +80 -0
- data/lib/spectre/string/directives.rb +51 -0
- data/lib/spectre/string/inputiterator.rb +57 -0
- data/lib/spectre/string/primitives.rb +400 -0
- data/test/base/closure_tests.rb +108 -0
- data/test/base/grammar_tests.rb +97 -0
- data/test/base/operator_tests.rb +335 -0
- data/test/base/semanticaction_tests.rb +53 -0
- data/test/generic/directive_tests.rb +224 -0
- data/test/generic/negation_tests.rb +146 -0
- data/test/generic/primitive_tests.rb +99 -0
- data/test/string/POD2Parser_tests.rb +93 -0
- data/test/string/additional_tests.rb +43 -0
- data/test/string/directive_tests.rb +32 -0
- data/test/string/primitive_tests.rb +173 -0
- data/test/tests.rb +33 -0
- data/test/tutorial/funnymath_tests.rb +57 -0
- data/test/tutorial/html_tests.rb +171 -0
- data/test/tutorial/skipping_tests.rb +60 -0
- metadata +109 -0
data/CHANGELOG
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1 :: First release, basic functionality up, all tests passing
|
data/LICENSE
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Boost Software License - Version 1.0 - August 17th, 2003
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person or organization
|
4
|
+
obtaining a copy of the software and accompanying documentation covered by
|
5
|
+
this license (the "Software") to use, reproduce, display, distribute,
|
6
|
+
execute, and transmit the Software, and to prepare derivative works of the
|
7
|
+
Software, and to permit third-parties to whom the Software is furnished to
|
8
|
+
do so, all subject to the following:
|
9
|
+
|
10
|
+
The copyright notices in the Software and this entire statement, including
|
11
|
+
the above license grant, this restriction and the following disclaimer,
|
12
|
+
must be included in all copies of the Software, in whole or in part, and
|
13
|
+
all derivative works of the Software, unless such copies or derivative
|
14
|
+
works are solely in the form of machine-executable object code generated by
|
15
|
+
a source language processor.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
20
|
+
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
21
|
+
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
22
|
+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
23
|
+
DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
This is Spectre, a parser framework inspired by Boost.Spirit,
|
3
|
+
which can be found at http://spirit.sourceforge.net/.
|
4
|
+
|
5
|
+
_______________________________________________________
|
6
|
+
|
7
|
+
License: Boost Software License 1.0
|
8
|
+
For further information regarding this license, visit:
|
9
|
+
http://www.boost.org/LICENSE_1_0.txt
|
10
|
+
______________________________________________________
|
11
|
+
|
12
|
+
|
13
|
+
Support for Spectre is given at http://spectre.rubyforge.org/ .
|
14
|
+
===============================
|
15
|
+
|
16
|
+
If you have questions, problems, want to report bugs or request features, this is the
|
17
|
+
place for you.
|
18
|
+
|
19
|
+
Have fun with it!
|
20
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
# This is Spectre, a parser framework inspired by Boost.Spirit,
|
2
|
+
# which can be found at http://spirit.sourceforge.net/.
|
3
|
+
#
|
4
|
+
# If you want to find out more or need a tutorial, go to
|
5
|
+
# http://spectre.rubyforge.org/
|
6
|
+
# You'll find a nice wiki there!
|
7
|
+
#
|
8
|
+
# Author:: Fabian Streitel (karottenreibe)
|
9
|
+
# Copyright:: Copyright (c) 2009 Fabian Streitel
|
10
|
+
# License:: Boost Software License 1.0
|
11
|
+
# For further information regarding this license, you can go to
|
12
|
+
# http://www.boost.org/LICENSE_1_0.txt
|
13
|
+
# or read the file LICENSE distributed with this software.
|
14
|
+
# Homepage:: http://spectre.rubyforge.org/
|
15
|
+
# Git repo:: http://rubyforge.org/scm/?group_id=7618
|
16
|
+
#
|
17
|
+
|
18
|
+
require 'rubygems'
|
19
|
+
require 'rake/gempackagetask'
|
20
|
+
require 'rake/rdoctask'
|
21
|
+
require 'rake/testtask'
|
22
|
+
|
23
|
+
$VERBOSE = nil
|
24
|
+
|
25
|
+
GEM_NAME = 'Spectre'
|
26
|
+
GEM_AUTHORS = ['Fabian Streitel']
|
27
|
+
GEM_HOMEPAGE = 'http://spectre.rubyforge.org/'
|
28
|
+
GEM_RUBYFORGE = 'spectre'
|
29
|
+
GEM_SUMMARY = "This is Spectre, a parser framework inspired by Boost.Spirit."
|
30
|
+
GEM_EMAIL = "karottenreibe @nospam@ gmail.com"
|
31
|
+
|
32
|
+
spec = Gem::Specification.new do |s|
|
33
|
+
if ARGV.any? { |arg| arg == 'gem' }
|
34
|
+
puts
|
35
|
+
puts
|
36
|
+
puts "Versioning policy:"
|
37
|
+
puts "1 = implementation details changed"
|
38
|
+
puts "2 = compatible new feature"
|
39
|
+
puts "3 = incompatible changes"
|
40
|
+
puts
|
41
|
+
puts "Last build: " + (Dir['pkg/*'].sort)[-1].to_s
|
42
|
+
print "Enter version number > "
|
43
|
+
ver = STDIN.gets.strip
|
44
|
+
print "Enter changelog > "
|
45
|
+
chl = STDIN.gets
|
46
|
+
|
47
|
+
File.open('CHANGELOG', 'a') do |f|
|
48
|
+
f.write "#{ver.ljust 8} :: #{chl}"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
s.platform = Gem::Platform::RUBY
|
53
|
+
s.name = GEM_NAME
|
54
|
+
s.version = ver || "99"
|
55
|
+
s.authors = GEM_AUTHORS
|
56
|
+
s.email = GEM_EMAIL
|
57
|
+
s.homepage = GEM_HOMEPAGE
|
58
|
+
s.rubyforge_project = GEM_RUBYFORGE
|
59
|
+
s.summary = GEM_SUMMARY
|
60
|
+
s.files = FileList['lib/**/*.rb', 'test/**/*', '[A-Z]*'].to_a
|
61
|
+
s.require_path = "lib"
|
62
|
+
s.test_files = FileList['test/**/*.rb']
|
63
|
+
s.has_rdoc = true
|
64
|
+
s.extra_rdoc_files = ["README", "CHANGELOG", "LICENSE"]
|
65
|
+
end
|
66
|
+
|
67
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
68
|
+
pkg.need_tar = true
|
69
|
+
end
|
70
|
+
|
71
|
+
task :gem => "pkg/#{GEM_NAME}-#{spec.version}.gem" do
|
72
|
+
puts "generated gem"
|
73
|
+
end
|
74
|
+
|
75
|
+
Rake::RDocTask.new :real_doc do |rdoc|
|
76
|
+
rdoc.rdoc_files.include "lib/**/*.rb"
|
77
|
+
end
|
78
|
+
|
79
|
+
task :doc => [:real_doc] do
|
80
|
+
sh 'rm -r rdoc' if File::exists? 'rdoc'
|
81
|
+
sh 'mv html rdoc'
|
82
|
+
end
|
83
|
+
|
84
|
+
task :clean do
|
85
|
+
sh 'rm -r rdoc'
|
86
|
+
sh 'rm -r pkg'
|
87
|
+
end
|
88
|
+
|
89
|
+
Rake::TestTask.new :test do |t|
|
90
|
+
t.libs << "test"
|
91
|
+
t.test_files = ['test/tests.rb']
|
92
|
+
t.verbose = true
|
93
|
+
end
|
94
|
+
|
95
|
+
task :upload => [:rdoc] do
|
96
|
+
sh "rsync -azv --no-perms --no-times rdoc/* karottenreibe@rubyforge.org:/var/www/gforge-projects/#{GEM_RUBYFORGE}/rdoc/"
|
97
|
+
sh "rsync -azv --no-perms --no-times homepage/* karottenreibe@rubyforge.org:/var/www/gforge-projects/#{GEM_RUBYFORGE}/"
|
98
|
+
end
|
99
|
+
|
100
|
+
task :sftp do
|
101
|
+
sh "sftp karottenreibe@rubyforge.org:/var/www/gforge-projects/#{GEM_RUBYFORGE}/"
|
102
|
+
end
|
103
|
+
|
104
|
+
task :install => [:package] do
|
105
|
+
sh "sudo gem install pkg/#{GEM_NAME}-#{spec.version}.gem"
|
106
|
+
sh "rm pkg/#{GEM_NAME}-#{spec.version}.gem"
|
107
|
+
end
|
108
|
+
|
109
|
+
task :default => [:gem, :doc]
|
110
|
+
task :all => [:clean, :gem, :doc, :test]
|
111
|
+
task :rdoc => [:doc]
|
112
|
+
|
data/lib/spectre/base.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# This is Spectre, a parser framework inspired by Boost.Spirit,
|
2
|
+
# which can be found at http://spirit.sourceforge.net/.
|
3
|
+
#
|
4
|
+
# If you want to find out more or need a tutorial, go to
|
5
|
+
# http://spectre.rubyforge.org/
|
6
|
+
# You'll find a nice wiki there!
|
7
|
+
#
|
8
|
+
# Author:: Fabian Streitel (karottenreibe)
|
9
|
+
# Copyright:: Copyright (c) 2009 Fabian Streitel
|
10
|
+
# License:: Boost Software License 1.0
|
11
|
+
# For further information regarding this license, you can go to
|
12
|
+
# http://www.boost.org/LICENSE_1_0.txt
|
13
|
+
# or read the file LICENSE distributed with this software.
|
14
|
+
# Homepage:: http://spectre.rubyforge.org/
|
15
|
+
# Git repo:: http://rubyforge.org/scm/?group_id=7618
|
16
|
+
#
|
17
|
+
# Requires the base classes needed for Spectre to work:
|
18
|
+
# InputIterator, Node, Parser, Grammar and Closure as well as the default
|
19
|
+
# Operators, semantic actions and Directives.
|
20
|
+
#
|
21
|
+
|
22
|
+
require 'spectre/base/inputiterator'
|
23
|
+
require 'spectre/base/node'
|
24
|
+
require 'spectre/base/parser'
|
25
|
+
require 'spectre/base/grammar'
|
26
|
+
require 'spectre/base/closure'
|
27
|
+
require 'spectre/base/operators'
|
28
|
+
require 'spectre/base/directive'
|
29
|
+
|
30
|
+
module Spectre
|
31
|
+
|
32
|
+
class << self
|
33
|
+
##
|
34
|
+
# Shortcut. Parses the +input+ using +parser+ (Parser or Node) and the InputIterator
|
35
|
+
# class +iter_klass+.
|
36
|
+
# +pre_skip+ will be passed on to +Node#parse+.
|
37
|
+
#
|
38
|
+
def parse input, parser, iter_klass, pre_skip = true
|
39
|
+
parser.to_p.parse iter_klass.new(input), pre_skip
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# This is Spectre, a parser framework inspired by Boost.Spirit,
|
2
|
+
# which can be found at http://spirit.sourceforge.net/.
|
3
|
+
#
|
4
|
+
# If you want to find out more or need a tutorial, go to
|
5
|
+
# http://spectre.rubyforge.org/
|
6
|
+
# You'll find a nice wiki there!
|
7
|
+
#
|
8
|
+
# Author:: Fabian Streitel (karottenreibe)
|
9
|
+
# Copyright:: Copyright (c) 2009 Fabian Streitel
|
10
|
+
# License:: Boost Software License 1.0
|
11
|
+
# For further information regarding this license, you can go to
|
12
|
+
# http://www.boost.org/LICENSE_1_0.txt
|
13
|
+
# or read the file LICENSE distributed with this software.
|
14
|
+
# Homepage:: http://spectre.rubyforge.org/
|
15
|
+
# Git repo:: http://rubyforge.org/scm/?group_id=7618
|
16
|
+
#
|
17
|
+
# Keeps the Closure class.
|
18
|
+
#
|
19
|
+
|
20
|
+
require 'spectre/base/parser'
|
21
|
+
require 'spectre/base/grammar'
|
22
|
+
|
23
|
+
module Spectre
|
24
|
+
|
25
|
+
##
|
26
|
+
# Provides a Closure over several semantic actions to allow them to interact with each other
|
27
|
+
# and temporarily store data.
|
28
|
+
# The default Closure is a simple hash, but actually it can be an arbitrary object, as long as
|
29
|
+
# it provides the Hash methods +[]+ and +[]=+ and the attributes +parser+ and +node+.
|
30
|
+
#
|
31
|
+
class Closure < Hash
|
32
|
+
|
33
|
+
##
|
34
|
+
# The Parser this Closure belongs to.
|
35
|
+
attr_accessor :parser
|
36
|
+
|
37
|
+
##
|
38
|
+
# The Node this Closure belongs to.
|
39
|
+
attr_accessor :node
|
40
|
+
|
41
|
+
def parent
|
42
|
+
@parser.parent.closure
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# Retrieves a value from the Closure and uses it as a Parser.
|
48
|
+
# The retrieval is performed at parse time.
|
49
|
+
#
|
50
|
+
class ClosureParser
|
51
|
+
include Parser
|
52
|
+
|
53
|
+
##
|
54
|
+
# The symbol that identifies the Parser inside the Closure.
|
55
|
+
attr_reader :sym
|
56
|
+
|
57
|
+
##
|
58
|
+
# +sym+ is the identifier for the value retrieved from the Closure.
|
59
|
+
#
|
60
|
+
def initialize sym
|
61
|
+
@sym = sym
|
62
|
+
end
|
63
|
+
|
64
|
+
def negation; NegatedClosureParser.new @sym; end
|
65
|
+
|
66
|
+
def scan iter
|
67
|
+
raise "symbol #{@sym.inspect} not found in closure #{@node.closure.inspect}" unless
|
68
|
+
@node.closure and @node.closure[@sym]
|
69
|
+
create_match iter, @node.closure[@sym].to_p.parse(iter)
|
70
|
+
end
|
71
|
+
|
72
|
+
def inspect
|
73
|
+
"[closure:#{@sym}]"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
##
|
78
|
+
# Negates the enclosed parser.
|
79
|
+
#
|
80
|
+
class NegatedClosureParser < ClosureParser
|
81
|
+
def scan iter
|
82
|
+
raise "symbol #{@sym.inspect} not found in closure #{@node.closure.inspect}" unless
|
83
|
+
@node.closure and @node.closure[@sym]
|
84
|
+
create_match iter, ( ~( @node.closure[@sym].to_p ) ).parse(iter)
|
85
|
+
end
|
86
|
+
|
87
|
+
def inspect
|
88
|
+
"(~[closure:#{@sym}])"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
##
|
93
|
+
# The ClosureParser shortcut is +closed+.
|
94
|
+
ShortcutsMixin.register_shortcut :closed => ClosureParser
|
95
|
+
end
|
96
|
+
|
@@ -0,0 +1,148 @@
|
|
1
|
+
# This is Spectre, a parser framework inspired by Boost.Spirit,
|
2
|
+
# which can be found at http://spirit.sourceforge.net/.
|
3
|
+
#
|
4
|
+
# If you want to find out more or need a tutorial, go to
|
5
|
+
# http://spectre.rubyforge.org/
|
6
|
+
# You'll find a nice wiki there!
|
7
|
+
#
|
8
|
+
# Author:: Fabian Streitel (karottenreibe)
|
9
|
+
# Copyright:: Copyright (c) 2009 Fabian Streitel
|
10
|
+
# License:: Boost Software License 1.0
|
11
|
+
# For further information regarding this license, you can go to
|
12
|
+
# http://www.boost.org/LICENSE_1_0.txt
|
13
|
+
# or read the file LICENSE distributed with this software.
|
14
|
+
# Homepage:: http://spectre.rubyforge.org/
|
15
|
+
# Git repo:: http://rubyforge.org/scm/?group_id=7618
|
16
|
+
#
|
17
|
+
# Keeps the Directive class.
|
18
|
+
#
|
19
|
+
|
20
|
+
require 'spectre/base/parser'
|
21
|
+
require 'spectre/base/node'
|
22
|
+
|
23
|
+
module Spectre
|
24
|
+
|
25
|
+
##
|
26
|
+
# Sets options for the Parser and InputIterator.
|
27
|
+
# Imitates the behaviour of a Node.
|
28
|
+
# Subclasses may call the singleton methods +::transformation!+ and +::policy!+ to set the input
|
29
|
+
# transformation and Parser policy hash to use.
|
30
|
+
# These hashes will get merged with the current options.
|
31
|
+
#
|
32
|
+
# The Directive acts like a node in order to apply the parser policy.
|
33
|
+
# It keeps a DirectiveParser, which applies the input transformation.
|
34
|
+
#
|
35
|
+
class Directive < Node
|
36
|
+
|
37
|
+
##
|
38
|
+
# The skipper to apply to the InputIterator for this Directive - lambda block.
|
39
|
+
attr_reader :iter_skipper
|
40
|
+
|
41
|
+
##
|
42
|
+
# The transformation to apply to the InputIterator for this Directive - lambda block.
|
43
|
+
attr_reader :iter_transformation
|
44
|
+
|
45
|
+
##
|
46
|
+
# Whether or not the child parser should do pre-skipping.
|
47
|
+
attr_reader :pre_skip
|
48
|
+
|
49
|
+
class << self
|
50
|
+
|
51
|
+
##
|
52
|
+
# The skipper to apply to the InputIterator for this subclass - lambda block.
|
53
|
+
attr_reader :skipper
|
54
|
+
|
55
|
+
##
|
56
|
+
# The transformation to apply to the InputIterator for this subclass - lambda block.
|
57
|
+
attr_reader :transformation
|
58
|
+
|
59
|
+
##
|
60
|
+
# The options to merge with the Parser options for this subclass.
|
61
|
+
#
|
62
|
+
def policy
|
63
|
+
@policy || {}
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
# Sets the skipper on the InputIterator for this subclass to either the +block+
|
68
|
+
# or if no block is given to the first argument given to the method.
|
69
|
+
#
|
70
|
+
def skipper! *args, &block
|
71
|
+
@skipper = block_given? ? block : args[0]
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# Sets the input transformation on the InputIterator for this subclass to either the +block+
|
76
|
+
# or if no block is given to the first argument given to the method.
|
77
|
+
#
|
78
|
+
def transformation! *args, &block
|
79
|
+
@transformation = block_given? ? block : args[0]
|
80
|
+
end
|
81
|
+
|
82
|
+
##
|
83
|
+
# Sets the Parser policy to use for this subclass.
|
84
|
+
# The provided +hash+ will be merged with any already existing policy hash, thus enabling
|
85
|
+
# you to leave current specifications the way they are by simply not mentioning them.
|
86
|
+
#
|
87
|
+
def policy! hash
|
88
|
+
@policy = hash
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
##
|
93
|
+
# Retrieves the options from the subclassclass definition.
|
94
|
+
#
|
95
|
+
def initialize
|
96
|
+
@iter_transformation ||= self.class.transformation
|
97
|
+
@iter_skipper ||= self.class.skipper
|
98
|
+
@pre_skip = true
|
99
|
+
super(DirectiveParser.new self)
|
100
|
+
pol = self.class.policy
|
101
|
+
@policy ? @policy.merge!(pol) : @policy = pol
|
102
|
+
end
|
103
|
+
|
104
|
+
##
|
105
|
+
# Unlike Nodes, the Directive cannot store semantic actions. Instead this operator is used to
|
106
|
+
# deliver the subnodes for it.
|
107
|
+
# Performs auto-conversion on +node+.
|
108
|
+
#
|
109
|
+
def [] node
|
110
|
+
@left = node.to_p
|
111
|
+
@left.parent = self
|
112
|
+
self
|
113
|
+
end
|
114
|
+
|
115
|
+
##
|
116
|
+
# Saves the pre_skipping flag as directives pass that on to their children.
|
117
|
+
#
|
118
|
+
def parse iter, pre_skip = true
|
119
|
+
@pre_skip = pre_skip
|
120
|
+
super(iter, pre_skip)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
##
|
125
|
+
# Does the setting and resetting of the input transformation on the InputIterator.
|
126
|
+
#
|
127
|
+
class DirectiveParser
|
128
|
+
include Parser
|
129
|
+
|
130
|
+
def initialize directive
|
131
|
+
@directive = directive
|
132
|
+
end
|
133
|
+
|
134
|
+
def scan iter
|
135
|
+
trans, skip = iter.transformation, iter.skipper
|
136
|
+
iter.transformation = @directive.iter_transformation if @directive.iter_transformation
|
137
|
+
iter.skipper = @directive.iter_skipper if @directive.iter_skipper
|
138
|
+
|
139
|
+
ret = @node.left.parse iter, @directive.pre_skip
|
140
|
+
|
141
|
+
iter.transformation, iter.skipper = trans, skip
|
142
|
+
|
143
|
+
create_match iter, ret
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|