| Preface |
|
xiii | |
|
|
|
1 | (51) |
|
Why study compiler construction? |
|
|
4 | (5) |
|
Compiler construction is very successful |
|
|
6 | (2) |
|
Compiler construction has a wide applicability |
|
|
8 | (1) |
|
Compilers contain generally useful algorithms |
|
|
8 | (1) |
|
A simple traditional modular compiler/interpreter |
|
|
9 | (13) |
|
|
|
9 | (2) |
|
Structure of the demo compiler |
|
|
11 | (1) |
|
The language for the demo compiler |
|
|
12 | (1) |
|
Lexical analysis for the demo compiler |
|
|
13 | (1) |
|
Syntax analysis for the demo compiler |
|
|
14 | (5) |
|
Context handling for the demo compiler |
|
|
19 | (1) |
|
Code generation for the demo compiler |
|
|
19 | (2) |
|
Interpretation for the demo compiler |
|
|
21 | (1) |
|
The structure of a more realistic compiler |
|
|
22 | (3) |
|
|
|
22 | (2) |
|
|
|
24 | (1) |
|
|
|
25 | (1) |
|
|
|
25 | (4) |
|
The width of the compiler |
|
|
26 | (1) |
|
|
|
27 | (2) |
|
Properties of a good compiler |
|
|
29 | (3) |
|
Portability and retargetability |
|
|
32 | (1) |
|
Place and usefulness of optimizations |
|
|
32 | (1) |
|
A short history of compiler construction |
|
|
33 | (1) |
|
1945--1960: code generation |
|
|
33 | (1) |
|
|
|
33 | (1) |
|
1975--present: code generation and code optimization; paradigms |
|
|
34 | (1) |
|
|
|
34 | (6) |
|
|
|
35 | (1) |
|
|
|
35 | (2) |
|
Extended forms of grammars |
|
|
37 | (1) |
|
|
|
38 | (1) |
|
|
|
38 | (2) |
|
|
|
40 | (5) |
|
An iterative implementation of the closure algorithm |
|
|
44 | (1) |
|
The outline code used in this book |
|
|
45 | (2) |
|
|
|
47 | (5) |
|
|
|
47 | (1) |
|
|
|
48 | (1) |
|
|
|
49 | (3) |
|
From program text to abstract syntax tree |
|
|
52 | (142) |
|
From program text to tokens - the lexical structure |
|
|
56 | (54) |
|
|
|
56 | (1) |
|
Lexical versus syntactic analysis |
|
|
57 | (1) |
|
Regular expressions and regular descriptions |
|
|
58 | (2) |
|
|
|
60 | (1) |
|
Creating a lexical analyzer by hand |
|
|
61 | (7) |
|
Creating a lexical analyzer automatically |
|
|
68 | (18) |
|
Transition table compression |
|
|
86 | (7) |
|
Error handling in lexical analyzers |
|
|
93 | (1) |
|
A traditional lexical analyzer generator - lex |
|
|
94 | (2) |
|
Lexical identification of tokens |
|
|
96 | (2) |
|
|
|
98 | (5) |
|
Macro processing and file inclusion |
|
|
103 | (6) |
|
|
|
109 | (1) |
|
From tokens to syntax tree - the syntax |
|
|
110 | (69) |
|
Two classes of parsing methods |
|
|
111 | (4) |
|
Error detection and error recovery |
|
|
115 | (2) |
|
Creating a top-down parser manually |
|
|
117 | (3) |
|
Creating a top-down parser automatically |
|
|
120 | (30) |
|
Creating a bottom-up parser automatically |
|
|
150 | (29) |
|
|
|
179 | (15) |
|
|
|
181 | (3) |
|
|
|
184 | (1) |
|
|
|
185 | (9) |
|
Annotating the abstract syntax tree - the context |
|
|
194 | (85) |
|
|
|
195 | (43) |
|
|
|
200 | (2) |
|
|
|
202 | (8) |
|
|
|
210 | (7) |
|
|
|
217 | (1) |
|
Multi-visit attribute grammars |
|
|
218 | (11) |
|
Summary of the types of attribute grammars |
|
|
229 | (1) |
|
|
|
230 | (5) |
|
|
|
235 | (1) |
|
Equivalence of L-attributed and S-attributed grammars |
|
|
235 | (2) |
|
Extended grammar notations and attribute grammars |
|
|
237 | (1) |
|
|
|
238 | (1) |
|
|
|
238 | (31) |
|
|
|
239 | (6) |
|
|
|
245 | (8) |
|
|
|
253 | (7) |
|
Interprocedural data-flow analysis |
|
|
260 | (2) |
|
Carrying the information upstream - live analysis |
|
|
262 | (5) |
|
Comparing symbolic interpretation and data-flow equations |
|
|
267 | (2) |
|
|
|
269 | (10) |
|
|
|
269 | (4) |
|
|
|
273 | (1) |
|
|
|
274 | (5) |
|
Processing the intermediate code |
|
|
279 | (117) |
|
|
|
281 | (9) |
|
|
|
281 | (4) |
|
|
|
285 | (5) |
|
|
|
290 | (85) |
|
Avoiding code generation altogether |
|
|
295 | (1) |
|
|
|
296 | (1) |
|
|
|
297 | (5) |
|
|
|
302 | (18) |
|
Code generation for basic blocks |
|
|
320 | (17) |
|
BURS code generation and dynamic programming |
|
|
337 | (20) |
|
Register allocation by graph coloring |
|
|
357 | (6) |
|
|
|
363 | (1) |
|
Evaluation of code generation techniques |
|
|
364 | (1) |
|
Debugging of code optimizers |
|
|
365 | (1) |
|
Preprocessing the intermediate code |
|
|
366 | (5) |
|
Postprocessing the target code |
|
|
371 | (3) |
|
|
|
374 | (1) |
|
Assemblers, linkers, and loaders |
|
|
375 | (8) |
|
|
|
378 | (3) |
|
|
|
381 | (2) |
|
|
|
383 | (13) |
|
|
|
383 | (6) |
|
|
|
389 | (1) |
|
|
|
389 | (7) |
|
|
|
396 | (42) |
|
Data allocation with explicit deallocation |
|
|
398 | (9) |
|
|
|
399 | (4) |
|
|
|
403 | (1) |
|
|
|
404 | (3) |
|
Data allocation with implicit deallocation |
|
|
407 | (24) |
|
Basic garbage collection algorithms |
|
|
407 | (2) |
|
|
|
409 | (6) |
|
|
|
415 | (5) |
|
|
|
420 | (5) |
|
|
|
425 | (3) |
|
|
|
428 | (1) |
|
Generational garbage collection |
|
|
429 | (2) |
|
|
|
431 | (7) |
|
|
|
431 | (3) |
|
|
|
434 | (1) |
|
|
|
435 | (3) |
|
Imperative and object-oriented programs |
|
|
438 | (100) |
|
|
|
440 | (20) |
|
|
|
441 | (8) |
|
|
|
449 | (11) |
|
|
|
460 | (1) |
|
Source language data representation and handling |
|
|
460 | (21) |
|
|
|
460 | (1) |
|
|
|
461 | (1) |
|
|
|
461 | (4) |
|
|
|
465 | (1) |
|
|
|
466 | (1) |
|
|
|
467 | (3) |
|
|
|
470 | (1) |
|
|
|
471 | (1) |
|
|
|
471 | (9) |
|
|
|
480 | (1) |
|
Routines and their activation |
|
|
481 | (20) |
|
|
|
482 | (3) |
|
|
|
485 | (1) |
|
|
|
486 | (3) |
|
|
|
489 | (2) |
|
|
|
491 | (8) |
|
|
|
499 | (1) |
|
|
|
500 | (1) |
|
Code generation for control flow statements |
|
|
501 | (22) |
|
|
|
502 | (10) |
|
|
|
512 | (7) |
|
|
|
519 | (4) |
|
Code generation for modules |
|
|
523 | (4) |
|
|
|
524 | (1) |
|
|
|
524 | (1) |
|
Code generation for generics |
|
|
525 | (2) |
|
|
|
527 | (11) |
|
|
|
528 | (3) |
|
|
|
531 | (1) |
|
|
|
532 | (6) |
|
|
|
538 | (58) |
|
|
|
540 | (8) |
|
|
|
540 | (1) |
|
|
|
541 | (1) |
|
|
|
542 | (1) |
|
|
|
543 | (1) |
|
|
|
543 | (1) |
|
|
|
544 | (1) |
|
|
|
545 | (2) |
|
|
|
547 | (1) |
|
Compiling functional languages |
|
|
548 | (3) |
|
|
|
549 | (2) |
|
Polymorphic type checking |
|
|
551 | (2) |
|
Polymorphic function application |
|
|
551 | (2) |
|
|
|
553 | (7) |
|
|
|
553 | (1) |
|
The translation of pattern matching |
|
|
553 | (4) |
|
The translation of list comprehension |
|
|
557 | (1) |
|
The translation of nested functions |
|
|
558 | (2) |
|
|
|
560 | (8) |
|
|
|
564 | (2) |
|
|
|
566 | (2) |
|
Code generation for functional core programs |
|
|
568 | (7) |
|
Avoiding the construction of some application spines |
|
|
573 | (2) |
|
Optimizing the functional core |
|
|
575 | (12) |
|
|
|
575 | (7) |
|
|
|
582 | (1) |
|
|
|
582 | (2) |
|
Accumulator transformation |
|
|
584 | (3) |
|
|
|
587 | (1) |
|
Advanced graph manipulation |
|
|
587 | (2) |
|
|
|
587 | (1) |
|
|
|
588 | (1) |
|
Aggregate node allocation |
|
|
588 | (1) |
|
|
|
588 | (1) |
|
|
|
589 | (7) |
|
|
|
589 | (3) |
|
|
|
592 | (1) |
|
|
|
593 | (3) |
|
|
|
596 | (60) |
|
The logic programming model |
|
|
598 | (3) |
|
|
|
598 | (2) |
|
|
|
600 | (1) |
|
The general implementation model, interpreted |
|
|
601 | (6) |
|
The interpreter instructions |
|
|
603 | (3) |
|
Avoiding redundant goal lists |
|
|
606 | (1) |
|
Avoiding copying goal list tails |
|
|
606 | (1) |
|
|
|
607 | (8) |
|
Unification of structures, lists, and sets |
|
|
607 | (2) |
|
The implementation of unification |
|
|
609 | (3) |
|
Unification of two unbound variables |
|
|
612 | (2) |
|
|
|
614 | (1) |
|
The general implementation model, compiled |
|
|
615 | (19) |
|
|
|
616 | (3) |
|
Compiled clause search and unification |
|
|
619 | (4) |
|
Optimized clause selection in the WAM |
|
|
623 | (5) |
|
Implementing the `cut' mechanism |
|
|
628 | (2) |
|
Implementing the predicates assert and retract |
|
|
630 | (4) |
|
Compiled code for unification |
|
|
634 | (22) |
|
Unification instructions in the WAM |
|
|
636 | (2) |
|
Deriving a unification instruction by manual partial evaluation |
|
|
638 | (1) |
|
Unification of structures in the WAM |
|
|
639 | (7) |
|
An optimization: read/write mode |
|
|
646 | (2) |
|
Further unification optimizations in the WAM |
|
|
648 | (2) |
|
|
|
650 | (1) |
|
|
|
650 | (3) |
|
|
|
653 | (1) |
|
|
|
653 | (3) |
|
Parallel and distributed programs |
|
|
656 | (43) |
|
Parallel programming models |
|
|
659 | (8) |
|
Shared variables and monitors |
|
|
659 | (2) |
|
|
|
661 | (2) |
|
Object-oriented languages |
|
|
663 | (1) |
|
|
|
664 | (1) |
|
|
|
665 | (2) |
|
|
|
667 | (1) |
|
|
|
668 | (3) |
|
|
|
669 | (1) |
|
|
|
669 | (2) |
|
|
|
671 | (3) |
|
|
|
672 | (1) |
|
|
|
672 | (1) |
|
Type checking of messages |
|
|
673 | (1) |
|
|
|
674 | (1) |
|
Parallel object-oriented languages |
|
|
674 | (4) |
|
|
|
675 | (1) |
|
|
|
676 | (1) |
|
|
|
677 | (1) |
|
|
|
678 | (6) |
|
Avoiding the overhead of associative addressing |
|
|
679 | (3) |
|
Distributed implementations of the tuple space |
|
|
682 | (2) |
|
Automatic parallelization |
|
|
684 | (9) |
|
Exploiting parallelism automatically |
|
|
685 | (1) |
|
|
|
686 | (2) |
|
|
|
688 | (2) |
|
Automatic parallelization for distributed-memory machines |
|
|
690 | (3) |
|
|
|
693 | (6) |
|
|
|
693 | (2) |
|
|
|
695 | (1) |
|
|
|
695 | (4) |
| Appendix A -- A simple object-oriented compiler/interpreter |
|
699 | (10) |
|
A.1 Syntax-determined classes and semantics-determining methods |
|
|
699 | (2) |
|
A.2 The simple object-oriented compiler |
|
|
701 | (1) |
|
A.3 Object-oriented parsing |
|
|
702 | (6) |
|
|
|
708 | (1) |
|
|
|
708 | (1) |
| Answers to exercises |
|
709 | (11) |
| References |
|
720 | (8) |
| Index |
|
728 | |