emfrp 0.1.2 → 0.1.3
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.
- checksums.yaml +4 -4
- data/README.md +45 -12
- data/bin/emfrp +4 -1
- data/examples/LCDClock/LCDClock.mfrp +93 -93
- data/examples/LCDClock/LCDClock_LPC1768.bin +0 -0
- data/examples/LCDClock/README.md +24 -24
- data/examples/LCDPositioner/LCDPositioner.mfrp +30 -30
- data/examples/LCDPositioner/LCDPositionerMain.c +15 -15
- data/examples/MostDistantPoint/MostDistantPoint.mfrp +25 -25
- data/examples/MostDistantPoint/MostDistantPointMain.c +14 -14
- data/lib/emfrp/compile/c/alloc.rb +200 -200
- data/lib/emfrp/compile/c/codegen.rb +18 -18
- data/lib/emfrp/compile/c/codegen_context.rb +218 -218
- data/lib/emfrp/compile/c/monofy.rb +185 -185
- data/lib/emfrp/compile/c/syntax_codegen.rb +364 -364
- data/lib/emfrp/compile/c/syntax_exp_codegen.rb +119 -119
- data/lib/emfrp/compile/graphviz/graphviz.rb +53 -53
- data/lib/emfrp/compile_error.rb +95 -95
- data/lib/emfrp/interpreter/command_manager.rb +367 -367
- data/lib/emfrp/interpreter/evaluater.rb +146 -146
- data/lib/emfrp/interpreter/file_loader.rb +52 -52
- data/lib/emfrp/interpreter/interpreter.rb +200 -195
- data/lib/emfrp/parser/expression.rb +386 -386
- data/lib/emfrp/parser/misc.rb +184 -184
- data/lib/emfrp/parser/newnode_convert.rb +72 -72
- data/lib/emfrp/parser/operator.rb +25 -25
- data/lib/emfrp/parser/parser.rb +150 -150
- data/lib/emfrp/parser/parsing_error.rb +49 -49
- data/lib/emfrp/parser/toplevel.rb +555 -555
- data/lib/emfrp/pre_convert/pre_convert.rb +32 -32
- data/lib/emfrp/syntax.rb +171 -171
- data/lib/emfrp/typing/typing_error.rb +47 -47
- data/lib/emfrp/typing/union_type.rb +197 -197
- data/lib/emfrp/version.rb +1 -1
- data/mfrp_include/Std.mfrp +122 -122
- data/tests/Rakefile +8 -8
- data/tests/Rakefile.common +27 -27
- data/tests/command/Rakefile +2 -2
- data/tests/command/ReplaceNode.mfrp +39 -39
- data/tests/compiler/ComplexDataType/ComplexDataType.mfrp +14 -14
- data/tests/compiler/ComplexDataType/ComplexDataTypeMain.c +15 -15
- data/tests/compiler/ComplexDataType/Rakefile +2 -2
- data/tests/compiler/ComplexDataType/expected_out.txt +0 -0
- data/tests/compiler/ComplexDataType/in.txt +5 -5
- data/tests/compiler/LCDClock/LCDClock.mfrp +90 -90
- data/tests/compiler/LCDClock/LCDClockMain.c +0 -0
- data/tests/compiler/LCDClock/Rakefile +2 -2
- data/tests/compiler/LCDClock/expected_out.txt +0 -0
- data/tests/compiler/LCDClock/in.txt +0 -0
- data/tests/compiler/LCDPositioner/LCDPositioner.mfrp +30 -30
- data/tests/compiler/LCDPositioner/LCDPositionerMain.c +15 -15
- data/tests/compiler/LCDPositioner/Rakefile +2 -2
- data/tests/compiler/LCDPositioner/graph.dot +0 -0
- data/tests/compiler/LCDPositioner/graph.png +0 -0
- data/tests/compiler/Rakefile +8 -8
- data/tests/compiler/Rakefile.common +23 -23
- data/tests/compiler/UseData/Rakefile +2 -2
- data/tests/compiler/UseData/UseData.mfrp +8 -8
- data/tests/compiler/UseSubModule/Rakefile +2 -2
- data/tests/compiler/UseSubModule/SubModule.mfrp +8 -8
- data/tests/compiler/UseSubModule/SubModule2.mfrp +5 -5
- data/tests/compiler/UseSubModule/UseSubModule.mfrp +11 -11
- data/tests/core/FromAnnotation.mfrp +18 -18
- data/tests/core/Last.mfrp +10 -10
- data/tests/core/Rakefile +2 -2
- data/tests/core/TypingTest.mfrp +11 -11
- data/tests/core/WithoutInputs.mfrp +19 -19
- data/tests/load_time_error/Rakefile +32 -32
- data/tests/load_time_error/TypeMismatch.mfrp +4 -4
- metadata +3 -3
@@ -1,386 +1,386 @@
|
|
1
|
-
require 'parser_combinator/string_parser'
|
2
|
-
|
3
|
-
module Emfrp
|
4
|
-
class Parser < ParserCombinator::StringParser
|
5
|
-
|
6
|
-
# Expression
|
7
|
-
# --------------------
|
8
|
-
|
9
|
-
parser :exp do
|
10
|
-
if_exp ^ builtin_operation
|
11
|
-
end
|
12
|
-
|
13
|
-
# Builtin Operator Expression
|
14
|
-
# --------------------
|
15
|
-
|
16
|
-
parser :if_exp do
|
17
|
-
seq(
|
18
|
-
symbol("if").name(:keyword),
|
19
|
-
many1(ws),
|
20
|
-
exp.err("if-exp", "valid conditional exp").name(:cond),
|
21
|
-
many1(ws),
|
22
|
-
str("then"),
|
23
|
-
many1(ws),
|
24
|
-
exp.err("if-exp", "valid then exp").name(:then),
|
25
|
-
many1(ws),
|
26
|
-
str("else"),
|
27
|
-
many1(ws),
|
28
|
-
exp.err("if-exp", "valid then exp").name(:else),
|
29
|
-
).map do |x|
|
30
|
-
true_sym = SSymbol.new(:desc => "True")
|
31
|
-
true_pat = ValuePattern.new(:name => true_sym, :args => [], :ref => nil, :type => nil)
|
32
|
-
true_case = Case.new(:pattern => true_pat, :exp => x[:then])
|
33
|
-
false_sym = SSymbol.new(:desc => "False")
|
34
|
-
false_pat = ValuePattern.new(:name => false_sym, :args => [], :ref => nil, :type => nil)
|
35
|
-
false_case = Case.new(:pattern => false_pat, :exp => x[:else])
|
36
|
-
MatchExp.new(:exp => x[:cond], :cases => [true_case, false_case])
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
parser :builtin_operation do
|
41
|
-
x = match_with_indent_case_group_op ^ match_with_liner_case_group_op
|
42
|
-
seq(
|
43
|
-
operator_exp.name(:exp),
|
44
|
-
many_fail(many1(ws) > x).name(:builtin_ops)
|
45
|
-
).map do |x|
|
46
|
-
x[:builtin_ops].inject(x[:exp]) do |acc, ep|
|
47
|
-
ep.call(acc)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
parser :match_with_indent_case_group_op do
|
53
|
-
seq(
|
54
|
-
str("of:"),
|
55
|
-
many(ws),
|
56
|
-
case_group.err("match-exp", "valid case statement").name(:cases)
|
57
|
-
).map do |x|
|
58
|
-
proc{|e| MatchExp.new(x.to_h, :exp => e)}
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
parser :match_with_liner_case_group_op do
|
63
|
-
seq(
|
64
|
-
str("of"),
|
65
|
-
many1(ws),
|
66
|
-
many1_fail(
|
67
|
-
seq(
|
68
|
-
pattern.name(:pattern).name(:pattern),
|
69
|
-
many1(ws),
|
70
|
-
str("->").err("lienr-match-exp", "->"),
|
71
|
-
many1(ws),
|
72
|
-
exp.err("liner-match-exp", "invalid exp").name(:exp)
|
73
|
-
).map{|x| Case.new(x.to_h)},
|
74
|
-
comma_separator
|
75
|
-
).name(:cases)
|
76
|
-
).map do |x|
|
77
|
-
proc{|e| MatchExp.new(x.to_h, :exp => e)}
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
parser :case_group do
|
82
|
-
cs = seq(
|
83
|
-
many1_fail(pattern, or_separator).name(:patterns),
|
84
|
-
many1(ws).err("case-exp", "space"),
|
85
|
-
str("->").err("case-exp", "'to'"),
|
86
|
-
many1(ws),
|
87
|
-
exp.err("match-exp", "invalid exp").name(:exp)
|
88
|
-
).map do |x|
|
89
|
-
x[:patterns].map{|pat| Case.new(:pattern => pat, :exp => x[:exp].deep_copy)}
|
90
|
-
end
|
91
|
-
many1_fail(cs, many1(ws)).map(&:flatten) < many1(ws) < str(":endcase")
|
92
|
-
end
|
93
|
-
|
94
|
-
parser :pattern do
|
95
|
-
pat = dont_care_pattern ^ name_pattern ^ recursive_pattern ^ no_arg_pattern ^ tuple_pattern ^ integral_pattern
|
96
|
-
seq(
|
97
|
-
pat.name(:pattern),
|
98
|
-
opt_fail(
|
99
|
-
many(ws) > str(":") > many(ws) >
|
100
|
-
type.err("param-def", "type")
|
101
|
-
).to_nil.name(:type)
|
102
|
-
).map do |x|
|
103
|
-
x[:pattern][:type] = x[:type]
|
104
|
-
x[:pattern]
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
parser :dont_care_pattern do
|
109
|
-
symbol("_").map do |c|
|
110
|
-
AnyPattern.new(:ref => nil, :keyword => c)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
parser :name_pattern do
|
115
|
-
ident_begin_lower.map do |n|
|
116
|
-
AnyPattern.new(:ref => n)
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
parser :recursive_pattern do
|
121
|
-
seq(
|
122
|
-
tvalue_symbol.name(:name),
|
123
|
-
many(ws),
|
124
|
-
str("("),
|
125
|
-
many(ws),
|
126
|
-
many1_fail(pattern, comma_separator).name(:args),
|
127
|
-
many(ws),
|
128
|
-
symbol(")").name(:keyword),
|
129
|
-
opt_fail(
|
130
|
-
many(ws) > str("as") > many1(ws) > var_name.err("pattern", "invalid name")
|
131
|
-
).to_nil.name(:ref)
|
132
|
-
).map{|x| ValuePattern.new(x.to_h)}
|
133
|
-
end
|
134
|
-
|
135
|
-
parser :no_arg_pattern do
|
136
|
-
seq(
|
137
|
-
tvalue_symbol.name(:name),
|
138
|
-
opt_fail(
|
139
|
-
many1(ws) > str("as") > var_name.err("pattern", "invalid name")
|
140
|
-
).to_nil.name(:ref)
|
141
|
-
).map{|x| ValuePattern.new(x.to_h, :args => [])}
|
142
|
-
end
|
143
|
-
|
144
|
-
parser :tuple_pattern do
|
145
|
-
seq(
|
146
|
-
symbol("(").name(:keyword1),
|
147
|
-
many(ws),
|
148
|
-
pattern.name(:arg_head),
|
149
|
-
many(ws),
|
150
|
-
str(","),
|
151
|
-
many(ws),
|
152
|
-
many1_fail(pattern, comma_separator).name(:arg_tail),
|
153
|
-
many(ws),
|
154
|
-
symbol(")").name(:keyword2),
|
155
|
-
opt_fail(
|
156
|
-
many(ws) > str("as") > many1(ws) > var_name.err("tuple-pattern", "invalid name")
|
157
|
-
).to_nil.name(:ref)
|
158
|
-
).map do |x|
|
159
|
-
args = [x[:arg_head]] + x[:arg_tail]
|
160
|
-
ValuePattern.new(
|
161
|
-
:name => SSymbol.new(:desc => "Tuple" + args.size.to_s),
|
162
|
-
:args => args,
|
163
|
-
:ref => x[:ref],
|
164
|
-
:keyword1 => x[:keyword1],
|
165
|
-
:keyword2 => x[:keyword2]
|
166
|
-
)
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
parser :integral_pattern do
|
171
|
-
integral_literal.map{|n| IntegralPattern.new(:val => n, :ref => nil)}
|
172
|
-
end
|
173
|
-
|
174
|
-
# Operator Expression
|
175
|
-
# --------------------
|
176
|
-
|
177
|
-
parser :operator_exp do
|
178
|
-
opexp = operator_general.map do |op|
|
179
|
-
proc do |l, r|
|
180
|
-
if l.is_a?(OperatorSeq)
|
181
|
-
OperatorSeq.new(:seq => l[:seq] + [op, r])
|
182
|
-
else
|
183
|
-
OperatorSeq.new(:seq => [l, op, r])
|
184
|
-
end
|
185
|
-
end
|
186
|
-
end
|
187
|
-
binopl_fail(primary, many(ws) > opexp < many(ws))
|
188
|
-
end
|
189
|
-
|
190
|
-
# Lower Expression
|
191
|
-
# --------------------
|
192
|
-
|
193
|
-
parser :primary do
|
194
|
-
atom >> proc{|a|
|
195
|
-
many(many(ws) > method_call).map do |cs|
|
196
|
-
if cs == [] then a else cs.inject(a){|acc, p| p.call(acc)} end
|
197
|
-
end
|
198
|
-
}
|
199
|
-
end
|
200
|
-
|
201
|
-
parser :method_call do
|
202
|
-
seq(
|
203
|
-
symbol(".").name(:keyword1),
|
204
|
-
many(ws),
|
205
|
-
ident_begin_lower.err("method_call", "invalid method name").name(:name),
|
206
|
-
opt_fail(
|
207
|
-
seq(
|
208
|
-
many(ws_without_newline),
|
209
|
-
symbol("(").name(:keyword2),
|
210
|
-
many(ws),
|
211
|
-
many_fail(exp, comma_separator).name(:args),
|
212
|
-
many(ws),
|
213
|
-
symbol(")").name(:keyword3)
|
214
|
-
)
|
215
|
-
).to_nil.name(:args)
|
216
|
-
).map do |x|
|
217
|
-
proc do |receiver|
|
218
|
-
if x[:args]
|
219
|
-
FuncCall.new(
|
220
|
-
:name => x[:name],
|
221
|
-
:keywords => [x[:keyword1], x[:args][:keyword2], x[:args][:keyword3]],
|
222
|
-
:args => [receiver] + x[:args][:args]
|
223
|
-
)
|
224
|
-
else
|
225
|
-
FuncCall.new(
|
226
|
-
:name => x[:name],
|
227
|
-
:keyword => x[:keyword1],
|
228
|
-
:args => [receiver]
|
229
|
-
)
|
230
|
-
end
|
231
|
-
end
|
232
|
-
end
|
233
|
-
end
|
234
|
-
|
235
|
-
parser :atom do
|
236
|
-
literal_exp ^ single_op ^ func_call ^ block_exp ^ value_cons ^ skip ^ var_ref
|
237
|
-
end
|
238
|
-
|
239
|
-
parser :single_op do
|
240
|
-
seq(operator, many(ws), atom).map do |x|
|
241
|
-
name = x[0].update(:desc => "@" + x[0][:desc])
|
242
|
-
FuncCall.new(:name => x[0], :args => [x[2]])
|
243
|
-
end
|
244
|
-
end
|
245
|
-
|
246
|
-
parser :func_call do
|
247
|
-
seq(
|
248
|
-
func_name.name(:name),
|
249
|
-
many(ws_without_newline),
|
250
|
-
symbol("(").name(:keyword1),
|
251
|
-
many(ws),
|
252
|
-
many1_fail(exp, comma_separator).name(:args),
|
253
|
-
many(ws),
|
254
|
-
symbol(")").name(:keyword2)
|
255
|
-
).map do |x|
|
256
|
-
FuncCall.new(x.to_h)
|
257
|
-
end
|
258
|
-
end
|
259
|
-
|
260
|
-
parser :block_exp do
|
261
|
-
seq(
|
262
|
-
symbol("{").name(:keyword1),
|
263
|
-
many(ws),
|
264
|
-
many_fail(many(ws) > assign).name(:assigns),
|
265
|
-
many(ws),
|
266
|
-
exp.err("block-exp", "valid return-exp").name(:exp),
|
267
|
-
many(ws),
|
268
|
-
symbol("}").name(:keyword2)
|
269
|
-
).map do |x|
|
270
|
-
x[:assigns].reverse.inject(x[:exp]) do |acc, a|
|
271
|
-
c = Case.new(:pattern => a[:pattern], :exp => acc)
|
272
|
-
MatchExp.new(:cases => [c], :exp => a[:exp])
|
273
|
-
end
|
274
|
-
end
|
275
|
-
end
|
276
|
-
|
277
|
-
parser :assign do # -> Hash
|
278
|
-
seq(
|
279
|
-
pattern.name(:pattern),
|
280
|
-
many(ws),
|
281
|
-
str("="),
|
282
|
-
many(ws),
|
283
|
-
exp.err("assign", "invalid assign statement").name(:exp)
|
284
|
-
).map do |x|
|
285
|
-
x.to_h
|
286
|
-
end
|
287
|
-
end
|
288
|
-
|
289
|
-
parser :value_cons do # -> ValueConst
|
290
|
-
seq(
|
291
|
-
tvalue_symbol.name(:name),
|
292
|
-
opt_fail(
|
293
|
-
seq(
|
294
|
-
many(ws_without_newline),
|
295
|
-
str("("),
|
296
|
-
many(ws),
|
297
|
-
many_fail(exp, comma_separator).name(:args),
|
298
|
-
many(ws),
|
299
|
-
symbol(")").name(:keyword)
|
300
|
-
).name(:args)
|
301
|
-
).to_nil.err("value-construction", "invalid form of argument").name(:args)
|
302
|
-
).map do |x|
|
303
|
-
if x[:args]
|
304
|
-
ValueConst.new(:name => x[:name], :args => x[:args][:args], :keyword => x[:args][:keyword])
|
305
|
-
else
|
306
|
-
ValueConst.new(:name => x[:name], :args => [])
|
307
|
-
end
|
308
|
-
end
|
309
|
-
end
|
310
|
-
|
311
|
-
parser :skip do
|
312
|
-
symbol("skip").map do |x|
|
313
|
-
SkipExp.new(:keyword => x)
|
314
|
-
end
|
315
|
-
end
|
316
|
-
|
317
|
-
parser :var_ref do
|
318
|
-
var_name_allow_last.map do |s|
|
319
|
-
VarRef.new(:name => s)
|
320
|
-
end
|
321
|
-
end
|
322
|
-
|
323
|
-
# Literal Expression
|
324
|
-
# --------------------
|
325
|
-
|
326
|
-
parser :literal_exp do
|
327
|
-
char_literal ^ parenth_or_tuple_literal ^ floating_literal ^ integral_literal
|
328
|
-
end
|
329
|
-
|
330
|
-
parser :char_literal do
|
331
|
-
seq(
|
332
|
-
symbol("'").name(:keyword1),
|
333
|
-
((backslash > item) | item).map{|i| i.item}.name(:entity),
|
334
|
-
symbol("'").name(:keyword2),
|
335
|
-
).map do |x|
|
336
|
-
LiteralChar.new(x.to_h)
|
337
|
-
end
|
338
|
-
end
|
339
|
-
|
340
|
-
parser :parenth_or_tuple_literal do
|
341
|
-
seq(
|
342
|
-
symbol("(").name(:keyword1),
|
343
|
-
many(ws),
|
344
|
-
many1_fail(exp, comma_separator).name(:entity),
|
345
|
-
many(ws),
|
346
|
-
symbol(")").name(:keyword2)
|
347
|
-
).map do |x|
|
348
|
-
if x[:entity].size == 1
|
349
|
-
ParenthExp.new(
|
350
|
-
:exp => x[:entity].first,
|
351
|
-
:keyword1 => x[:keyword1],
|
352
|
-
:keyword2 => x[:keyword2]
|
353
|
-
)
|
354
|
-
else
|
355
|
-
ValueConst.new(
|
356
|
-
:name => SSymbol.new(:desc => "Tuple" + x[:entity].size.to_s),
|
357
|
-
:args => x[:entity],
|
358
|
-
:parent_begin => x[:keyword1],
|
359
|
-
:parent_end => x[:keyword2]
|
360
|
-
)
|
361
|
-
end
|
362
|
-
end
|
363
|
-
end
|
364
|
-
|
365
|
-
parser :integral_literal do
|
366
|
-
(positive_integer | zero_integer).map do |x|
|
367
|
-
LiteralIntegral.new(:entity => x)
|
368
|
-
end
|
369
|
-
end
|
370
|
-
|
371
|
-
parser :floating_literal do
|
372
|
-
seq(
|
373
|
-
integral_literal.name(:prefix),
|
374
|
-
char("."),
|
375
|
-
many1(digit).name(:suffix)
|
376
|
-
).map do |x|
|
377
|
-
sym = SSymbol.new(:desc => x[:prefix][:entity][:desc] + "." + x[:suffix].map(&:item).join)
|
378
|
-
LiteralFloating.new(
|
379
|
-
:entity => sym,
|
380
|
-
:start_pos => x[:prefix][:entity][:start_pos],
|
381
|
-
:end_pos => x[:suffix][-1].tag
|
382
|
-
)
|
383
|
-
end
|
384
|
-
end
|
385
|
-
end
|
386
|
-
end
|
1
|
+
require 'parser_combinator/string_parser'
|
2
|
+
|
3
|
+
module Emfrp
|
4
|
+
class Parser < ParserCombinator::StringParser
|
5
|
+
|
6
|
+
# Expression
|
7
|
+
# --------------------
|
8
|
+
|
9
|
+
parser :exp do
|
10
|
+
if_exp ^ builtin_operation
|
11
|
+
end
|
12
|
+
|
13
|
+
# Builtin Operator Expression
|
14
|
+
# --------------------
|
15
|
+
|
16
|
+
parser :if_exp do
|
17
|
+
seq(
|
18
|
+
symbol("if").name(:keyword),
|
19
|
+
many1(ws),
|
20
|
+
exp.err("if-exp", "valid conditional exp").name(:cond),
|
21
|
+
many1(ws),
|
22
|
+
str("then"),
|
23
|
+
many1(ws),
|
24
|
+
exp.err("if-exp", "valid then exp").name(:then),
|
25
|
+
many1(ws),
|
26
|
+
str("else"),
|
27
|
+
many1(ws),
|
28
|
+
exp.err("if-exp", "valid then exp").name(:else),
|
29
|
+
).map do |x|
|
30
|
+
true_sym = SSymbol.new(:desc => "True")
|
31
|
+
true_pat = ValuePattern.new(:name => true_sym, :args => [], :ref => nil, :type => nil)
|
32
|
+
true_case = Case.new(:pattern => true_pat, :exp => x[:then])
|
33
|
+
false_sym = SSymbol.new(:desc => "False")
|
34
|
+
false_pat = ValuePattern.new(:name => false_sym, :args => [], :ref => nil, :type => nil)
|
35
|
+
false_case = Case.new(:pattern => false_pat, :exp => x[:else])
|
36
|
+
MatchExp.new(:exp => x[:cond], :cases => [true_case, false_case])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
parser :builtin_operation do
|
41
|
+
x = match_with_indent_case_group_op ^ match_with_liner_case_group_op
|
42
|
+
seq(
|
43
|
+
operator_exp.name(:exp),
|
44
|
+
many_fail(many1(ws) > x).name(:builtin_ops)
|
45
|
+
).map do |x|
|
46
|
+
x[:builtin_ops].inject(x[:exp]) do |acc, ep|
|
47
|
+
ep.call(acc)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
parser :match_with_indent_case_group_op do
|
53
|
+
seq(
|
54
|
+
str("of:"),
|
55
|
+
many(ws),
|
56
|
+
case_group.err("match-exp", "valid case statement").name(:cases)
|
57
|
+
).map do |x|
|
58
|
+
proc{|e| MatchExp.new(x.to_h, :exp => e)}
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
parser :match_with_liner_case_group_op do
|
63
|
+
seq(
|
64
|
+
str("of"),
|
65
|
+
many1(ws),
|
66
|
+
many1_fail(
|
67
|
+
seq(
|
68
|
+
pattern.name(:pattern).name(:pattern),
|
69
|
+
many1(ws),
|
70
|
+
str("->").err("lienr-match-exp", "->"),
|
71
|
+
many1(ws),
|
72
|
+
exp.err("liner-match-exp", "invalid exp").name(:exp)
|
73
|
+
).map{|x| Case.new(x.to_h)},
|
74
|
+
comma_separator
|
75
|
+
).name(:cases)
|
76
|
+
).map do |x|
|
77
|
+
proc{|e| MatchExp.new(x.to_h, :exp => e)}
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
parser :case_group do
|
82
|
+
cs = seq(
|
83
|
+
many1_fail(pattern, or_separator).name(:patterns),
|
84
|
+
many1(ws).err("case-exp", "space"),
|
85
|
+
str("->").err("case-exp", "'to'"),
|
86
|
+
many1(ws),
|
87
|
+
exp.err("match-exp", "invalid exp").name(:exp)
|
88
|
+
).map do |x|
|
89
|
+
x[:patterns].map{|pat| Case.new(:pattern => pat, :exp => x[:exp].deep_copy)}
|
90
|
+
end
|
91
|
+
many1_fail(cs, many1(ws)).map(&:flatten) < many1(ws) < str(":endcase")
|
92
|
+
end
|
93
|
+
|
94
|
+
parser :pattern do
|
95
|
+
pat = dont_care_pattern ^ name_pattern ^ recursive_pattern ^ no_arg_pattern ^ tuple_pattern ^ integral_pattern
|
96
|
+
seq(
|
97
|
+
pat.name(:pattern),
|
98
|
+
opt_fail(
|
99
|
+
many(ws) > str(":") > many(ws) >
|
100
|
+
type.err("param-def", "type")
|
101
|
+
).to_nil.name(:type)
|
102
|
+
).map do |x|
|
103
|
+
x[:pattern][:type] = x[:type]
|
104
|
+
x[:pattern]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
parser :dont_care_pattern do
|
109
|
+
symbol("_").map do |c|
|
110
|
+
AnyPattern.new(:ref => nil, :keyword => c)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
parser :name_pattern do
|
115
|
+
ident_begin_lower.map do |n|
|
116
|
+
AnyPattern.new(:ref => n)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
parser :recursive_pattern do
|
121
|
+
seq(
|
122
|
+
tvalue_symbol.name(:name),
|
123
|
+
many(ws),
|
124
|
+
str("("),
|
125
|
+
many(ws),
|
126
|
+
many1_fail(pattern, comma_separator).name(:args),
|
127
|
+
many(ws),
|
128
|
+
symbol(")").name(:keyword),
|
129
|
+
opt_fail(
|
130
|
+
many(ws) > str("as") > many1(ws) > var_name.err("pattern", "invalid name")
|
131
|
+
).to_nil.name(:ref)
|
132
|
+
).map{|x| ValuePattern.new(x.to_h)}
|
133
|
+
end
|
134
|
+
|
135
|
+
parser :no_arg_pattern do
|
136
|
+
seq(
|
137
|
+
tvalue_symbol.name(:name),
|
138
|
+
opt_fail(
|
139
|
+
many1(ws) > str("as") > var_name.err("pattern", "invalid name")
|
140
|
+
).to_nil.name(:ref)
|
141
|
+
).map{|x| ValuePattern.new(x.to_h, :args => [])}
|
142
|
+
end
|
143
|
+
|
144
|
+
parser :tuple_pattern do
|
145
|
+
seq(
|
146
|
+
symbol("(").name(:keyword1),
|
147
|
+
many(ws),
|
148
|
+
pattern.name(:arg_head),
|
149
|
+
many(ws),
|
150
|
+
str(","),
|
151
|
+
many(ws),
|
152
|
+
many1_fail(pattern, comma_separator).name(:arg_tail),
|
153
|
+
many(ws),
|
154
|
+
symbol(")").name(:keyword2),
|
155
|
+
opt_fail(
|
156
|
+
many(ws) > str("as") > many1(ws) > var_name.err("tuple-pattern", "invalid name")
|
157
|
+
).to_nil.name(:ref)
|
158
|
+
).map do |x|
|
159
|
+
args = [x[:arg_head]] + x[:arg_tail]
|
160
|
+
ValuePattern.new(
|
161
|
+
:name => SSymbol.new(:desc => "Tuple" + args.size.to_s),
|
162
|
+
:args => args,
|
163
|
+
:ref => x[:ref],
|
164
|
+
:keyword1 => x[:keyword1],
|
165
|
+
:keyword2 => x[:keyword2]
|
166
|
+
)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
parser :integral_pattern do
|
171
|
+
integral_literal.map{|n| IntegralPattern.new(:val => n, :ref => nil)}
|
172
|
+
end
|
173
|
+
|
174
|
+
# Operator Expression
|
175
|
+
# --------------------
|
176
|
+
|
177
|
+
parser :operator_exp do
|
178
|
+
opexp = operator_general.map do |op|
|
179
|
+
proc do |l, r|
|
180
|
+
if l.is_a?(OperatorSeq)
|
181
|
+
OperatorSeq.new(:seq => l[:seq] + [op, r])
|
182
|
+
else
|
183
|
+
OperatorSeq.new(:seq => [l, op, r])
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
binopl_fail(primary, many(ws) > opexp < many(ws))
|
188
|
+
end
|
189
|
+
|
190
|
+
# Lower Expression
|
191
|
+
# --------------------
|
192
|
+
|
193
|
+
parser :primary do
|
194
|
+
atom >> proc{|a|
|
195
|
+
many(many(ws) > method_call).map do |cs|
|
196
|
+
if cs == [] then a else cs.inject(a){|acc, p| p.call(acc)} end
|
197
|
+
end
|
198
|
+
}
|
199
|
+
end
|
200
|
+
|
201
|
+
parser :method_call do
|
202
|
+
seq(
|
203
|
+
symbol(".").name(:keyword1),
|
204
|
+
many(ws),
|
205
|
+
ident_begin_lower.err("method_call", "invalid method name").name(:name),
|
206
|
+
opt_fail(
|
207
|
+
seq(
|
208
|
+
many(ws_without_newline),
|
209
|
+
symbol("(").name(:keyword2),
|
210
|
+
many(ws),
|
211
|
+
many_fail(exp, comma_separator).name(:args),
|
212
|
+
many(ws),
|
213
|
+
symbol(")").name(:keyword3)
|
214
|
+
)
|
215
|
+
).to_nil.name(:args)
|
216
|
+
).map do |x|
|
217
|
+
proc do |receiver|
|
218
|
+
if x[:args]
|
219
|
+
FuncCall.new(
|
220
|
+
:name => x[:name],
|
221
|
+
:keywords => [x[:keyword1], x[:args][:keyword2], x[:args][:keyword3]],
|
222
|
+
:args => [receiver] + x[:args][:args]
|
223
|
+
)
|
224
|
+
else
|
225
|
+
FuncCall.new(
|
226
|
+
:name => x[:name],
|
227
|
+
:keyword => x[:keyword1],
|
228
|
+
:args => [receiver]
|
229
|
+
)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
parser :atom do
|
236
|
+
literal_exp ^ single_op ^ func_call ^ block_exp ^ value_cons ^ skip ^ var_ref
|
237
|
+
end
|
238
|
+
|
239
|
+
parser :single_op do
|
240
|
+
seq(operator, many(ws), atom).map do |x|
|
241
|
+
name = x[0].update(:desc => "@" + x[0][:desc])
|
242
|
+
FuncCall.new(:name => x[0], :args => [x[2]])
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
parser :func_call do
|
247
|
+
seq(
|
248
|
+
func_name.name(:name),
|
249
|
+
many(ws_without_newline),
|
250
|
+
symbol("(").name(:keyword1),
|
251
|
+
many(ws),
|
252
|
+
many1_fail(exp, comma_separator).name(:args),
|
253
|
+
many(ws),
|
254
|
+
symbol(")").name(:keyword2)
|
255
|
+
).map do |x|
|
256
|
+
FuncCall.new(x.to_h)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
parser :block_exp do
|
261
|
+
seq(
|
262
|
+
symbol("{").name(:keyword1),
|
263
|
+
many(ws),
|
264
|
+
many_fail(many(ws) > assign).name(:assigns),
|
265
|
+
many(ws),
|
266
|
+
exp.err("block-exp", "valid return-exp").name(:exp),
|
267
|
+
many(ws),
|
268
|
+
symbol("}").name(:keyword2)
|
269
|
+
).map do |x|
|
270
|
+
x[:assigns].reverse.inject(x[:exp]) do |acc, a|
|
271
|
+
c = Case.new(:pattern => a[:pattern], :exp => acc)
|
272
|
+
MatchExp.new(:cases => [c], :exp => a[:exp])
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
parser :assign do # -> Hash
|
278
|
+
seq(
|
279
|
+
pattern.name(:pattern),
|
280
|
+
many(ws),
|
281
|
+
str("="),
|
282
|
+
many(ws),
|
283
|
+
exp.err("assign", "invalid assign statement").name(:exp)
|
284
|
+
).map do |x|
|
285
|
+
x.to_h
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
parser :value_cons do # -> ValueConst
|
290
|
+
seq(
|
291
|
+
tvalue_symbol.name(:name),
|
292
|
+
opt_fail(
|
293
|
+
seq(
|
294
|
+
many(ws_without_newline),
|
295
|
+
str("("),
|
296
|
+
many(ws),
|
297
|
+
many_fail(exp, comma_separator).name(:args),
|
298
|
+
many(ws),
|
299
|
+
symbol(")").name(:keyword)
|
300
|
+
).name(:args)
|
301
|
+
).to_nil.err("value-construction", "invalid form of argument").name(:args)
|
302
|
+
).map do |x|
|
303
|
+
if x[:args]
|
304
|
+
ValueConst.new(:name => x[:name], :args => x[:args][:args], :keyword => x[:args][:keyword])
|
305
|
+
else
|
306
|
+
ValueConst.new(:name => x[:name], :args => [])
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
parser :skip do
|
312
|
+
symbol("skip").map do |x|
|
313
|
+
SkipExp.new(:keyword => x)
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
parser :var_ref do
|
318
|
+
var_name_allow_last.map do |s|
|
319
|
+
VarRef.new(:name => s)
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
# Literal Expression
|
324
|
+
# --------------------
|
325
|
+
|
326
|
+
parser :literal_exp do
|
327
|
+
char_literal ^ parenth_or_tuple_literal ^ floating_literal ^ integral_literal
|
328
|
+
end
|
329
|
+
|
330
|
+
parser :char_literal do
|
331
|
+
seq(
|
332
|
+
symbol("'").name(:keyword1),
|
333
|
+
((backslash > item) | item).map{|i| i.item}.name(:entity),
|
334
|
+
symbol("'").name(:keyword2),
|
335
|
+
).map do |x|
|
336
|
+
LiteralChar.new(x.to_h)
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
parser :parenth_or_tuple_literal do
|
341
|
+
seq(
|
342
|
+
symbol("(").name(:keyword1),
|
343
|
+
many(ws),
|
344
|
+
many1_fail(exp, comma_separator).name(:entity),
|
345
|
+
many(ws),
|
346
|
+
symbol(")").name(:keyword2)
|
347
|
+
).map do |x|
|
348
|
+
if x[:entity].size == 1
|
349
|
+
ParenthExp.new(
|
350
|
+
:exp => x[:entity].first,
|
351
|
+
:keyword1 => x[:keyword1],
|
352
|
+
:keyword2 => x[:keyword2]
|
353
|
+
)
|
354
|
+
else
|
355
|
+
ValueConst.new(
|
356
|
+
:name => SSymbol.new(:desc => "Tuple" + x[:entity].size.to_s),
|
357
|
+
:args => x[:entity],
|
358
|
+
:parent_begin => x[:keyword1],
|
359
|
+
:parent_end => x[:keyword2]
|
360
|
+
)
|
361
|
+
end
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
parser :integral_literal do
|
366
|
+
(positive_integer | zero_integer).map do |x|
|
367
|
+
LiteralIntegral.new(:entity => x)
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
parser :floating_literal do
|
372
|
+
seq(
|
373
|
+
integral_literal.name(:prefix),
|
374
|
+
char("."),
|
375
|
+
many1(digit).name(:suffix)
|
376
|
+
).map do |x|
|
377
|
+
sym = SSymbol.new(:desc => x[:prefix][:entity][:desc] + "." + x[:suffix].map(&:item).join)
|
378
|
+
LiteralFloating.new(
|
379
|
+
:entity => sym,
|
380
|
+
:start_pos => x[:prefix][:entity][:start_pos],
|
381
|
+
:end_pos => x[:suffix][-1].tag
|
382
|
+
)
|
383
|
+
end
|
384
|
+
end
|
385
|
+
end
|
386
|
+
end
|