petooh 6.0.0
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/README.md +50 -0
- data/bin/petooh +19 -0
- data/gen/LICENSE +21 -0
- data/gen/PETOOH.md +49 -0
- data/gen/lib/petooh.rb +375 -0
- metadata +61 -0
data/README.md
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
### DESCRIPTION
|
2
|
+
|
3
|
+
PETOOH interpreter written in [Ruby](http://ruby-lang.org) and [GPL](https://github.com/LavirtheWhiolet/self-bootstrap).
|
4
|
+
|
5
|
+
### DEPENDS
|
6
|
+
|
7
|
+
[Ruby](http://ruby-lang.org) 1.9.3 or higer.
|
8
|
+
|
9
|
+
### BUILD
|
10
|
+
|
11
|
+
First, you need to install:
|
12
|
+
* [Rake](http://docs.seattlerb.org/rake/). Usually it comes with Ruby, but if it isn't then you may install it with the command `gem install rake`.
|
13
|
+
* [GPL](https://github.com/LavirtheWhiolet/self-bootstrap). Just download ["peg2rb.rb"](https://github.com/LavirtheWhiolet/self-bootstrap/blob/master/peg2rb.rb) into this directory and you are ready.
|
14
|
+
|
15
|
+
To (re-)build PETOOH interpreter as a standalone Ruby script you give the command:
|
16
|
+
|
17
|
+
rake petooh.rb
|
18
|
+
|
19
|
+
To build a Ruby gem you give the command:
|
20
|
+
|
21
|
+
rake gem
|
22
|
+
|
23
|
+
To build everything in this package you just give the command:
|
24
|
+
|
25
|
+
rake
|
26
|
+
|
27
|
+
To clean up your directory give the command:
|
28
|
+
|
29
|
+
rake clean
|
30
|
+
|
31
|
+
### INSTALL
|
32
|
+
|
33
|
+
Copy "petooh.rb" to some directory.
|
34
|
+
|
35
|
+
Or install the corresponding Ruby gem by giving the command:
|
36
|
+
|
37
|
+
gem install petooh
|
38
|
+
|
39
|
+
### USAGE
|
40
|
+
|
41
|
+
To run:
|
42
|
+
|
43
|
+
~$ ruby petooh.rb [options] file
|
44
|
+
|
45
|
+
Or, if you have installed the interpreter as a Ruby gem:
|
46
|
+
|
47
|
+
~$ petooh [options] file
|
48
|
+
|
49
|
+
Options:
|
50
|
+
* `-h` - Get some help.
|
data/bin/petooh
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
require 'petooh'
|
4
|
+
|
5
|
+
# Parse args.
|
6
|
+
case ARGV
|
7
|
+
when [], ["-h"], ["--help"]
|
8
|
+
puts <<-HELP
|
9
|
+
Usage: ruby #{File.basename(__FILE__)} file.koko
|
10
|
+
HELP
|
11
|
+
exit
|
12
|
+
end
|
13
|
+
file = ARGV[0]
|
14
|
+
# Run!
|
15
|
+
include PETOOH
|
16
|
+
File.open(file) do |io|
|
17
|
+
program = parse(io)
|
18
|
+
run program
|
19
|
+
end
|
data/gen/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2012 Roman Nuritdinov
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/gen/PETOOH.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
PETOOH – a fundamentally new programming language
|
2
|
+
==================================================
|
3
|
+
|
4
|
+
Basics
|
5
|
+
------
|
6
|
+
|
7
|
+
<table>
|
8
|
+
<tr>
|
9
|
+
<td>Kudah</td>
|
10
|
+
<td>increment the data pointer (to point to the next cell to the right)</td>
|
11
|
+
</tr>
|
12
|
+
<tr>
|
13
|
+
<td>kudah</td>
|
14
|
+
<td>decrement the data pointer (to point to the next cell to the left)</td>
|
15
|
+
</tr>
|
16
|
+
<tr>
|
17
|
+
<td>Ko</td>
|
18
|
+
<td>increment (increase by one) the byte at the data pointer</td>
|
19
|
+
</tr>
|
20
|
+
<tr>
|
21
|
+
<td>kO</td>
|
22
|
+
<td>decrement (decrease by one) the byte at the data pointer</td>
|
23
|
+
</tr>
|
24
|
+
<tr>
|
25
|
+
<td>Kukarek</td>
|
26
|
+
<td>output the byte at the data pointer as an ASCII encoded character</td>
|
27
|
+
</tr>
|
28
|
+
<tr>
|
29
|
+
<td>Kud</td>
|
30
|
+
<td>if the byte at the data pointer is zero, then instead of moving the instruction pointer forward to the next command</td>
|
31
|
+
</tr>
|
32
|
+
<tr>
|
33
|
+
<td>kud</td>
|
34
|
+
<td>if the byte at the data pointer is nonzero, then instead of moving the instruction pointer forward to the next command</td>
|
35
|
+
</tr>
|
36
|
+
</table>
|
37
|
+
|
38
|
+
Code sample
|
39
|
+
-----------
|
40
|
+
|
41
|
+
KoKoKoKoKoKoKoKoKoKo Kud-Kudah
|
42
|
+
KoKoKoKoKoKoKoKo kudah kO kud-Kudah Kukarek kudah
|
43
|
+
KoKoKo Kud-Kudah
|
44
|
+
kOkOkOkO kudah kO kud-Kudah Ko Kukarek kudah
|
45
|
+
KoKoKoKo Kud-Kudah KoKoKoKo kudah kO kud-Kudah kO Kukarek
|
46
|
+
kOkOkOkOkO Kukarek Kukarek kOkOkOkOkOkOkO
|
47
|
+
Kukarek
|
48
|
+
|
49
|
+
[Try now!](http://ky6uk.github.io/PETOOH/)
|
data/gen/lib/petooh.rb
ADDED
@@ -0,0 +1,375 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# Generated from "lib/petooh.peg" on 2015-09-20 00:13:12 +0500
|
4
|
+
|
5
|
+
module PETOOH
|
6
|
+
|
7
|
+
#
|
8
|
+
# +program+ is an Array of PETOOH keywords (in the form of String-s).
|
9
|
+
#
|
10
|
+
# +debug+ - if true then PETOOH VM state is dumped on each execution step.
|
11
|
+
#
|
12
|
+
def run(program, debug = false)
|
13
|
+
# Init virtual machine.
|
14
|
+
mem = [0] * 16
|
15
|
+
data_ptr = 0
|
16
|
+
pc = 0 # Index of current instruction in program.
|
17
|
+
# Run!
|
18
|
+
while pc < program.size
|
19
|
+
# Log (if needed).
|
20
|
+
if debug
|
21
|
+
STDERR.puts "MEM: #{mem.join(" ")}"
|
22
|
+
STDERR.puts "PC: #{pc} (#{program[pc]})"
|
23
|
+
STDERR.puts "DP: #{data_ptr} (#{mem[data_ptr]})"
|
24
|
+
end
|
25
|
+
# Analyze current program instruction.
|
26
|
+
case program[pc]
|
27
|
+
when "Kudah"
|
28
|
+
#
|
29
|
+
data_ptr += 1
|
30
|
+
# Expand memory if needed.
|
31
|
+
if data_ptr >= mem.size
|
32
|
+
mem.concat([0] * 16)
|
33
|
+
end
|
34
|
+
#
|
35
|
+
pc += 1
|
36
|
+
when "kudah"
|
37
|
+
#
|
38
|
+
data_ptr -= 1
|
39
|
+
# Convert the machine's state from the form of
|
40
|
+
# { data_ptr = -1, mem = { -1:x, 0:y, 1:z, … } }
|
41
|
+
# to the form of
|
42
|
+
# { data_ptr = 0, mem = { 0:x, 1:y, 2:z, … } }
|
43
|
+
if data_ptr < 0
|
44
|
+
mem.unshift(0)
|
45
|
+
data_ptr = 0
|
46
|
+
end
|
47
|
+
#
|
48
|
+
pc += 1
|
49
|
+
when "Ko"
|
50
|
+
mem[data_ptr] += 1
|
51
|
+
pc += 1
|
52
|
+
when "kO"
|
53
|
+
mem[data_ptr] -= 1
|
54
|
+
pc += 1
|
55
|
+
when "Kukarek"
|
56
|
+
print mem[data_ptr].chr
|
57
|
+
pc += 1
|
58
|
+
when "Kud"
|
59
|
+
if mem[data_ptr] == 0
|
60
|
+
# Increment PC until corresponding "kud" is encountered
|
61
|
+
# (taking nested "Kud"/"kud" into account).
|
62
|
+
nest_level = 1
|
63
|
+
pc += 1
|
64
|
+
while pc < program.size and nest_level > 0
|
65
|
+
case program[pc]
|
66
|
+
when "Kud"
|
67
|
+
nest_level += 1
|
68
|
+
when "kud"
|
69
|
+
nest_level -= 1
|
70
|
+
end
|
71
|
+
pc += 1
|
72
|
+
end
|
73
|
+
else
|
74
|
+
# Just skip the instruction.
|
75
|
+
pc += 1
|
76
|
+
end
|
77
|
+
when "kud"
|
78
|
+
if mem[data_ptr] != 0
|
79
|
+
# Decrement PC until corresponding "Kud" is encountered
|
80
|
+
# (taking nested "Kud"/"kud" into account).
|
81
|
+
nest_level = 1
|
82
|
+
pc -= 1
|
83
|
+
while pc > 0 and nest_level > 0
|
84
|
+
case program[pc]
|
85
|
+
when "Kud"
|
86
|
+
nest_level -= 1
|
87
|
+
when "kud"
|
88
|
+
nest_level += 1
|
89
|
+
end
|
90
|
+
pc -= 1
|
91
|
+
end
|
92
|
+
# Position PC right to the corresponding "Kud".
|
93
|
+
pc += 1
|
94
|
+
else
|
95
|
+
# Just skip the instruction.
|
96
|
+
pc += 1
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
#
|
103
|
+
# reads PETOOH program from +io+ and parses it into Array of PETOOH
|
104
|
+
# keywords (in the form of String-s).
|
105
|
+
#
|
106
|
+
def parse(io)
|
107
|
+
yy_parse(io)
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
# Generated by Generator of Parsers of Lavir AKA self-bootstrap.
|
113
|
+
|
114
|
+
|
115
|
+
|
116
|
+
#
|
117
|
+
# +input+ is IO. It must have working IO#pos, IO#pos= and
|
118
|
+
# IO#set_encoding() methods.
|
119
|
+
#
|
120
|
+
# It may raise YY_SyntaxError.
|
121
|
+
#
|
122
|
+
def yy_parse(input)
|
123
|
+
input.set_encoding("UTF-8", "UTF-8")
|
124
|
+
context = YY_ParsingContext.new(input)
|
125
|
+
yy_from_pcv(
|
126
|
+
yy_nonterm1(context) ||
|
127
|
+
# TODO: context.worst_error can not be nil here. Prove it.
|
128
|
+
raise(context.worst_error)
|
129
|
+
)
|
130
|
+
end
|
131
|
+
|
132
|
+
# TODO: Allow to pass String to the entry point.
|
133
|
+
|
134
|
+
|
135
|
+
# :nodoc:
|
136
|
+
### converts value to parser-compatible value (which is always non-false and
|
137
|
+
### non-nil).
|
138
|
+
def yy_to_pcv(value)
|
139
|
+
if value.nil? then :yy_nil
|
140
|
+
elsif value == false then :yy_false
|
141
|
+
else value
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# :nodoc:
|
146
|
+
### converts value got by #yy_to_pcv() to actual value.
|
147
|
+
def yy_from_pcv(value)
|
148
|
+
if value == :yy_nil then nil
|
149
|
+
elsif value == :yy_false then false
|
150
|
+
else value
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
# :nodoc:
|
155
|
+
class YY_ParsingContext
|
156
|
+
|
157
|
+
# +input+ is IO.
|
158
|
+
def initialize(input)
|
159
|
+
@input = input
|
160
|
+
@worst_error = nil
|
161
|
+
end
|
162
|
+
|
163
|
+
attr_reader :input
|
164
|
+
|
165
|
+
# It is YY_SyntaxExpectationError or nil.
|
166
|
+
attr_accessor :worst_error
|
167
|
+
|
168
|
+
# adds possible error to this YY_ParsingContext.
|
169
|
+
#
|
170
|
+
# +error+ is YY_SyntaxExpectationError.
|
171
|
+
#
|
172
|
+
def << error
|
173
|
+
# Update worst_error.
|
174
|
+
if worst_error.nil? or worst_error.pos < error.pos then
|
175
|
+
@worst_error = error
|
176
|
+
elsif worst_error.pos == error.pos then
|
177
|
+
@worst_error = @worst_error.or error
|
178
|
+
end
|
179
|
+
#
|
180
|
+
return self
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
|
185
|
+
# :nodoc:
|
186
|
+
def yy_string(context, string)
|
187
|
+
#
|
188
|
+
string_start_pos = context.input.pos
|
189
|
+
# Read string.
|
190
|
+
read_string = context.input.read(string.bytesize)
|
191
|
+
# Set the string's encoding; check if it fits the argument.
|
192
|
+
unless read_string and (read_string.force_encoding(Encoding::UTF_8)) == string then
|
193
|
+
#
|
194
|
+
context << YY_SyntaxExpectationError.new(yy_displayed(string), string_start_pos)
|
195
|
+
#
|
196
|
+
return nil
|
197
|
+
end
|
198
|
+
#
|
199
|
+
return read_string
|
200
|
+
end
|
201
|
+
|
202
|
+
# :nodoc:
|
203
|
+
def yy_end?(context)
|
204
|
+
#
|
205
|
+
if not context.input.eof?
|
206
|
+
context << YY_SyntaxExpectationError.new("the end", context.input.pos)
|
207
|
+
return nil
|
208
|
+
end
|
209
|
+
#
|
210
|
+
return true
|
211
|
+
end
|
212
|
+
|
213
|
+
# :nodoc:
|
214
|
+
def yy_begin?(context)
|
215
|
+
#
|
216
|
+
if not(context.input.pos == 0)
|
217
|
+
context << YY_SyntaxExpectationError.new("the beginning", context.input.pos)
|
218
|
+
return nil
|
219
|
+
end
|
220
|
+
#
|
221
|
+
return true
|
222
|
+
end
|
223
|
+
|
224
|
+
# :nodoc:
|
225
|
+
def yy_char(context)
|
226
|
+
#
|
227
|
+
char_start_pos = context.input.pos
|
228
|
+
# Read a char.
|
229
|
+
c = context.input.getc
|
230
|
+
#
|
231
|
+
unless c then
|
232
|
+
#
|
233
|
+
context << YY_SyntaxExpectationError.new("a character", char_start_pos)
|
234
|
+
#
|
235
|
+
return nil
|
236
|
+
end
|
237
|
+
#
|
238
|
+
return c
|
239
|
+
end
|
240
|
+
|
241
|
+
# :nodoc:
|
242
|
+
def yy_char_range(context, from, to)
|
243
|
+
#
|
244
|
+
char_start_pos = context.input.pos
|
245
|
+
# Read the char.
|
246
|
+
c = context.input.getc
|
247
|
+
# Check if it fits the range.
|
248
|
+
# NOTE: c has UTF-8 encoding.
|
249
|
+
unless c and (from <= c and c <= to) then
|
250
|
+
#
|
251
|
+
context << YY_SyntaxExpectationError.new(%(#{yy_displayed from}...#{yy_displayed to}), char_start_pos)
|
252
|
+
#
|
253
|
+
return nil
|
254
|
+
end
|
255
|
+
#
|
256
|
+
return c
|
257
|
+
end
|
258
|
+
|
259
|
+
# :nodoc:
|
260
|
+
### The form of +string+ suitable for displaying in messages.
|
261
|
+
def yy_displayed(string)
|
262
|
+
if string.length == 1 then
|
263
|
+
char = string[0]
|
264
|
+
char_code = char.ord
|
265
|
+
case char_code
|
266
|
+
when 0x00...0x20, 0x2028, 0x2029 then %(#{yy_unicode_s char_code})
|
267
|
+
when 0x20...0x80 then %("#{char}")
|
268
|
+
when 0x80...Float::INFINITY then %("#{char} (#{yy_unicode_s char_code})")
|
269
|
+
end
|
270
|
+
else
|
271
|
+
%("#{string}")
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
# :nodoc:
|
276
|
+
### "U+XXXX" string corresponding to +char_code+.
|
277
|
+
def yy_unicode_s(char_code)
|
278
|
+
"U+#{"%04X" % char_code}"
|
279
|
+
end
|
280
|
+
|
281
|
+
class YY_SyntaxError < Exception
|
282
|
+
|
283
|
+
def initialize(message, pos)
|
284
|
+
super(message)
|
285
|
+
@pos = pos
|
286
|
+
end
|
287
|
+
|
288
|
+
attr_reader :pos
|
289
|
+
|
290
|
+
end
|
291
|
+
|
292
|
+
# :nodoc:
|
293
|
+
class YY_SyntaxExpectationError < YY_SyntaxError
|
294
|
+
|
295
|
+
#
|
296
|
+
# +expectations+ are String-s.
|
297
|
+
#
|
298
|
+
def initialize(*expectations, pos)
|
299
|
+
super(nil, pos)
|
300
|
+
@expectations = expectations
|
301
|
+
end
|
302
|
+
|
303
|
+
#
|
304
|
+
# returns other YY_SyntaxExpectationError with #expectations combined.
|
305
|
+
#
|
306
|
+
# +other+ is another YY_SyntaxExpectationError.
|
307
|
+
#
|
308
|
+
# #pos of this YY_SyntaxExpectationError and +other+ must be equal.
|
309
|
+
#
|
310
|
+
def or other
|
311
|
+
raise %(can not "or" #{YY_SyntaxExpectationError}s with different pos) unless self.pos == other.pos
|
312
|
+
YY_SyntaxExpectationError.new(*(self.expectations + other.expectations), pos)
|
313
|
+
end
|
314
|
+
|
315
|
+
def message
|
316
|
+
expectations = self.expectations.uniq
|
317
|
+
(
|
318
|
+
if expectations.size == 1 then expectations.first
|
319
|
+
else [expectations[0...-1].join(", "), expectations[-1]].join(" or ")
|
320
|
+
end
|
321
|
+
) + " is expected"
|
322
|
+
end
|
323
|
+
|
324
|
+
protected
|
325
|
+
|
326
|
+
# Private
|
327
|
+
attr_reader :expectations
|
328
|
+
|
329
|
+
end
|
330
|
+
|
331
|
+
# :nodoc:
|
332
|
+
def yy_nonterm1(yy_context)
|
333
|
+
val = nil
|
334
|
+
(begin
|
335
|
+
val = []
|
336
|
+
true
|
337
|
+
end and while true
|
338
|
+
yy_var8 = yy_context.input.pos
|
339
|
+
if not(begin; yy_var6 = yy_context.input.pos; begin
|
340
|
+
yy_var7 = yy_nonterm9(yy_context)
|
341
|
+
if yy_var7 then
|
342
|
+
val << yy_from_pcv(yy_var7)
|
343
|
+
end
|
344
|
+
yy_var7
|
345
|
+
end or (yy_context.input.pos = yy_var6; yy_nontermh(yy_context)); end) then
|
346
|
+
yy_context.input.pos = yy_var8
|
347
|
+
break true
|
348
|
+
end
|
349
|
+
end) and yy_to_pcv(val)
|
350
|
+
end
|
351
|
+
|
352
|
+
# :nodoc:
|
353
|
+
def yy_nonterm9(yy_context)
|
354
|
+
val = nil
|
355
|
+
begin
|
356
|
+
val = ""
|
357
|
+
yy_varf = yy_context.input.pos
|
358
|
+
begin; yy_vare = yy_context.input.pos; yy_string(yy_context, "Kudah") or (yy_context.input.pos = yy_vare; yy_string(yy_context, "kudah")) or (yy_context.input.pos = yy_vare; yy_string(yy_context, "Ko")) or (yy_context.input.pos = yy_vare; yy_string(yy_context, "kO")) or (yy_context.input.pos = yy_vare; yy_string(yy_context, "Kukarek")) or (yy_context.input.pos = yy_vare; yy_string(yy_context, "Kud")) or (yy_context.input.pos = yy_vare; yy_string(yy_context, "kud")); end and begin
|
359
|
+
yy_varg = yy_context.input.pos
|
360
|
+
yy_context.input.pos = yy_varf
|
361
|
+
val << yy_context.input.read(yy_varg - yy_varf).force_encoding(Encoding::UTF_8)
|
362
|
+
end
|
363
|
+
end and yy_to_pcv(val)
|
364
|
+
end
|
365
|
+
|
366
|
+
# :nodoc:
|
367
|
+
def yy_nontermh(yy_context)
|
368
|
+
val = nil
|
369
|
+
yy_char(yy_context) and yy_to_pcv(val)
|
370
|
+
end
|
371
|
+
|
372
|
+
# End of generated code.
|
373
|
+
|
374
|
+
end
|
375
|
+
|
metadata
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: petooh
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 6.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Roman Nuritdinov
|
9
|
+
- Lavir the Whiolet
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2015-09-19 00:00:00.000000000 Z
|
14
|
+
dependencies: []
|
15
|
+
description: ! 'Interpreter of PETOOH - the fundamentally new programming language.
|
16
|
+
|
17
|
+
'
|
18
|
+
email:
|
19
|
+
- ky6uk.kun@gmail.com
|
20
|
+
- Lavir.th.Whiolet@gmail.com
|
21
|
+
executables:
|
22
|
+
- petooh
|
23
|
+
extensions: []
|
24
|
+
extra_rdoc_files:
|
25
|
+
- README.md
|
26
|
+
- gen/PETOOH.md
|
27
|
+
- gen/LICENSE
|
28
|
+
files:
|
29
|
+
- gen/lib/petooh.rb
|
30
|
+
- README.md
|
31
|
+
- gen/PETOOH.md
|
32
|
+
- gen/LICENSE
|
33
|
+
- bin/petooh
|
34
|
+
homepage: http://ky6uk.github.io/PETOOH/
|
35
|
+
licenses:
|
36
|
+
- The MIT License (MIT)
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options: []
|
39
|
+
require_paths:
|
40
|
+
- lib
|
41
|
+
- gen/lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
requirements: []
|
55
|
+
rubyforge_project:
|
56
|
+
rubygems_version: 1.8.23
|
57
|
+
signing_key:
|
58
|
+
specification_version: 3
|
59
|
+
summary: PETOOH interpreter
|
60
|
+
test_files: []
|
61
|
+
has_rdoc:
|