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.
@@ -0,0 +1,230 @@
1
+ #!/usr/bin/env ruby
2
+ require "strscan"
3
+ class RMetaII
4
+ def compile(str, out)
5
+ @i, @o = StringScanner.new(str), out
6
+ compile_program
7
+ end
8
+ def compile_outarg
9
+ begin
10
+ @i.scan /\s*/; s="$"; l=s.length;
11
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
12
+ if @f
13
+ @o.print "@o.print @t"
14
+ @o.print "\n"
15
+ end
16
+ break if @f
17
+ @i.scan /\s*/; @f = @t = @i.scan /\047[^\047]*\047/
18
+ if @f
19
+ @o.print "@o.print "
20
+ @o.print @t
21
+ @o.print "\n"
22
+ end
23
+ end while false
24
+ end
25
+ def compile_out
26
+ begin
27
+ @i.scan /\s*/; s="<"; l=s.length;
28
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
29
+ if @f
30
+ begin
31
+ compile_outarg
32
+ end while @f
33
+ @f = true
34
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
35
+ @i.scan /\s*/; s=">"; l=s.length;
36
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
37
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
38
+ @o.print "@o.print \"\\n\""
39
+ @o.print "\n"
40
+ end
41
+ end while false
42
+ end
43
+ def compile_exp3
44
+ begin
45
+ @i.scan /\s*/; @f = @t = @i.scan /[A-Za-z]+[A-Za-z0-9_]+/
46
+ if @f
47
+ @o.print "compile_"
48
+ @o.print @t
49
+ @o.print "\n"
50
+ end
51
+ break if @f
52
+ @i.scan /\s*/; @f = @t = @i.scan /\047[^\047]*\047/
53
+ if @f
54
+ @o.print "@i.scan /\\s*/; s="
55
+ @o.print @t
56
+ @o.print "; l=s.length;"
57
+ @o.print "\n"
58
+ @o.print "@f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil"
59
+ @o.print "\n"
60
+ end
61
+ break if @f
62
+ @i.scan /\s*/; s=".id"; l=s.length;
63
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
64
+ if @f
65
+ @o.print "@i.scan /\\s*/; @f = @t = @i.scan /[A-Za-z]+[A-Za-z0-9_]+/"
66
+ @o.print "\n"
67
+ end
68
+ break if @f
69
+ @i.scan /\s*/; s=".string"; l=s.length;
70
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
71
+ if @f
72
+ @o.print "@i.scan /\\s*/; @f = @t = @i.scan /\\047[^\\047]*\\047/"
73
+ @o.print "\n"
74
+ end
75
+ break if @f
76
+ @i.scan /\s*/; s="("; l=s.length;
77
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
78
+ if @f
79
+ compile_exp1
80
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
81
+ @i.scan /\s*/; s=")"; l=s.length;
82
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
83
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
84
+ end
85
+ break if @f
86
+ @i.scan /\s*/; s=".e"; l=s.length;
87
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
88
+ if @f
89
+ @o.print "@f = true"
90
+ @o.print "\n"
91
+ end
92
+ break if @f
93
+ @i.scan /\s*/; s="*"; l=s.length;
94
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
95
+ if @f
96
+ @o.print "begin"
97
+ @o.print "\n"
98
+ compile_exp3
99
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
100
+ @o.print "end while @f"
101
+ @o.print "\n"
102
+ @o.print "@f = true"
103
+ @o.print "\n"
104
+ end
105
+ end while false
106
+ end
107
+ def compile_exp2
108
+ begin
109
+ begin
110
+ compile_exp3
111
+ if @f
112
+ @o.print "if @f"
113
+ @o.print "\n"
114
+ end
115
+ break if @f
116
+ compile_out
117
+ if @f
118
+ @o.print "if true"
119
+ @o.print "\n"
120
+ end
121
+ end while false
122
+ if @f
123
+ begin
124
+ begin
125
+ compile_exp3
126
+ if @f
127
+ @o.print "raise(\"error at: \" + @i.rest.split(\"\\n\")[0]) if !@f"
128
+ @o.print "\n"
129
+ end
130
+ break if @f
131
+ compile_out
132
+ if @f
133
+ end
134
+ end while false
135
+ end while @f
136
+ @f = true
137
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
138
+ @o.print "end"
139
+ @o.print "\n"
140
+ end
141
+ end while false
142
+ end
143
+ def compile_exp1
144
+ begin
145
+ @o.print "begin"
146
+ @o.print "\n"
147
+ if true
148
+ compile_exp2
149
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
150
+ begin
151
+ begin
152
+ @i.scan /\s*/; s="|"; l=s.length;
153
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
154
+ if @f
155
+ @o.print "break if @f"
156
+ @o.print "\n"
157
+ compile_exp2
158
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
159
+ end
160
+ end while false
161
+ end while @f
162
+ @f = true
163
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
164
+ @o.print "end while false"
165
+ @o.print "\n"
166
+ end
167
+ end while false
168
+ end
169
+ def compile_rule
170
+ begin
171
+ @i.scan /\s*/; @f = @t = @i.scan /[A-Za-z]+[A-Za-z0-9_]+/
172
+ if @f
173
+ @o.print "def compile_"
174
+ @o.print @t
175
+ @o.print "\n"
176
+ @i.scan /\s*/; s="="; l=s.length;
177
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
178
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
179
+ compile_exp1
180
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
181
+ @i.scan /\s*/; s=";"; l=s.length;
182
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
183
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
184
+ @o.print "end"
185
+ @o.print "\n"
186
+ end
187
+ end while false
188
+ end
189
+ def compile_program
190
+ begin
191
+ @i.scan /\s*/; s=".syntax"; l=s.length;
192
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
193
+ if @f
194
+ @i.scan /\s*/; @f = @t = @i.scan /[A-Za-z]+[A-Za-z0-9_]+/
195
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
196
+ @o.print "#!/usr/bin/env ruby"
197
+ @o.print "\n"
198
+ @o.print "require \"strscan\""
199
+ @o.print "\n"
200
+ @o.print "class "
201
+ @o.print @t
202
+ @o.print "\n"
203
+ @o.print "def compile(str, out)"
204
+ @o.print "\n"
205
+ @o.print "@i, @o = StringScanner.new(str), out"
206
+ @o.print "\n"
207
+ @o.print "compile_program"
208
+ @o.print "\n"
209
+ @o.print "end"
210
+ @o.print "\n"
211
+ begin
212
+ compile_rule
213
+ end while @f
214
+ @f = true
215
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
216
+ @i.scan /\s*/; s=".end"; l=s.length;
217
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
218
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
219
+ @o.print "end"
220
+ @o.print "\n"
221
+ @o.print "begin; puts(\"Use: \" + $0 + \" <in> <out>\"); exit; end if ARGV.length != 2"
222
+ @o.print "\n"
223
+ @o.print "File.open(ARGV[1], \"w\") {|f| RMetaII.new.compile(File.read(ARGV[0]), f)}"
224
+ @o.print "\n"
225
+ end
226
+ end while false
227
+ end
228
+ end
229
+ begin; puts("Use: " + $0 + " <in> <out>"); exit; end if ARGV.length != 2
230
+ File.open(ARGV[1], "w") {|f| RMetaII.new.compile(File.read(ARGV[0]), f)}
@@ -0,0 +1,242 @@
1
+ #include <stdlib.h>
2
+ #include <stdio.h>
3
+ #include <string.h>
4
+
5
+ char *output_name = NULL;
6
+ FILE *output = NULL;
7
+ char *source = NULL;
8
+ int pos = 0;
9
+ int line = 1;
10
+ int test_flag = 0;
11
+ char *token = NULL;
12
+
13
+ void skip_whitespace(void)
14
+ {
15
+ while (source[pos] == '\x20' || source[pos] == '\t' ||
16
+ source[pos] == '\r' || source[pos] == '\n') {
17
+ // increment line counter when new line reached
18
+ if (source[pos] == '\n') {
19
+ line++;
20
+ }
21
+ pos++;
22
+ }
23
+ }
24
+
25
+ void make_token(int start_pos)
26
+ {
27
+ int length = pos - start_pos;
28
+ free(token);
29
+ token = malloc(length + 1);
30
+ token[length] = '\0';
31
+ memcpy(token, &source[start_pos], length);
32
+ }
33
+
34
+ // emits the currently recognized token
35
+ void emit_token(void)
36
+ {
37
+ int i;
38
+ // strings are converted to C format
39
+ if (token[0] == '\'') {
40
+ fprintf(output, "\"");
41
+ for (i = 1; token[i] != '\0' && token[i] != '\''; i++) {
42
+ switch (token[i]) {
43
+ case '\"':
44
+ fprintf(output, "\\\"");
45
+ break;
46
+ case '\\':
47
+ fprintf(output, "\\\\");
48
+ break;
49
+ default:
50
+ fprintf(output, "%c", token[i]);
51
+ break;
52
+ }
53
+ }
54
+ fprintf(output, "\"");
55
+ return;
56
+ }
57
+ // if token is not a string, emit as-is
58
+ fprintf(output, "%s", token);
59
+ }
60
+
61
+ void emit(const char *str)
62
+ {
63
+ fprintf(output, "%s", str);
64
+ }
65
+
66
+ void emit_nl(void)
67
+ {
68
+ fprintf(output, "\n");
69
+ }
70
+
71
+ void read_literal(const char *literal)
72
+ {
73
+ int entry_pos;
74
+ int i;
75
+
76
+ skip_whitespace();
77
+ // compare source with the literal
78
+ entry_pos = pos;
79
+ i = 0;
80
+ while (source[pos] != '\0' && literal[i] != '\0' &&
81
+ source[pos] == literal[i]) {
82
+ pos++;
83
+ i++;
84
+ }
85
+ // if the end of the literal has been reached, comparison successful
86
+ if (literal[i] == '\0') {
87
+ test_flag = 1;
88
+ make_token(entry_pos);
89
+ } else {
90
+ // reset position
91
+ pos = entry_pos;
92
+ test_flag = 0;
93
+ }
94
+ }
95
+
96
+ void read_id(void)
97
+ {
98
+ int entry_pos;
99
+
100
+ skip_whitespace();
101
+ // recognize initial alphabetic character
102
+ entry_pos = pos;
103
+ if (('A' <= source[pos] && source[pos] <= 'A') ||
104
+ ('a' <= source[pos] && source[pos] <= 'z')) {
105
+ pos++;
106
+ test_flag = 1;
107
+ } else {
108
+ test_flag = 0;
109
+ return;
110
+ }
111
+ // recognize alphanumeric characters
112
+ while (('A' <= source[pos] && source[pos] <= 'A') ||
113
+ ('a' <= source[pos] && source[pos] <= 'z') ||
114
+ ('0' <= source[pos] && source[pos] <= '9')) {
115
+ pos++;
116
+ }
117
+ // recognition successful, copy into token
118
+ make_token(entry_pos);
119
+ }
120
+
121
+ void read_number(void)
122
+ {
123
+ int entry_pos;
124
+
125
+ skip_whitespace();
126
+ // recognize optional negative sign
127
+ entry_pos = pos;
128
+ if (source[pos] == '-') {
129
+ pos++;
130
+ }
131
+ // recognize initial numeric character
132
+ if ('0' <= source[pos] && source[pos] <= '9') {
133
+ pos++;
134
+ test_flag = 1;
135
+ } else {
136
+ test_flag = 0;
137
+ return;
138
+ }
139
+ // recognize subsequent numeric characters
140
+ while ('0' <= source[pos] && source[pos] <= '9') {
141
+ pos++;
142
+ }
143
+ // recognition successful, copy into token
144
+ make_token(entry_pos);
145
+ }
146
+
147
+ void read_string(void)
148
+ {
149
+ int entry_pos;
150
+
151
+ skip_whitespace();
152
+ // recognize initial single quote
153
+ entry_pos = pos;
154
+ if (source[pos] == '\'') {
155
+ pos++;
156
+ // test_flag is not set as recognition can still fail
157
+ } else {
158
+ test_flag = 0;
159
+ return;
160
+ }
161
+
162
+ // recognize contents
163
+ while (source[pos] != '\0' && source[pos] != '\'') {
164
+ // increment line counter when new line reached
165
+ if (source[pos] == '\n') {
166
+ line++;
167
+ }
168
+ pos++;
169
+ }
170
+
171
+ // recognize final single quote
172
+ if (source[pos] == '\'') {
173
+ pos++;
174
+ test_flag = 1;
175
+ make_token(entry_pos);
176
+ } else if (source[pos] == '\0') {
177
+ // reset position
178
+ pos = entry_pos;
179
+ test_flag = 0;
180
+ }
181
+ }
182
+
183
+ void error_if_false(void)
184
+ {
185
+ if (!test_flag) {
186
+ fprintf(stderr, "error in line %i at token %s\n", line, token);
187
+ fclose(output);
188
+ // delete the output file
189
+ remove(output_name);
190
+ free(source);
191
+ free(token);
192
+ exit(1);
193
+ }
194
+ }
195
+
196
+ void meta_program(void);
197
+ void meta_exp1(void);
198
+
199
+ int main(int argc, char *argv[])
200
+ {
201
+ FILE *input;
202
+ int length;
203
+
204
+ if (argc < 3) {
205
+ fprintf(stderr, "usage: meta <input> <output>\n");
206
+ exit(1);
207
+ }
208
+
209
+ // open input and output
210
+ input = fopen(argv[1], "r");
211
+ if (input == NULL) {
212
+ fprintf(stderr, "invalid input file\n");
213
+ exit(1);
214
+ }
215
+ output_name = argv[2];
216
+ output = fopen(output_name, "w");
217
+ if (output == NULL) {
218
+ fprintf(stderr, "invalid output file\n");
219
+ exit(1);
220
+ }
221
+ // read entire input into source
222
+ fseek(input, 0, SEEK_END);
223
+ length = (int)ftell(input);
224
+ fseek(input, 0, SEEK_SET);
225
+ source = malloc(length + 1);
226
+ fread(source, 1, length, input);
227
+ source[length] = '\0';
228
+ fclose(input);
229
+
230
+ // initially we have empty token; token is never NULL
231
+ token = malloc(1);
232
+ token[0] = '\0';
233
+
234
+ // run meta
235
+ meta_program();
236
+ fclose(output);
237
+ free(source);
238
+ free(token);
239
+ return 0;
240
+ }
241
+
242
+ /* end */
@@ -0,0 +1,242 @@
1
+ #include <stdlib.h>
2
+ #include <stdio.h>
3
+ #include <string.h>
4
+
5
+ char *output_name = NULL;
6
+ FILE *output = NULL;
7
+ char *source = NULL;
8
+ int pos = 0;
9
+ int line = 1;
10
+ int test_flag = 0;
11
+ char *token = NULL;
12
+
13
+ void skip_whitespace(void)
14
+ {
15
+ while (source[pos] == '\x20' || source[pos] == '\t' ||
16
+ source[pos] == '\r' || source[pos] == '\n') {
17
+ // increment line counter when new line reached
18
+ if (source[pos] == '\n') {
19
+ line++;
20
+ }
21
+ pos++;
22
+ }
23
+ }
24
+
25
+ void make_token(int start_pos)
26
+ {
27
+ int length = pos - start_pos;
28
+ free(token);
29
+ token = malloc(length + 1);
30
+ token[length] = '\0';
31
+ memcpy(token, &source[start_pos], length);
32
+ }
33
+
34
+ // emits the currently recognized token
35
+ void emit_token(void)
36
+ {
37
+ int i;
38
+ // strings are converted to C format
39
+ if (token[0] == '\'') {
40
+ fprintf(output, "\"");
41
+ for (i = 1; token[i] != '\0' && token[i] != '\''; i++) {
42
+ switch (token[i]) {
43
+ case '\"':
44
+ fprintf(output, "\\\"");
45
+ break;
46
+ case '\\':
47
+ fprintf(output, "\\\\");
48
+ break;
49
+ default:
50
+ fprintf(output, "%c", token[i]);
51
+ break;
52
+ }
53
+ }
54
+ fprintf(output, "\"");
55
+ return;
56
+ }
57
+ // if token is not a string, emit as-is
58
+ fprintf(output, "%s", token);
59
+ }
60
+
61
+ void emit(const char *str)
62
+ {
63
+ fprintf(output, "%s", str);
64
+ }
65
+
66
+ void emit_nl(void)
67
+ {
68
+ fprintf(output, "\n");
69
+ }
70
+
71
+ void read_literal(const char *literal)
72
+ {
73
+ int entry_pos;
74
+ int i;
75
+
76
+ skip_whitespace();
77
+ // compare source with the literal
78
+ entry_pos = pos;
79
+ i = 0;
80
+ while (source[pos] != '\0' && literal[i] != '\0' &&
81
+ source[pos] == literal[i]) {
82
+ pos++;
83
+ i++;
84
+ }
85
+ // if the end of the literal has been reached, comparison successful
86
+ if (literal[i] == '\0') {
87
+ test_flag = 1;
88
+ make_token(entry_pos);
89
+ } else {
90
+ // reset position
91
+ pos = entry_pos;
92
+ test_flag = 0;
93
+ }
94
+ }
95
+
96
+ void read_id(void)
97
+ {
98
+ int entry_pos;
99
+
100
+ skip_whitespace();
101
+ // recognize initial alphabetic character
102
+ entry_pos = pos;
103
+ if (('A' <= source[pos] && source[pos] <= 'Z') ||
104
+ ('a' <= source[pos] && source[pos] <= 'z')) {
105
+ pos++;
106
+ test_flag = 1;
107
+ } else {
108
+ test_flag = 0;
109
+ return;
110
+ }
111
+ // recognize alphanumeric characters
112
+ while (('A' <= source[pos] && source[pos] <= 'Z') ||
113
+ ('a' <= source[pos] && source[pos] <= 'z') ||
114
+ ('0' <= source[pos] && source[pos] <= '9')) {
115
+ pos++;
116
+ }
117
+ // recognition successful, copy into token
118
+ make_token(entry_pos);
119
+ }
120
+
121
+ void read_number(void)
122
+ {
123
+ int entry_pos;
124
+
125
+ skip_whitespace();
126
+ // recognize optional negative sign
127
+ entry_pos = pos;
128
+ if (source[pos] == '-') {
129
+ pos++;
130
+ }
131
+ // recognize initial numeric character
132
+ if ('0' <= source[pos] && source[pos] <= '9') {
133
+ pos++;
134
+ test_flag = 1;
135
+ } else {
136
+ test_flag = 0;
137
+ return;
138
+ }
139
+ // recognize subsequent numeric characters
140
+ while ('0' <= source[pos] && source[pos] <= '9') {
141
+ pos++;
142
+ }
143
+ // recognition successful, copy into token
144
+ make_token(entry_pos);
145
+ }
146
+
147
+ void read_string(void)
148
+ {
149
+ int entry_pos;
150
+
151
+ skip_whitespace();
152
+ // recognize initial single quote
153
+ entry_pos = pos;
154
+ if (source[pos] == '\'') {
155
+ pos++;
156
+ // test_flag is not set as recognition can still fail
157
+ } else {
158
+ test_flag = 0;
159
+ return;
160
+ }
161
+
162
+ // recognize contents
163
+ while (source[pos] != '\0' && (source[pos] != '\'' || (source[pos] == '\'' && source[pos-1] == '\\'))) {
164
+ // increment line counter when new line reached
165
+ if (source[pos] == '\n') {
166
+ line++;
167
+ }
168
+ pos++;
169
+ }
170
+
171
+ // recognize final single quote
172
+ if (source[pos] == '\'') {
173
+ pos++;
174
+ test_flag = 1;
175
+ make_token(entry_pos);
176
+ } else if (source[pos] == '\0') {
177
+ // reset position
178
+ pos = entry_pos;
179
+ test_flag = 0;
180
+ }
181
+ }
182
+
183
+ void error_if_false(void)
184
+ {
185
+ if (!test_flag) {
186
+ fprintf(stderr, "error in line %i at token %s\n", line, token);
187
+ fclose(output);
188
+ // delete the output file
189
+ remove(output_name);
190
+ free(source);
191
+ free(token);
192
+ exit(1);
193
+ }
194
+ }
195
+
196
+ void meta_program(void);
197
+ void meta_exp1(void);
198
+
199
+ int main(int argc, char *argv[])
200
+ {
201
+ FILE *input;
202
+ int length;
203
+
204
+ if (argc < 3) {
205
+ fprintf(stderr, "usage: meta <input> <output>\n");
206
+ exit(1);
207
+ }
208
+
209
+ // open input and output
210
+ input = fopen(argv[1], "r");
211
+ if (input == NULL) {
212
+ fprintf(stderr, "invalid input file\n");
213
+ exit(1);
214
+ }
215
+ output_name = argv[2];
216
+ output = fopen(output_name, "w");
217
+ if (output == NULL) {
218
+ fprintf(stderr, "invalid output file\n");
219
+ exit(1);
220
+ }
221
+ // read entire input into source
222
+ fseek(input, 0, SEEK_END);
223
+ length = (int)ftell(input);
224
+ fseek(input, 0, SEEK_SET);
225
+ source = malloc(length + 1);
226
+ fread(source, 1, length, input);
227
+ source[length] = '\0';
228
+ fclose(input);
229
+
230
+ // initially we have empty token; token is never NULL
231
+ token = malloc(1);
232
+ token[0] = '\0';
233
+
234
+ // run meta
235
+ meta_program();
236
+ fclose(output);
237
+ free(source);
238
+ free(token);
239
+ return 0;
240
+ }
241
+
242
+ /* end */
@@ -0,0 +1,13 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'meta_compile'
3
+ s.version = '0.0.6'
4
+ s.date = '2012-11-25'
5
+ s.summary = "meta compiler framework"
6
+ s.description = "A meta compilation framework à la Meta-II by Val Schorre"
7
+ s.authors = ["Robert Feldt"]
8
+ s.email = 'robert.feldt@gmail.com'
9
+ s.files = ["Rakefile", "README.md", "meta_compile.gemspec"] + Dir.glob("bin/*") + Dir.glob("bootstrap/*")
10
+ s.executables << 'meta_compile'
11
+ s.homepage =
12
+ 'http://rubygems.org/gems/meta_compile'
13
+ end