meta_compile 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +4 -4
- data/Rakefile +98 -50
- data/bin/meta_compile +295 -195
- data/bin/metac_minimal +231 -0
- data/bin/metac_readable +331 -0
- data/bin/{metacomp_re → metac_regexp} +0 -0
- data/meta_compile.gemspec +1 -1
- data/syntaxes/meta_to_ruby.meta +66 -43
- metadata +5 -3
data/bin/metac_minimal
ADDED
@@ -0,0 +1,231 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "strscan"
|
3
|
+
class C_program
|
4
|
+
$c = self
|
5
|
+
def compile(str, out)
|
6
|
+
@i, @o = StringScanner.new(str), out
|
7
|
+
compile_program
|
8
|
+
end
|
9
|
+
def compile_outarg
|
10
|
+
begin
|
11
|
+
@i.scan /\s*/; s='$'; l=s.length;
|
12
|
+
@f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
|
13
|
+
if @f
|
14
|
+
@o.print '@o.print @t'
|
15
|
+
@o.print "\n"
|
16
|
+
end
|
17
|
+
break if @f
|
18
|
+
@i.scan /\s*/; @f = @t = @i.scan /\047[^\047]*\047/
|
19
|
+
if @f
|
20
|
+
@o.print '@o.print '
|
21
|
+
@o.print @t
|
22
|
+
@o.print "\n"
|
23
|
+
end
|
24
|
+
end while false
|
25
|
+
end
|
26
|
+
def compile_out
|
27
|
+
begin
|
28
|
+
@i.scan /\s*/; s='<'; l=s.length;
|
29
|
+
@f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
|
30
|
+
if @f
|
31
|
+
begin
|
32
|
+
compile_outarg
|
33
|
+
end while @f
|
34
|
+
@f = true
|
35
|
+
raise("error at: " + @i.rest.split("\n")[0]) if !@f
|
36
|
+
@i.scan /\s*/; s='>'; l=s.length;
|
37
|
+
@f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
|
38
|
+
raise("error at: " + @i.rest.split("\n")[0]) if !@f
|
39
|
+
@o.print '@o.print "\n"'
|
40
|
+
@o.print "\n"
|
41
|
+
end
|
42
|
+
end while false
|
43
|
+
end
|
44
|
+
def compile_exp3
|
45
|
+
begin
|
46
|
+
@i.scan /\s*/; @f = @t = @i.scan /[A-Za-z]+[A-Za-z0-9_]+/
|
47
|
+
if @f
|
48
|
+
@o.print 'compile_'
|
49
|
+
@o.print @t
|
50
|
+
@o.print "\n"
|
51
|
+
end
|
52
|
+
break if @f
|
53
|
+
@i.scan /\s*/; @f = @t = @i.scan /\047[^\047]*\047/
|
54
|
+
if @f
|
55
|
+
@o.print '@i.scan /\s*/; s='
|
56
|
+
@o.print @t
|
57
|
+
@o.print '; l=s.length;'
|
58
|
+
@o.print "\n"
|
59
|
+
@o.print '@f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil'
|
60
|
+
@o.print "\n"
|
61
|
+
end
|
62
|
+
break if @f
|
63
|
+
@i.scan /\s*/; s='.id'; l=s.length;
|
64
|
+
@f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
|
65
|
+
if @f
|
66
|
+
@o.print '@i.scan /\s*/; @f = @t = @i.scan /[A-Za-z]+[A-Za-z0-9_]+/'
|
67
|
+
@o.print "\n"
|
68
|
+
end
|
69
|
+
break if @f
|
70
|
+
@i.scan /\s*/; s='.string'; l=s.length;
|
71
|
+
@f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
|
72
|
+
if @f
|
73
|
+
@o.print '@i.scan /\s*/; @f = @t = @i.scan /\047[^\047]*\047/'
|
74
|
+
@o.print "\n"
|
75
|
+
end
|
76
|
+
break if @f
|
77
|
+
@i.scan /\s*/; s='('; l=s.length;
|
78
|
+
@f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
|
79
|
+
if @f
|
80
|
+
compile_exp1
|
81
|
+
raise("error at: " + @i.rest.split("\n")[0]) if !@f
|
82
|
+
@i.scan /\s*/; s=')'; l=s.length;
|
83
|
+
@f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
|
84
|
+
raise("error at: " + @i.rest.split("\n")[0]) if !@f
|
85
|
+
end
|
86
|
+
break if @f
|
87
|
+
@i.scan /\s*/; s='.e'; l=s.length;
|
88
|
+
@f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
|
89
|
+
if @f
|
90
|
+
@o.print '@f = true'
|
91
|
+
@o.print "\n"
|
92
|
+
end
|
93
|
+
break if @f
|
94
|
+
@i.scan /\s*/; s='*'; l=s.length;
|
95
|
+
@f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
|
96
|
+
if @f
|
97
|
+
@o.print 'begin'
|
98
|
+
@o.print "\n"
|
99
|
+
compile_exp3
|
100
|
+
raise("error at: " + @i.rest.split("\n")[0]) if !@f
|
101
|
+
@o.print 'end while @f'
|
102
|
+
@o.print "\n"
|
103
|
+
@o.print '@f = true'
|
104
|
+
@o.print "\n"
|
105
|
+
end
|
106
|
+
end while false
|
107
|
+
end
|
108
|
+
def compile_exp2
|
109
|
+
begin
|
110
|
+
begin
|
111
|
+
compile_exp3
|
112
|
+
if @f
|
113
|
+
@o.print 'if @f'
|
114
|
+
@o.print "\n"
|
115
|
+
end
|
116
|
+
break if @f
|
117
|
+
compile_out
|
118
|
+
if @f
|
119
|
+
@o.print 'if true'
|
120
|
+
@o.print "\n"
|
121
|
+
end
|
122
|
+
end while false
|
123
|
+
if @f
|
124
|
+
begin
|
125
|
+
begin
|
126
|
+
compile_exp3
|
127
|
+
if @f
|
128
|
+
@o.print 'raise("error at: " + @i.rest.split("\n")[0]) if !@f'
|
129
|
+
@o.print "\n"
|
130
|
+
end
|
131
|
+
break if @f
|
132
|
+
compile_out
|
133
|
+
if @f
|
134
|
+
end
|
135
|
+
end while false
|
136
|
+
end while @f
|
137
|
+
@f = true
|
138
|
+
raise("error at: " + @i.rest.split("\n")[0]) if !@f
|
139
|
+
@o.print 'end'
|
140
|
+
@o.print "\n"
|
141
|
+
end
|
142
|
+
end while false
|
143
|
+
end
|
144
|
+
def compile_exp1
|
145
|
+
begin
|
146
|
+
@o.print 'begin'
|
147
|
+
@o.print "\n"
|
148
|
+
if true
|
149
|
+
compile_exp2
|
150
|
+
raise("error at: " + @i.rest.split("\n")[0]) if !@f
|
151
|
+
begin
|
152
|
+
begin
|
153
|
+
@i.scan /\s*/; s='|'; l=s.length;
|
154
|
+
@f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
|
155
|
+
if @f
|
156
|
+
@o.print 'break if @f'
|
157
|
+
@o.print "\n"
|
158
|
+
compile_exp2
|
159
|
+
raise("error at: " + @i.rest.split("\n")[0]) if !@f
|
160
|
+
end
|
161
|
+
end while false
|
162
|
+
end while @f
|
163
|
+
@f = true
|
164
|
+
raise("error at: " + @i.rest.split("\n")[0]) if !@f
|
165
|
+
@o.print 'end while false'
|
166
|
+
@o.print "\n"
|
167
|
+
end
|
168
|
+
end while false
|
169
|
+
end
|
170
|
+
def compile_rule
|
171
|
+
begin
|
172
|
+
@i.scan /\s*/; @f = @t = @i.scan /[A-Za-z]+[A-Za-z0-9_]+/
|
173
|
+
if @f
|
174
|
+
@o.print 'def compile_'
|
175
|
+
@o.print @t
|
176
|
+
@o.print "\n"
|
177
|
+
@i.scan /\s*/; s='='; l=s.length;
|
178
|
+
@f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
|
179
|
+
raise("error at: " + @i.rest.split("\n")[0]) if !@f
|
180
|
+
compile_exp1
|
181
|
+
raise("error at: " + @i.rest.split("\n")[0]) if !@f
|
182
|
+
@i.scan /\s*/; s=';'; l=s.length;
|
183
|
+
@f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
|
184
|
+
raise("error at: " + @i.rest.split("\n")[0]) if !@f
|
185
|
+
@o.print 'end'
|
186
|
+
@o.print "\n"
|
187
|
+
end
|
188
|
+
end while false
|
189
|
+
end
|
190
|
+
def compile_program
|
191
|
+
begin
|
192
|
+
@i.scan /\s*/; s='.syntax'; l=s.length;
|
193
|
+
@f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
|
194
|
+
if @f
|
195
|
+
@i.scan /\s*/; @f = @t = @i.scan /[A-Za-z]+[A-Za-z0-9_]+/
|
196
|
+
raise("error at: " + @i.rest.split("\n")[0]) if !@f
|
197
|
+
@o.print '#!/usr/bin/env ruby'
|
198
|
+
@o.print "\n"
|
199
|
+
@o.print 'require "strscan"'
|
200
|
+
@o.print "\n"
|
201
|
+
@o.print 'class C_'
|
202
|
+
@o.print @t
|
203
|
+
@o.print "\n"
|
204
|
+
@o.print '$c = self'
|
205
|
+
@o.print "\n"
|
206
|
+
@o.print 'def compile(str, out)'
|
207
|
+
@o.print "\n"
|
208
|
+
@o.print '@i, @o = StringScanner.new(str), out'
|
209
|
+
@o.print "\n"
|
210
|
+
@o.print 'compile_'
|
211
|
+
@o.print @t
|
212
|
+
@o.print "\n"
|
213
|
+
@o.print 'end'
|
214
|
+
@o.print "\n"
|
215
|
+
begin
|
216
|
+
compile_rule
|
217
|
+
end while @f
|
218
|
+
@f = true
|
219
|
+
raise("error at: " + @i.rest.split("\n")[0]) if !@f
|
220
|
+
@i.scan /\s*/; s='.end'; l=s.length;
|
221
|
+
@f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
|
222
|
+
raise("error at: " + @i.rest.split("\n")[0]) if !@f
|
223
|
+
@o.print 'end'
|
224
|
+
@o.print "\n"
|
225
|
+
@o.print '$c.new.compile(File.read(ARGV[0]), STDOUT)'
|
226
|
+
@o.print "\n"
|
227
|
+
end
|
228
|
+
end while false
|
229
|
+
end
|
230
|
+
end
|
231
|
+
$c.new.compile(File.read(ARGV[0]), STDOUT)
|
data/bin/metac_readable
ADDED
@@ -0,0 +1,331 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "strscan"
|
3
|
+
class StringScanner
|
4
|
+
# Add scan for string since base StringScanner lack that...
|
5
|
+
def scan_str(string)
|
6
|
+
return nil unless self.peek(string.length) == string
|
7
|
+
self.pos += string.length # Advance the position in the input string
|
8
|
+
return string
|
9
|
+
end
|
10
|
+
alias :old_scan :scan
|
11
|
+
def scan(strOrRegexp)
|
12
|
+
String === strOrRegexp ? scan_str(strOrRegexp) : old_scan(strOrRegexp)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
class MetaCompiler_program
|
16
|
+
$compiler_class = self # Save class in global var for later reference below
|
17
|
+
def compile_string(string, outFile)
|
18
|
+
@in, @out = StringScanner.new(string), outFile
|
19
|
+
compile_program # call the main compile method to start compiling
|
20
|
+
end
|
21
|
+
# Scan for a string or regexp and update state based on match. Skips leading whitespace.
|
22
|
+
def scan strOrRegexp
|
23
|
+
@in.scan /\s*/ # Skip whitespace
|
24
|
+
@match = @in.scan strOrRegexp
|
25
|
+
# Since nil is same as false in Ruby we can set the flag to the matched token
|
26
|
+
@last_matched_token = @match if @match # Update last matched only if a token was matched
|
27
|
+
end
|
28
|
+
def report_error
|
29
|
+
pre_lines = @in.string[0, @in.pos].split("\n") # lines of input up to current position
|
30
|
+
post_lines = @in.rest.split("\n") # lines of input after current position
|
31
|
+
message = "PARSE ERROR at line #{pre_lines.length}:\n " + pre_lines.last.inspect + " @ "
|
32
|
+
message += post_lines.first.inspect
|
33
|
+
message += "\n Last matched token: #{@last_matched_token}"
|
34
|
+
raise message
|
35
|
+
end
|
36
|
+
def self.compile_file(inFile, out = nil)
|
37
|
+
outfh = (out == nil ? STDOUT : File.open(out, "w"))
|
38
|
+
self.new.compile_string(File.read(inFile), outfh)
|
39
|
+
outfh.close if out == nil
|
40
|
+
end
|
41
|
+
def compile_outarg
|
42
|
+
begin
|
43
|
+
scan '$'
|
44
|
+
if @match
|
45
|
+
@out.print '@out.print @match # Print last matched token on output stream' # Print literal string on output stream
|
46
|
+
@out.print "\n" # Print newline on output stream
|
47
|
+
end
|
48
|
+
break if @match
|
49
|
+
scan /\047[^\047]*\047/
|
50
|
+
if @match
|
51
|
+
@out.print '@out.print ' # Print literal string on output stream
|
52
|
+
@out.print @match # Print last matched token on output stream
|
53
|
+
@out.print ' # Print literal string on output stream' # Print literal string on output stream
|
54
|
+
@out.print "\n" # Print newline on output stream
|
55
|
+
end
|
56
|
+
end while false # This "while false" is needed since the break is not parsed correctly by Ruby otherwise
|
57
|
+
end
|
58
|
+
def compile_out
|
59
|
+
begin
|
60
|
+
scan '<'
|
61
|
+
if @match
|
62
|
+
begin
|
63
|
+
compile_outarg # Call the method for a rule
|
64
|
+
end while @match # Loop while there is a match
|
65
|
+
@match = true # Since also zero matches is ok set flag here.
|
66
|
+
report_error() unless @match
|
67
|
+
scan '>'
|
68
|
+
report_error() unless @match
|
69
|
+
@out.print '@out.print "\n" # Print newline on output stream' # Print literal string on output stream
|
70
|
+
@out.print "\n" # Print newline on output stream
|
71
|
+
end
|
72
|
+
end while false # This "while false" is needed since the break is not parsed correctly by Ruby otherwise
|
73
|
+
end
|
74
|
+
def compile_exp3
|
75
|
+
begin
|
76
|
+
scan /[A-Za-z]+[A-Za-z0-9_]+/
|
77
|
+
if @match
|
78
|
+
@out.print 'compile_' # Print literal string on output stream
|
79
|
+
@out.print @match # Print last matched token on output stream
|
80
|
+
@out.print ' # Call the method for a rule' # Print literal string on output stream
|
81
|
+
@out.print "\n" # Print newline on output stream
|
82
|
+
end
|
83
|
+
break if @match
|
84
|
+
scan /\047[^\047]*\047/
|
85
|
+
if @match
|
86
|
+
@out.print 'scan ' # Print literal string on output stream
|
87
|
+
@out.print @match # Print last matched token on output stream
|
88
|
+
@out.print "\n" # Print newline on output stream
|
89
|
+
end
|
90
|
+
break if @match
|
91
|
+
scan '.id'
|
92
|
+
if @match
|
93
|
+
@out.print 'scan /[A-Za-z]+[A-Za-z0-9_]+/' # Print literal string on output stream
|
94
|
+
@out.print "\n" # Print newline on output stream
|
95
|
+
end
|
96
|
+
break if @match
|
97
|
+
scan '.string'
|
98
|
+
if @match
|
99
|
+
@out.print 'scan /\047[^\047]*\047/' # Print literal string on output stream
|
100
|
+
@out.print "\n" # Print newline on output stream
|
101
|
+
end
|
102
|
+
break if @match
|
103
|
+
scan '('
|
104
|
+
if @match
|
105
|
+
compile_exp1 # Call the method for a rule
|
106
|
+
report_error() unless @match
|
107
|
+
scan ')'
|
108
|
+
report_error() unless @match
|
109
|
+
end
|
110
|
+
break if @match
|
111
|
+
scan '.e'
|
112
|
+
if @match
|
113
|
+
@out.print '@match = true # .e means empty so always matches => set flag.' # Print literal string on output stream
|
114
|
+
@out.print "\n" # Print newline on output stream
|
115
|
+
end
|
116
|
+
break if @match
|
117
|
+
scan '*'
|
118
|
+
if @match
|
119
|
+
@out.print 'begin' # Print literal string on output stream
|
120
|
+
@out.print "\n" # Print newline on output stream
|
121
|
+
compile_exp3 # Call the method for a rule
|
122
|
+
report_error() unless @match
|
123
|
+
@out.print 'end while @match # Loop while there is a match' # Print literal string on output stream
|
124
|
+
@out.print "\n" # Print newline on output stream
|
125
|
+
@out.print '@match = true # Since also zero matches is ok set flag here.' # Print literal string on output stream
|
126
|
+
@out.print "\n" # Print newline on output stream
|
127
|
+
end
|
128
|
+
end while false # This "while false" is needed since the break is not parsed correctly by Ruby otherwise
|
129
|
+
end
|
130
|
+
def compile_exp2
|
131
|
+
begin
|
132
|
+
begin
|
133
|
+
compile_exp3 # Call the method for a rule
|
134
|
+
if @match
|
135
|
+
@out.print 'if @match' # Print literal string on output stream
|
136
|
+
@out.print "\n" # Print newline on output stream
|
137
|
+
end
|
138
|
+
break if @match
|
139
|
+
compile_out # Call the method for a rule
|
140
|
+
if @match
|
141
|
+
@out.print 'if true' # Print literal string on output stream
|
142
|
+
@out.print "\n" # Print newline on output stream
|
143
|
+
end
|
144
|
+
end while false # This "while false" is needed since the break is not parsed correctly by Ruby otherwise
|
145
|
+
if @match
|
146
|
+
begin
|
147
|
+
begin
|
148
|
+
compile_exp3 # Call the method for a rule
|
149
|
+
if @match
|
150
|
+
@out.print 'report_error() unless @match' # Print literal string on output stream
|
151
|
+
@out.print "\n" # Print newline on output stream
|
152
|
+
end
|
153
|
+
break if @match
|
154
|
+
compile_out # Call the method for a rule
|
155
|
+
if @match
|
156
|
+
end
|
157
|
+
end while false # This "while false" is needed since the break is not parsed correctly by Ruby otherwise
|
158
|
+
end while @match # Loop while there is a match
|
159
|
+
@match = true # Since also zero matches is ok set flag here.
|
160
|
+
report_error() unless @match
|
161
|
+
@out.print 'end' # Print literal string on output stream
|
162
|
+
@out.print "\n" # Print newline on output stream
|
163
|
+
end
|
164
|
+
end while false # This "while false" is needed since the break is not parsed correctly by Ruby otherwise
|
165
|
+
end
|
166
|
+
def compile_exp1
|
167
|
+
begin
|
168
|
+
@out.print 'begin' # Print literal string on output stream
|
169
|
+
@out.print "\n" # Print newline on output stream
|
170
|
+
if true
|
171
|
+
compile_exp2 # Call the method for a rule
|
172
|
+
report_error() unless @match
|
173
|
+
begin
|
174
|
+
begin
|
175
|
+
scan '|'
|
176
|
+
if @match
|
177
|
+
@out.print 'break if @match' # Print literal string on output stream
|
178
|
+
@out.print "\n" # Print newline on output stream
|
179
|
+
compile_exp2 # Call the method for a rule
|
180
|
+
report_error() unless @match
|
181
|
+
end
|
182
|
+
end while false # This "while false" is needed since the break is not parsed correctly by Ruby otherwise
|
183
|
+
end while @match # Loop while there is a match
|
184
|
+
@match = true # Since also zero matches is ok set flag here.
|
185
|
+
report_error() unless @match
|
186
|
+
@out.print 'end while false # This "while false" is needed since the break is not parsed correctly by Ruby otherwise' # Print literal string on output stream
|
187
|
+
@out.print "\n" # Print newline on output stream
|
188
|
+
end
|
189
|
+
end while false # This "while false" is needed since the break is not parsed correctly by Ruby otherwise
|
190
|
+
end
|
191
|
+
def compile_rule
|
192
|
+
begin
|
193
|
+
scan /[A-Za-z]+[A-Za-z0-9_]+/
|
194
|
+
if @match
|
195
|
+
@out.print 'def compile_' # Print literal string on output stream
|
196
|
+
@out.print @match # Print last matched token on output stream
|
197
|
+
@out.print "\n" # Print newline on output stream
|
198
|
+
scan '='
|
199
|
+
report_error() unless @match
|
200
|
+
compile_exp1 # Call the method for a rule
|
201
|
+
report_error() unless @match
|
202
|
+
scan ';'
|
203
|
+
report_error() unless @match
|
204
|
+
@out.print 'end' # Print literal string on output stream
|
205
|
+
@out.print "\n" # Print newline on output stream
|
206
|
+
end
|
207
|
+
end while false # This "while false" is needed since the break is not parsed correctly by Ruby otherwise
|
208
|
+
end
|
209
|
+
def compile_program
|
210
|
+
begin
|
211
|
+
scan '.syntax'
|
212
|
+
if @match
|
213
|
+
scan /[A-Za-z]+[A-Za-z0-9_]+/
|
214
|
+
report_error() unless @match
|
215
|
+
@out.print '#!/usr/bin/env ruby' # Print literal string on output stream
|
216
|
+
@out.print "\n" # Print newline on output stream
|
217
|
+
@out.print 'require "strscan"' # Print literal string on output stream
|
218
|
+
@out.print "\n" # Print newline on output stream
|
219
|
+
@out.print 'class StringScanner' # Print literal string on output stream
|
220
|
+
@out.print "\n" # Print newline on output stream
|
221
|
+
@out.print ' # Add scan for string since base StringScanner lack that...' # Print literal string on output stream
|
222
|
+
@out.print "\n" # Print newline on output stream
|
223
|
+
@out.print ' def scan_str(string)' # Print literal string on output stream
|
224
|
+
@out.print "\n" # Print newline on output stream
|
225
|
+
@out.print ' return nil unless self.peek(string.length) == string' # Print literal string on output stream
|
226
|
+
@out.print "\n" # Print newline on output stream
|
227
|
+
@out.print ' self.pos += string.length # Advance the position in the input string' # Print literal string on output stream
|
228
|
+
@out.print "\n" # Print newline on output stream
|
229
|
+
@out.print ' return string' # Print literal string on output stream
|
230
|
+
@out.print "\n" # Print newline on output stream
|
231
|
+
@out.print ' end' # Print literal string on output stream
|
232
|
+
@out.print "\n" # Print newline on output stream
|
233
|
+
@out.print ' alias :old_scan :scan' # Print literal string on output stream
|
234
|
+
@out.print "\n" # Print newline on output stream
|
235
|
+
@out.print ' def scan(strOrRegexp)' # Print literal string on output stream
|
236
|
+
@out.print "\n" # Print newline on output stream
|
237
|
+
@out.print ' String === strOrRegexp ? scan_str(strOrRegexp) : old_scan(strOrRegexp)' # Print literal string on output stream
|
238
|
+
@out.print "\n" # Print newline on output stream
|
239
|
+
@out.print ' end' # Print literal string on output stream
|
240
|
+
@out.print "\n" # Print newline on output stream
|
241
|
+
@out.print 'end' # Print literal string on output stream
|
242
|
+
@out.print "\n" # Print newline on output stream
|
243
|
+
@out.print 'class MetaCompiler_' # Print literal string on output stream
|
244
|
+
@out.print @match # Print last matched token on output stream
|
245
|
+
@out.print "\n" # Print newline on output stream
|
246
|
+
@out.print ' $compiler_class = self # Save class in global var for later reference below' # Print literal string on output stream
|
247
|
+
@out.print "\n" # Print newline on output stream
|
248
|
+
@out.print ' def compile_string(string, outFile)' # Print literal string on output stream
|
249
|
+
@out.print "\n" # Print newline on output stream
|
250
|
+
@out.print ' @in, @out = StringScanner.new(string), outFile' # Print literal string on output stream
|
251
|
+
@out.print "\n" # Print newline on output stream
|
252
|
+
@out.print ' compile_' # Print literal string on output stream
|
253
|
+
@out.print @match # Print last matched token on output stream
|
254
|
+
@out.print ' # call the main compile method to start compiling' # Print literal string on output stream
|
255
|
+
@out.print "\n" # Print newline on output stream
|
256
|
+
@out.print ' end' # Print literal string on output stream
|
257
|
+
@out.print "\n" # Print newline on output stream
|
258
|
+
@out.print ' # Scan for a string or regexp and update state based on match. Skips leading whitespace.' # Print literal string on output stream
|
259
|
+
@out.print "\n" # Print newline on output stream
|
260
|
+
@out.print ' def scan strOrRegexp' # Print literal string on output stream
|
261
|
+
@out.print "\n" # Print newline on output stream
|
262
|
+
@out.print ' @in.scan /\s*/ # Skip whitespace' # Print literal string on output stream
|
263
|
+
@out.print "\n" # Print newline on output stream
|
264
|
+
@out.print ' @match = @in.scan strOrRegexp' # Print literal string on output stream
|
265
|
+
@out.print "\n" # Print newline on output stream
|
266
|
+
@out.print ' # Since nil is same as false in Ruby we can set the flag to the matched token' # Print literal string on output stream
|
267
|
+
@out.print "\n" # Print newline on output stream
|
268
|
+
@out.print ' @last_matched_token = @match if @match # Update last matched only if a token was matched' # Print literal string on output stream
|
269
|
+
@out.print "\n" # Print newline on output stream
|
270
|
+
@out.print ' end' # Print literal string on output stream
|
271
|
+
@out.print "\n" # Print newline on output stream
|
272
|
+
@out.print ' def report_error' # Print literal string on output stream
|
273
|
+
@out.print "\n" # Print newline on output stream
|
274
|
+
@out.print ' pre_lines = @in.string[0, @in.pos].split("\n") # lines of input up to current position' # Print literal string on output stream
|
275
|
+
@out.print "\n" # Print newline on output stream
|
276
|
+
@out.print ' post_lines = @in.rest.split("\n") # lines of input after current position' # Print literal string on output stream
|
277
|
+
@out.print "\n" # Print newline on output stream
|
278
|
+
@out.print ' message = "PARSE ERROR at line #{pre_lines.length}:\n " + pre_lines.last.inspect + " @ "' # Print literal string on output stream
|
279
|
+
@out.print "\n" # Print newline on output stream
|
280
|
+
@out.print ' message += post_lines.first.inspect' # Print literal string on output stream
|
281
|
+
@out.print "\n" # Print newline on output stream
|
282
|
+
@out.print ' message += "\n Last matched token: #{@last_matched_token}"' # Print literal string on output stream
|
283
|
+
@out.print "\n" # Print newline on output stream
|
284
|
+
@out.print ' raise message' # Print literal string on output stream
|
285
|
+
@out.print "\n" # Print newline on output stream
|
286
|
+
@out.print ' end' # Print literal string on output stream
|
287
|
+
@out.print "\n" # Print newline on output stream
|
288
|
+
@out.print ' def self.compile_file(inFile, out = nil)' # Print literal string on output stream
|
289
|
+
@out.print "\n" # Print newline on output stream
|
290
|
+
@out.print ' outfh = (out == nil ? STDOUT : File.open(out, "w"))' # Print literal string on output stream
|
291
|
+
@out.print "\n" # Print newline on output stream
|
292
|
+
@out.print ' self.new.compile_string(File.read(inFile), outfh)' # Print literal string on output stream
|
293
|
+
@out.print "\n" # Print newline on output stream
|
294
|
+
@out.print ' outfh.close if out == nil' # Print literal string on output stream
|
295
|
+
@out.print "\n" # Print newline on output stream
|
296
|
+
@out.print ' end' # Print literal string on output stream
|
297
|
+
@out.print "\n" # Print newline on output stream
|
298
|
+
begin
|
299
|
+
compile_rule # Call the method for a rule
|
300
|
+
end while @match # Loop while there is a match
|
301
|
+
@match = true # Since also zero matches is ok set flag here.
|
302
|
+
report_error() unless @match
|
303
|
+
scan '.end'
|
304
|
+
report_error() unless @match
|
305
|
+
@out.print 'end' # Print literal string on output stream
|
306
|
+
@out.print "\n" # Print newline on output stream
|
307
|
+
@out.print 'if ARGV.length < 1 || ARGV.length > 2' # Print literal string on output stream
|
308
|
+
@out.print "\n" # Print newline on output stream
|
309
|
+
@out.print ' puts "ERROR: wrong number of parameters\n\n"' # Print literal string on output stream
|
310
|
+
@out.print "\n" # Print newline on output stream
|
311
|
+
@out.print ' puts "Usage: #{File.basename($0)} <input_file> [output_file]"' # Print literal string on output stream
|
312
|
+
@out.print "\n" # Print newline on output stream
|
313
|
+
@out.print ' exit(-1)' # Print literal string on output stream
|
314
|
+
@out.print "\n" # Print newline on output stream
|
315
|
+
@out.print 'else' # Print literal string on output stream
|
316
|
+
@out.print "\n" # Print newline on output stream
|
317
|
+
@out.print ' $compiler_class.compile_file(ARGV[0], ARGV[1])' # Print literal string on output stream
|
318
|
+
@out.print "\n" # Print newline on output stream
|
319
|
+
@out.print 'end' # Print literal string on output stream
|
320
|
+
@out.print "\n" # Print newline on output stream
|
321
|
+
end
|
322
|
+
end while false # This "while false" is needed since the break is not parsed correctly by Ruby otherwise
|
323
|
+
end
|
324
|
+
end
|
325
|
+
if ARGV.length < 1 || ARGV.length > 2
|
326
|
+
puts "ERROR: wrong number of parameters\n\n"
|
327
|
+
puts "Usage: #{File.basename($0)} <input_file> [output_file]"
|
328
|
+
exit(-1)
|
329
|
+
else
|
330
|
+
$compiler_class.compile_file(ARGV[0], ARGV[1])
|
331
|
+
end
|