Mercurial > repos > tabletprog
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 }); |