meta_compile 0.0.5 → 0.0.6
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/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
|