/parse-js.ss
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