metal 0.0.2 → 0.0.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.
- data/Manifest.txt +14 -1
- data/bin/metal +63 -16
- data/bin/metal-run +16 -13
- data/config/hoe.rb +4 -2
- data/ext/metal/boot/metal_boot.h +32 -0
- data/{lib/metal/boot.metal → ext/metal/boot/metal_boot.metal} +40 -53
- data/ext/metal/boot/metal_boot.mm +1294 -0
- data/ext/metal/boot/metal_boot_extconf.rb +16 -0
- data/ext/metal/boot/metal_boot_rb.mm +20 -0
- data/ext/metal/runtime/extconf.rb +35 -0
- data/ext/metal/runtime/input.mm +99 -0
- data/ext/metal/runtime/rbinit.mm +17 -0
- data/ext/metal/runtime/runtime.mm +660 -0
- data/include/metal.h +4 -0
- data/include/metal/exception.h +15 -0
- data/include/metal/input.h +42 -0
- data/include/metal/rbcode.h +24 -0
- data/include/metal/runtime.h +97 -0
- data/lib/metal/boot.rb +1 -353
- data/lib/metal/generator.rb +313 -203
- data/lib/metal/runtime.rb +1 -386
- data/lib/metal/version.rb +1 -1
- metadata +32 -8
data/include/metal.h
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#import <vector>
|
|
2
|
+
#import <stack>
|
|
3
|
+
|
|
4
|
+
namespace Metal {
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Input {
|
|
8
|
+
public:
|
|
9
|
+
Input() {}
|
|
10
|
+
virtual ~Input() {}
|
|
11
|
+
|
|
12
|
+
struct at_t {
|
|
13
|
+
at_t() {}
|
|
14
|
+
at_t(const char* pos_, unsigned charlen_) :
|
|
15
|
+
pos(pos_), charlen(charlen_) {}
|
|
16
|
+
const char* pos;
|
|
17
|
+
unsigned charlen;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
virtual at_t at(size_t pos) = 0;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class BufferedInput : public Input {
|
|
25
|
+
public:
|
|
26
|
+
BufferedInput(const char* src, size_t len);
|
|
27
|
+
~BufferedInput();
|
|
28
|
+
public:
|
|
29
|
+
at_t at(size_t pos);
|
|
30
|
+
private:
|
|
31
|
+
size_t m_cur;
|
|
32
|
+
const char* m_pos;
|
|
33
|
+
const char* const m_endpos;
|
|
34
|
+
private:
|
|
35
|
+
inline void prev();
|
|
36
|
+
inline unsigned charlen();
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
} // namespace Metal
|
|
41
|
+
|
|
42
|
+
// vim: ft=objcpp
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#import "metal/runtime.h"
|
|
2
|
+
#import "metal/exception.h"
|
|
3
|
+
#import "metal/input.h"
|
|
4
|
+
|
|
5
|
+
namespace Metal {
|
|
6
|
+
|
|
7
|
+
template <typename Parser>
|
|
8
|
+
static VALUE parse_method_template(VALUE self, VALUE src)
|
|
9
|
+
{
|
|
10
|
+
StringValue(src);
|
|
11
|
+
Metal::BufferedInput input(RSTRING_PTR(src), RSTRING_LEN(src));
|
|
12
|
+
id parser = [[Parser alloc] init:self];
|
|
13
|
+
try {
|
|
14
|
+
VALUE ret = [parser parse:input];
|
|
15
|
+
[parser free];
|
|
16
|
+
return ret;
|
|
17
|
+
} catch (Metal::ParseError& e) {
|
|
18
|
+
[parser free];
|
|
19
|
+
rb_raise(rb_eException, e.what());
|
|
20
|
+
return Qnil;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
} // namespace Metal
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#import "ruby.h"
|
|
2
|
+
#import <objc/Object.h>
|
|
3
|
+
|
|
4
|
+
#define RB_P(val) { \
|
|
5
|
+
rb_define_variable("$RB_P", &val); \
|
|
6
|
+
rb_eval_string("p $RB_P"); \
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
namespace Metal {
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
typedef const char* param_t;
|
|
13
|
+
param_t param_lookup(const char* name);
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class EnvIMPL;
|
|
17
|
+
class Env {
|
|
18
|
+
public:
|
|
19
|
+
Env();
|
|
20
|
+
~Env();
|
|
21
|
+
public:
|
|
22
|
+
VALUE& operator[](param_t key);
|
|
23
|
+
private:
|
|
24
|
+
EnvIMPL* m_impl;
|
|
25
|
+
VALUE m_gc_marker;
|
|
26
|
+
friend class EnvIMPL;
|
|
27
|
+
private:
|
|
28
|
+
Env(const Env&);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class Context;
|
|
33
|
+
|
|
34
|
+
class Lambda {
|
|
35
|
+
public:
|
|
36
|
+
Lambda(Context* _ctx, Env& _env) : ctx(_ctx), env(_env) {}
|
|
37
|
+
virtual ~Lambda() { }
|
|
38
|
+
virtual VALUE call() = 0;
|
|
39
|
+
protected:
|
|
40
|
+
Context* const ctx;
|
|
41
|
+
Env& env;
|
|
42
|
+
private:
|
|
43
|
+
Lambda();
|
|
44
|
+
Lambda(const Lambda&);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class Input;
|
|
49
|
+
|
|
50
|
+
class ContextIMPL;
|
|
51
|
+
class Context {
|
|
52
|
+
public:
|
|
53
|
+
Context(id instance, VALUE rb_instance, Input& input);
|
|
54
|
+
~Context();
|
|
55
|
+
|
|
56
|
+
public:
|
|
57
|
+
VALUE apply(SEL method);
|
|
58
|
+
|
|
59
|
+
VALUE act_or(Lambda** blocks);
|
|
60
|
+
VALUE act_many(Lambda* block);
|
|
61
|
+
VALUE act_many1(Lambda* block);
|
|
62
|
+
VALUE act_may(Lambda* block);
|
|
63
|
+
VALUE act_not(Lambda* block);
|
|
64
|
+
VALUE act_lookahead(Lambda* block);
|
|
65
|
+
VALUE act_char(const char* c, unsigned clen);
|
|
66
|
+
VALUE act_token(const char* s, unsigned slen);
|
|
67
|
+
VALUE act_any();
|
|
68
|
+
VALUE act_charclass(const char* s, unsigned slen);
|
|
69
|
+
|
|
70
|
+
VALUE act_run(Env& env, const char* code, unsigned code_len);
|
|
71
|
+
VALUE act_where(Env& env, const char* code, unsigned code_len);
|
|
72
|
+
|
|
73
|
+
VALUE act_end();
|
|
74
|
+
|
|
75
|
+
private:
|
|
76
|
+
ContextIMPL* m_impl;
|
|
77
|
+
friend class ContextIMPL;
|
|
78
|
+
private:
|
|
79
|
+
Context();
|
|
80
|
+
Context(const Context&);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
} // namespace Metal
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@interface MetalParserBase : Object
|
|
88
|
+
{
|
|
89
|
+
VALUE instance;
|
|
90
|
+
}
|
|
91
|
+
-(id)init:(VALUE)instance;
|
|
92
|
+
-(VALUE)parse:(Metal::Input&)input withRule:(SEL)name;
|
|
93
|
+
-(VALUE)parse:(Metal::Input&)input;
|
|
94
|
+
@end
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
// vim: ft=objcpp
|
data/lib/metal/boot.rb
CHANGED
|
@@ -1,353 +1 @@
|
|
|
1
|
-
|
|
2
|
-
# Metal Bootstrap Parser
|
|
3
|
-
#
|
|
4
|
-
# Copyright (C) 2008 FURUHASHI Sadayuki
|
|
5
|
-
#
|
|
6
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
-
# you may not use this file except in compliance with the License.
|
|
8
|
-
# You may obtain a copy of the License at
|
|
9
|
-
#
|
|
10
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
-
#
|
|
12
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
13
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
-
# See the License for the specific language governing permissions and
|
|
16
|
-
# limitations under the License.
|
|
17
|
-
#
|
|
18
|
-
require 'metal/generator'
|
|
19
|
-
|
|
20
|
-
class MetalParser < Metal::ParserBase
|
|
21
|
-
include Metal::Generator
|
|
22
|
-
def rule_main()
|
|
23
|
-
m = apply(:meta)
|
|
24
|
-
apply(:end)
|
|
25
|
-
m
|
|
26
|
-
end
|
|
27
|
-
def rule_meta()
|
|
28
|
-
xs = act_many(lambda{act_or([lambda{apply(:grammar)
|
|
29
|
-
},
|
|
30
|
-
lambda{apply(:meta_command)
|
|
31
|
-
},
|
|
32
|
-
])
|
|
33
|
-
})
|
|
34
|
-
apply(:s)
|
|
35
|
-
Meta.new(xs)
|
|
36
|
-
end
|
|
37
|
-
def rule_meta_command()
|
|
38
|
-
apply(:s)
|
|
39
|
-
apply(:precode)
|
|
40
|
-
end
|
|
41
|
-
def rule_grammar()
|
|
42
|
-
apply(:s)
|
|
43
|
-
i = apply(:interface_attr)
|
|
44
|
-
n = apply(:grammar_name)
|
|
45
|
-
apply(:s)
|
|
46
|
-
e = act_may(lambda{apply(:extend_attr)})
|
|
47
|
-
apply(:s)
|
|
48
|
-
act_token('{')
|
|
49
|
-
b = apply(:grammar_body)
|
|
50
|
-
act_token('}')
|
|
51
|
-
Grammar.new(n, b, e, i)
|
|
52
|
-
end
|
|
53
|
-
def rule_interface_attr()
|
|
54
|
-
act_or([lambda{act_token('module')
|
|
55
|
-
apply(:fs)
|
|
56
|
-
true
|
|
57
|
-
},
|
|
58
|
-
lambda{act_token('class')
|
|
59
|
-
apply(:fs)
|
|
60
|
-
false
|
|
61
|
-
},
|
|
62
|
-
lambda{ false
|
|
63
|
-
},
|
|
64
|
-
])
|
|
65
|
-
end
|
|
66
|
-
def rule_extend_attr()
|
|
67
|
-
act_token('<')
|
|
68
|
-
apply(:s)
|
|
69
|
-
apply(:grammar_name)
|
|
70
|
-
end
|
|
71
|
-
def rule_grammar_body()
|
|
72
|
-
apply(:s)
|
|
73
|
-
act_many(lambda{act_or([lambda{apply(:rule)
|
|
74
|
-
},
|
|
75
|
-
lambda{apply(:grammar_command)
|
|
76
|
-
},
|
|
77
|
-
])
|
|
78
|
-
})
|
|
79
|
-
end
|
|
80
|
-
def rule_grammar_command()
|
|
81
|
-
act_or([lambda{apply(:precode)
|
|
82
|
-
},
|
|
83
|
-
lambda{apply(:mixin)
|
|
84
|
-
},
|
|
85
|
-
])
|
|
86
|
-
end
|
|
87
|
-
def rule_precode()
|
|
88
|
-
act_token('@{')
|
|
89
|
-
s = act_many1(lambda{act_or([lambda{act_not(lambda{act_token('@')})
|
|
90
|
-
act_any
|
|
91
|
-
},
|
|
92
|
-
lambda{act_token('@')
|
|
93
|
-
act_not(lambda{act_token('}')})
|
|
94
|
-
'@'
|
|
95
|
-
},
|
|
96
|
-
])
|
|
97
|
-
})
|
|
98
|
-
act_token('@}')
|
|
99
|
-
apply(:s)
|
|
100
|
-
Precode.new(s.join)
|
|
101
|
-
end
|
|
102
|
-
def rule_mixin()
|
|
103
|
-
act_token('@include')
|
|
104
|
-
apply(:fs)
|
|
105
|
-
n = apply(:scoped_grammar_name)
|
|
106
|
-
apply(:s)
|
|
107
|
-
Mixin.new(n)
|
|
108
|
-
end
|
|
109
|
-
def rule_scoped_grammar_name()
|
|
110
|
-
xs = act_many1(lambda{s = act_may(lambda{act_token('::')})
|
|
111
|
-
n = apply(:grammar_name)
|
|
112
|
-
"#{s}#{n}"
|
|
113
|
-
})
|
|
114
|
-
xs.join
|
|
115
|
-
end
|
|
116
|
-
def rule_rule()
|
|
117
|
-
act_token('-')
|
|
118
|
-
apply(:s)
|
|
119
|
-
n = apply(:rule_name)
|
|
120
|
-
a = apply(:rule_args)
|
|
121
|
-
apply(:fs)
|
|
122
|
-
r = apply(:or_set)
|
|
123
|
-
apply(:s)
|
|
124
|
-
Rule.new(n, r, a)
|
|
125
|
-
end
|
|
126
|
-
def rule_rule_args()
|
|
127
|
-
act_many(lambda{apply(:s)
|
|
128
|
-
act_token(':')
|
|
129
|
-
apply(:var_name)
|
|
130
|
-
})
|
|
131
|
-
end
|
|
132
|
-
def rule_or_set()
|
|
133
|
-
x = apply(:and_set)
|
|
134
|
-
apply(:s)
|
|
135
|
-
xs = act_many(lambda{apply(:s)
|
|
136
|
-
act_token('/')
|
|
137
|
-
apply(:and_set)
|
|
138
|
-
})
|
|
139
|
-
OrSet.new([x] + xs)
|
|
140
|
-
end
|
|
141
|
-
def rule_and_set()
|
|
142
|
-
apply(:s)
|
|
143
|
-
xs = act_may(lambda{x = apply(:expr)
|
|
144
|
-
xs = act_many(lambda{apply(:fs)
|
|
145
|
-
apply(:expr)
|
|
146
|
-
})
|
|
147
|
-
[x]+xs
|
|
148
|
-
})
|
|
149
|
-
AndSet.new(xs || [])
|
|
150
|
-
end
|
|
151
|
-
def rule_expr()
|
|
152
|
-
p = apply(:pred)
|
|
153
|
-
p = act_may(lambda{apply(:iter,p)})
|
|
154
|
-
v = act_may(lambda{apply(:var)})
|
|
155
|
-
Expression.new(p, v)
|
|
156
|
-
end
|
|
157
|
-
def rule_pred()
|
|
158
|
-
act_or([lambda{act_token('!')
|
|
159
|
-
p = apply(:pred)
|
|
160
|
-
PredNot.new(p)
|
|
161
|
-
},
|
|
162
|
-
lambda{act_token('&')
|
|
163
|
-
f = apply(:literal)
|
|
164
|
-
PredLookahead.new(f)
|
|
165
|
-
},
|
|
166
|
-
lambda{apply(:literal)
|
|
167
|
-
},
|
|
168
|
-
])
|
|
169
|
-
end
|
|
170
|
-
def rule_iter(x)
|
|
171
|
-
act_or([lambda{act_token('*')
|
|
172
|
-
IterMany.new(x)
|
|
173
|
-
},
|
|
174
|
-
lambda{act_token('+')
|
|
175
|
-
IterMany1.new(x)
|
|
176
|
-
},
|
|
177
|
-
lambda{act_token('?')
|
|
178
|
-
IterMay.new(x)
|
|
179
|
-
},
|
|
180
|
-
lambda{ x
|
|
181
|
-
},
|
|
182
|
-
])
|
|
183
|
-
end
|
|
184
|
-
def rule_literal()
|
|
185
|
-
act_or([lambda{apply(:apply_rule)
|
|
186
|
-
},
|
|
187
|
-
lambda{apply(:action)
|
|
188
|
-
},
|
|
189
|
-
lambda{apply(:where)
|
|
190
|
-
},
|
|
191
|
-
lambda{s = apply(:q_string)
|
|
192
|
-
LiteralQuotedToken.new(s)
|
|
193
|
-
},
|
|
194
|
-
lambda{s = apply(:dq_string)
|
|
195
|
-
LiteralToken.new(s)
|
|
196
|
-
},
|
|
197
|
-
lambda{s = apply(:charclass)
|
|
198
|
-
LiteralCharset.new(s)
|
|
199
|
-
},
|
|
200
|
-
lambda{act_token('.')
|
|
201
|
-
LiteralAny.new
|
|
202
|
-
},
|
|
203
|
-
lambda{apply(:other_call)
|
|
204
|
-
},
|
|
205
|
-
lambda{act_token('(')
|
|
206
|
-
apply(:s)
|
|
207
|
-
r = apply(:or_set)
|
|
208
|
-
apply(:s)
|
|
209
|
-
act_token(')')
|
|
210
|
-
r
|
|
211
|
-
},
|
|
212
|
-
])
|
|
213
|
-
end
|
|
214
|
-
def rule_var()
|
|
215
|
-
act_token(':')
|
|
216
|
-
n = apply(:var_name)
|
|
217
|
-
n
|
|
218
|
-
end
|
|
219
|
-
def rule_apply_rule()
|
|
220
|
-
r = apply(:rule_name)
|
|
221
|
-
a = act_may(lambda{apply(:apply_args)})
|
|
222
|
-
|
|
223
|
-
if r == "super"
|
|
224
|
-
Super.new(a)
|
|
225
|
-
elsif r == "self"
|
|
226
|
-
Self.new(a || [])
|
|
227
|
-
else
|
|
228
|
-
Apply.new(r, a || [])
|
|
229
|
-
end
|
|
230
|
-
end
|
|
231
|
-
def rule_other_call()
|
|
232
|
-
g = apply(:grammar_name)
|
|
233
|
-
act_token('.')
|
|
234
|
-
r = apply(:rule_name)
|
|
235
|
-
a = act_may(lambda{apply(:apply_args)})
|
|
236
|
-
Other.new(g, r, a || [])
|
|
237
|
-
end
|
|
238
|
-
def rule_apply_args()
|
|
239
|
-
act_token('(')
|
|
240
|
-
a = act_may(lambda{apply(:s)
|
|
241
|
-
x = apply(:var_name)
|
|
242
|
-
xs = act_many(lambda{act_token(',')
|
|
243
|
-
apply(:s)
|
|
244
|
-
apply(:var_name)
|
|
245
|
-
})
|
|
246
|
-
[x] + xs
|
|
247
|
-
})
|
|
248
|
-
act_token(')')
|
|
249
|
-
a || []
|
|
250
|
-
end
|
|
251
|
-
def rule_action()
|
|
252
|
-
act_token('{*')
|
|
253
|
-
s = act_many1(lambda{act_or([lambda{act_not(lambda{act_token('*')})
|
|
254
|
-
act_any
|
|
255
|
-
},
|
|
256
|
-
lambda{act_token('*')
|
|
257
|
-
act_not(lambda{act_token('}')})
|
|
258
|
-
'*'
|
|
259
|
-
},
|
|
260
|
-
])
|
|
261
|
-
})
|
|
262
|
-
act_token('*}')
|
|
263
|
-
Action.new(s.join)
|
|
264
|
-
end
|
|
265
|
-
def rule_where()
|
|
266
|
-
act_token('?{*')
|
|
267
|
-
s = act_many1(lambda{act_or([lambda{act_not(lambda{act_token('*')})
|
|
268
|
-
act_any
|
|
269
|
-
},
|
|
270
|
-
lambda{act_token('*')
|
|
271
|
-
act_not(lambda{act_token('}')})
|
|
272
|
-
'*'
|
|
273
|
-
},
|
|
274
|
-
])
|
|
275
|
-
})
|
|
276
|
-
act_token('*}')
|
|
277
|
-
Where.new(s.join)
|
|
278
|
-
end
|
|
279
|
-
def rule_rule_name()
|
|
280
|
-
x = act_charset(%[a-z_])
|
|
281
|
-
xs = act_many(lambda{act_charset(%[a-zA-Z_0-9])})
|
|
282
|
-
([x] + xs).join
|
|
283
|
-
end
|
|
284
|
-
def rule_var_name()
|
|
285
|
-
x = act_charset(%[a-z_])
|
|
286
|
-
xs = act_many(lambda{act_charset(%[a-zA-Z_0-9])})
|
|
287
|
-
([x] + xs).join
|
|
288
|
-
end
|
|
289
|
-
def rule_grammar_name()
|
|
290
|
-
x = act_charset(%[A-Z])
|
|
291
|
-
xs = act_many(lambda{act_charset(%[a-zA-Z_0-9])})
|
|
292
|
-
([x] + xs).join
|
|
293
|
-
end
|
|
294
|
-
def rule_dq_string()
|
|
295
|
-
act_token('"')
|
|
296
|
-
s = act_many1(lambda{act_or([lambda{act_not(lambda{act_token('"')})
|
|
297
|
-
act_any
|
|
298
|
-
},
|
|
299
|
-
lambda{act_token('\"')
|
|
300
|
-
},
|
|
301
|
-
])
|
|
302
|
-
})
|
|
303
|
-
act_token('"')
|
|
304
|
-
s.join
|
|
305
|
-
end
|
|
306
|
-
def rule_q_string()
|
|
307
|
-
act_token("'")
|
|
308
|
-
s = act_many1(lambda{act_or([lambda{act_not(lambda{act_token("'")})
|
|
309
|
-
act_any
|
|
310
|
-
},
|
|
311
|
-
lambda{act_token("\\'")
|
|
312
|
-
},
|
|
313
|
-
])
|
|
314
|
-
})
|
|
315
|
-
act_token("'")
|
|
316
|
-
s.join
|
|
317
|
-
end
|
|
318
|
-
def rule_charclass()
|
|
319
|
-
act_token('[')
|
|
320
|
-
s = act_many1(lambda{act_or([lambda{act_not(lambda{act_token(']')})
|
|
321
|
-
act_any
|
|
322
|
-
},
|
|
323
|
-
lambda{act_token('\]')
|
|
324
|
-
},
|
|
325
|
-
])
|
|
326
|
-
})
|
|
327
|
-
act_token(']')
|
|
328
|
-
s.join
|
|
329
|
-
end
|
|
330
|
-
def rule_s()
|
|
331
|
-
act_many(lambda{act_or([lambda{apply(:comment)
|
|
332
|
-
},
|
|
333
|
-
lambda{act_charset(%[ \t\r\n])
|
|
334
|
-
},
|
|
335
|
-
])
|
|
336
|
-
})
|
|
337
|
-
end
|
|
338
|
-
def rule_fs()
|
|
339
|
-
act_many1(lambda{act_or([lambda{apply(:comment)
|
|
340
|
-
},
|
|
341
|
-
lambda{act_charset(%[ \t\r\n])
|
|
342
|
-
},
|
|
343
|
-
])
|
|
344
|
-
})
|
|
345
|
-
end
|
|
346
|
-
def rule_comment()
|
|
347
|
-
act_token('#')
|
|
348
|
-
act_many(lambda{act_not(lambda{act_token("\n")})
|
|
349
|
-
act_any
|
|
350
|
-
})
|
|
351
|
-
act_token("\n")
|
|
352
|
-
end
|
|
353
|
-
end
|
|
1
|
+
require 'metal_boot'
|