petooh 6.0.0

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