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.
Files changed (6) hide show
  1. data/README.md +50 -0
  2. data/bin/petooh +19 -0
  3. data/gen/LICENSE +21 -0
  4. data/gen/PETOOH.md +49 -0
  5. data/gen/lib/petooh.rb +375 -0
  6. metadata +61 -0
@@ -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.
@@ -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
@@ -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.
@@ -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/)
@@ -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: