Mercurial > repos > tabletprog
comparison parser.js @ 217:adad61ea2f3a
Switched to a less hacky implementation of hygiene and exposed more AST properties to macros
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 21 Dec 2013 12:07:51 -0800 |
parents | e01137a97654 |
children | 7435367a932a |
comparison
equal
deleted
inserted
replaced
216:2dac67e9d18b | 217:adad61ea2f3a |
---|---|
1 | 1 |
2 function op(left, op, right) | 2 function op(left, op, right) |
3 { | 3 { |
4 this.left = left; | 4 this.left = left; |
5 if (op instanceof Array) { | |
6 op = op[0]; | |
7 } | |
5 this.op = op; | 8 this.op = op; |
6 this.right = right; | 9 this.right = right; |
7 } | 10 } |
11 op.prototype.valueOf = function(indent) { | |
12 return this.left.valueOf(indent) + ' ' + this.op.valueOf(indent) + ' ' + this.right.valueOf(indent); | |
13 }; | |
8 | 14 |
9 function symbol(name, symbols) | 15 function symbol(name, symbols) |
10 { | 16 { |
11 this.name = name; | 17 this.name = name; |
12 this.symbols = symbols; | 18 this.symbols = symbols; |
19 this.dirty = false; | |
13 } | 20 } |
14 symbol.prototype.cleanName = function() { | 21 symbol.prototype.cleanName = function() { |
15 return this.name[0] == ':' ? this.name.substr(1) : this.name; | 22 return this.name[0] == ':' ? this.name.substr(1) : this.name; |
16 } | 23 } |
24 symbol.prototype.valueOf = function() { | |
25 return this.name; | |
26 }; | |
17 | 27 |
18 function intlit(val, bits, unsigned) | 28 function intlit(val, bits, unsigned) |
19 { | 29 { |
20 if (!bits) { | 30 if (!bits) { |
21 bits = 32; | 31 bits = 32; |
25 } | 35 } |
26 this.unsigned = unsigned; | 36 this.unsigned = unsigned; |
27 this.bits = bits; | 37 this.bits = bits; |
28 this.val = val; | 38 this.val = val; |
29 } | 39 } |
40 intlit.prototype.valueOf = function() { | |
41 var val = '' + this.val; | |
42 if (this.bits != 32 || this.unsigned) { | |
43 val += this.unsigned ? 'u' : 'i' | |
44 val += this.bits; | |
45 } | |
46 return val; | |
47 }; | |
30 | 48 |
31 function floatlit(val) | 49 function floatlit(val) |
32 { | 50 { |
33 this.val = val; | 51 this.val = val; |
34 } | 52 } |
53 floatlit.prototype.valueOf = function() { | |
54 return '' + val; | |
55 }; | |
35 | 56 |
36 function strlit(val) | 57 function strlit(val) |
37 { | 58 { |
38 this.val = val; | 59 this.val = val; |
39 } | 60 } |
61 strlit.prototype.valueOf = function() { | |
62 return '"'+this.val+'"'; | |
63 }; | |
40 | 64 |
41 function listlit(val) | 65 function listlit(val) |
42 { | 66 { |
43 this.val = val; | 67 this.val = val; |
44 } | 68 } |
69 listlit.prototype.valueOf = function(indent) { | |
70 if (indent === undefined) { | |
71 indent = ''; | |
72 } | |
73 var nextindent = indent + '\t'; | |
74 var val = '[' | |
75 for (var i = 0; i < this.val.length; i++) { | |
76 val += '\n' + nextindent + this.val[i].valueOf(nextindent); | |
77 } | |
78 if (this.val.length) { | |
79 val += '\n' + indent; | |
80 } | |
81 val += ']'; | |
82 return val; | |
83 }; | |
45 | 84 |
46 function arraylit(val) | 85 function arraylit(val) |
47 { | 86 { |
48 this.val = val; | 87 this.val = val; |
49 } | 88 } |
89 arraylit.prototype.valueOf = function(indent) { | |
90 if (indent === undefined) { | |
91 indent = ''; | |
92 } | |
93 var nextindent = indent + '\t'; | |
94 var val = '#[' | |
95 for (var i = 0; i < this.val.length; i++) { | |
96 val += '\n' + nextindent + this.val[i].valueOf(nextindent); | |
97 } | |
98 if (this.val.length) { | |
99 val += '\n' + indent; | |
100 } | |
101 val += ']'; | |
102 return val; | |
103 }; | |
50 | 104 |
51 function funcall(name, args) | 105 function funcall(name, args) |
52 { | 106 { |
53 this.name = name; | 107 this.name = name; |
54 this.args = args; | 108 this.args = args; |
55 this.receiver = null; | 109 this.receiver = null; |
56 } | 110 this.dirty = false; |
111 } | |
112 funcall.prototype.valueOf = function(indent) { | |
113 var parts = this.name.split(':'); | |
114 var val = ''; | |
115 if (this.receiver) { | |
116 val += this.receiver.valueOf(indent); | |
117 } | |
118 var curarg = 0; | |
119 for (var i = 0; i < parts.length; i++) { | |
120 if (val) { | |
121 val += ' '; | |
122 } | |
123 if (parts[i]) { | |
124 val += parts[i] + ': '; | |
125 } | |
126 if (curarg < this.args.length) { | |
127 val += this.args[curarg++].valueOf(indent); | |
128 } | |
129 } | |
130 while (curarg < this.args.length) { | |
131 val += ' ' + this.args[curarg++].valueOf(indent); | |
132 } | |
133 return val; | |
134 }; | |
57 | 135 |
58 function object(messages) | 136 function object(messages) |
59 { | 137 { |
60 this.messages = messages; | 138 this.messages = messages; |
61 this.name = null; | 139 this.name = null; |
62 } | 140 } |
141 object.prototype.valueOf = function(indent) { | |
142 if (indent === undefined) { | |
143 indent = ''; | |
144 } | |
145 var nextindent = indent + '\t'; | |
146 var val = '#{'; | |
147 for (var i = 0; i < this.messages.length; i++) { | |
148 val += '\n' + nextindent + this.messages[i].valueOf(nextindent); | |
149 } | |
150 if (val.length > 2) { | |
151 val += '\n' + indent; | |
152 } | |
153 val += '}'; | |
154 return val; | |
155 }; | |
63 | 156 |
64 function lambda(args, expressions) | 157 function lambda(args, expressions) |
65 { | 158 { |
66 this.args = args ? args : []; | 159 this.args = args ? args : []; |
67 this.expressions = expressions; | 160 this.expressions = expressions; |
68 } | 161 } |
162 lambda.prototype.valueOf = function(indent) { | |
163 if (indent === undefined) { | |
164 indent = ''; | |
165 } | |
166 var nextindent = indent + '\t'; | |
167 var val = ''; | |
168 for (var i = 0; i < this.args.length; i++) { | |
169 val += this.args[i].valueOf(indent) + ' '; | |
170 } | |
171 val += '{'; | |
172 for (var i = 0; i < this.expressions.length; i++) { | |
173 val += '\n' + nextindent + this.expressions[i].valueOf(nextindent); | |
174 } | |
175 if (this.expressions.length) { | |
176 val += '\n' + indent; | |
177 } | |
178 val += '}'; | |
179 return val; | |
180 }; | |
69 | 181 |
70 function assignment(sym, expr) | 182 function assignment(sym, expr) |
71 { | 183 { |
72 this.symbol = sym; | 184 this.symbol = sym; |
73 this.expression = expr; | 185 this.expression = expr; |
74 } | 186 } |
187 assignment.prototype.valueOf = function(indent) { | |
188 return this.symbol.valueOf(indent) + ' <- ' + this.expression.valueOf(indent); | |
189 }; | |
75 | 190 |
76 function isLambda(node) | 191 function isLambda(node) |
77 { | 192 { |
78 return node instanceof lambda; | 193 return node instanceof lambda; |
79 } | 194 } |
85 'expr = e:(funcall / methcall / assignment / opexpr) ws { return e; };' + | 200 'expr = e:(funcall / methcall / assignment / opexpr) ws { return e; };' + |
86 'opexpr = left:compareop pieces:(hws ("&&" / "||") hws compareop)* { if (pieces.length) { var cur = new op(left, pieces[0][1], pieces[0][3]); for (var i = 1; i < pieces.length; i++) { cur = new op(cur, pieces[i][1], pieces[i][3]); } return cur; } else { return left; } };'+ | 201 'opexpr = left:compareop pieces:(hws ("&&" / "||") hws compareop)* { if (pieces.length) { var cur = new op(left, pieces[0][1], pieces[0][3]); for (var i = 1; i < pieces.length; i++) { cur = new op(cur, pieces[i][1], pieces[i][3]); } return cur; } else { return left; } };'+ |
87 'compareop = left:maybecons pieces:(hws ("<=" / ">=" / "<" / ">" / "=" / "!=") hws maybecons)* { if (pieces.length) { var cur = new op(left, pieces[0][1], pieces[0][3]); for (var i = 1; i < pieces.length; i++) { cur = new op(cur, pieces[i][1], pieces[i][3]); } return cur; } else { return left; } };'+ | 202 'compareop = left:maybecons pieces:(hws ("<=" / ">=" / "<" / ">" / "=" / "!=") hws maybecons)* { if (pieces.length) { var cur = new op(left, pieces[0][1], pieces[0][3]); for (var i = 1; i < pieces.length; i++) { cur = new op(cur, pieces[i][1], pieces[i][3]); } return cur; } else { return left; } };'+ |
88 'maybecons = consop / addsub;' + | 203 'maybecons = consop / addsub;' + |
89 'consop = left:addsub hws "|" hws right:maybecons { return new op(left, "|", right); };'+ | 204 'consop = left:addsub hws "|" hws right:maybecons { return new op(left, "|", right); };'+ |
90 'addsub = left:muldiv pieces:(hws ("+"/"-"/"xor"/"and"/"or"/".") hws muldiv)* { if (pieces.length) { var cur = new op(left, pieces[0][1], pieces[0][3]); for (var i = 1; i < pieces.length; i++) { cur = new op(cur, pieces[i][1], pieces[i][3]); } return cur; } else { return left; } };'+ | 205 'addsub = left:muldiv pieces:(hws ((("xor"/"and"/"or") ! [a-zA-Z_!?@0-9])/("+"/"-"/".")) hws muldiv)* { if (pieces.length) { var cur = new op(left, pieces[0][1], pieces[0][3]); for (var i = 1; i < pieces.length; i++) { cur = new op(cur, pieces[i][1], pieces[i][3]); } return cur; } else { return left; } };'+ |
91 'muldiv = left:primlitsym pieces:(hws ("*"/"/"/"%") hws primlitsym)* { if (pieces.length) { var cur = new op(left, pieces[0][1], pieces[0][3]); for (var i = 1; i < pieces.length; i++) { cur = new op(cur, pieces[i][1], pieces[i][3]); } return cur; } else { return left; } };'+ | 206 'muldiv = left:primlitsym pieces:(hws ("*"/"/"/"%") hws primlitsym)* { if (pieces.length) { var cur = new op(left, pieces[0][1], pieces[0][3]); for (var i = 1; i < pieces.length; i++) { cur = new op(cur, pieces[i][1], pieces[i][3]); } return cur; } else { return left; } };'+ |
92 'primlitsym = hws val:(float / hex / binary / int / string / symbol / object / array / list / lambda / "(" ws expr:expr hws ")" { return expr; }) { return val; };' + | 207 'primlitsym = hws val:(float / hex / binary / int / string / symbol / object / array / list / lambda / "(" ws expr:expr hws ")" { return expr; }) { return val; };' + |
93 'symbol = chars:[a-zA-Z_!?@]+ trailing:(":"? [a-zA-Z_!?@0-9])* ! ":" { for (var i = 0; i < trailing.length; i++) { trailing[i] = trailing[i].join(""); } return new symbol(chars.join("") + trailing.join("")); };' + | 208 'symbol = chars:[a-zA-Z_!?@]+ trailing:(":"? [a-zA-Z_!?@0-9])* ! ":" { for (var i = 0; i < trailing.length; i++) { trailing[i] = trailing[i].join(""); } return new symbol(chars.join("") + trailing.join("")); };' + |
94 'float = digits:[0-9]+ "." decimals:[0-9]+ { return new floatlit(parseFloat(digits.join("") + "." + decimals.join(""))); };' + | 209 'float = digits:[0-9]+ "." decimals:[0-9]+ { return new floatlit(parseFloat(digits.join("") + "." + decimals.join(""))); };' + |
95 'binary = "0b" digits:[01]+ { return new intlit(parseInt(digits.join(""), 2)); };' + | 210 'binary = "0b" digits:[01]+ { return new intlit(parseInt(digits.join(""), 2)); };' + |