Skip to content

Commit 8c0522d

Browse files
committed
Adding files
0 parents  commit 8c0522d

22 files changed

+3024
-0
lines changed

js_compiler.rb

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#!ruby
2+
# coding: utf-8
3+
#
4+
# js_compiler.rb
5+
#
6+
# Created by Erik Österlund on 1/14/10.
7+
# Copyright 2010 Växjö Universitet. All rights reserved.
8+
#
9+
10+
require 'table_generator'
11+
12+
module LALR
13+
14+
class InterpreterGenerator
15+
16+
def generate_compiler
17+
<<-end.here_with_pipe
18+
|function compile(){
19+
|var di = o.length;
20+
|var ti = t.length;
21+
|#{@compiler}
22+
|function N(){
23+
|this.$ = [];
24+
|}
25+
|N.prototype.e = function(){$.push(this.$[0]);};
26+
|var R = [#{
27+
@rules.size.times.map do |i|
28+
rule = @rules[i]
29+
prods = rule.productions
30+
31+
str = "function N#{i}(){"
32+
str << "this.$ = [];"
33+
if i == 0
34+
str << "n = new R[o[--di]];"
35+
str << "this.e = function(){this.$[0].e();};"
36+
str << "this.$.push(n);"
37+
else
38+
prods.size.times.reverse_each do |p|
39+
product = prods[p]
40+
str << "var n;"
41+
case product
42+
when Symbol
43+
str << "n = new R[o[--di]];"
44+
str << "this.$.unshift(n);"
45+
else
46+
str << "n = new N();"
47+
str << "n.$.push(t[--ti]);"
48+
str << "this.$.unshift(n);"
49+
end
50+
end
51+
end
52+
str << "}"
53+
str
54+
end.join(",")
55+
}];
56+
|#{
57+
(1...@rules.size).each.map do |i|
58+
evaluator = @rule_evaluators[i-1]
59+
"R[#{i}].prototype.e = function(){#{evaluator}};"
60+
end.join("")
61+
}
62+
|var $ = [];
63+
|#{@compiler_name ? "var context = new #{@compiler_name}();" : ""}
64+
|new R[0]().e();
65+
|postMessage($.join(""));
66+
|}
67+
end
68+
69+
end
70+
71+
end
72+
73+
end

js_compiler_single.rb

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#!ruby
2+
# coding: utf-8
3+
#
4+
# js_compiler.rb
5+
#
6+
# Created by Erik Österlund on 1/14/10.
7+
# Copyright 2010 Växjö Universitet. All rights reserved.
8+
#
9+
10+
require 'table_generator'
11+
require 'set'
12+
13+
module LALR
14+
15+
class InterpreterGenerator
16+
17+
def generate_compiler_single
18+
token_to_num = {}
19+
@tokens.size.times do |i|
20+
token_to_num[@tokens[i]] = i + 1 # Start symbol is 0
21+
end
22+
known_token_set = Set.new
23+
@token_lit.each do |str, num|
24+
known_token_set << num
25+
end
26+
27+
<<-end.here_with_pipe
28+
|
29+
|#{@name}_parser.prototype.compile = function(t, o){
30+
|var di = o.length;
31+
|var ti = t.length;
32+
|#{@compiler}
33+
|function N(){
34+
|this.$0=t[--ti];
35+
|}
36+
|N.prototype.e = function(){$.push(this.$0);};
37+
|var R = [#{
38+
@rules.size.times.map do |i|
39+
rule = @rules[i]
40+
prods = rule.productions
41+
42+
str = "function N#{i}(){"
43+
if i == 0
44+
str << "n = new R[o[--di]];"
45+
str << "this.e = function(){this.$1.e();};"
46+
str << "this.$1=n;"
47+
else
48+
prods.size.times.reverse_each do |p|
49+
product = prods[p]
50+
case product
51+
when Symbol
52+
str << "this.$#{p+1}=new R[o[--di]];"
53+
when Regexp
54+
if not known_token_set.include? token_to_num[p]
55+
str << "this.$#{p+1}=new N();"
56+
else
57+
str << "ti--;"
58+
end
59+
end
60+
end
61+
end
62+
str << "}"
63+
str
64+
end.join(",")
65+
}];
66+
|#{
67+
(1...@rules.size).each.map do |i|
68+
evaluator = @rule_evaluators[i-1]
69+
"R[#{i}].prototype.e = function(){#{evaluator}};"
70+
end.join("")
71+
}
72+
|var $ = [];
73+
|#{@compiler_name ? "var context = new #{@compiler_name}();" : ""}
74+
|var start = new Date().getTime();
75+
|var tree = new R[0]();
76+
|console.log("Constructing tree: " + (new Date().getTime() - start));
77+
|var start = new Date().getTime();
78+
|tree.e();
79+
|console.log("Evaluating tree: " + (new Date().getTime() - start));
80+
|return [$.join(""), context._dependencies];
81+
|}
82+
end
83+
84+
end
85+
86+
end
87+
88+
end

js_interpreter_generator.rb

+197
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
#!ruby
2+
# coding: utf-8
3+
#
4+
# js_interpreter_generator.rb
5+
#
6+
# Created by Erik Österlund on 1/14/10.
7+
# Copyright 2010 Växjö Universitet. All rights reserved.
8+
#
9+
10+
require 'table_generator'
11+
require 'parser'
12+
require 'set'
13+
require 'digest'
14+
require 'js_compiler'
15+
require 'js_parser'
16+
require 'js_lexer'
17+
require 'js_interpreter_generator_single'
18+
19+
class String
20+
def here_with_pipe
21+
lines = self.split("\n")
22+
lines.map! {|c| c.sub!(/\s*\|/, '')}
23+
new_string = lines.join("\n")
24+
self.replace(new_string)
25+
end
26+
end
27+
28+
module LALR
29+
30+
class InterpreterGenerator
31+
include Marshal
32+
33+
def compiler(arg)
34+
@compiler = yield.gsub(/\n\s*/m, "")
35+
@compiler_name = arg
36+
end
37+
38+
def header()
39+
@header = yield
40+
end
41+
42+
def footer()
43+
@footer = yield
44+
end
45+
46+
def comment(arg)
47+
@comments << arg
48+
end
49+
50+
def commentAmbiguity(arg)
51+
@commentAmbiguities << arg
52+
end
53+
54+
def token(arg, literal = nil)
55+
reg = fix_regex arg if arg.is_a? Regexp
56+
@token_lit[literal] = @tokens.length if literal
57+
end
58+
59+
def rule(arg)
60+
arg.each do |k,v|
61+
if v.is_a? Array
62+
v.size.times do |i|
63+
v[i] = fix_regex v[i] if v[i].is_a? Regexp
64+
end
65+
@rules << Rule.new(k, v)
66+
else
67+
v = fix_regex v if v.is_a? Regexp
68+
@rules << Rule.new(k, [v])
69+
end
70+
end
71+
@rule_evaluators << yield.gsub(/\$(\d+)/m){|m|"this.$#{m[1].to_i}.$0"}.
72+
gsub(/\${2}/m, 'this.$0').gsub(/\@(\d+)/m){|m|"this.$#{m[1].to_i}"}.
73+
gsub(/\@{2}/m, 'this').gsub(/\n\s*/m, "")
74+
end
75+
76+
def start(arg)
77+
@start = arg
78+
end
79+
80+
def initialize(arg, file)
81+
@rules = []
82+
@rule_evaluators = []
83+
@tokens = []
84+
@token_lit = {}
85+
@comments = []
86+
@commentAmbiguities = []
87+
@name, @file = arg, file
88+
@compiler = ""
89+
@compiler_name = nil
90+
end
91+
92+
def symbol_to_index
93+
symbols = Set.new
94+
@rules.each do |rule|
95+
symbols << rule.name
96+
end
97+
symbols = symbols.to_a
98+
sm = {}
99+
symbols.size.times do |i|
100+
sm[symbols[i]] = i
101+
end
102+
sm
103+
end
104+
105+
def generate_interpreter
106+
our_dump = dump(@rules.map{|rule|rule.name.to_s + rule.productions.to_s}) +
107+
dump(@start) + dump(@tokens.sort{|a, b|a.source <=> b.source}) + dump(@comments.sort{|a, b|a.source <=> b.source})
108+
current_dump = ""
109+
File.open(@file + ".grammar", "r"){|f|
110+
current_dump = f.read
111+
} if File.exists?(@file + ".grammar")
112+
113+
if Digest::SHA256.digest(our_dump) == Digest::SHA256.digest(current_dump) and
114+
File.exists?(@file + ".gotos") and File.exists?(@file + ".actions")
115+
File.open(@file + ".gotos", "r"){|f|
116+
@gotos = Marshal.restore(f.read())
117+
}
118+
File.open(@file + ".actions", "r"){|f|
119+
@actions = Marshal.restore(f.read())
120+
}
121+
@rules.insert 0, Rule.new(:S, [@start])
122+
else
123+
generator = TableGenerator.new(@rules, @start)
124+
@actions, @gotos = generator.generate_tables
125+
126+
File.open(@file + ".grammar", "w"){|f|
127+
f.write(our_dump)
128+
}
129+
File.open(@file + ".gotos", "w"){|f|
130+
f.write(Marshal.dump(@gotos))
131+
}
132+
File.open(@file + ".actions", "w"){|f|
133+
f.write(Marshal.dump(@actions))
134+
}
135+
end
136+
137+
File.open(@file + ".js", "w"){|f|
138+
f.write generate_interface
139+
}
140+
File.open(@file + "_lexer.js", "w"){|f|
141+
f.write generate_lexer
142+
}
143+
File.open(@file + "_parser.js", "w"){|f|
144+
f.write generate_parser
145+
}
146+
File.open(@file + "_single.js", "w"){|f|
147+
f.write generate_interface_single
148+
}
149+
end
150+
151+
private
152+
def fix_regex(reg)
153+
r = Regexp.new("(" + reg.source + ")", Regexp::MULTILINE)
154+
@tokens << r unless @tokens.include? r
155+
r
156+
end
157+
158+
def generate_interface
159+
<<-end.here_with_pipe
160+
|function #{@name}_compiler(str, path, bundle, callback)
161+
|{
162+
|this._lexer = new Worker('#{@file + "_lexer.js"}');
163+
|this._parser = new Worker('#{@file + "_parser.js"}');
164+
|var parser = this._parser;
165+
|this._executable = null;
166+
|this._code = str;
167+
|this._dependencies = [];
168+
|var dependencies = this._dependencies;
169+
|this._bundle = bundle;
170+
|this._path = path;
171+
|
172+
|this._lexer.onmessage = function(message)
173+
|{
174+
|parser.postMessage(message.data);
175+
|}
176+
|
177+
|this._parser.onmessage = function(message)
178+
|{
179+
|callback(new Executable(message.data, dependencies));
180+
|}
181+
|}
182+
|#{@name}_compiler.prototype.parse = function()
183+
|{
184+
|this._start = new Date();
185+
|this._startLexing = this._start;
186+
|this._lexer.postMessage(this._code);
187+
|}
188+
|function preprocess(str, path, bundle, callback)
189+
|{
190+
|new #{@name}_compiler(str, path, bundle, callback).parse();
191+
|}
192+
end
193+
end
194+
195+
end
196+
197+
end

0 commit comments

Comments
 (0)