PageRenderTime 86ms CodeModel.GetById 30ms app.highlight 34ms RepoModel.GetById 16ms app.codeStats 0ms

/parse-js.ss

http://github.com/yinwang0/ydiff
Scheme | 694 lines | 370 code | 230 blank | 94 comment | 0 complexity | d9a870b5e6d2c82b12954b8549900cc9 MD5 | raw file
  1;; ydiff - a language-aware tool for comparing programs
  2;; Copyright (C) 2011 Yin Wang (yinwang0@gmail.com)
  3
  4;; This program is free software: you can redistribute it and/or modify
  5;; it under the terms of the GNU General Public License as published by
  6;; the Free Software Foundation, either version 3 of the License, or
  7;; (at your option) any later version.
  8
  9;; This program is distributed in the hope that it will be useful,
 10;; but WITHOUT ANY WARRANTY; without even the implied warranty of
 11;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12;; GNU General Public License for more details.
 13
 14;; You should have received a copy of the GNU General Public License
 15;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
 16
 17
 18
 19(load "parsec.ss")
 20
 21
 22
 23
 24;-------------------------------------------------------------
 25;                     scanner settings
 26;-------------------------------------------------------------
 27
 28(define *delims* (list "("  ")"  "["  "]"  "{"  "}" ","  "`"  ";"))
 29
 30(define *operators*
 31  (list
 32   ">>>="
 33
 34   "<<=" ">>=" ">>>" "===" "!=="
 35
 36   "==" "!="  ">=" "<=" "&&" "||" ">>" "<<" "++" "--"
 37   "+=" "-=" "*=" "/=" "%=" "&=" "^=" "|="
 38
 39   "=" "+" "-" "*" "/" "%" "~" "!" ":" "?" "." ">" "<"
 40))
 41
 42
 43(define *line-comment* (list "//"))
 44(define *comment-start*  "/*")
 45(define *comment-end*    "*/")
 46(define *quotation-marks*  '(#\" #\'))
 47(define *significant-whitespaces*
 48  (list #\newline #\linefeed #\u2028 #\u2029))
 49
 50
 51(define alpha?
 52  (predor char-alphabetic?
 53          (lambda (x) (char=? x #\$))))
 54
 55
 56
 57
 58;-------------------------------------------------------------
 59;                     primitive parsers
 60;-------------------------------------------------------------
 61
 62(:: $identifier
 63  ($pred
 64   (lambda (t)
 65     (and (Token? t)
 66          (id? (Token-text t))))))
 67
 68
 69(:: $numeral-literal
 70  ($pred
 71   (lambda (t)
 72     (and (Token? t)
 73          (numeral? (Token-text t))))))
 74
 75
 76(:: $string-literal ($pred Str?))
 77(:: $newline ($pred Newline?))
 78(:: $comment ($pred Comment?))
 79
 80
 81;; delimeters
 82(::  |,|   (@_ ","))
 83(::  |;|   (@~ ";"))
 84(::  |:|   (@_ ":"))
 85(::  |(|   (@~ "("))
 86(::  |)|   (@~ ")"))
 87(::  |[|   (@~ "["))
 88(::  |]|   (@~ "]"))
 89(::  |{|   (@~ "{"))
 90(::  |}|   (@~ "}"))
 91
 92
 93;; $glob^ and $*^ needed to define |\n|, because the
 94;; definition of |\n| must not contain any call to @seq
 95;; otherwise the parser will go into infinite loop
 96(::  |\n|  ($glob^ (@*^ $newline)))
 97(::  |;\n| (@or |;| |\n|))
 98
 99
100;; Redefine sequence to get over newlines
101(define old-seq @seq)
102(define @seq
103  (lambda ps
104    (let ([psj (join ps |\n|)])
105      (apply old-seq `(,|\n| ,@psj ,|\n|)))))
106
107
108;; ($eval (@seq ($$ "foo") ($$ "bar"))
109;; (scan "
110;; foo
111;;  bar "))
112
113
114
115
116;-------------------------------------------------------------
117;                       compound parsers
118;-------------------------------------------------------------
119
120(::= $program 'program
121     (@* $statement))
122
123
124
125(:: $statement
126    (@or $statement-block
127         $empty-statement
128         $function-definition
129         $variable-statement
130         $with-statement
131
132         $if-statement
133         $switch-statement
134         $do-while-statement
135         $while-statement
136         $for-statement
137         $for-in-statement
138         $continue-statement
139         $break-statement
140         $try-statement
141         $throw-statement
142         $return-statement
143
144         $labelled-statement
145         $expression-statement
146))
147
148
149
150(::= $statement-block 'block
151     |{| (@* $statement) |}|
152)
153
154
155(:: $empty-statement |;|)
156
157
158(::= $function-definition 'function
159     ($$ "function") (@= 'name $identifier) $formal-parameter-list
160     $function-body)
161
162
163;; function-expression can be unnamed
164(::= $function-expression 'function
165     ($$ "function") (@= 'name (@? $identifier)) $formal-parameter-list
166     $function-body)
167
168
169(::= $formal-parameter-list 'parameters
170     (@or (@... |(|  (@? (@.@ $identifier |,|))  |)|    )
171          $identifier))
172
173
174(::= $function-body 'body
175     $statement-block
176)
177
178
179
180;;---------------- variable statement -----------------
181(::= $variable-statement 'variable-declaration
182     ($$ "var") (@.@ $variable-declaration |,|) |;\n|
183)
184
185
186(::= $variable-declaration 'variable-declaration
187     $identifier (@? $initializer))
188
189
190(::= $initializer 'initializer
191     (@... ($$ "=") $assignment-expression))
192
193
194;;--------------------------------------------
195(::= $with-statement 'with
196     ($$ "with") (@= 'obj |(|  $expression  |)|)
197     $statement
198)
199
200
201;;--------------------------------------------
202(::= $if-statement 'if
203     ($$ "if")  (@= 'test |(| $expression |)|)   $statement
204     (@? (@= 'else ($$ "else") $statement
205)))
206
207
208;;--------------------------------------------
209(::= $do-while-statement 'do-while
210     ($$ "do") $statement
211     (@= 'while-do ($$ "while")  (@= 'test |(| $expression |)|   ))
212     |;\n|
213)
214
215
216;;--------------------------------------------
217(::= $while-statement 'while
218     ($$ "while")  (@= 'test |(| $expression |)|   )
219     $statement
220)
221
222
223;;--------------------------------------------
224(::= $for-statement 'for
225     ($$ "for") (@= 'iter
226                    |(| (@? $for-initaliser) |;|
227                        (@? $expression)     |;|
228                        (@? $expression)
229                    |)|
230                 )
231     $statement
232)
233
234
235(::= $for-initaliser 'for-initializer
236     (@or (@= 'variable-declaration
237              ($$ "var") (@.@ $variable-declaration |,|))
238
239          $expression
240))
241
242
243;;--------------------------------------------
244(::= $for-in-statement 'for-in
245     ($$ "for") (@= 'iter
246                    |(|  (@? $for-in-initalizer) ($$ "in") $expression  |)|)
247     $statement
248)
249
250
251(::= $for-in-initalizer 'for-in-initializer
252     (@or (@= 'variable-declaration
253              ($$ "var") (@.@ $variable-declaration |,|))
254
255          $expression
256))
257
258
259;;--------------------------------------------
260(::= $continue-statement 'continue
261    ($$ "continue") (@= 'label (@? $identifier)) |;\n|
262)
263
264
265;;--------------------------------------------
266(::= $break-statement 'break
267     ($$ "break") (@= 'label (@? $identifier)) |;\n|
268)
269
270
271;;--------------------------------------------
272(::= $return-statement 'return
273    ($$ "return") (@= 'value (@? $expression)) |;\n|
274)
275
276
277;;--------------------------------------------
278(::= $labelled-statement 'labelled-statement
279     $identifier |:| $statement
280)
281
282
283;;--------------------------------------------
284(::= $switch-statement 'switch-statement
285     ($$ "switch")  |(| $expression |)|
286     |{|  (@* $case-clause)
287          (@? $default-clause
288          (@* $case-clause))
289     |}|
290)
291
292
293(::= $case-clause 'case-clause
294     ($$ "case") $expression |:| (@* $statement)
295)
296
297
298(::= $default-clause 'default
299     ($$ "default") |:| (@* $statement)
300)
301
302
303;;--------------------------------------------
304(::= $throw-statement 'throw
305    ($$ "throw") $expression  |;\n|
306)
307
308
309;;--------------------------------------------
310(::= $try-statement 'try
311     ($$ "try") $statement-block
312     (@or $finally-clause
313          (@... $catch-clause (@? $finally-clause)))
314     )
315
316
317(::= $catch-clause 'catch
318     ($$ "catch") |(| $identifier |)| $statement-block
319     )
320
321
322(::= $finally-clause 'finally
323    ($$ "finally") $statement-block
324    )
325
326
327;;--------------------------------------------
328(::= $expression-statement 'expression-statement
329     $expression |;\n|
330     )
331
332
333
334
335;-------------------------------------------------------------
336;                       expressions
337;-------------------------------------------------------------
338
339;; utility for constructing operators
340(define op
341  (lambda (s)
342    (@= 'op ($$ s))))
343
344
345
346(:: $expression
347    $comma-expression)
348
349
350
351;; 18. comma
352;;--------------------------------------------
353(::= $comma-expression 'comma
354     (@.@ $assignment-expression |,|))
355
356
357
358;; 16. assignment
359;;--------------------------------------------
360(:: $assignment-expression
361    (@or (@= 'assignment
362             $conditional-expression
363             $assignment-operator
364             $assignment-expression)
365
366         $conditional-expression
367         ))
368
369
370(:: $assignment-operator
371     (@or (op "=")
372          (op "*=")
373          (op "/=")
374          (op "%=")
375          (op "+=")
376          (op "-=")
377          (op "<<=")
378          (op ">>=")
379          (op ">>>=")
380          (op "&=")
381          (op "^=")
382          (op "|=")
383          ))
384
385
386
387;; 15.	?:	 Ternary conditional
388;;--------------------------------------------
389(:: $conditional-expression
390    (@or (@= 'conditional-expression
391             (@= 'test $logical-or-expression)
392             (@~ "?") (@= 'then $conditional-expression)
393             (@~ ":") (@= 'else $conditional-expression))
394
395         $logical-or-expression
396         ))
397
398
399; ($eval $conditional-expression (scan "x > 0? x-1 : x"))
400
401
402
403
404;; 14.	||	 Logical OR
405;;--------------------------------------------
406(:: $logical-or-expression
407     (@or (@infix-left 'binop
408                       $logical-and-expression
409                       (op "||"))
410
411          $logical-and-expression
412          ))
413
414; ($eval $logical-or-expression (scan "x || y"))
415
416
417
418;; 13.	&&	 Logical AND
419;;--------------------------------------------
420(:: $logical-and-expression
421     (@or (@infix-left 'binop
422                       $bitwise-or-expression
423                       (op "&&"))
424
425          $bitwise-or-expression
426          ))
427
428
429;; 12.	|	 Bitwise OR (inclusive or)
430;;--------------------------------------------
431(:: $bitwise-or-expression
432     (@or (@infix-left 'binop
433                       $bitwise-xor-expression
434                       (op "|"))
435
436          $bitwise-xor-expression
437          ))
438
439
440
441;; 11.	^	 Bitwise XOR (exclusive or)
442;;--------------------------------------------
443(:: $bitwise-xor-expression
444     (@or (@infix-left 'binop
445                       $bitwise-and-expression
446                       (op "^"))
447
448          $bitwise-and-expression
449          ))
450
451
452
453;; 10.	&	 Bitwise AND
454;;--------------------------------------------
455(:: $bitwise-and-expression
456     (@or (@infix-left 'binop
457                       $equality-expression
458                       (op "&"))
459
460       $equality-expression
461       ))
462
463
464
465;; 9. equality
466;;--------------------------------------------
467(:: $equality-expression
468     (@or (@infix-left 'binop
469                       $relational-expression
470                       $equality-operator)
471
472          $relational-expression
473          ))
474
475(:: $equality-operator
476     (@or (op "==")
477          (op "!=")
478          (op "===")
479          (op "!==")
480))
481
482
483
484;; 8. relational
485;;--------------------------------------------
486(:: $relational-expression
487     (@or (@infix-left 'binop
488                       $bitwise-shift-expression
489                       $relational-operator)
490
491          $bitwise-shift-expression
492          ))
493
494(:: $relational-operator
495     (@or (op "<")
496          (op "<=")
497          (op ">")
498          (op ">=")
499          (op "instanceof")
500          (op "in")
501          ))
502
503
504
505;; 7. bitwise shift
506;;--------------------------------------------
507(:: $bitwise-shift-expression
508    (@or (@infix-left 'binop
509                      $additive-expression
510                      $bitwise-shift-operator)
511
512         $additive-expression
513))
514
515(:: $bitwise-shift-operator
516    (@or (op "<<")
517         (op ">>")
518         (op ">>>")
519         ))
520
521
522
523;; 6. additive
524;;--------------------------------------------
525(:: $additive-expression
526    (@or (@infix-left 'binop
527                      $multiplicative-expression
528                      $additive-operator)
529
530         $multiplicative-expression
531))
532
533
534(:: $additive-operator
535    (@or (op "+")
536         (op "-")))
537
538
539;; ($eval $additive-expression (scan "x + y + z"))
540
541
542
543
544;; 5. multiplicative
545;;--------------------------------------------
546(:: $multiplicative-expression
547    (@or (@infix-left 'binop
548                      $unary-expression
549                      $multiplicative-operator)
550
551         $unary-expression))
552
553(:: $multiplicative-operator
554    (@or (op "*")
555         (op "/")
556         (op "%")))
557
558
559
560
561;; 3. prefix
562;; 2. postfix
563;;--------------------------------------------
564(:: $unary-expression
565    $prefix-expression)
566
567
568(:: $prefix-expression
569    (@or (@prefix 'prefix
570                  $postfix-expression
571                  $prefix-operator)
572         $postfix-expression))
573
574
575(:: $postfix-expression
576    (@or (@postfix 'postfix
577                   $primary-expression
578                   $postfix-operator)
579         $primary-expression))
580
581
582(:: $prefix-operator
583    (@or (op "new")
584         (op "delete")
585         (op "void")
586         (op "typeof")
587         (op "++")
588         (op "--")
589         (op "+")
590         (op "-")
591         (op "~")
592         (op "!")
593         ))
594
595
596(:: $postfix-operator
597    (@or $index-suffix
598         $property-reference-suffix
599         $arguments
600         (op "++")
601         (op "--")))
602
603
604(::= $index-suffix 'index
605     |[|  $expression  |]|
606     )
607
608
609(::= $property-reference-suffix 'property
610     (@_ ".") $identifier)
611
612
613(::= $arguments 'arguments
614     |(|  (@? (@.@ $assignment-expression |,|))  |)|
615     )
616
617
618(::= $new-expression 'new
619     ($$ "new") $postfix-expression)
620
621
622
623;; 1. primary
624;;--------------------------------------------
625(:: $primary-expression
626    (@or $function-expression
627         $identifier
628         $literal
629         (@= 'expression |(|  $expression  |)|  )
630         ))
631
632
633
634
635;;-----------
636(::= $array-literal 'array-literal
637     |[|  (@? (@.@ $assignment-expression |,|))  |]|
638     )
639
640
641
642;;-----------
643(::= $object-literal 'object-literal
644     |{|  $property-name-value (@* |,| $property-name-value)  |}|
645     )
646
647
648(::= $property-name-value 'property-name-value
649     $property-name |:| $assignment-expression)
650
651
652(:: $property-name
653    (@or $identifier
654         $string-literal
655         $numeral-literal))
656
657
658
659;;-----------
660(:: $literal
661    (@or ($$ "null")
662         ($$ "true")
663         ($$ "false")
664         (@= 'this ($$ "this"))
665         $string-literal
666         $numeral-literal
667         $array-literal
668         $object-literal
669))
670
671
672
673
674
675;-------------------------------------------------------------
676;                       parse-js
677;-------------------------------------------------------------
678
679(define parse-js
680  (lambda (s)
681    (first-val
682     ($eval $program
683            (filter (lambda (x) (not (Comment? x)))
684                    (scan s))))))
685
686
687
688
689;-------------------------------------------------------------
690;                          tests
691;-------------------------------------------------------------
692
693;; (parse-js (read-file "nav-div.js"))
694