Commit | Line | Data |
---|---|---|
5dcd3e48 AW |
1 | ;;; ECMAScript for Guile |
2 | ||
0ecd70a2 | 3 | ;; Copyright (C) 2009, 2010 Free Software Foundation, Inc. |
5dcd3e48 | 4 | |
53befeb7 NJ |
5 | ;;;; This library is free software; you can redistribute it and/or |
6 | ;;;; modify it under the terms of the GNU Lesser General Public | |
7 | ;;;; License as published by the Free Software Foundation; either | |
8 | ;;;; version 3 of the License, or (at your option) any later version. | |
9 | ;;;; | |
10 | ;;;; This library is distributed in the hope that it will be useful, | |
11 | ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | ;;;; Lesser General Public License for more details. | |
14 | ;;;; | |
15 | ;;;; You should have received a copy of the GNU Lesser General Public | |
16 | ;;;; License along with this library; if not, write to the Free Software | |
17 | ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
5dcd3e48 AW |
18 | |
19 | ;;; Code: | |
20 | ||
21 | (define-module (language ecmascript parse) | |
0ecd70a2 | 22 | #:use-module (system base lalr) |
5dcd3e48 | 23 | #:use-module (language ecmascript tokenize) |
0ecd70a2 | 24 | #:export (read-ecmascript read-ecmascript/1 make-parser)) |
5dcd3e48 | 25 | |
0b229e81 AW |
26 | (define (syntax-error message . args) |
27 | (apply throw 'SyntaxError message args)) | |
28 | ||
5dcd3e48 | 29 | (define (read-ecmascript port) |
0ecd70a2 LC |
30 | (let ((parse (make-parser))) |
31 | (parse (make-tokenizer port) syntax-error))) | |
5dcd3e48 AW |
32 | |
33 | (define (read-ecmascript/1 port) | |
0ecd70a2 LC |
34 | (let ((parse (make-parser))) |
35 | (parse (make-tokenizer/1 port) syntax-error))) | |
5dcd3e48 | 36 | |
131f7d6c AW |
37 | (define *eof-object* |
38 | (call-with-input-string "" read-char)) | |
39 | ||
0ecd70a2 LC |
40 | (define (make-parser) |
41 | ;; Return a fresh ECMAScript parser. Parsers produced by `lalr-scm' are now | |
42 | ;; stateful (e.g., they won't invoke the tokenizer any more once it has | |
43 | ;; returned `*eoi*'), hence the need to instantiate new parsers. | |
44 | ||
5dcd3e48 AW |
45 | (lalr-parser |
46 | ;; terminal (i.e. input) token types | |
47 | (lbrace rbrace lparen rparen lbracket rbracket dot semicolon comma < | |
48 | > <= >= == != === !== + - * % ++ -- << >> >>> & bor ^ ! ~ && or ? | |
49 | colon = += -= *= %= <<= >>= >>>= &= bor= ^= / /= | |
50 | ||
51 | break else new var case finally return void catch for switch while | |
52 | continue function this with default if throw delete in try do | |
53 | instanceof typeof null true false | |
54 | ||
55 | Identifier StringLiteral NumericLiteral RegexpLiteral) | |
56 | ||
57 | ||
0ecd70a2 LC |
58 | (Program (SourceElements) : $1 |
59 | (*eoi*) : *eof-object*) | |
5dcd3e48 AW |
60 | |
61 | ;; | |
62 | ;; Verily, here we define statements. Expressions are defined | |
63 | ;; afterwards. | |
64 | ;; | |
65 | ||
0ecd70a2 LC |
66 | (SourceElement (Statement) : $1 |
67 | (FunctionDeclaration) : $1) | |
68 | ||
69 | (FunctionDeclaration (function Identifier lparen rparen lbrace FunctionBody rbrace) : `(var (,$2 (lambda () ,$6))) | |
70 | (function Identifier lparen FormalParameterList rparen lbrace FunctionBody rbrace) : `(var (,$2 (lambda ,$4 ,$7)))) | |
71 | (FunctionExpression (function lparen rparen lbrace FunctionBody rbrace) : `(lambda () ,$5) | |
72 | (function Identifier lparen rparen lbrace FunctionBody rbrace) : `(lambda () ,$6) | |
73 | (function lparen FormalParameterList rparen lbrace FunctionBody rbrace) : `(lambda ,$3 ,$6) | |
74 | (function Identifier lparen FormalParameterList rparen lbrace FunctionBody rbrace) : `(lambda ,$4 ,$7)) | |
75 | (FormalParameterList (Identifier) : `(,$1) | |
76 | (FormalParameterList comma Identifier) : `(,@$1 ,$3)) | |
77 | (SourceElements (SourceElement) : $1 | |
78 | (SourceElements SourceElement) : (if (and (pair? $1) (eq? (car $1) 'begin)) | |
5dcd3e48 AW |
79 | `(begin ,@(cdr $1) ,$2) |
80 | `(begin ,$1 ,$2))) | |
0ecd70a2 LC |
81 | (FunctionBody (SourceElements) : $1) |
82 | ||
83 | (Statement (Block) : $1 | |
84 | (VariableStatement) : $1 | |
85 | (EmptyStatement) : $1 | |
86 | (ExpressionStatement) : $1 | |
87 | (IfStatement) : $1 | |
88 | (IterationStatement) : $1 | |
89 | (ContinueStatement) : $1 | |
90 | (BreakStatement) : $1 | |
91 | (ReturnStatement) : $1 | |
92 | (WithStatement) : $1 | |
93 | (LabelledStatement) : $1 | |
94 | (SwitchStatement) : $1 | |
95 | (ThrowStatement) : $1 | |
96 | (TryStatement) : $1) | |
97 | ||
98 | (Block (lbrace StatementList rbrace) : `(block ,$2)) | |
99 | (StatementList (Statement) : $1 | |
100 | (StatementList Statement) : (if (and (pair? $1) (eq? (car $1) 'begin)) | |
5dcd3e48 AW |
101 | `(begin ,@(cdr $1) ,$2) |
102 | `(begin ,$1 ,$2))) | |
103 | ||
0ecd70a2 LC |
104 | (VariableStatement (var VariableDeclarationList) : `(var ,@$2)) |
105 | (VariableDeclarationList (VariableDeclaration) : `(,$1) | |
106 | (VariableDeclarationList comma VariableDeclaration) : `(,@$1 ,$2)) | |
107 | (VariableDeclarationListNoIn (VariableDeclarationNoIn) : `(,$1) | |
108 | (VariableDeclarationListNoIn comma VariableDeclarationNoIn) : `(,@$1 ,$2)) | |
109 | (VariableDeclaration (Identifier) : `(,$1) | |
110 | (Identifier Initialiser) : `(,$1 ,$2)) | |
111 | (VariableDeclarationNoIn (Identifier) : `(,$1) | |
112 | (Identifier Initialiser) : `(,$1 ,$2)) | |
113 | (Initialiser (= AssignmentExpression) : $2) | |
114 | (InitialiserNoIn (= AssignmentExpressionNoIn) : $2) | |
5dcd3e48 | 115 | |
0ecd70a2 | 116 | (EmptyStatement (semicolon) : '(begin)) |
5dcd3e48 | 117 | |
0ecd70a2 | 118 | (ExpressionStatement (Expression semicolon) : $1) |
5dcd3e48 | 119 | |
0ecd70a2 LC |
120 | (IfStatement (if lparen Expression rparen Statement else Statement) : `(if ,$3 ,$5 ,$7) |
121 | (if lparen Expression rparen Statement) : `(if ,$3 ,$5)) | |
5dcd3e48 | 122 | |
0ecd70a2 | 123 | (IterationStatement (do Statement while lparen Expression rparen semicolon) : `(do ,$2 ,$5) |
5dcd3e48 | 124 | |
0ecd70a2 | 125 | (while lparen Expression rparen Statement) : `(while ,$3 ,$5) |
5dcd3e48 | 126 | |
0ecd70a2 LC |
127 | (for lparen semicolon semicolon rparen Statement) : `(for #f #f #f ,$6) |
128 | (for lparen semicolon semicolon Expression rparen Statement) : `(for #f #f ,$5 ,$7) | |
129 | (for lparen semicolon Expression semicolon rparen Statement) : `(for #f ,$4 #f ,$7) | |
130 | (for lparen semicolon Expression semicolon Expression rparen Statement) : `(for #f ,$4 ,$6 ,$8) | |
5dcd3e48 | 131 | |
0ecd70a2 LC |
132 | (for lparen ExpressionNoIn semicolon semicolon rparen Statement) : `(for ,$3 #f #f ,$7) |
133 | (for lparen ExpressionNoIn semicolon semicolon Expression rparen Statement) : `(for ,$3 #f ,$6 ,$8) | |
134 | (for lparen ExpressionNoIn semicolon Expression semicolon rparen Statement) : `(for ,$3 ,$5 #f ,$8) | |
135 | (for lparen ExpressionNoIn semicolon Expression semicolon Expression rparen Statement) : `(for ,$3 ,$5 ,$7 ,$9) | |
5dcd3e48 | 136 | |
0ecd70a2 LC |
137 | (for lparen var VariableDeclarationListNoIn semicolon semicolon rparen Statement) : `(for (var ,@$4) #f #f ,$8) |
138 | (for lparen var VariableDeclarationListNoIn semicolon semicolon Expression rparen Statement) : `(for (var ,@$4) #f ,$7 ,$9) | |
139 | (for lparen var VariableDeclarationListNoIn semicolon Expression semicolon rparen Statement) : `(for (var ,@$4) ,$6 #f ,$9) | |
140 | (for lparen var VariableDeclarationListNoIn semicolon Expression semicolon Expression rparen Statement) : `(for (var ,@$4) ,$6 ,$8 ,$10) | |
5dcd3e48 | 141 | |
0ecd70a2 LC |
142 | (for lparen LeftHandSideExpression in Expression rparen Statement) : `(for-in ,$3 ,$5 ,$7) |
143 | (for lparen var VariableDeclarationNoIn in Expression rparen Statement) : `(begin (var ,$4) (for-in (ref ,@$4) ,$6 ,$8))) | |
5dcd3e48 | 144 | |
0ecd70a2 LC |
145 | (ContinueStatement (continue Identifier semicolon) : `(continue ,$2) |
146 | (continue semicolon) : `(continue)) | |
5dcd3e48 | 147 | |
0ecd70a2 LC |
148 | (BreakStatement (break Identifier semicolon) : `(break ,$2) |
149 | (break semicolon) : `(break)) | |
5dcd3e48 | 150 | |
0ecd70a2 LC |
151 | (ReturnStatement (return Expression semicolon) : `(return ,$2) |
152 | (return semicolon) : `(return)) | |
5dcd3e48 | 153 | |
0ecd70a2 | 154 | (WithStatement (with lparen Expression rparen Statement) : `(with ,$3 ,$5)) |
5dcd3e48 | 155 | |
0ecd70a2 LC |
156 | (SwitchStatement (switch lparen Expression rparen CaseBlock) : `(switch ,$3 ,@$5)) |
157 | (CaseBlock (lbrace rbrace) : '() | |
158 | (lbrace CaseClauses rbrace) : $2 | |
159 | (lbrace CaseClauses DefaultClause rbrace) : `(,@$2 ,@$3) | |
160 | (lbrace DefaultClause rbrace) : `(,$2) | |
161 | (lbrace DefaultClause CaseClauses rbrace) : `(,@$2 ,@$3)) | |
162 | (CaseClauses (CaseClause) : `(,$1) | |
163 | (CaseClauses CaseClause) : `(,@$1 ,$2)) | |
164 | (CaseClause (case Expression colon) : `(case ,$2) | |
165 | (case Expression colon StatementList) : `(case ,$2 ,$4)) | |
166 | (DefaultClause (default colon) : `(default) | |
167 | (default colon StatementList) : `(default ,$3)) | |
5dcd3e48 | 168 | |
0ecd70a2 | 169 | (LabelledStatement (Identifier colon Statement) : `(label ,$1 ,$3)) |
5dcd3e48 | 170 | |
0ecd70a2 | 171 | (ThrowStatement (throw Expression semicolon) : `(throw ,$2)) |
5dcd3e48 | 172 | |
0ecd70a2 LC |
173 | (TryStatement (try Block Catch) : `(try ,$2 ,$3 #f) |
174 | (try Block Finally) : `(try ,$2 #f ,$3) | |
175 | (try Block Catch Finally) : `(try ,$2 ,$3 ,$4)) | |
176 | (Catch (catch lparen Identifier rparen Block) : `(catch ,$3 ,$5)) | |
177 | (Finally (finally Block) : `(finally ,$2)) | |
5dcd3e48 AW |
178 | |
179 | ;; | |
180 | ;; As promised, expressions. We build up to Expression bottom-up, so | |
181 | ;; as to get operator precedence right. | |
182 | ;; | |
183 | ||
0ecd70a2 LC |
184 | (PrimaryExpression (this) : 'this |
185 | (null) : 'null | |
186 | (true) : 'true | |
187 | (false) : 'false | |
188 | (Identifier) : `(ref ,$1) | |
189 | (StringLiteral) : `(string ,$1) | |
190 | (RegexpLiteral) : `(regexp ,$1) | |
191 | (NumericLiteral) : `(number ,$1) | |
192 | (ArrayLiteral) : $1 | |
193 | (ObjectLiteral) : $1 | |
194 | (lparen Expression rparen) : $2) | |
195 | ||
196 | (ArrayLiteral (lbracket rbracket) : '(array) | |
197 | (lbracket Elision rbracket) : '(array ,@$2) | |
198 | (lbracket ElementList rbracket) : `(array ,@$2) | |
199 | (lbracket ElementList comma rbracket) : `(array ,@$2) | |
200 | (lbracket ElementList comma Elision rbracket) : `(array ,@$2)) | |
201 | (ElementList (AssignmentExpression) : `(,$1) | |
202 | (Elision AssignmentExpression) : `(,@$1 ,$2) | |
203 | (ElementList comma AssignmentExpression) : `(,@$1 ,$3) | |
204 | (ElementList comma Elision AssignmentExpression) : `(,@$1 ,@$3 ,$4)) | |
205 | (Elision (comma) : '((number 0)) | |
206 | (Elision comma) : `(,@$1 (number 0))) | |
207 | ||
208 | (ObjectLiteral (lbrace rbrace) : `(object) | |
209 | (lbrace PropertyNameAndValueList rbrace) : `(object ,@$2)) | |
210 | (PropertyNameAndValueList (PropertyName colon AssignmentExpression) : `((,$1 ,$3)) | |
211 | (PropertyNameAndValueList comma PropertyName colon AssignmentExpression) : `(,@$1 (,$3 ,$5))) | |
212 | (PropertyName (Identifier) : $1 | |
213 | (StringLiteral) : (string->symbol $1) | |
214 | (NumericLiteral) : $1) | |
215 | ||
216 | (MemberExpression (PrimaryExpression) : $1 | |
217 | (FunctionExpression) : $1 | |
218 | (MemberExpression lbracket Expression rbracket) : `(aref ,$1 ,$3) | |
219 | (MemberExpression dot Identifier) : `(pref ,$1 ,$3) | |
220 | (new MemberExpression Arguments) : `(new ,$2 ,$3)) | |
221 | ||
222 | (NewExpression (MemberExpression) : $1 | |
223 | (new NewExpression) : `(new ,$2 ())) | |
224 | ||
225 | (CallExpression (MemberExpression Arguments) : `(call ,$1 ,$2) | |
226 | (CallExpression Arguments) : `(call ,$1 ,$2) | |
227 | (CallExpression lbracket Expression rbracket) : `(aref ,$1 ,$3) | |
228 | (CallExpression dot Identifier) : `(pref ,$1 ,$3)) | |
229 | (Arguments (lparen rparen) : '() | |
230 | (lparen ArgumentList rparen) : $2) | |
231 | (ArgumentList (AssignmentExpression) : `(,$1) | |
232 | (ArgumentList comma AssignmentExpression) : `(,@$1 ,$3)) | |
233 | ||
234 | (LeftHandSideExpression (NewExpression) : $1 | |
235 | (CallExpression) : $1) | |
236 | ||
237 | (PostfixExpression (LeftHandSideExpression) : $1 | |
238 | (LeftHandSideExpression ++) : `(postinc ,$1) | |
239 | (LeftHandSideExpression --) : `(postdec ,$1)) | |
240 | ||
241 | (UnaryExpression (PostfixExpression) : $1 | |
242 | (delete UnaryExpression) : `(delete ,$2) | |
243 | (void UnaryExpression) : `(void ,$2) | |
244 | (typeof UnaryExpression) : `(typeof ,$2) | |
245 | (++ UnaryExpression) : `(preinc ,$2) | |
246 | (-- UnaryExpression) : `(predec ,$2) | |
247 | (+ UnaryExpression) : `(+ ,$2) | |
248 | (- UnaryExpression) : `(- ,$2) | |
249 | (~ UnaryExpression) : `(~ ,$2) | |
250 | (! UnaryExpression) : `(! ,$2)) | |
251 | ||
252 | (MultiplicativeExpression (UnaryExpression) : $1 | |
253 | (MultiplicativeExpression * UnaryExpression) : `(* ,$1 ,$3) | |
254 | (MultiplicativeExpression / UnaryExpression) : `(/ ,$1 ,$3) | |
255 | (MultiplicativeExpression % UnaryExpression) : `(% ,$1 ,$3)) | |
256 | ||
257 | (AdditiveExpression (MultiplicativeExpression) : $1 | |
258 | (AdditiveExpression + MultiplicativeExpression) : `(+ ,$1 ,$3) | |
259 | (AdditiveExpression - MultiplicativeExpression) : `(- ,$1 ,$3)) | |
260 | ||
261 | (ShiftExpression (AdditiveExpression) : $1 | |
262 | (ShiftExpression << MultiplicativeExpression) : `(<< ,$1 ,$3) | |
263 | (ShiftExpression >> MultiplicativeExpression) : `(>> ,$1 ,$3) | |
264 | (ShiftExpression >>> MultiplicativeExpression) : `(>>> ,$1 ,$3)) | |
265 | ||
266 | (RelationalExpression (ShiftExpression) : $1 | |
267 | (RelationalExpression < ShiftExpression) : `(< ,$1 ,$3) | |
268 | (RelationalExpression > ShiftExpression) : `(> ,$1 ,$3) | |
269 | (RelationalExpression <= ShiftExpression) : `(<= ,$1 ,$3) | |
270 | (RelationalExpression >= ShiftExpression) : `(>= ,$1 ,$3) | |
271 | (RelationalExpression instanceof ShiftExpression) : `(instanceof ,$1 ,$3) | |
272 | (RelationalExpression in ShiftExpression) : `(in ,$1 ,$3)) | |
273 | ||
274 | (RelationalExpressionNoIn (ShiftExpression) : $1 | |
275 | (RelationalExpressionNoIn < ShiftExpression) : `(< ,$1 ,$3) | |
276 | (RelationalExpressionNoIn > ShiftExpression) : `(> ,$1 ,$3) | |
277 | (RelationalExpressionNoIn <= ShiftExpression) : `(<= ,$1 ,$3) | |
278 | (RelationalExpressionNoIn >= ShiftExpression) : `(>= ,$1 ,$3) | |
279 | (RelationalExpressionNoIn instanceof ShiftExpression) : `(instanceof ,$1 ,$3)) | |
280 | ||
281 | (EqualityExpression (RelationalExpression) : $1 | |
282 | (EqualityExpression == RelationalExpression) : `(== ,$1 ,$3) | |
283 | (EqualityExpression != RelationalExpression) : `(!= ,$1 ,$3) | |
284 | (EqualityExpression === RelationalExpression) : `(=== ,$1 ,$3) | |
285 | (EqualityExpression !== RelationalExpression) : `(!== ,$1 ,$3)) | |
286 | ||
287 | (EqualityExpressionNoIn (RelationalExpressionNoIn) : $1 | |
288 | (EqualityExpressionNoIn == RelationalExpressionNoIn) : `(== ,$1 ,$3) | |
289 | (EqualityExpressionNoIn != RelationalExpressionNoIn) : `(!= ,$1 ,$3) | |
290 | (EqualityExpressionNoIn === RelationalExpressionNoIn) : `(=== ,$1 ,$3) | |
291 | (EqualityExpressionNoIn !== RelationalExpressionNoIn) : `(!== ,$1 ,$3)) | |
292 | ||
293 | (BitwiseANDExpression (EqualityExpression) : $1 | |
294 | (BitwiseANDExpression & EqualityExpression) : `(& ,$1 ,$3)) | |
295 | (BitwiseANDExpressionNoIn (EqualityExpressionNoIn) : $1 | |
296 | (BitwiseANDExpressionNoIn & EqualityExpressionNoIn) : `(& ,$1 ,$3)) | |
297 | ||
298 | (BitwiseXORExpression (BitwiseANDExpression) : $1 | |
299 | (BitwiseXORExpression ^ BitwiseANDExpression) : `(^ ,$1 ,$3)) | |
300 | (BitwiseXORExpressionNoIn (BitwiseANDExpressionNoIn) : $1 | |
301 | (BitwiseXORExpressionNoIn ^ BitwiseANDExpressionNoIn) : `(^ ,$1 ,$3)) | |
302 | ||
303 | (BitwiseORExpression (BitwiseXORExpression) : $1 | |
304 | (BitwiseORExpression bor BitwiseXORExpression) : `(bor ,$1 ,$3)) | |
305 | (BitwiseORExpressionNoIn (BitwiseXORExpressionNoIn) : $1 | |
306 | (BitwiseORExpressionNoIn bor BitwiseXORExpressionNoIn) : `(bor ,$1 ,$3)) | |
307 | ||
308 | (LogicalANDExpression (BitwiseORExpression) : $1 | |
309 | (LogicalANDExpression && BitwiseORExpression) : `(and ,$1 ,$3)) | |
310 | (LogicalANDExpressionNoIn (BitwiseORExpressionNoIn) : $1 | |
311 | (LogicalANDExpressionNoIn && BitwiseORExpressionNoIn) : `(and ,$1 ,$3)) | |
312 | ||
313 | (LogicalORExpression (LogicalANDExpression) : $1 | |
314 | (LogicalORExpression or LogicalANDExpression) : `(or ,$1 ,$3)) | |
315 | (LogicalORExpressionNoIn (LogicalANDExpressionNoIn) : $1 | |
316 | (LogicalORExpressionNoIn or LogicalANDExpressionNoIn) : `(or ,$1 ,$3)) | |
317 | ||
318 | (ConditionalExpression (LogicalORExpression) : $1 | |
319 | (LogicalORExpression ? AssignmentExpression colon AssignmentExpression) : `(if ,$1 ,$3 ,$5)) | |
320 | (ConditionalExpressionNoIn (LogicalORExpressionNoIn) : $1 | |
321 | (LogicalORExpressionNoIn ? AssignmentExpressionNoIn colon AssignmentExpressionNoIn) : `(if ,$1 ,$3 ,$5)) | |
322 | ||
323 | (AssignmentExpression (ConditionalExpression) : $1 | |
324 | (LeftHandSideExpression AssignmentOperator AssignmentExpression) : `(,$2 ,$1 ,$3)) | |
325 | (AssignmentExpressionNoIn (ConditionalExpressionNoIn) : $1 | |
326 | (LeftHandSideExpression AssignmentOperator AssignmentExpressionNoIn) : `(,$2 ,$1 ,$3)) | |
327 | (AssignmentOperator (=) : '= | |
328 | (*=) : '*= | |
329 | (/=) : '/= | |
330 | (%=) : '%= | |
331 | (+=) : '+= | |
332 | (-=) : '-= | |
333 | (<<=) : '<<= | |
334 | (>>=) : '>>= | |
335 | (>>>=) : '>>>= | |
336 | (&=) : '&= | |
337 | (^=) : '^= | |
338 | (bor=) : 'bor=) | |
339 | ||
340 | (Expression (AssignmentExpression) : $1 | |
341 | (Expression comma AssignmentExpression) : `(begin ,$1 ,$3)) | |
342 | (ExpressionNoIn (AssignmentExpressionNoIn) : $1 | |
343 | (ExpressionNoIn comma AssignmentExpressionNoIn) : `(begin ,$1 ,$3)))) |