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.
@@ -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