grammar 0.5 → 0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,163 +0,0 @@
1
- #!/bin/env ruby
2
-
3
- require 'rubygems'
4
- require 'cursor/io'
5
- require 'cursor/indexed'
6
- require 'grammar'
7
- require 'duck'
8
- require 'set'
9
-
10
- class Tcl
11
-
12
- def initialize
13
-
14
- @variables = {}
15
- @procs = {}
16
-
17
- space = Grammar::Element[Set[?\ ,?\t].duck!(:==,:include?)].discard
18
- newline = Grammar::Element[?\n]
19
- command_separator = newline|Grammar::Element[?;]
20
- hex = Grammar::Element[(
21
- Set[]+(?0..?9)+(?a..?f)+(?A..?F)
22
- ).duck!(:==,:include?)]
23
- octal = Grammar::Element[(?0..?7).duck!(:==,:===)]
24
- alphanum = Grammar::Element[(
25
- Set[?_]+(?0..?9)+(?a..?z)+(?A..?Z)
26
- ).duck!(:==,:include?)]
27
-
28
- backslashed = Grammar::Element[?\\].discard+(
29
- Grammar::Element[?a].filter { "\a" } |
30
- Grammar::Element[?b].filter { "\b" } |
31
- Grammar::Element[?f].filter { "\f" } |
32
- Grammar::Element[?n].filter { "\n" } |
33
- Grammar::Element[?r].filter { "\r" } |
34
- Grammar::Element[?t].filter { "\t" } |
35
- Grammar::Element[?v].filter { "\v" } |
36
- Grammar::Element[?x].discard+hex.list1.filter { |n|
37
- eval(%Q("\\x#{n}"))
38
- } |
39
- Grammar::Element[?u].discard+hex.list1 { |n| # don't know what to do with unicode
40
- eval(%Q("\\x#{n}"))
41
- } |
42
- octal.list1.filter { |n|
43
- eval(%Q("\\#{n}"))
44
- } |
45
- (newline.discard+space.list0).filter { " " } |
46
- Grammar::ANY
47
- )
48
-
49
- braced_element = Grammar.new { |braced_element|
50
- Grammar::Element[?\{]+braced_element.list0(Grammar::Element[?\}]) |
51
- Grammar::Element[?\\].discard+(
52
- (newline.discard+space.list0).filter { " " } |
53
- Grammar::NULL.filter { "\\" }
54
- ) |
55
- newline |
56
- Grammar::ANY
57
- }
58
- braced = Grammar::Element[?\{].discard+braced_element.list0(Grammar::Element[?\}].discard)
59
-
60
- element = Grammar.new
61
-
62
- varname = (
63
- alphanum |
64
- Grammar::Element[?\:]*(2..+1.0/0)
65
- ).list1
66
- index = Grammar::Element[?\(]+element.list1(Grammar::Element[?\)])
67
- variable = (Grammar::Element[?\$].discard + (
68
- varname.group(String) + index.group(String).optional |
69
- braced.group(String)
70
- )).filter { |var| @variables[var.to_s.to_sym].to_s }
71
-
72
- quoted = Grammar::Element[?\"].discard+element.list1(Grammar::Element[?\"].discard)
73
- comment = (Grammar::Element[?\#]+Grammar::ANY.list0(newline)).discard
74
-
75
- commander = lambda { |terminator|
76
- word_terminator = space.list1|+command_separator|+terminator
77
- word = ((braced|quoted)+word_terminator|element.list1(word_terminator)).
78
- group(String).filter {|x,t| t.concat(x)}
79
- command = space.list0 + (
80
- comment |
81
- word.list0(command_separator.discard|+terminator).
82
- filter(Array) { |com,ret|
83
- com.empty? ? ret : ret.replace(send(*com).to_s)
84
- }
85
- )
86
- command.list0(terminator.discard)
87
- }
88
-
89
- bracketed = Grammar::Element[?[].discard+commander[Grammar::Element[?]]]
90
-
91
- @interpreter = commander[Grammar::EOF]
92
-
93
- element << (backslashed | bracketed | variable | newline | Grammar::ANY)
94
-
95
- end
96
-
97
- def interpret(cursor)
98
- @interpreter.scan(cursor,"",false)
99
- end
100
-
101
- def method_missing(name,*args)
102
- vars,body = *@procs[name]
103
- return "<#{name}#{args.inspect}>" if !body
104
- variables = @variables
105
- @variables = {}
106
- vars.zip(args).each { |var,val| @variables[var.to_sym] = val }
107
- ret = interpret(body.to_cursor)
108
- @variables = variables
109
- ret
110
- end
111
-
112
- def proc(name,args,body)
113
- @procs[name.to_sym] = [args,body]
114
- ""
115
- end
116
-
117
- def set(name,value)
118
- @variables[name.to_sym] = value
119
- end
120
-
121
- def if(condition,body)
122
- # should really use expr to get condition
123
- unless %w(0 false no off).include?(condition.to_s)
124
- interpret(body.to_cursor)
125
- end
126
- # need to handle elsif and else
127
- ""
128
- end
129
-
130
- def sum(*values)
131
- values.inject(0) { |sum, v| sum + eval(v) }
132
- end
133
-
134
- def product(*values)
135
- values.inject(1) { |sum, v| sum * eval(v) }
136
- end
137
-
138
- def subtract(a,b)
139
- eval(a)-eval(b)
140
- end
141
-
142
- def divide(a,b)
143
- eval(a)/eval(b)
144
- end
145
-
146
- def puts(str)
147
- $stdout.print(str,"\n")
148
- ""
149
- end
150
-
151
- def concat(*args)
152
- args.inject("") { |concatenated, arg| concatenated.concat(arg) }
153
- end
154
-
155
- end
156
-
157
- if $0==__FILE__
158
- result = Tcl.new.interpret($stdin.to_cursor)
159
- p result
160
- result
161
- end
162
-
163
-
@@ -1,4 +0,0 @@
1
- "one\n" *
2
- (2+3.0 /4e0*(5E+0+6.0e-0)-07)+
3
- (" eight\t"*nine)
4
-
@@ -1,274 +0,0 @@
1
- #!/bin/env ruby
2
-
3
- require 'rubygems'
4
- require 'test/unit'
5
- require 'test/unit/collector'
6
- require 'cursor/indexed'
7
- require 'grammar'
8
-
9
- module Test
10
- module Unit
11
- class AutoRunner
12
- alias_method(:_options_,:options)
13
- def options
14
- @options = _options_
15
- @options.on('-i', '--iterations=NUMBER', Float,
16
- "Randomly run tests for a number of iterations.") do |iterations|
17
- $random_iterations = iterations
18
- end
19
- @options.on('-s', '--seed=NUMBER', Integer,
20
- "Random seed.") do |seed|
21
- $random_seed = seed.nonzero?
22
- end
23
- @options
24
- end
25
- alias_method(:_run_,:run)
26
- def run
27
- $output_level = @output_level
28
- $random_seed ||= (srand;srand)
29
- srand($random_seed)
30
- _run_
31
- end
32
- end
33
- module Collector
34
- alias_method(:_add_suite_,:add_suite)
35
- def add_suite(destination, suite)
36
- _add_suite_(destination, suite)
37
- if $random_iterations
38
- (class << suite.tests;self;end).class_eval {
39
- def each
40
- n = size
41
- ($random_iterations*n).to_i.times {
42
- yield(slice(rand(n)))
43
- }
44
- end
45
- }
46
- end
47
- destination
48
- end
49
- end
50
- class TestSuite
51
- def run(result, &progress_block)
52
- yield(STARTED, name)
53
- catch(:stop_suite) {
54
- @tests.each { |test|
55
- catch(:invalid_test) {
56
- test.run(result, &progress_block)
57
- }
58
- }
59
- }
60
- yield(FINISHED, name)
61
- end
62
- end
63
- class RandomTestCase < TestCase
64
- def self.suite
65
- suite = super
66
- puts("random_seed: #{$random_seed}") if !suite.tests.empty? and $output_level>=UI::NORMAL
67
- suite
68
- end
69
- undef_method(:default_test) # so that RandomTestCase is empty
70
- def teardown
71
- if not passed?
72
- puts("\nrandom_seed: #{$random_seed}")
73
- throw(:stop_suite)
74
- end
75
- end
76
- end
77
- end
78
- end
79
-
80
-
81
- class Grammar
82
-
83
- class Test < ::Test::Unit::RandomTestCase
84
-
85
- class Grammars
86
- include ::Test::Unit::Assertions
87
- def initialize
88
- @grammar = []
89
- @match = []
90
- @parsed = []
91
- @mismatch = []
92
- @partial_match = []
93
- end
94
- def get
95
- i = rand(@grammar.size.nonzero? || throw(:invalid_test))
96
- return @grammar[i],@match[i],@parsed[i],@mismatch[i],@partial_match[i]
97
- end
98
- def add(grammar,match,parsed,mismatch=nil,partial_match=nil)
99
- puts("#{grammar.inspect} #{match.inspect} #{parsed.inspect} #{mismatch.inspect} #{partial_match.inspect}") if
100
- $output_level>=::Test::Unit::UI::VERBOSE
101
- match.size.times { |i|
102
- assert_equal(parsed[i],grammar.scan(match[i].to_cursor))
103
- }
104
- if mismatch
105
- assert_raise(Grammar::Error){p grammar.scan(mismatch.to_cursor)}
106
- assert_equal(false,grammar.scan(mismatch.to_cursor,[],true))
107
- end
108
- if partial_match
109
- assert_raise(Grammar::Error){grammar.scan(partial_match.to_cursor)}
110
- end
111
- @grammar << grammar
112
- @match << match
113
- @parsed << parsed
114
- @mismatch << mismatch
115
- @partial_match << partial_match
116
- nil
117
- end
118
- end
119
-
120
- def self.suite
121
- suite = super
122
- self.plant
123
- suite
124
- end
125
-
126
- def self.plant
127
- @@grammars = Grammars.new
128
- end
129
-
130
- def test_Sequence
131
- partial = rand(2)==1
132
- value = ["a","bc"][rand(2)]
133
- match = value.dup
134
- if partial
135
- match = [match,match[0,1+rand(value.size)]]
136
- else
137
- match = [match]
138
- end
139
- parsed = match.map{|s|s.unpack("C*")}
140
- @@grammars.add(Grammar::Sequence.new(value,partial),match,parsed,"")
141
- end
142
-
143
- def test_Element
144
- value = [?a,?b][rand(2)]
145
- match = ["" << value]
146
- parsed = [[value]]
147
- @@grammars.add(Grammar::Element.new(value),match,parsed,"")
148
- end
149
-
150
- def test_NULL
151
- @@grammars.add(Grammar::NULL,[""],[[]])
152
- end
153
-
154
- def test_or
155
- grammar1,match1,parsed1,mismatch1,partial1 = @@grammars.get
156
- grammar2,match2,parsed2,mismatch2,partial2 = @@grammars.get
157
- i = rand(match1.size)
158
- match1 = match1[i]
159
- parsed1 = parsed1[i]
160
- i = rand(match2.size)
161
- match2 = match2[i]
162
- parsed2 = parsed2[i]
163
- begin
164
- # match2 shouldn't match grammar1
165
- grammar1.scan(match2.to_cursor,[],true) and throw(:invalid_test)
166
- rescue Grammar::Error
167
- throw(:invalid_test) # partial match
168
- end
169
- @@grammars.add(
170
- grammar1|grammar2,
171
- [match1,match2],
172
- [parsed1,parsed2],
173
- mismatch1==mismatch2 ? mismatch1 : nil,
174
- partial1==partial2 ? partial1 : nil
175
- )
176
- end
177
-
178
- def test_plus
179
- grammar1,match1,parsed1,mismatch1,partial1 = @@grammars.get
180
- grammar2,match2,parsed2,mismatch2,partial2 = @@grammars.get
181
- i = rand(match1.size)
182
- match1 = match1[i]
183
- parsed1 = parsed1[i]
184
- i = rand(match2.size)
185
- match2 = match2[i]
186
- parsed2 = parsed2[i]
187
- # grammar1 shouldn't eat into match2
188
- begin
189
- grammar1.scan((match1+match2).to_cursor)==parsed1 or
190
- throw(:invalid_test)
191
- rescue Grammar::Error
192
- throw(:invalid_test)
193
- end
194
- @@grammars.add(
195
- grammar1+grammar2,
196
- [match1+match2],
197
- [parsed1+parsed2],
198
- mismatch1,
199
- partial1 || (mismatch2 && match1+mismatch2)
200
- )
201
- end
202
-
203
- def test_Grammar
204
- grammar1,match1,parsed1,mismatch1,partial1 = @@grammars.get
205
- grammar2,match2,parsed2,mismatch2,partial2 = @@grammars.get
206
- i = rand(match1.size)
207
- match1 = match1[i]
208
- parsed1 = parsed1[i]
209
- i = rand(match2.size)
210
- match2 = match2[i]
211
- parsed2 = parsed2[i]
212
- !match1.empty? or throw(:invalid_test)
213
- begin
214
- (grammar1.scan((match1+match1).to_cursor)==parsed1 and
215
- grammar1.scan((match1+match2).to_cursor)==parsed1 and
216
- grammar2.scan((match2+match2).to_cursor)==parsed2) or
217
- throw(:invalid_test)
218
- grammar1.scan(match2.to_cursor,[],true) and throw(:invalid_test)
219
- rescue Grammar::Error
220
- throw(:invalid_test)
221
- end
222
- grammar = Grammar.new
223
- grammar << grammar1+(grammar|Grammar::NULL)+grammar2
224
- @@grammars.add(
225
- grammar,
226
- [match1+match2,match1+match1+match1+match2+match2+match2],
227
- [parsed1+parsed2,parsed1+parsed1+parsed1+parsed2+parsed2+parsed2],
228
- mismatch1,
229
- partial1
230
- )
231
- end
232
-
233
- def test_times
234
- grammar1,match1,parsed1,mismatch1,partial1 = @@grammars.get
235
- begin
236
- grammar1.scan("".to_cursor,[],true) and throw(:invalid_test)
237
- rescue Grammar::Error
238
- throw(:invalid_test)
239
- end
240
- min = rand(2)
241
- diff = rand(4)
242
- match = ""
243
- parsed = []
244
- match0 = nil
245
- parsed0 = nil
246
- (min+rand(diff+1)).times {
247
- i = rand(match1.size)
248
- match.concat(match1[i])
249
- parsed.concat(parsed1[i])
250
- if match0
251
- begin
252
- grammar1.scan((match0+match1[i]).to_cursor)==parsed0 or
253
- throw(:invalid_test)
254
- rescue Grammar::Error
255
- throw(:invalid_test)
256
- end
257
- end
258
- match0 = match1[i]
259
- parsed0 = parsed1[i]
260
- }
261
- diff = 1.0/0.0 if diff==3
262
- multiplier = (diff.zero? && rand(2).zero?) ? min : (min..(min+diff))
263
- @@grammars.add(
264
- grammar1*multiplier,
265
- [match],
266
- [parsed],
267
- min.zero? ? nil : mismatch1,
268
- min.zero? ? nil : (partial1 || (min>1 && match1[rand(match1.size)]))
269
- )
270
- end
271
-
272
- end
273
- end
274
-