meta_compile 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +1 -1
- data/Rakefile +111 -0
- data/bin/meta_compile +2 -2
- data/bootstrap/bootstrap.c +260 -0
- data/bootstrap/bootstrapped_c +0 -0
- data/bootstrap/compile_syntax_c_to_ruby.c +214 -0
- data/bootstrap/meta_for_c.txt +38 -0
- data/bootstrap/meta_for_ruby.txt +1 -1
- data/bootstrap/meta_for_ruby_single_flag.txt +35 -0
- data/bootstrap/meta_r +0 -0
- data/bootstrap/meta_ruby_compiler.rb +230 -0
- data/bootstrap/meta_ruby_compiler2.rb +230 -0
- data/bootstrap/meta_ruby_compiler3.rb +230 -0
- data/bootstrap/meta_ruby_compiler_from_c.rb +230 -0
- data/bootstrap/original_support.h +242 -0
- data/bootstrap/support.h +242 -0
- data/meta_compile.gemspec +13 -0
- metadata +16 -2
data/README.md
CHANGED
@@ -3,7 +3,7 @@ meta_compile
|
|
3
3
|
|
4
4
|
A meta compilation framework for Ruby à la [Meta-II by Val Schorre](http://ibm-1401.info/Meta-II-schorre.pdf).
|
5
5
|
|
6
|
-
Uses a C version of Meta-II developed by Long Nguyen's ([meta](https://github.com/impeachgod/meta)) to bootstrap a Ruby version from a [fully self-contained
|
6
|
+
Uses a C version of Meta-II developed by Long Nguyen's ([meta](https://github.com/impeachgod/meta)) to bootstrap a Ruby version from a [fully self-contained 27 (non-empty) line specification file](https://raw.github.com/robertfeldt/meta_compile/master/bootstrap/meta_for_ruby.txt). The [generated Ruby Meta-II compiler file](https://github.com/robertfeldt/meta_compile/blob/master/bin/meta_compile) is 230 lines of non-empty Ruby code.
|
7
7
|
|
8
8
|
Install
|
9
9
|
-------
|
data/Rakefile
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
# A system command that prints commands to stdout before running them
|
4
|
+
def pexec(str)
|
5
|
+
puts str
|
6
|
+
STDOUT.flush
|
7
|
+
system str
|
8
|
+
puts ""
|
9
|
+
end
|
10
|
+
|
11
|
+
desc "Bootstrap our version of Long Nguyen's C version of Meta-II"
|
12
|
+
task :bootstrap_c do
|
13
|
+
Dir.chdir "bootstrap"
|
14
|
+
puts "1. Build bootstrap compiler"
|
15
|
+
pexec "gcc -o bootstrapped_c bootstrap.c"
|
16
|
+
puts "2. Use the bootstrapped meta compiler to compile the meta_for_c.txt description of itself"
|
17
|
+
pexec "./bootstrapped_c meta_for_c.txt meta_compiler_from_boostrapped_c.c"
|
18
|
+
puts "3. Build the compiler we created from the meta description"
|
19
|
+
pexec "gcc -o meta_c meta_compiler_from_boostrapped_c.c"
|
20
|
+
puts "4. Now use the generated compiler to generate itself"
|
21
|
+
pexec "./meta_c meta_for_c.txt meta_compiler.c"
|
22
|
+
puts "5. Now ensure the compilers are exactly the same"
|
23
|
+
pexec "diff meta_compiler_from_boostrapped_c.c meta_compiler.c"
|
24
|
+
end
|
25
|
+
|
26
|
+
# Non-empty Lines of Code calc
|
27
|
+
def loc(filename)
|
28
|
+
File.readlines(filename).map {|l| l.strip.length==0?nil:l}.compact.length
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "Bootstrap the Ruby Meta-II compiler"
|
32
|
+
task :bootstrap do
|
33
|
+
Dir.chdir("bootstrap") do
|
34
|
+
puts "1. Build bootstrap compiler"
|
35
|
+
pexec "gcc -o bootstrapped_c bootstrap.c"
|
36
|
+
puts "2. Use the c meta compiler to compile the meta_for_ruby.txt description"
|
37
|
+
pexec "./bootstrapped_c meta_for_ruby.txt compile_syntax_c_to_ruby.c"
|
38
|
+
puts "3. Build the stepping stone ruby compiler we created from the meta description"
|
39
|
+
pexec "gcc -o meta_r compile_syntax_c_to_ruby.c"
|
40
|
+
puts "4. Now use the generated stepping stone compiler to generate a ruby compiler for the ruby meta syntax"
|
41
|
+
pexec "./meta_r meta_for_ruby.txt meta_ruby_compiler_from_c.rb"
|
42
|
+
puts "5. Run the generated ruby meta compiler to a ruby version"
|
43
|
+
pexec "ruby -I. meta_ruby_compiler_from_c.rb meta_for_ruby.txt meta_ruby_compiler.rb"
|
44
|
+
puts "6. The Ruby version differ in that it has single quotes instead of double quotes around emitted strings"
|
45
|
+
#pexec "diff meta_ruby_compiler_from_c.rb meta_ruby_compiler.rb"
|
46
|
+
puts "7. But we can generate again and ensure it is a meta compiler"
|
47
|
+
pexec "ruby -I. meta_ruby_compiler.rb meta_for_ruby.txt meta_ruby_compiler2.rb"
|
48
|
+
pexec "diff meta_ruby_compiler.rb meta_ruby_compiler2.rb"
|
49
|
+
puts "8. One more round just to show off... :)"
|
50
|
+
pexec "ruby -I. meta_ruby_compiler2.rb meta_for_ruby.txt meta_ruby_compiler3.rb"
|
51
|
+
pexec "diff meta_ruby_compiler.rb meta_ruby_compiler3.rb"
|
52
|
+
puts "Summary:\nCreated a #{loc('meta_ruby_compiler.rb')} line meta-II meta compiler from a #{loc('meta_for_ruby.txt')} line meta-II spec\n\n"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
desc "Make binary from the bootstrapped ruby meta-II compiler"
|
57
|
+
task :make_bin => [:bootstrap] do
|
58
|
+
# First ensure it is a meta compiler
|
59
|
+
puts "Ensure it is a meta-compiler"
|
60
|
+
pexec "ruby bootstrap/meta_ruby_compiler.rb bootstrap/meta_for_ruby.txt t.rb"
|
61
|
+
if File.read("t.rb") != File.read("bootstrap/meta_ruby_compiler.rb")
|
62
|
+
puts "ERROR: bootstrap/meta_ruby_compiler.rb is NOT a meta compiler"
|
63
|
+
exit(-1)
|
64
|
+
else
|
65
|
+
puts "YES it is meta!!!"
|
66
|
+
end
|
67
|
+
FileUtils.cp "bootstrap/meta_ruby_compiler.rb", "bin/meta_compile"
|
68
|
+
FileUtils.chmod 0755, "bin/meta_compile"
|
69
|
+
puts "Created binary in bin/meta_compile"
|
70
|
+
end
|
71
|
+
|
72
|
+
desc "Update line counts in README.template.md to make README.md"
|
73
|
+
task :update_readme => [:bootstrap] do
|
74
|
+
rmeta2_compiler_loc = loc('bootstrap/meta_ruby_compiler.rb')
|
75
|
+
rmeta2_spec_loc = loc('bootstrap/meta_for_ruby.txt')
|
76
|
+
readme = File.read("README.template.md").gsub("%%RMetaII_SPEC_LOC%%", rmeta2_spec_loc.to_s)
|
77
|
+
readme = readme.gsub("%%RMetaII_COMPILER_LOC%%", rmeta2_compiler_loc.to_s)
|
78
|
+
File.open("README.md", "w") {|f| f.puts readme}
|
79
|
+
end
|
80
|
+
|
81
|
+
task :default => :make_bin
|
82
|
+
|
83
|
+
desc "Build the gem"
|
84
|
+
task :build_gem => [:make_bin] do
|
85
|
+
pexec "rm *.gem"
|
86
|
+
pexec "gem build meta_compile.gemspec"
|
87
|
+
end
|
88
|
+
|
89
|
+
desc "Build and install gem"
|
90
|
+
task :install_gem => [:build_gem] do
|
91
|
+
pexec "sudo gem install meta_compile*.gem"
|
92
|
+
end
|
93
|
+
|
94
|
+
desc "Deploy gem"
|
95
|
+
task :deploy => [:install_gem] do
|
96
|
+
pexec "gem push meta_compile*.gem"
|
97
|
+
end
|
98
|
+
|
99
|
+
task :clean do
|
100
|
+
Dir.chdir("bootstrap") do
|
101
|
+
FileUtils.rm_f %w{bootstrapped_c meta_compiler_from_boostrapped_c.c meta_compiler.c meta_ruby_compiler2.rb meta_ruby_compiler3.rb meta_ruby_compiler_from_c.rb compile_syntax_c_to_ruby.c meta_c meta_r}
|
102
|
+
end
|
103
|
+
FileUtils.rm_f Dir.glob("t*.rb")
|
104
|
+
end
|
105
|
+
|
106
|
+
task :clobber => [:clean] do
|
107
|
+
Dir.chdir("bootstrap") do
|
108
|
+
FileUtils.rm_f %w{meta_ruby_compiler.rb meta_compile*.gem}
|
109
|
+
end
|
110
|
+
FileUtils.rm_f Dir.glob("meta_compile-*.gem")
|
111
|
+
end
|
data/bin/meta_compile
CHANGED
@@ -218,7 +218,7 @@ raise("error at: " + @i.rest.split("\n")[0]) if !@f
|
|
218
218
|
raise("error at: " + @i.rest.split("\n")[0]) if !@f
|
219
219
|
@o.print 'end'
|
220
220
|
@o.print "\n"
|
221
|
-
@o.print 'begin; puts
|
221
|
+
@o.print 'begin; puts("Use: " + $0 + " <in> <out>"); exit; end if ARGV.length != 2'
|
222
222
|
@o.print "\n"
|
223
223
|
@o.print 'File.open(ARGV[1], "w") {|f| RMetaII.new.compile(File.read(ARGV[0]), f)}'
|
224
224
|
@o.print "\n"
|
@@ -226,5 +226,5 @@ end
|
|
226
226
|
end while false
|
227
227
|
end
|
228
228
|
end
|
229
|
-
begin; puts
|
229
|
+
begin; puts("Use: " + $0 + " <in> <out>"); exit; end if ARGV.length != 2
|
230
230
|
File.open(ARGV[1], "w") {|f| RMetaII.new.compile(File.read(ARGV[0]), f)}
|
@@ -0,0 +1,260 @@
|
|
1
|
+
#include "support.h"
|
2
|
+
|
3
|
+
void meta_arg(void)
|
4
|
+
{
|
5
|
+
do {
|
6
|
+
read_literal("$");
|
7
|
+
if (test_flag) {
|
8
|
+
emit("emit_token();");
|
9
|
+
emit_nl();
|
10
|
+
}
|
11
|
+
|
12
|
+
if (test_flag) { break; }
|
13
|
+
|
14
|
+
read_string();
|
15
|
+
if (test_flag) {
|
16
|
+
emit("emit(");
|
17
|
+
emit_token();
|
18
|
+
emit(");");
|
19
|
+
emit_nl();
|
20
|
+
}
|
21
|
+
} while (0);
|
22
|
+
}
|
23
|
+
|
24
|
+
void meta_output(void)
|
25
|
+
{
|
26
|
+
do {
|
27
|
+
read_literal("<");
|
28
|
+
if (test_flag) {
|
29
|
+
do {
|
30
|
+
meta_arg();
|
31
|
+
} while (test_flag);
|
32
|
+
test_flag = 1;
|
33
|
+
error_if_false();
|
34
|
+
|
35
|
+
read_literal(">");
|
36
|
+
error_if_false();
|
37
|
+
|
38
|
+
emit("emit_nl();");
|
39
|
+
emit_nl();
|
40
|
+
}
|
41
|
+
} while (0);
|
42
|
+
}
|
43
|
+
|
44
|
+
void meta_exp3(void)
|
45
|
+
{
|
46
|
+
do {
|
47
|
+
read_id();
|
48
|
+
if (test_flag) {
|
49
|
+
emit("meta_");
|
50
|
+
emit_token();
|
51
|
+
emit("();");
|
52
|
+
emit_nl();
|
53
|
+
}
|
54
|
+
|
55
|
+
if (test_flag) { break; }
|
56
|
+
|
57
|
+
read_string();
|
58
|
+
if (test_flag) {
|
59
|
+
emit("read_literal(");
|
60
|
+
emit_token();
|
61
|
+
emit(");");
|
62
|
+
emit_nl();
|
63
|
+
}
|
64
|
+
|
65
|
+
if (test_flag) { break; }
|
66
|
+
|
67
|
+
read_literal(".id");
|
68
|
+
if (test_flag) {
|
69
|
+
emit("read_id();");
|
70
|
+
emit_nl();
|
71
|
+
}
|
72
|
+
|
73
|
+
if (test_flag) { break; }
|
74
|
+
|
75
|
+
read_literal(".number");
|
76
|
+
if (test_flag) {
|
77
|
+
emit("read_number();");
|
78
|
+
emit_nl();
|
79
|
+
}
|
80
|
+
|
81
|
+
if (test_flag) { break; }
|
82
|
+
|
83
|
+
read_literal(".string");
|
84
|
+
if (test_flag) {
|
85
|
+
emit("read_string();");
|
86
|
+
emit_nl();
|
87
|
+
}
|
88
|
+
|
89
|
+
if (test_flag) { break; }
|
90
|
+
|
91
|
+
read_literal("(");
|
92
|
+
if (test_flag) {
|
93
|
+
meta_exp1();
|
94
|
+
error_if_false();
|
95
|
+
|
96
|
+
read_literal(")");
|
97
|
+
error_if_false();
|
98
|
+
}
|
99
|
+
|
100
|
+
if (test_flag) { break; }
|
101
|
+
|
102
|
+
read_literal(".e");
|
103
|
+
if (test_flag) {
|
104
|
+
emit("test_flag = 1;");
|
105
|
+
emit_nl();
|
106
|
+
}
|
107
|
+
|
108
|
+
if (test_flag) { break; }
|
109
|
+
|
110
|
+
read_literal("*");
|
111
|
+
if (test_flag) {
|
112
|
+
emit("do {");
|
113
|
+
emit_nl();
|
114
|
+
|
115
|
+
meta_exp3();
|
116
|
+
error_if_false();
|
117
|
+
|
118
|
+
emit("} while (test_flag);");
|
119
|
+
emit_nl();
|
120
|
+
|
121
|
+
emit("test_flag = 1;");
|
122
|
+
emit_nl();
|
123
|
+
}
|
124
|
+
} while (0);
|
125
|
+
}
|
126
|
+
|
127
|
+
void meta_exp2(void)
|
128
|
+
{
|
129
|
+
do {
|
130
|
+
// open
|
131
|
+
do {
|
132
|
+
meta_exp3();
|
133
|
+
if (test_flag) {
|
134
|
+
emit("if (test_flag) {");
|
135
|
+
emit_nl();
|
136
|
+
}
|
137
|
+
|
138
|
+
if (test_flag) { break; }
|
139
|
+
|
140
|
+
meta_output();
|
141
|
+
if (test_flag) {
|
142
|
+
emit("if (1) {");
|
143
|
+
emit_nl();
|
144
|
+
}
|
145
|
+
} while (0);
|
146
|
+
// close
|
147
|
+
|
148
|
+
if (test_flag) {
|
149
|
+
do {
|
150
|
+
// open
|
151
|
+
do {
|
152
|
+
meta_exp3();
|
153
|
+
if (test_flag) {
|
154
|
+
emit("error_if_false();");
|
155
|
+
emit_nl();
|
156
|
+
}
|
157
|
+
|
158
|
+
if (test_flag) { break; }
|
159
|
+
|
160
|
+
meta_output();
|
161
|
+
if (test_flag) {
|
162
|
+
}
|
163
|
+
} while (0);
|
164
|
+
// close
|
165
|
+
|
166
|
+
} while (test_flag);
|
167
|
+
test_flag = 1;
|
168
|
+
error_if_false();
|
169
|
+
|
170
|
+
emit("}");
|
171
|
+
emit_nl();
|
172
|
+
}
|
173
|
+
} while (0);
|
174
|
+
}
|
175
|
+
|
176
|
+
void meta_exp1(void)
|
177
|
+
{
|
178
|
+
do {
|
179
|
+
emit("do {");
|
180
|
+
emit_nl();
|
181
|
+
if (1) {
|
182
|
+
meta_exp2();
|
183
|
+
error_if_false();
|
184
|
+
|
185
|
+
do {
|
186
|
+
// open
|
187
|
+
do {
|
188
|
+
read_literal("|");
|
189
|
+
if (test_flag) {
|
190
|
+
emit("if (test_flag) { break; }");
|
191
|
+
emit_nl();
|
192
|
+
|
193
|
+
meta_exp2();
|
194
|
+
error_if_false();
|
195
|
+
}
|
196
|
+
} while (0);
|
197
|
+
// close
|
198
|
+
|
199
|
+
} while (test_flag);
|
200
|
+
test_flag = 1;
|
201
|
+
error_if_false();
|
202
|
+
|
203
|
+
emit("} while (0);");
|
204
|
+
emit_nl();
|
205
|
+
}
|
206
|
+
} while (0);
|
207
|
+
}
|
208
|
+
|
209
|
+
void meta_stat(void)
|
210
|
+
{
|
211
|
+
do {
|
212
|
+
read_id();
|
213
|
+
if (test_flag) {
|
214
|
+
emit("void meta_");
|
215
|
+
emit_token();
|
216
|
+
emit("(void)");
|
217
|
+
emit_nl();
|
218
|
+
|
219
|
+
emit("{");
|
220
|
+
emit_nl();
|
221
|
+
|
222
|
+
read_literal("=");
|
223
|
+
error_if_false();
|
224
|
+
|
225
|
+
meta_exp1();
|
226
|
+
error_if_false();
|
227
|
+
|
228
|
+
read_literal(";");
|
229
|
+
error_if_false();
|
230
|
+
|
231
|
+
emit("}");
|
232
|
+
emit_nl();
|
233
|
+
}
|
234
|
+
} while (0);
|
235
|
+
}
|
236
|
+
|
237
|
+
void meta_program(void)
|
238
|
+
{
|
239
|
+
do {
|
240
|
+
read_literal(".syntax");
|
241
|
+
if (test_flag) {
|
242
|
+
read_id();
|
243
|
+
error_if_false();
|
244
|
+
|
245
|
+
emit("#include \"support.h\"");
|
246
|
+
emit_nl();
|
247
|
+
|
248
|
+
do {
|
249
|
+
meta_stat();
|
250
|
+
} while (test_flag);
|
251
|
+
test_flag = 1;
|
252
|
+
error_if_false();
|
253
|
+
|
254
|
+
read_literal(".end");
|
255
|
+
error_if_false();
|
256
|
+
}
|
257
|
+
} while (0);
|
258
|
+
}
|
259
|
+
|
260
|
+
// end
|
Binary file
|
@@ -0,0 +1,214 @@
|
|
1
|
+
#include "support.h"
|
2
|
+
void meta_outarg(void)
|
3
|
+
{
|
4
|
+
do {
|
5
|
+
read_literal("$");
|
6
|
+
if (test_flag) {
|
7
|
+
emit("@o.print @t");
|
8
|
+
emit_nl();
|
9
|
+
}
|
10
|
+
if (test_flag) { break; }
|
11
|
+
read_string();
|
12
|
+
if (test_flag) {
|
13
|
+
emit("@o.print ");
|
14
|
+
emit_token();
|
15
|
+
emit_nl();
|
16
|
+
}
|
17
|
+
} while (0);
|
18
|
+
}
|
19
|
+
void meta_out(void)
|
20
|
+
{
|
21
|
+
do {
|
22
|
+
read_literal("<");
|
23
|
+
if (test_flag) {
|
24
|
+
do {
|
25
|
+
meta_outarg();
|
26
|
+
} while (test_flag);
|
27
|
+
test_flag = 1;
|
28
|
+
error_if_false();
|
29
|
+
read_literal(">");
|
30
|
+
error_if_false();
|
31
|
+
emit("@o.print \"\\n\"");
|
32
|
+
emit_nl();
|
33
|
+
}
|
34
|
+
} while (0);
|
35
|
+
}
|
36
|
+
void meta_exp3(void)
|
37
|
+
{
|
38
|
+
do {
|
39
|
+
read_id();
|
40
|
+
if (test_flag) {
|
41
|
+
emit("compile_");
|
42
|
+
emit_token();
|
43
|
+
emit_nl();
|
44
|
+
}
|
45
|
+
if (test_flag) { break; }
|
46
|
+
read_string();
|
47
|
+
if (test_flag) {
|
48
|
+
emit("@i.scan /\\s*/; s=");
|
49
|
+
emit_token();
|
50
|
+
emit("; l=s.length;");
|
51
|
+
emit_nl();
|
52
|
+
emit("@f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil");
|
53
|
+
emit_nl();
|
54
|
+
}
|
55
|
+
if (test_flag) { break; }
|
56
|
+
read_literal(".id");
|
57
|
+
if (test_flag) {
|
58
|
+
emit("@i.scan /\\s*/; @f = @t = @i.scan /[A-Za-z]+[A-Za-z0-9_]+/");
|
59
|
+
emit_nl();
|
60
|
+
}
|
61
|
+
if (test_flag) { break; }
|
62
|
+
read_literal(".string");
|
63
|
+
if (test_flag) {
|
64
|
+
emit("@i.scan /\\s*/; @f = @t = @i.scan /\\047[^\\047]*\\047/");
|
65
|
+
emit_nl();
|
66
|
+
}
|
67
|
+
if (test_flag) { break; }
|
68
|
+
read_literal("(");
|
69
|
+
if (test_flag) {
|
70
|
+
meta_exp1();
|
71
|
+
error_if_false();
|
72
|
+
read_literal(")");
|
73
|
+
error_if_false();
|
74
|
+
}
|
75
|
+
if (test_flag) { break; }
|
76
|
+
read_literal(".e");
|
77
|
+
if (test_flag) {
|
78
|
+
emit("@f = true");
|
79
|
+
emit_nl();
|
80
|
+
}
|
81
|
+
if (test_flag) { break; }
|
82
|
+
read_literal("*");
|
83
|
+
if (test_flag) {
|
84
|
+
emit("begin");
|
85
|
+
emit_nl();
|
86
|
+
meta_exp3();
|
87
|
+
error_if_false();
|
88
|
+
emit("end while @f");
|
89
|
+
emit_nl();
|
90
|
+
emit("@f = true");
|
91
|
+
emit_nl();
|
92
|
+
}
|
93
|
+
} while (0);
|
94
|
+
}
|
95
|
+
void meta_exp2(void)
|
96
|
+
{
|
97
|
+
do {
|
98
|
+
do {
|
99
|
+
meta_exp3();
|
100
|
+
if (test_flag) {
|
101
|
+
emit("if @f");
|
102
|
+
emit_nl();
|
103
|
+
}
|
104
|
+
if (test_flag) { break; }
|
105
|
+
meta_out();
|
106
|
+
if (test_flag) {
|
107
|
+
emit("if true");
|
108
|
+
emit_nl();
|
109
|
+
}
|
110
|
+
} while (0);
|
111
|
+
if (test_flag) {
|
112
|
+
do {
|
113
|
+
do {
|
114
|
+
meta_exp3();
|
115
|
+
if (test_flag) {
|
116
|
+
emit("raise(\"error at: \" + @i.rest.split(\"\\n\")[0]) if !@f");
|
117
|
+
emit_nl();
|
118
|
+
}
|
119
|
+
if (test_flag) { break; }
|
120
|
+
meta_out();
|
121
|
+
if (test_flag) {
|
122
|
+
}
|
123
|
+
} while (0);
|
124
|
+
} while (test_flag);
|
125
|
+
test_flag = 1;
|
126
|
+
error_if_false();
|
127
|
+
emit("end");
|
128
|
+
emit_nl();
|
129
|
+
}
|
130
|
+
} while (0);
|
131
|
+
}
|
132
|
+
void meta_exp1(void)
|
133
|
+
{
|
134
|
+
do {
|
135
|
+
emit("begin");
|
136
|
+
emit_nl();
|
137
|
+
if (1) {
|
138
|
+
meta_exp2();
|
139
|
+
error_if_false();
|
140
|
+
do {
|
141
|
+
do {
|
142
|
+
read_literal("|");
|
143
|
+
if (test_flag) {
|
144
|
+
emit("break if @f");
|
145
|
+
emit_nl();
|
146
|
+
meta_exp2();
|
147
|
+
error_if_false();
|
148
|
+
}
|
149
|
+
} while (0);
|
150
|
+
} while (test_flag);
|
151
|
+
test_flag = 1;
|
152
|
+
error_if_false();
|
153
|
+
emit("end while false");
|
154
|
+
emit_nl();
|
155
|
+
}
|
156
|
+
} while (0);
|
157
|
+
}
|
158
|
+
void meta_rule(void)
|
159
|
+
{
|
160
|
+
do {
|
161
|
+
read_id();
|
162
|
+
if (test_flag) {
|
163
|
+
emit("def compile_");
|
164
|
+
emit_token();
|
165
|
+
emit_nl();
|
166
|
+
read_literal("=");
|
167
|
+
error_if_false();
|
168
|
+
meta_exp1();
|
169
|
+
error_if_false();
|
170
|
+
read_literal(";");
|
171
|
+
error_if_false();
|
172
|
+
emit("end");
|
173
|
+
emit_nl();
|
174
|
+
}
|
175
|
+
} while (0);
|
176
|
+
}
|
177
|
+
void meta_program(void)
|
178
|
+
{
|
179
|
+
do {
|
180
|
+
read_literal(".syntax");
|
181
|
+
if (test_flag) {
|
182
|
+
read_id();
|
183
|
+
error_if_false();
|
184
|
+
emit("#!/usr/bin/env ruby");
|
185
|
+
emit_nl();
|
186
|
+
emit("require \"strscan\"");
|
187
|
+
emit_nl();
|
188
|
+
emit("class ");
|
189
|
+
emit_token();
|
190
|
+
emit_nl();
|
191
|
+
emit("def compile(str, out)");
|
192
|
+
emit_nl();
|
193
|
+
emit("@i, @o = StringScanner.new(str), out");
|
194
|
+
emit_nl();
|
195
|
+
emit("compile_program");
|
196
|
+
emit_nl();
|
197
|
+
emit("end");
|
198
|
+
emit_nl();
|
199
|
+
do {
|
200
|
+
meta_rule();
|
201
|
+
} while (test_flag);
|
202
|
+
test_flag = 1;
|
203
|
+
error_if_false();
|
204
|
+
read_literal(".end");
|
205
|
+
error_if_false();
|
206
|
+
emit("end");
|
207
|
+
emit_nl();
|
208
|
+
emit("begin; puts(\"Use: \" + $0 + \" <in> <out>\"); exit; end if ARGV.length != 2");
|
209
|
+
emit_nl();
|
210
|
+
emit("File.open(ARGV[1], \"w\") {|f| RMetaII.new.compile(File.read(ARGV[0]), f)}");
|
211
|
+
emit_nl();
|
212
|
+
}
|
213
|
+
} while (0);
|
214
|
+
}
|
@@ -0,0 +1,38 @@
|
|
1
|
+
.syntax meta
|
2
|
+
|
3
|
+
arg = '$' <'emit_token();'>
|
4
|
+
| .string <'emit(' $ ');'>;
|
5
|
+
|
6
|
+
output = '<' *arg '>' <'emit_nl();'>;
|
7
|
+
|
8
|
+
exp3 = .id <'meta_' $ '();'>
|
9
|
+
| .string <'read_literal(' $ ');'>
|
10
|
+
| '.id' <'read_id();'>
|
11
|
+
| '.number' <'read_number();'>
|
12
|
+
| '.string' <'read_string();'>
|
13
|
+
| '(' exp1 ')'
|
14
|
+
| '.e' <'test_flag = 1;'>
|
15
|
+
| '*' <'do {'>
|
16
|
+
exp3 <'} while (test_flag);'>
|
17
|
+
<'test_flag = 1;'>;
|
18
|
+
|
19
|
+
exp2 = ( exp3 <'if (test_flag) {'>
|
20
|
+
| output <'if (1) {'> )
|
21
|
+
*( exp3 <'error_if_false();'>
|
22
|
+
| output )
|
23
|
+
<'}'>;
|
24
|
+
|
25
|
+
exp1 = <'do {'> exp2
|
26
|
+
*( '|' <'if (test_flag) { break; }'> exp2 )
|
27
|
+
<'} while (0);'>;
|
28
|
+
|
29
|
+
stat = .id <'void meta_' $ '(void)'>
|
30
|
+
<'{'>
|
31
|
+
'=' exp1 ';'
|
32
|
+
<'}'>;
|
33
|
+
|
34
|
+
program = '.syntax' .id <'#include "support.h"'>
|
35
|
+
*stat
|
36
|
+
'.end';
|
37
|
+
|
38
|
+
.end
|
data/bootstrap/meta_for_ruby.txt
CHANGED
@@ -29,7 +29,7 @@ program = '.syntax' .id
|
|
29
29
|
<'@i, @o = StringScanner.new(str), out'>
|
30
30
|
<'compile_program'> <'end'>
|
31
31
|
*rule '.end' <'end'>
|
32
|
-
<'begin; puts
|
32
|
+
<'begin; puts("Use: " + $0 + " <in> <out>"); exit; end if ARGV.length != 2'>
|
33
33
|
<'File.open(ARGV[1], "w") {|f| RMetaII.new.compile(File.read(ARGV[0]), f)}'>;
|
34
34
|
|
35
35
|
.end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
.syntax RMetaII
|
2
|
+
|
3
|
+
outarg = '$' <'@o.print @t'> | .string <'@o.print ' $>;
|
4
|
+
|
5
|
+
out = '<' *outarg '>' <'@o.print "\n"'>;
|
6
|
+
|
7
|
+
exp3 = .id <'compile_' $>
|
8
|
+
| .string <'@i.scan /\s*/; s=' $ '; l=s.length;'>
|
9
|
+
<'@t = (@i.peek(l) == s) ? (@i.pos += l; s) : nil'>
|
10
|
+
| '.id' <'@i.scan /\s*/; @t = @i.scan /[A-Za-z]+[A-Za-z0-9_]+/'>
|
11
|
+
| '.string' <'@i.scan /\s*/; @t = @i.scan /\047[^\047]*\047/'>
|
12
|
+
| '(' exp1 ')'
|
13
|
+
| '.e' <'@t = true'>
|
14
|
+
| '*' <'begin'> exp3 <'end while @t'> <'@t = true'>;
|
15
|
+
|
16
|
+
exp2 = ( exp3 <'if @t'> | out <'if true'> )
|
17
|
+
*( exp3 <'raise("error at:\n" + @i.rest.split("\n")[0]) if !@t'>
|
18
|
+
| out ) <'end'>;
|
19
|
+
|
20
|
+
exp1 = <'begin'> exp2
|
21
|
+
*( '|' <'break if @t'> exp2 )
|
22
|
+
<'end while false'>;
|
23
|
+
|
24
|
+
rule = .id <'def compile_' $> '=' exp1 ';' <'end'>;
|
25
|
+
|
26
|
+
program = '.syntax' .id
|
27
|
+
<'#!/usr/bin/env ruby'> <'require "strscan"'>
|
28
|
+
<'class ' $> <'def compile(str, out)'>
|
29
|
+
<'@i, @o = StringScanner.new(str), out'>
|
30
|
+
<'compile_program'> <'end'>
|
31
|
+
*rule '.end' <'end'>
|
32
|
+
<'begin; puts("Use: " + $0 + " <in> <out>"); exit; end if ARGV.length != 2'>
|
33
|
+
<'File.open(ARGV[1], "w") {|f| RMetaII.new.compile(File.read(ARGV[0]), f)}'>;
|
34
|
+
|
35
|
+
.end
|
data/bootstrap/meta_r
ADDED
Binary file
|