p-lang 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,23 @@
1
+ module PLang
2
+ module Parser
3
+ class Node
4
+ attr_reader :type
5
+ def initialize(type, params)
6
+ @type = type
7
+ @params = params
8
+ end
9
+
10
+ def method_missing(name, *args)
11
+ return @params[name]
12
+ end
13
+
14
+ def inspect
15
+ ret = [@type]
16
+ @params.each do |id, value|
17
+ ret << value
18
+ end
19
+ ret
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,378 @@
1
+ module PLang
2
+ module Parser
3
+ class SyntaxAnalyser
4
+ def initialize(src)
5
+ @eof = Token.new(:eof)
6
+ @lexer = Lexer.new(src)
7
+ consume
8
+ end
9
+
10
+ def parse
11
+ program
12
+ end
13
+
14
+ private
15
+
16
+ def skip_breaks
17
+ while token
18
+ break unless token.type == :break
19
+ consume
20
+ end
21
+ end
22
+
23
+ def program
24
+ p = []
25
+ skip_breaks
26
+ while token.type != :eof
27
+ p << expr
28
+ end
29
+ p
30
+ end
31
+
32
+ def expr
33
+ if token.type == :begin
34
+ ast = pbegin
35
+ elsif token.type == :list
36
+ ast = plist
37
+ elsif token.type == :if
38
+ ast = pif
39
+ elsif token.type == :not
40
+ ast = pnot
41
+ elsif ast = element
42
+ skip_breaks
43
+ case token.type
44
+ when :add, :sub, :mul, :div, :mod
45
+ ast = arithmetic(ast)
46
+ when :equal, :diff, :major, :major_equal, :minor, :minor_equal, :and, :or
47
+ ast = conditional(ast)
48
+ when :let
49
+ ast = let(ast)
50
+ end
51
+ end
52
+ skip_breaks
53
+ ast
54
+ end
55
+
56
+ def plambda
57
+
58
+ if token.type == :lsquare
59
+ consume_and_skip_breaks
60
+ params = expr_list
61
+ if token.type == :pipe
62
+ consume_and_skip_breaks
63
+ body = expr
64
+ if token.type == :rsquare
65
+ consume
66
+ else
67
+ Error.syntax_error(token.line, token.src, token.i, "unexpected '#{token.value}', expecting ']'")
68
+ end
69
+ else
70
+ if token.type == :rsquare
71
+ if params.length == 1
72
+ body = params[0]
73
+ params = []
74
+ else
75
+ Error.syntax_error(token.line, token.src, token.i, "invalid function body")
76
+ end
77
+ consume
78
+ else
79
+ Error.syntax_error(token.line, token.src, token.i, "unexpected '#{token.value}', expecting ']'")
80
+ end
81
+ end
82
+ end
83
+ if token.type == :colon
84
+ consume_and_skip_breaks
85
+ w = where
86
+ else
87
+ w = []
88
+ end
89
+ if token.type == :semicolon
90
+ consume_and_skip_breaks
91
+ return Node.new(:lambda, {:params => params, :body => body, :where => w, :next_lambda => plambda})
92
+ else
93
+ return Node.new(:lambda, {:params => params, :body => body, :where => w, :next_lambda => nil})
94
+ end
95
+ end
96
+
97
+ def where
98
+ if token.type == :lround
99
+ consume_and_skip_breaks
100
+ ll = let_list
101
+ if token.type == :rround
102
+ consume
103
+ return ll
104
+ else
105
+ Error.syntax_error(token.line, token.src, token.i, "unexpected '#{token.value}', expecting ')'")
106
+ end
107
+ end
108
+ end
109
+
110
+ def let_list
111
+ ll = []
112
+ e = element
113
+ if token.type == :let
114
+ e = let(e)
115
+ else
116
+ Error.syntax_error(token.line, token.src, token.i, "unexpected '#{token.value}', expecting '='")
117
+ end
118
+ ll << e
119
+ while token.type == :comma
120
+ consume_and_skip_breaks
121
+ e = element
122
+ if token.type == :let
123
+ e = let(e)
124
+ else
125
+ Error.syntax_error(token.line, token.src, token.i, "unexpected '#{token.value}', expecting '='")
126
+ end
127
+ ll << e
128
+ end
129
+ ll
130
+ end
131
+
132
+ def pobject
133
+ if token.type == :lcurly
134
+ consume_and_skip_breaks
135
+ id = token
136
+ if id.type == :id
137
+ consume_and_skip_breaks
138
+ if token.type == :colon
139
+ consume_and_skip_breaks
140
+ ast = Node.new(:object, {:id => Node.new(:id, {:value => id.value}), :params => expr_list})
141
+ if token.type == :rcurly
142
+ consume_and_skip_breaks
143
+ return ast
144
+ else
145
+ Error.syntax_error(token.line, token.src, token.i, "unexpected '#{token.value}', expecting '}'")
146
+ end
147
+ elsif token.type == :rcurly
148
+ consume_and_skip_breaks
149
+ ast = Node.new(:object, {:id => Node.new(:id, {:value => id.value}), :params => []})
150
+ else
151
+ Error.syntax_error(token.line, token.src, token.i, "unexpected '#{token.value}', expecting ':'")
152
+ end
153
+ else
154
+ Error.syntax_error(token.line, token.src, token.i, "unexpected '#{token.value}', expecting an identifier")
155
+ end
156
+ end
157
+ end
158
+
159
+ def plist
160
+ if token.type == :list
161
+ consume
162
+ if token.type == :lround
163
+ consume_and_skip_breaks
164
+ if token.type == :rround
165
+ consume_and_skip_breaks
166
+ return Node.new(:list, {:elements => []})
167
+ end
168
+ e = expr_list
169
+ if token.type == :rround
170
+ consume_and_skip_breaks
171
+ return Node.new(:list, {:elements => e})
172
+ else
173
+ Error.syntax_error(token.line, token.src, token.i, "unexpected '#{token.value}', expecting ')'")
174
+ end
175
+ else
176
+ Error.syntax_error(token.line, token.src, token.i, "unexpected '#{token.value}', expecting '('")
177
+ end
178
+ end
179
+ end
180
+
181
+ def pbegin
182
+ if token.type == :begin
183
+ consume
184
+ if token.type == :lround
185
+ consume_and_skip_breaks
186
+ e = expr_list
187
+ if token.type == :rround
188
+ consume_and_skip_breaks
189
+ return Node.new(:begin, {:expressions => e})
190
+ else
191
+ Error.syntax_error(token.line, token.src, token.i, "unexpected '#{token.value}', expecting ')'")
192
+ end
193
+ else
194
+ Error.syntax_error(token.line, token.src, token.i, "unexpected '#{token.value}', expecting '('")
195
+ end
196
+ end
197
+ end
198
+
199
+ def pif
200
+ if token.type == :if
201
+ consume
202
+ if token.type == :lround
203
+ consume_and_skip_breaks
204
+ cond = expr
205
+ if token.type == :comma
206
+ consume_and_skip_breaks
207
+ true_expr = expr
208
+ if token.type == :comma
209
+ consume_and_skip_breaks
210
+ false_expr = expr
211
+ if token.type == :rround
212
+ consume_and_skip_breaks
213
+ return Node.new(:if, {:condition=>cond, :true_expr => true_expr, :false_expr => false_expr})
214
+ else
215
+ Error.syntax_error(token.line, token.src, token.i, "unexpected '#{token.value}', expecting ')'")
216
+ end
217
+ else
218
+ Error.syntax_error(token.line, token.src, token.i, "unexpected '#{token.value}', expecting ','")
219
+ end
220
+ else
221
+ Error.syntax_error(token.line, token.src, token.i, "unexpected '#{token.value}', expecting ','")
222
+ end
223
+ else
224
+ Error.syntax_error(token.line, token.src, token.i, "unexpected '#{token.value}', expecting '('")
225
+ end
226
+ end
227
+ end
228
+
229
+ def expr_list
230
+ e = [expr]
231
+ while token.type == :comma
232
+ consume_and_skip_breaks
233
+ e << expr
234
+ end
235
+ e
236
+ end
237
+
238
+ def let(ast)
239
+ if token.type == :let
240
+ consume_and_skip_breaks
241
+ Node.new(:let, {:lhs => ast, :rhs => expr})
242
+ end
243
+ end
244
+
245
+ def pnot
246
+ t = token
247
+ case t.type
248
+ when :not
249
+ consume_and_skip_breaks
250
+ Node.new(:not, {:lhs => expr})
251
+ end
252
+ end
253
+
254
+ def conditional(ast)
255
+ t = token
256
+ case t.type
257
+ when :equal, :diff, :major, :major_equal, :minor, :minor_equal, :and, :or, :not
258
+ consume_and_skip_breaks
259
+ conditional(Node.new(t.type, {:lhs => ast, :rhs => element}))
260
+ else
261
+ ast
262
+ end
263
+ end
264
+
265
+ def arithmetic(ast)
266
+ t = token
267
+ case t.type
268
+ when :add, :sub, :mul, :div, :mod
269
+ consume_and_skip_breaks
270
+ arithmetic(Node.new(t.type, {:lhs => ast, :rhs => element}))
271
+ else
272
+ ast
273
+ end
274
+ end
275
+
276
+ def element
277
+ case token.type
278
+ when :integer, :decimal, :string, :char
279
+ t = token
280
+ consume
281
+ ast = Node.new(t.type, {:value => t.value})
282
+ when :true
283
+ t = token
284
+ consume
285
+ ast = Node.new(:boolean, {:value => :true})
286
+ when :false
287
+ t = token
288
+ consume
289
+ ast = Node.new(:boolean, {:value => :false})
290
+ when :lsquare
291
+ ast = plambda
292
+ if token.type == :lround
293
+ ast = pcall(ast)
294
+ end
295
+ when :lcurly
296
+ ast = pobject
297
+ when :id
298
+ t = token
299
+ consume
300
+ ast = Node.new(:id, {:value => t.value})
301
+ if token.type == :lround
302
+ ast = pcall(ast)
303
+ end
304
+ when :lround
305
+ consume_and_skip_breaks
306
+ e = expr
307
+ if token.type == :rround
308
+ consume
309
+ ast = e
310
+ else
311
+ Error.syntax_error(token.line, token.src, token.i, "unexpected '#{token.value}', expecting ')'")
312
+ end
313
+ else
314
+ Error.syntax_error(token.line, token.src, token.i, "unexpected '#{token.value}', expecting '<element>'")
315
+ end
316
+ skip_breaks
317
+ if token.type == :arrow
318
+ ast = object_message(ast)
319
+ if token.type == :lround
320
+ ast = pcall(ast)
321
+ end
322
+ end
323
+ ast
324
+ end
325
+
326
+ def pcall(ast)
327
+ consume_and_skip_breaks
328
+ params = []
329
+ params = expr_list unless token.type == :rround
330
+ if token.type == :rround
331
+ consume
332
+ ast = Node.new(:call, {:lambda => ast, :params => params})
333
+ if token.type == :lround
334
+ ast = pcall(ast)
335
+ end
336
+ if token.type == :arrow
337
+ ast = object_message(ast)
338
+ if token.type == :lround
339
+ ast = pcall(ast)
340
+ end
341
+ end
342
+ else
343
+ Error.syntax_error(token.line, token.src, token.i, "unexpected '#{token.value}', expecting ')'")
344
+ end
345
+ ast
346
+ end
347
+
348
+ def object_message(ast)
349
+ if token.type == :arrow
350
+ consume_and_skip_breaks
351
+ id = token
352
+ if id.type == :id
353
+ consume
354
+ Node.new(:object_message, {:object => ast, :message => Node.new(:id, {:value=>id.value})})
355
+ end
356
+ end
357
+ end
358
+
359
+ def consume
360
+ t = @lexer.next_token
361
+ if t
362
+ @token = t
363
+ else
364
+ @token.type = :eof
365
+ end
366
+ end
367
+
368
+ def consume_and_skip_breaks
369
+ consume
370
+ skip_breaks
371
+ end
372
+
373
+ def token
374
+ @token || @eof
375
+ end
376
+ end
377
+ end
378
+ end
@@ -0,0 +1,19 @@
1
+ module PLang
2
+ module Parser
3
+ class Token
4
+ attr_accessor :value
5
+ attr_accessor :type
6
+ attr_accessor :line
7
+ attr_accessor :i
8
+ attr_accessor :src
9
+
10
+ def initialize(type)
11
+ @type = type
12
+ end
13
+
14
+ def to_s
15
+ "\#{#{type.to_s}: #{value}}"
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ module PLang
2
+ module VM
3
+ module PFunctions
4
+ def add_to_interpreter_boolean_functions
5
+
6
+ object_message "{boolean: x}", :_and do |object|
7
+ plambda "{boolean: y}" do |value|
8
+ PObject.new(:boolean, [(object.params[0] and value[0].params[0])])
9
+ end
10
+ end
11
+
12
+ object_message "{boolean: x}", :_or do |object|
13
+ plambda "{boolean: y}" do |value|
14
+ PObject.new(:boolean, [(object.params[0] or value[0].params[0])])
15
+ end
16
+ end
17
+
18
+ object_message "{boolean: x}", :_not do |object|
19
+ plambda do
20
+ PObject.new(:boolean, [(not object.params[0])])
21
+ end
22
+ end
23
+
24
+ end
25
+ end
26
+ end
27
+ end