具体描述
编辑推荐
内容简介
《编译原理》是编译领域无可替代的经典著作,被广大计算机专业人士誉为“龙书”。《编译原理》上一版自1986年出版以来,被世界各地的著名高等院校和研究机构(包括美国哥伦比亚大学、斯坦福大学、哈佛大学、普林斯顿大学、贝尔实验室)作为本科生和研究生的编译原理课程的教材。该书对我国高等计算机教育领域也产生了重大影响。
第2版对每一章都进行了全面的修订,以反映自上一版出版二十多年来软件工程、程序设计语言和计算机体系结构方面的发展对编译技术的影响。
《编译原理》全面介绍了编译器的设计。并强调编译技术在软件设计和开发中的广泛应用,每章中都包含大量的习题和丰富的参考文献。《编译原理》适合作为高等院校计算机专业本科生和研究生的编译原理与技术课程的教材,也可供广大计算机技术人员参考。 作者简介
AlfredV.Aho,美国哥伦比亚大学教授。美国国家工程院院士,ACM和lEEE会士,曾获得IEEE的冯·诺伊曼奖。著有多部算法、数据结构、编译器、数据库系统及计算机科学基础方面的著作。
MonicaS.Lam,斯坦福大学计算机科学系教授。曾任T'ensilica的首席科学家,也是Moka5的首任CEO。曾经主持SLJIF项目。
Ravi Sethi,Avaya实验室总裁。曾任贝尔实验室高级副总裁和LLicentTectlIlologies通信软件的CTO。他曾在宾夕法尼亚州立大学、亚利桑那州立大学和普林斯顿大学任教,是ACM会士。
Jeffrey D.UIIman,斯坦福大学计算机科学系教授和GradianceCEO。他的研究兴趣包括数据库理论、数据库集成、数据挖掘和利用信息基础设施教学等。他是美国国家工程院院士、IEEE会士,获得过ACM的Karlstrom杰出教育奖和Knufh奖。 目录
1 introduction
1.1 language processors
1.2 the structure of a compiler
1.3 the evolution of programming languages
1.4 the science of building a compiler
1.5 applications of compiler technology
1.6 programming language basics
1.7 summary of chapter 1
1.8 references for chapter 1
2 a simple syntax-directed translator
2.1 introduction
2.2 syntax definition
2.3 syntax-directed translation
2.4 parsing
2.5 a translator for simple expressions
2.6 lexical analysis
2.7 symbol tables
2.8 intermediate code generation
2.9 summary of chapter 2
3 lexical analysis
3.1 the role of the lexical analyzer
3.2 input buffering
3.3 specification of tokens
3.4 recognition of tokens
3.5 the lexical-analyzer generator lex
3.6 finite automata
3.7 from regular expressions to automata
3.8 design of a lexical-analyzer generator
3.9 optimization of dfa-based pattern matchers
3.10 summary of chapter 3
3.11 references for chapter 3
4 syntax analysis
4.1 introduction
4.2 context-free grammars
4.3 writing a grammar
4.4 top-down parsing
4.5 bottom-up parsing
4.6 introduction to lr parsing: simple lr
4.7 more powerful lr parsers
4.8 using ambiguous grammars
4.9 parser generators
4.10 summary of chapter 4
4.11 references for chapter 4
5 syntax-directed translation
5.1 syntax-directed definitions
5.2 evaluation orders for sdd's
5.3 applications of syntax-directed translation
5.4 syntax-directed translation schemes
5.5 hnplementing l-attributed sdd's
5.6 summary of chapter 5
5.7 references for chapter 5
6 intermediate-code generation
6.1 variants of syntax trees
6.2 three-address code
6.3 types and declarations
6.4 translation of expressions
6.5 type checking
6.6 control flow
6.7 backpatching
6.8 switch-statements
6.9 intermediate code for procedures
6.10 summary of chapter 6
6.11 references for chapter 6
7 run-time environments
7.1 storage organization
7.2 stack allocation of space
7.3 access to nonlocal data on the stack
7.4 heap management
7.5 introduction to garbage collection
7.6 introduction to trace-based collection
7.7 short-pause garbage collection
7.8 advanced topics in garbage collection
7.9 summary of chapter 7
7.10 references for chapter 7
8 code generation
8.1 issues m the design of a code generator
8.2 the target language
8.3 addresses in the target code
8.4 basic blocks and flow graphs
8.5 optimization of basic blocks
8.6 a simple code generator
8.7 peephole optimization
8.8 register allocation and assignment
8.9 instruction selection by tree rewriting
8.10 optimal code generation for expressions
8.11 dynamic programming code-generation
8.12 summary of chapter 8
8.13 references for chapter 8
9 machine-independent optimizations
9.1 the principal sources of optimization
9.2 introduction to data-flow analysis
9.3 foundations of data-flow analysis
9.4 constant propagation
9.5 partial-redundancy elimination
9.6 loops in flow graphs
9.7 region-based analysis
9.8 symbolic analysis
9.9 summary of chapter 9
9.10 references for chapter 9
10 instruction-level parallelism
10.1 processor architectures
10.2 code-scheduling constraints
10.3 basic-block scheduling
10.4 global code scheduling
10.5 software pipelining
10.6 summary of chapter 10
10.7 references for chapter 10
11 optimizing for parallelism and locality
11.1 basic concepts
11.2 matrix multiply: an in-depth example
11.3 iteration spaces
11.4 aftlne array indexes
11.5 data reuse
11.6 array data-dependence analysis
11.7 finding synchronization-free parallelism
11.8 synchronization between parallel loops
11.9 pipelining
11.10 locality optimizations
11.11 other uses of affine transforms
11.12 summarv of chapter 11
11.13 references for chapter 11
12 interprocedural analysis
12.1 basic concepts
12.2 why interprocedural analysis?
12.3 a logical representation of data flow
12.4 a simple pointer-analysis algorithm
12.5 context-insensitive interprocedural analysis
12.6 context-sensitive pointer analysis
12.7 datalog implementation by bdd's
12.8 summary of chapter 12
12.9 references for chapter 12
a a complete front end
a.1 the source language
a.2 main
a.3 lexical analyzer
a.4 symbol tables and types
a.5 intermediate code for expressions
a.6 jumping code for boolean expressions
a.7 intermediate code for statements
a.8 parser
a.9 creating the front end
b finding linearly independent solutions
index 精彩书摘
Languagel, are used to search databases. Database queries consist of predicatescontaining relational and boolean operators. They can be interpreted or com-piled into commands to search a database for records satisfying that predicate.Compiled SimulationSimulation is a general technique used in many scientific and engineering disci-plines to understand a phenomenon or to validate a design. Inputs to a simula-tor usually include the description of the design and specific input parametersfor that particular simulation run. Simulations can be very expensive. We typi-cally need to simulate many possible design alternatives on many different inputsets, and each experiment may take days to complete on a high-performancemachine. Instead of writing a simulator that interprets the design, it is fasterto compile the design to produce machine code that simulates that particulardesign natively. Compiled simulation can run orders of magnitude faster thanan interpreter-based approach. Compiled simulation is used in many state-of-the-art tools that simulate designs written in Verilog or VHDL.1.5.5 Software Productivity ToolsPrograms are arguably the most complicated engineering artifacts ever pro-duced; they consist of many many details, every one of which must be correctbefore the program will work completely. As a result, errors are rampant inprograms; errors may crash a system, produce wrong results, render a systemvulnerable to security attacks, or even lead to catastrophic failures in criticalsystems. Testing is the primary technique for locating errors in programs.
An interesting and promising complementary approach is to use data-flowanalysis to locate errors statically (that is, before the program is run). Data-flow analysis can find errors along all the possible execution paths, and notjust those exercised by the input data sets, as in the case of program testing.Many of the data-flow-analysis techniques, originally developed for compileroptimizations, can be used to create tools that assist programmers in theirsoftware engineering tasks.
The problem of finding all program'errors is undecidable. A data-flow anal-ysis may be designed to warn the programmers of all possible statements witha particular category of errors. But if most of these warnings are false alarms,users will not use the tool. Thus, practical error detectors are often neithersound nor complete. That is, they may not find all the errors in the program,and not all errors reported are guaranteed to be real errors. Nonetheless, var-ious static analyses have been developed and shown to be effective in findingerrors, such as dereferencing null or freed pointers, in real programs. The factthat error detectors may be unsound makes them significantly different fromcompiler optimizations. Optimizers must be conservative and cannot alter thesemantics of the program under any circumstances.
…… 前言/序言
In the time since the 1986 edition of this book, the world of compiler designhas changed significantly. Programming languages have evolved to present newcompilation problems. Computer architectures offer a variety of resources ofwhich the compiler designer must take advantage. Perhaps most interestingly,the venerable technology of code optimization has found use outside compilers.It is now used in tools that find bugs in software, and most importantly, findsecurity holes in existing code. And much of the "front-end" technology ——grammars, regular expressions, parsers, and syntax-directed translators —— arestill in wide use.
Thus, our philosophy from previous versions of the book has not changed.We recognize that few readers will build, or even maintain, a compiler for amajor programming language. Yet the models, theory, and algorithms associ-ated with a compiler can be applied to a wide range of problems in softwaredesign and software development. We therefore emphasize problems that aremost commonly encountered in designing a language processor, regardless ofthe source language or target machine.Use of the BookIt takes at least two quarters or even two semesters to cover all or most of thematerial in this book. It is common to cover the first half in an undergraduatecourse and the second half of the book —— stressing code optimization —— ina second course at the graduate or mezzanine level. Here is an outline of thechapters:Chapter 1 contains motivational material and also presents some backgroundissues in computer architecture and programming-language principles.Chapter 2 develops a miniature compiler and introduces many of the impor-taut concepts, which are then developed in later chapters. The compiler itselfappears in the appendix.Chapter 3 covers lexical analysis, regular expressions, finite-state machines, andscanner-generator tools. This material is fundamental to text-processing of allsorts.
alt="" />
数据结构与算法实战指南 内容简介 本书是一本深入探讨数据结构与算法的实践性指南,旨在帮助读者掌握解决复杂计算问题的核心工具与方法。本书不同于纯理论的学术著作,它侧重于将抽象的数据结构和算法概念转化为实际可操作的代码和解决策略,通过大量精选的实际案例,引导读者理解数据结构与算法在软件开发中的重要性以及它们如何有效地提升程序性能和效率。 核心内容概览 本书的结构经过精心设计,从基础概念的梳理到高级主题的深入剖析,层层递进,循序渐进。 第一部分:数据结构基础 本部分首先建立起坚实的数据结构理论基础,但重点在于理解其背后的设计思想和应用场景。 数组与字符串: 从最基础的线性数据结构开始,本书不仅讲解数组和字符串的定义、操作,更深入探讨其在内存中的表示方式、访问效率以及它们在实际开发中(如文本处理、数据存储)的应用。我们将学习如何利用数组实现动态分配、稀疏矩阵等,并分析字符串匹配算法(如朴素匹配、KMP算法)的原理和性能。 链表: 链表作为一种灵活的动态数据结构,在本书中被细致地剖析。我们会详细讲解单向链表、双向链表、循环链表的实现,并着重分析它们在插入、删除操作上的优势,以及与数组在内存分配和访问效率上的权衡。本书将通过实例展示链表在实现栈、队列、多项式运算等方面的应用。 栈与队列: 这两种基本的数据结构在计算机科学中无处不在。本书不仅会介绍它们的LIFO(后进先出)和FIFO(先进先出)特性,更重要的是,我们将通过实际编程问题来体现它们的作用,例如使用栈实现表达式求值、函数调用栈的模拟,以及使用队列实现广度优先搜索(BFS)和任务调度。 树: 树形结构是处理层次化数据的关键。本书将从二叉树入手,深入讲解二叉搜索树(BST)的插入、删除、查找操作,并探讨其性能分析。随后,我们将介绍平衡二叉搜索树(如AVL树、红黑树)的原理,以及它们如何通过自平衡机制保证查找效率。此外,堆(Heap)作为一种特殊的完全二叉树,其在优先队列和堆排序中的应用也将被详尽阐述。 图: 图数据结构用于表示对象之间的复杂关系。本书将系统介绍图的几种表示方法(邻接矩阵、邻接表),并在此基础上深入讲解经典的图算法。我们将重点分析深度优先搜索(DFS)和广度优先搜索(BFS)的遍历过程及其在连通性判断、拓扑排序等问题中的应用。 第二部分:经典算法与技巧 在掌握了基本的数据结构之后,本书将聚焦于解决问题的核心算法,并引入一系列高效的算法设计技巧。 排序算法: 排序是数据处理中最常见也是最基础的操作。本书将详细讲解各种排序算法的实现原理、时间复杂度和空间复杂度。从简单的冒泡排序、插入排序、选择排序,到效率更高的快速排序、归并排序、堆排序,再到特定的场景如基数排序、桶排序,本书都将提供清晰的解释和代码示例。更重要的是,我们将分析这些算法的适用场景以及在实际应用中的性能表现。 查找算法: 除了数组和二叉搜索树中的查找,本书还将探讨更广泛的查找技术。二分查找(Binary Search)作为提高查找效率的经典算法,其原理和应用将被深入解析。对于哈希表(Hash Table),本书将详细介绍哈希函数的设计、冲突解决策略(如链地址法、开放寻址法)以及其在常数平均时间复杂度下的查找、插入和删除操作。 递归与分治: 递归是许多复杂算法的基石。本书将深入讲解递归的定义、工作原理,并通过经典的例子,如斐波那契数列、汉诺塔、阶乘等,帮助读者掌握递归的思维方式。分治法(Divide and Conquer)作为一种重要的算法设计范式,其思想将在解决一些复杂问题时得到体现,如快速排序和归并排序本身就是分治法的应用。 贪心算法: 贪心算法是一种局部最优选择能够导致全局最优解的算法设计策略。本书将通过实例,如活动选择问题、霍夫曼编码、最小生成树(Prim/Kruskal算法)等,展示贪心算法的应用。我们将重点分析贪心策略的设计以及证明其正确性的方法。 动态规划: 动态规划是解决具有重叠子问题和最优子结构特性的复杂问题的强大工具。本书将从最基础的斐波那契数列开始,逐步引入动态规划的核心思想:状态定义、状态转移方程、最优解计算。我们将通过经典的动态规划问题,如背包问题(0/1背包、完全背包)、最长公共子序列(LCS)、最短路径(如Floyd-Warshall算法)、矩阵链乘法等,系统讲解动态规划的应用。本书会强调如何识别一个问题是否适合使用动态规划,以及如何有效地设计状态和转移方程。 第三部分:高级主题与应用 在掌握了核心的数据结构和算法后,本书将进一步探讨一些更高级的主题,以及数据结构与算法在实际工程中的应用。 字符串匹配算法: 除了前文提到的KMP算法,本书还将介绍其他高效的字符串匹配算法,如Boyer-Moore算法,并分析它们在不同场景下的性能特点。 图算法进阶: 在基础图遍历之后,本书将深入探讨更高级的图算法,如最短路径算法(Dijkstra算法、Bellman-Ford算法)、最小生成树算法(Prim算法、Kruskal算法)、以及强连通分量(Tarjan算法/Kosaraju算法)等。这些算法在网络路由、社交网络分析、资源分配等领域有着广泛的应用。 数据结构与算法在特定领域的应用: 本书还将探讨数据结构与算法在实际开发中的具体应用,例如: 数据库索引: B-tree和B+ tree等数据结构如何在数据库中实现高效的数据检索。 操作系统: 队列在任务调度、进程管理中的作用;内存管理中的数据结构。 网络协议: 哈希表在缓存、路由表中的应用。 图形学: KD-tree在空间搜索中的应用。 机器学习: 各种特征选择、模型训练中涉及的数据结构和算法。 性能优化与复杂度分析: 本书贯穿始终的重点是对算法的时间复杂度和空间复杂度进行精确分析,并指导读者如何根据具体场景选择最合适的数据结构和算法来优化程序性能。我们将讨论常数时间、对数时间、线性时间、平方时间等不同复杂度等级的含义,以及如何通过减少冗余计算、优化数据访问模式来提升效率。 学习方法与特点 本书的编写遵循以下核心原则: 1. 理论与实践相结合: 每介绍一种数据结构或算法,都将伴随具体的代码实现和详细的伪代码,并通过多个精心设计的实际问题来展示其应用。 2. 案例驱动: 大量精选的、来自实际编程挑战的案例,让读者在解决问题的过程中学习和巩固知识。 3. 清晰易懂的解释: 复杂概念将以直观易懂的方式进行阐述,辅以图示和比喻,力求消除读者的理解障碍。 4. 强调设计思想: 不仅关注“是什么”,更关注“为什么”,深入分析每种数据结构和算法的设计初衷、权衡取舍以及适用范围。 5. 循序渐进: 从基础概念到高级主题,内容组织逻辑清晰,难度逐步提升,适合不同水平的读者。 适用读者 本书适合以下人群: 计算机科学与技术专业的学生: 作为数据结构与算法课程的补充读物,帮助理解理论知识并提升编程实践能力。 软件工程师: 旨在巩固和提升自身在算法设计与数据结构运用方面的技能,以应对更复杂、更高效的软件开发挑战。 准备技术面试者: 数据结构与算法是各大科技公司面试的重中之重,本书将提供系统性的复习和实战指导。 对算法和编程感兴趣的自学者: 渴望深入理解计算机科学核心概念,提升解决问题能力的学习者。 通过本书的学习,读者不仅能掌握丰富的数据结构和算法知识,更能培养出独立分析问题、设计高效解决方案的能力,为未来的编程生涯打下坚实的基础。