Spectre 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+