rubypeg 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,302 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), *%w[.])
2
+ $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
3
+ require 'rubypeg'
4
+ require 'textpeg'
5
+ require 'textpeg2rubypeg'
6
+
7
+ describe TextPeg2RubyPeg do
8
+
9
+ def check(input,output)
10
+ ruby = TextPeg2RubyPeg.new
11
+ peg = TextPeg.parse(input)
12
+ peg.visit(ruby)
13
+ ruby.to_ruby.should == output
14
+ end
15
+
16
+ it "creates a class that extends RubyPeg and is named after the first rule" do
17
+ input = <<END
18
+ one = .
19
+ END
20
+ output = <<END
21
+ require 'rubypeg'
22
+
23
+ class One < RubyPeg
24
+
25
+ def root
26
+ one
27
+ end
28
+
29
+ def one
30
+ any_character
31
+ end
32
+
33
+ end
34
+ END
35
+ check input, output
36
+ end
37
+
38
+ it "creates sequences" do
39
+ input = <<END
40
+ one = . . .
41
+ END
42
+ output = <<END
43
+ require 'rubypeg'
44
+
45
+ class One < RubyPeg
46
+
47
+ def root
48
+ one
49
+ end
50
+
51
+ def one
52
+ any_character && any_character && any_character
53
+ end
54
+
55
+ end
56
+ END
57
+ check input, output
58
+ end
59
+
60
+ it "creates alternatives" do
61
+ input = <<END
62
+ one = . | . | .
63
+ END
64
+ output = <<END
65
+ require 'rubypeg'
66
+
67
+ class One < RubyPeg
68
+
69
+ def root
70
+ one
71
+ end
72
+
73
+ def one
74
+ any_character || any_character || any_character
75
+ end
76
+
77
+ end
78
+ END
79
+ check input, output
80
+ end
81
+
82
+ it "creates alternatives and sequences together" do
83
+ input = <<END
84
+ one = (. .) | .
85
+ END
86
+ output = <<END
87
+ require 'rubypeg'
88
+
89
+ class One < RubyPeg
90
+
91
+ def root
92
+ one
93
+ end
94
+
95
+ def one
96
+ (any_character && any_character) || any_character
97
+ end
98
+
99
+ end
100
+ END
101
+ check input, output
102
+ end
103
+
104
+ it "creates nodes" do
105
+ input = <<END
106
+ one := . . .
107
+ END
108
+ output = <<END
109
+ require 'rubypeg'
110
+
111
+ class One < RubyPeg
112
+
113
+ def root
114
+ one
115
+ end
116
+
117
+ def one
118
+ node :one do
119
+ any_character && any_character && any_character
120
+ end
121
+ end
122
+
123
+ end
124
+ END
125
+ check input, output
126
+ end
127
+
128
+ it "creates positive and negative lookaheads and ignores" do
129
+ input = <<END
130
+ one = !. &. `.
131
+ END
132
+ output = <<END
133
+ require 'rubypeg'
134
+
135
+ class One < RubyPeg
136
+
137
+ def root
138
+ one
139
+ end
140
+
141
+ def one
142
+ not_followed_by { any_character } && followed_by { any_character } && ignore { any_character }
143
+ end
144
+
145
+ end
146
+ END
147
+ check input, output
148
+ end
149
+
150
+ it "creates repeated occurrence suffixes" do
151
+ input = <<END
152
+ one = .? .+ .*
153
+ END
154
+ output = <<END
155
+ require 'rubypeg'
156
+
157
+ class One < RubyPeg
158
+
159
+ def root
160
+ one
161
+ end
162
+
163
+ def one
164
+ optional { any_character } && one_or_more { any_character } && any_number_of { any_character }
165
+ end
166
+
167
+ end
168
+ END
169
+ check input, output
170
+ end
171
+
172
+ it "creates terminal strings" do
173
+ input = <<END
174
+ one = "one"
175
+ END
176
+ output = <<END
177
+ require 'rubypeg'
178
+
179
+ class One < RubyPeg
180
+
181
+ def root
182
+ one
183
+ end
184
+
185
+ def one
186
+ terminal("one")
187
+ end
188
+
189
+ end
190
+ END
191
+ check input, output
192
+ end
193
+
194
+ it "creates terminal strings, escaping where relevant" do
195
+ input = <<END
196
+ one = '"'
197
+ END
198
+ output = <<END
199
+ require 'rubypeg'
200
+
201
+ class One < RubyPeg
202
+
203
+ def root
204
+ one
205
+ end
206
+
207
+ def one
208
+ terminal("\\"")
209
+ end
210
+
211
+ end
212
+ END
213
+ check input, output
214
+ end
215
+
216
+ it "creates terminal character ranges" do
217
+ input = <<END
218
+ one = [a-z]
219
+ END
220
+ output = <<END
221
+ require 'rubypeg'
222
+
223
+ class One < RubyPeg
224
+
225
+ def root
226
+ one
227
+ end
228
+
229
+ def one
230
+ terminal(/[a-z]/)
231
+ end
232
+
233
+ end
234
+ END
235
+ check input, output
236
+ end
237
+
238
+ it "creates terminal regular expressions" do
239
+ input = <<END
240
+ one = /one/
241
+ END
242
+ output = <<END
243
+ require 'rubypeg'
244
+
245
+ class One < RubyPeg
246
+
247
+ def root
248
+ one
249
+ end
250
+
251
+ def one
252
+ terminal(/one/)
253
+ end
254
+
255
+ end
256
+ END
257
+ check input, output
258
+ end
259
+
260
+ it "has a helper class method parse_to_ruby(text_peg) that does the parsing and compiling in one shot" do
261
+ input = <<END
262
+ one = /one/
263
+ END
264
+ output = <<END
265
+ require 'rubypeg'
266
+
267
+ class One < RubyPeg
268
+
269
+ def root
270
+ one
271
+ end
272
+
273
+ def one
274
+ terminal(/one/)
275
+ end
276
+
277
+ end
278
+ END
279
+ TextPeg2RubyPeg.parse_to_ruby(input).should == output
280
+ end
281
+
282
+ it "has a helper class method parse_to_loaded_class(text_peg) that parses the text peg, compiles it to ruby and then evaluates it so it is immediately available" do
283
+ parser = TextPeg2RubyPeg.parse_to_loaded_class("one := /one/")
284
+ parser.parse("one").to_ast.should == [:one,"one"]
285
+ end
286
+
287
+ it "has a helper class method parse_file_to_loaded_class(filename) that loads a text peg then parses and compiles it to ruby before evaluating it so that it is immediately available" do
288
+ parser = TextPeg2RubyPeg.parse_file_to_loaded_class(File.join(File.dirname(__FILE__),'../lib/textpeg.txt'))
289
+ parser.parse("one := /one/").to_ast.should == [:text_peg, [:node, [:identifier, "one"], [:sequence, [:terminal_regexp, "one"]]]]
290
+ end
291
+
292
+ it "parses its own grammar" do
293
+ input = IO.readlines(File.join(File.dirname(__FILE__),'../lib/textpeg.txt')).join
294
+ output = IO.readlines(File.join(File.dirname(__FILE__),'../lib/textpeg.rb')).join
295
+ ruby = TextPeg2RubyPeg.new
296
+ peg = TextPeg.parse(input)
297
+ peg.visit(ruby)
298
+ r = ruby.to_ruby
299
+ r.should == output
300
+ end
301
+
302
+ end
@@ -0,0 +1,123 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), *%w[.])
2
+ $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
3
+ require 'rubypeg'
4
+ require 'textpeg'
5
+
6
+ describe TextPeg do
7
+
8
+ it "parses rules, one per line" do
9
+ input = <<END
10
+ one = .
11
+ two = .
12
+ END
13
+ TextPeg.parse(input).to_ast.should == [:text_peg,[:definition,[:identifier,"one"],[:sequence,[:any_character]]],[:definition,[:identifier,"two"],[:sequence,[:any_character]]]]
14
+ end
15
+
16
+ it "assigns nodes, one per line" do
17
+ input = <<END
18
+ one := .
19
+ two := .
20
+ END
21
+ TextPeg.parse(input).to_ast.should == [:text_peg,[:node,[:identifier,"one"],[:sequence,[:any_character]]],[:node,[:identifier,"two"],[:sequence,[:any_character]]]]
22
+ end
23
+
24
+ it "parses terminal strings in double quotes" do
25
+ input = <<END
26
+ one = "terminal string"
27
+ END
28
+ TextPeg.parse(input).to_ast.should == [:text_peg,[:definition,[:identifier,"one"],[:sequence,[:terminal_string,"terminal string"]]]]
29
+ end
30
+
31
+ it "parses terminal strings in single quotes" do
32
+ input = <<END
33
+ one = 'terminal string'
34
+ END
35
+ TextPeg.parse(input).to_ast.should == [:text_peg,[:definition,[:identifier,"one"],[:sequence,[:terminal_string,"terminal string"]]]]
36
+ end
37
+
38
+ it "parses terminal character matches" do
39
+ input = <<END
40
+ one = [a-z]
41
+ END
42
+ TextPeg.parse(input).to_ast.should == [:text_peg,[:definition,[:identifier,"one"],[:sequence,[:terminal_character_range,"[a-z]"]]]]
43
+ end
44
+
45
+ it "parses terminal regular expression matches" do
46
+ input = <<END
47
+ one = /one/
48
+ END
49
+ TextPeg.parse(input).to_ast.should == [:text_peg,[:definition,[:identifier,"one"],[:sequence,[:terminal_regexp,"one"]]]]
50
+ end
51
+
52
+ it "parses terminal regular expression matches with tricky inners" do
53
+ input = <<END
54
+ one = /\\/one\\/two\\/three/
55
+ END
56
+ TextPeg.parse(input).to_ast.should == [:text_peg,[:definition,[:identifier,"one"],[:sequence,[:terminal_regexp,"\\/one\\/two\\/three"]]]]
57
+ end
58
+
59
+ it "parses any character matches" do
60
+ input = <<END
61
+ one = .
62
+ END
63
+ TextPeg.parse(input).to_ast.should == [:text_peg,[:definition,[:identifier,"one"],[:sequence,[:any_character]]]]
64
+ end
65
+
66
+ it "parses alternatives" do
67
+ input = <<END
68
+ one = "one" | "two" | "three"
69
+ END
70
+ TextPeg.parse(input).to_ast.should == [:text_peg,[:definition,[:identifier,"one"],[:alternatives,[:terminal_string,"one"],[:terminal_string,"two"],[:terminal_string,"three"]]]]
71
+ end
72
+
73
+ it "parses sequences" do
74
+ input = <<END
75
+ one = "one" "two" "three"
76
+ END
77
+ TextPeg.parse(input).to_ast.should == [:text_peg,[:definition,[:identifier,"one"],[:sequence,[:terminal_string,"one"],[:terminal_string,"two"],[:terminal_string,"three"]]]]
78
+
79
+ end
80
+
81
+ it "parses alternatives in sequences" do
82
+ input = <<END
83
+ one = ("one"|"1") "two" ( "three" | "3" )
84
+ END
85
+ TextPeg.parse(input).to_ast.should == [:text_peg,[:definition,[:identifier,"one"],[:sequence,[:bracketed_expression, [:alternatives,[:terminal_string,"one"],[:terminal_string,'1']]],[:terminal_string,"two"],[:bracketed_expression,[:alternatives,[:terminal_string,"three"],[:terminal_string,'3']]]]]]
86
+
87
+ end
88
+
89
+ it "parses sequences in alternatives" do
90
+ input = <<END
91
+ one = ( "one" "two" "three" ) | ("1" "2" "3")
92
+ END
93
+ TextPeg.parse(input).to_ast.should == [:text_peg,[:definition,[:identifier,"one"],[:alternatives,[:bracketed_expression,[:sequence,[:terminal_string,"one"],[:terminal_string,"two"],[:terminal_string,"three"]]],[:bracketed_expression,[:sequence,[:terminal_string,'1'],[:terminal_string,'2'],[:terminal_string,'3']]]]]]
94
+ end
95
+
96
+ it "parses suffix elements" do
97
+ input = <<END
98
+ one = "one"? "two"* "three"+ ("four" | "five")?
99
+ END
100
+ TextPeg.parse(input).to_ast.should == [:text_peg,[:definition,[:identifier,"one"],[:sequence,[:optional,[:terminal_string,"one"]],[:any_number_of,[:terminal_string,"two"]],[:one_or_more,[:terminal_string,"three"]],[:optional,[:bracketed_expression,[:alternatives,[:terminal_string,"four"],[:terminal_string,"five"]]]]]]]
101
+ end
102
+
103
+ it "parses lookaheads" do
104
+ input = <<END
105
+ one = !"one" &"two"
106
+ END
107
+ TextPeg.parse(input).to_ast.should == [:text_peg,[:definition,[:identifier,"one"],[:sequence,[:not_followed_by,[:terminal_string,"one"]],[:followed_by,[:terminal_string,"two"]]]]]
108
+ end
109
+
110
+
111
+ it "parses ignores" do
112
+ input = <<END
113
+ one = `"one" &"two"
114
+ END
115
+ TextPeg.parse(input).to_ast.should == [:text_peg,[:definition,[:identifier,"one"],[:sequence,[:ignored,[:terminal_string,"one"]],[:followed_by,[:terminal_string,"two"]]]]]
116
+ end
117
+
118
+ it "parses its own grammar" do
119
+ input = IO.readlines(File.join(File.dirname(__FILE__),'../lib/textpeg.txt')).join
120
+ o = TextPeg.parse(input)
121
+ o.should_not == nil
122
+ end
123
+ end
@@ -0,0 +1,67 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
2
+ require 'rubypeg'
3
+
4
+ class SimplePeg < RubyPeg
5
+ def root
6
+ node :root do
7
+ one && two && three
8
+ end
9
+ end
10
+
11
+ def one
12
+ terminal('one')
13
+ end
14
+
15
+ def two
16
+ node :two do
17
+ terminal('2') || terminal('two')
18
+ end
19
+ end
20
+
21
+ def three
22
+ node :three do
23
+ one_or_more { terminal('x') }
24
+ end
25
+ end
26
+ end
27
+
28
+ describe SimplePeg do
29
+
30
+ it "matches one2xxx" do
31
+ SimplePeg.parse("one2xxx").to_ast.should == [:root,'one',[:two,'2'],[:three,'x','x','x']]
32
+ end
33
+ end
34
+
35
+ class EmptyPegBuilder
36
+
37
+ end
38
+
39
+ describe EmptyPegBuilder do
40
+ it "demonstrates the way that terminals are reduced to strings" do
41
+ SimplePeg.parse("one2xxx").visit(EmptyPegBuilder.new).should == ['one','2',['x','x','x']]
42
+ end
43
+ end
44
+
45
+
46
+ class NonTerminalPegBuilder
47
+
48
+ def root(one,two,three)
49
+ "one:#{one},two:#{two.visit(self)},three:#{three.visit(self)}"
50
+ end
51
+
52
+ def two(number)
53
+ number.visit(self).to_i + 1
54
+ end
55
+
56
+ def three(*args)
57
+ args.size
58
+ end
59
+
60
+ end
61
+
62
+ describe EmptyPegBuilder do
63
+ it "demonstrates the way that non terminals optionally call methods on the builder to be converted" do
64
+ SimplePeg.parse("one2xxx").visit(NonTerminalPegBuilder.new).should == "one:one,two:3,three:3"
65
+ end
66
+ end
67
+
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rubypeg
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 2
9
+ version: 0.0.2
10
+ platform: ruby
11
+ authors:
12
+ - Thomas Counsell, Green on Black Ltd
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-04-26 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rubyscriptwriter
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :runtime
31
+ version_requirements: *id001
32
+ description:
33
+ email: ruby-peg@greenonblack.com
34
+ executables:
35
+ - text-peg2ruby-peg
36
+ extensions: []
37
+
38
+ extra_rdoc_files: []
39
+
40
+ files:
41
+ - README
42
+ - spec/any_character_spec.rb
43
+ - spec/lookahead_spec.rb
44
+ - spec/non_terminal_spec.rb
45
+ - spec/peg_leg_spec.rb
46
+ - spec/repetition_spec.rb
47
+ - spec/sequence_spec.rb
48
+ - spec/terminal_spec.rb
49
+ - spec/text_peg2ruby_peg_spec.rb
50
+ - spec/text_peg_spec.rb
51
+ - spec/visit_spec.rb
52
+ - lib/rubypeg.rb
53
+ - lib/textpeg.rb
54
+ - lib/textpeg.txt
55
+ - lib/textpeg2rubypeg.rb
56
+ - bin/text-peg2ruby-peg
57
+ - examples/arithmetic/arithmetic_peg.rb
58
+ - examples/arithmetic/arithmetic_peg.txt
59
+ - examples/arithmetic/arithmetic_peg_spec.rb
60
+ - examples/arithmetic/calculator.rb
61
+ - examples/arithmetic/calculator_spec.rb
62
+ - examples/excel/excel_peg.txt
63
+ - examples/excel/excel_peg_spec.rb
64
+ has_rdoc: true
65
+ homepage: http://wiki.github.com/tamc/rubypeg/
66
+ licenses: []
67
+
68
+ post_install_message:
69
+ rdoc_options: []
70
+
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ segments:
78
+ - 0
79
+ version: "0"
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ segments:
85
+ - 0
86
+ version: "0"
87
+ requirements: []
88
+
89
+ rubyforge_project:
90
+ rubygems_version: 1.3.6
91
+ signing_key:
92
+ specification_version: 3
93
+ summary: RubyPeg helps you to create readable Parsing Expression Grammars (PEG) in, err, ruby
94
+ test_files: []
95
+