comparison parser.js @ 7:8af72f11714e

Initial version of FFI
author Mike Pavone <pavone@retrodev.com>
date Wed, 21 Mar 2012 20:12:12 -0700
parents 554602d4cbc6
children 04ae32e91598
comparison
equal deleted inserted replaced
6:554602d4cbc6 7:8af72f11714e
26 this.names = {}; 26 this.names = {};
27 this.lastname = null; 27 this.lastname = null;
28 } 28 }
29 osymbols.prototype.find = function(name) { 29 osymbols.prototype.find = function(name) {
30 if (name in this.names) { 30 if (name in this.names) {
31 if (this.names[name] instanceof funcall && this.names[name].name == 'foreign:') {
32 return {
33 type: 'foreign',
34 def: this.names[name]
35 };
36 }
31 return { 37 return {
32 type: 'self', 38 type: 'self',
33 def: this.names[name], 39 def: this.names[name],
34 }; 40 };
35 } else if(this.parent) { 41 } else if(this.parent) {
64 this.lastname = null; 70 this.lastname = null;
65 this.needsSelfVar = false; 71 this.needsSelfVar = false;
66 } 72 }
67 lsymbols.prototype.find = function(name) { 73 lsymbols.prototype.find = function(name) {
68 if (name in this.names) { 74 if (name in this.names) {
75 if (this.names[name] instanceof funcall && this.names[name].name == 'foreign:') {
76 return {
77 type: 'foreign',
78 def: this.names[name]
79 };
80 }
69 return { 81 return {
70 type: 'local', 82 type: 'local',
71 def: this.names[name] 83 def: this.names[name]
72 }; 84 };
73 } else if(this.parent) { 85 } else if(this.parent) {
117 { 129 {
118 this.name = name; 130 this.name = name;
119 } 131 }
120 symbol.prototype.toJS = function(symbols) { 132 symbol.prototype.toJS = function(symbols) {
121 var name = this.cleanName(); 133 var name = this.cleanName();
122 return name == 'self' ? symbols.selfVar() : 's' + name.replace("_", "UN_").replace(":", "CN_").replace("!", "EX_").replace('?', 'QS_').replace('@', 'AT_'); 134 if (name == 'self') {
135 return symbols.selfVar();
136 }
137 name = name.replace("_", "UN_").replace(":", "CN_").replace("!", "EX_").replace('?', 'QS_').replace('@', 'AT_');
138 var reserved = {'true': true, 'false': true, 'this': true, 'if': true, 'else': true, 'NaN': true};
139 if (name in reserved) {
140 name = 's' + name;
141 }
142 return name;
123 } 143 }
124 symbol.prototype.cleanName = function() { 144 symbol.prototype.cleanName = function() {
125 return this.name[0] == ':' ? this.name.substr(1) : this.name; 145 return this.name[0] == ':' ? this.name.substr(1) : this.name;
126 } 146 }
127 147
144 function strlit(val) 164 function strlit(val)
145 { 165 {
146 this.val = val; 166 this.val = val;
147 } 167 }
148 strlit.prototype.toJS = function(symbols) { 168 strlit.prototype.toJS = function(symbols) {
169 console.log('string:', this.val);
149 return '"' + this.val.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n').replace('\r', '\\r') + '"'; 170 return '"' + this.val.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n').replace('\r', '\\r') + '"';
150 } 171 }
151 172
152 function funcall(name, args) 173 function funcall(name, args)
153 { 174 {
186 case 'parent': 207 case 'parent':
187 var ret = 'this'; 208 var ret = 'this';
188 for (var i = 0; i < funinfo.depth; ++i) { 209 for (var i = 0; i < funinfo.depth; ++i) {
189 ret += '.parent'; 210 ret += '.parent';
190 } 211 }
212 for (var i in args) {
213 args[i] = args[i].toJS(symbols);
214 }
191 ret += (new symbol(name)).toJS(symbols) + '(' + args.join(', ') + ')'; 215 ret += (new symbol(name)).toJS(symbols) + '(' + args.join(', ') + ')';
192 return ret; 216 return ret;
193 case 'local': 217 case 'local':
194 case 'upvar': 218 case 'upvar':
219 case 'foreign':
220 for (var i in args) {
221 args[i] = args[i].toJS(symbols);
222 }
195 return (new symbol(name)).toJS(symbols) + '(' + args.join(', ') + ')'; 223 return (new symbol(name)).toJS(symbols) + '(' + args.join(', ') + ')';
196 } 224 }
197 } 225 }
198 226
199 function object(messages) 227 function object(messages)
200 { 228 {
201 this.messages = messages; 229 this.messages = messages;
202 } 230 }
203 object.prototype.toJS = function(symbols) { 231 object.prototype.toJS = function(symbols) {
204 var messages = this.messages.slice(0, this.messages.length); 232 var messages = this.messages;
205 symbols = new osymbols(symbols); 233 symbols = new osymbols(symbols);
234 var compiled = []
206 for (var i in messages) { 235 for (var i in messages) {
207 messages[i] = indent(messages[i].toJSObject(symbols)); 236 var js = messages[i].toJSObject(symbols);
208 } 237 if (js) {
209 return '{\n\tparent: ' + symbols.parentObject() + ',\n\t' + messages.join(',\n\t') + '\n}'; 238 compiled.push(indent(js));
239 }
240 }
241 return '{\n\tparent: ' + symbols.parentObject() + ',\n\t' + compiled.join(',\n\t') + '\n}';
210 } 242 }
211 243
212 object.prototype.toJSModule = function() { 244 object.prototype.toJSModule = function() {
213 return '(function () {\n\tvar module = ' + indent(this.toJS(null)) + ';\n\treturn module;\n})' 245 return '(function () {\n\tvar module = ' + indent(this.toJS(null)) + ';\n\treturn module;\n})'
214 } 246 }
221 lambda.prototype.toJS = function(symbols) { 253 lambda.prototype.toJS = function(symbols) {
222 var args = this.args ? this.args.slice(0, this.args.length) : []; 254 var args = this.args ? this.args.slice(0, this.args.length) : [];
223 if (args.length && args[0].cleanName() == 'self') { 255 if (args.length && args[0].cleanName() == 'self') {
224 args.splice(0, 1); 256 args.splice(0, 1);
225 } 257 }
226 var exprs = this.expressions.slice(0, this.expressions.length); 258 var exprs = this.expressions;
227 symbols = new lsymbols(symbols); 259 symbols = new lsymbols(symbols);
228 for (var i in args) { 260 for (var i in args) {
229 symbols.defineVar(args[i].cleanName(), null); 261 symbols.defineVar(args[i].cleanName(), null);
230 args[i] = args[i].toJS(symbols); 262 args[i] = args[i].toJS(symbols);
231 } 263 }
264 var compiled = []
232 for (var i in exprs) { 265 for (var i in exprs) {
233 exprs[i] = indent(exprs[i].toJS(symbols)); 266 var js = exprs[i].toJS(symbols);
234 } 267 if (js) {
268 compiled.push(indent(js));
269 }
270 }
271 exprs = compiled;
235 if (exprs.length) { 272 if (exprs.length) {
236 exprs[exprs.length-1] = 'return ' + exprs[exprs.length-1] + ';'; 273 exprs[exprs.length-1] = 'return ' + exprs[exprs.length-1] + ';';
237 } 274 }
238 return 'function (' + args.join(', ') + ') {\n\t' + (symbols.needsSelfVar ? 'var self = this;\n\t' : '') + exprs.join(';\n\t') + '\n}' 275 return 'function (' + args.join(', ') + ') {\n\t' + (symbols.needsSelfVar ? 'var self = this;\n\t' : '') + exprs.join(';\n\t') + '\n}'
239 }; 276 };
262 prefix += 'parent.'; 299 prefix += 'parent.';
263 } 300 }
264 break; 301 break;
265 } 302 }
266 } 303 }
304 if (this.expression instanceof funcall && this.expression.name == 'foreign:') {
305 return null;
306 }
267 return prefix + this.symbol.toJS(symbols) + ' = ' + this.expression.toJS(symbols); 307 return prefix + this.symbol.toJS(symbols) + ' = ' + this.expression.toJS(symbols);
268 }; 308 };
269 assignment.prototype.toJSObject = function(symbols) { 309 assignment.prototype.toJSObject = function(symbols) {
270 symbols.defineMsg(this.symbol.name, this.expression); 310 symbols.defineMsg(this.symbol.name, this.expression);
311 if (this.expression instanceof funcall && this.expression.name == 'foreign:') {
312 return null;
313 }
271 return this.symbol.toJS(symbols) + ': ' + this.expression.toJS(symbols); 314 return this.symbol.toJS(symbols) + ': ' + this.expression.toJS(symbols);
272 }; 315 };
273 316
274 var grammar = 317 var grammar =
275 'start = ws module:(object / lambda) ws { return module; };' + 318 'start = ws module:(object / lambda) ws { return module; };' +
323 var text = q('textarea').value; 366 var text = q('textarea').value;
324 //try { 367 //try {
325 var parsed = parser.parse(text); 368 var parsed = parser.parse(text);
326 var js = parsed.toJSModule(); 369 var js = parsed.toJSModule();
327 mainModule = eval(js)(); 370 mainModule = eval(js)();
328 q('pre').innerHTML = mainModule.smain(); 371 q('pre').innerHTML = mainModule.main();
329 /*} catch(e) { 372 /*} catch(e) {
330 q('pre').innerHTML = e.message + '\nLine: ' + e.line + '\nCol: ' + e.column; 373 q('pre').innerHTML = e.message + '\nLine: ' + e.line + '\nCol: ' + e.column;
331 }*/ 374 }*/
332 } 375 }
333 }); 376 });