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.
Files changed (38) hide show
  1. data/CHANGELOG +1 -0
  2. data/LICENSE +23 -0
  3. data/README +20 -0
  4. data/Rakefile +112 -0
  5. data/lib/spectre/base.rb +44 -0
  6. data/lib/spectre/base/closure.rb +96 -0
  7. data/lib/spectre/base/directive.rb +148 -0
  8. data/lib/spectre/base/grammar.rb +269 -0
  9. data/lib/spectre/base/inputiterator.rb +276 -0
  10. data/lib/spectre/base/node.rb +393 -0
  11. data/lib/spectre/base/operators.rb +342 -0
  12. data/lib/spectre/base/parser.rb +110 -0
  13. data/lib/spectre/generic.rb +115 -0
  14. data/lib/spectre/generic/directives.rb +246 -0
  15. data/lib/spectre/generic/negations.rb +68 -0
  16. data/lib/spectre/generic/primitives.rb +172 -0
  17. data/lib/spectre/generic/semanticaction.rb +43 -0
  18. data/lib/spectre/string.rb +57 -0
  19. data/lib/spectre/string/additionals.rb +80 -0
  20. data/lib/spectre/string/directives.rb +51 -0
  21. data/lib/spectre/string/inputiterator.rb +57 -0
  22. data/lib/spectre/string/primitives.rb +400 -0
  23. data/test/base/closure_tests.rb +108 -0
  24. data/test/base/grammar_tests.rb +97 -0
  25. data/test/base/operator_tests.rb +335 -0
  26. data/test/base/semanticaction_tests.rb +53 -0
  27. data/test/generic/directive_tests.rb +224 -0
  28. data/test/generic/negation_tests.rb +146 -0
  29. data/test/generic/primitive_tests.rb +99 -0
  30. data/test/string/POD2Parser_tests.rb +93 -0
  31. data/test/string/additional_tests.rb +43 -0
  32. data/test/string/directive_tests.rb +32 -0
  33. data/test/string/primitive_tests.rb +173 -0
  34. data/test/tests.rb +33 -0
  35. data/test/tutorial/funnymath_tests.rb +57 -0
  36. data/test/tutorial/html_tests.rb +171 -0
  37. data/test/tutorial/skipping_tests.rb +60 -0
  38. metadata +109 -0
@@ -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
+
@@ -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
+
@@ -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
+