Compiler construction in java

Introduction to compiler construction in a Java world

Compilation; Compilers; Why Should We Study Compilers?; How Does a Compiler Work? The Phases of Compilation; An Overview of the j — to JVM Compiler; The j — Compiler Source Tree; The Organization of This Book Lexical Analysis; Introduction; Scanning Tokens; Regular Expressions; Finite State Automata; Nondeterministic Finite-State Automata (NFA) vs. Deterministic Finite-State Automata (DFA); Regular Expressions to NFA; NFA to DFA; A Minimal DFA; JavaCC: A Tool for Generating Scanners Parsing; Introduction; Context-Free Grammars and Languages; Top-down Deterministic Parsing; Bottom-up Deterministic Parsing; Parser Generation Using JavaCC Type Checking; Introduction; The j — Types; j — Symbol Tables; Pre-Analysis of j — Programs; Analysis of j

Programs; The Visitor Pattern and the AST Traversal Mechanism; Programming Language Design and Symbol Table Structure; Attribute Grammars JVM Code Generation; Introduction; Generating Code for Classes and Their Members; Generating Code for Control and Logical Expressions; Generating Code for Message Expressions

Field Selection and Array Expressions; Generating Code for Assignment and Similar Operations; Generating Code for String Concatenation; Generating Code for Casts Translating JVM Code to MIPS Code; Introduction; SPIM and the MIPS Architecture; Our Translator Register Allocation; Introduction; Naïve Register Allocation; Local Register Allocation; Global Register Allocation Celebrity Compilers; Introduction; The Java HotSpot Compiler; The Eclipse Compiler for Java (ECJ); The GNU Java Compiler (GCJ); Microsoft C# Compiler for .NET Framework Appendix A: Setting Up and Running j — ; Appendix B: The j

Language; Appendix C: Java Syntax; Appendix D: The JVM, Class Files and the CLEmitter; Appendix E: MIPS and the SPIM Simulator Bibliography Index Further Readings and Exercises appear at the end of each chapter

Access-restricted-item true Addeddate 2022-10-26 17:02:26 Associated-names Iyer, Swami; Akbal-Delibas, Bahar Boxid IA1769310 External-identifier urn:lcp:introductiontoco00unse:lcpdf:d16f700a-17ba-403b-8c77-e7133eeaf6bd
urn:lcp:introductiontoco00unse:epub:3573e9d5-f7ec-40a8-bd5b-fa64f4c986a0 Foldoutcount 0 Identifier introductiontoco00unse Identifier-ark ark:/13960/s2mnwx7pxwc Invoice 11 Isbn 1439860882
9781439860885
9781482215076
1482215071 Lccn 2012030751 Ocr tesseract 5.1.0-1-ge935 Ocr_detected_lang en Ocr_detected_lang_conf 1.0000 Ocr_detected_script Latin Ocr_detected_script_conf 0.9426 Ocr_module_version 0.0.16 Ocr_parameters -l eng Page-progression lr Page_number_confidence 90.56 Pages 394 Pdf_module_version 0.0.18 Ppi 400 Republisher_date 20220712085233 Republisher_operator associate-ladonna-hartmann@archive.org Republisher_time 466 Scandate 20220711174409 Scanner scribe7.indiana.archive.org Scanningcenter indiana Sku T1-BCA-696 Tts_version 5.2-initial-88-g0de236a8 Worldcat (source edition) 874011890

Источник

Compiler Construction/Java

In Java, there are four kinds of method invocation, namely invokestatic, invokespecial, invokevirtual, invokeinterface. As the names suggest, the first is used to invoke static method and the rest instance methods. Since a static method cannot be overridden, invokestatic is very simple; it is essentially the same as calling a function in C.

Читайте также:  CSS Button Style

We now see the mechanism of invocation of instance methods. Consider the following piece of code.

class A < public static int f () < return 1; >private int g_private () < return 2; >public final int g_final () < return 3; >public int g_non_final () < return 4; >public void test (A a) < a.f (); // static; this is always 1. a.g_private (); // special; this is always 2. a.g_final (); // special; this is always 3. a.g_non_final (); // virtual; this may be 4 or something else. >> class B extends A < public int g_non_final () < return 6; >> class C extends B < public int g_non_final () < return 7; >public int foo () < return A.this.g_non_final (); >>

invokestatic is invoked with the references to the class name and the method name and pops arguments from the stack. An expression A.f (2) is complied to:

iconst_2 // push a constant 2 onto the stack invokestatic A.f // invoke a static method // the return value is at the top of the stack.

In Java, a private method cannot be overridden. Thus, a method has to be called based on a class regardless of how an object is created. invokespecial allows this; the instruction is the same as invokestatic except that it also pops the object reference besides supplied arguments. Thus far, dynamic binding is not in use, and it is not necessary to have information about binding at runtime about private methods.

Specifically, invokespecial can be used either (1) calling a private method or (2) a invoking a method of the super class (including the constructor for the super class, namely ). To call a super method other than , one has to write like super.f () where f is the name of the super method.

In semantics invokeinterface doesn’t differ from invokevirtual , but it can give the compiler a hit about the invocation.

Class methods [ edit | edit source ]

Class methods can be defined with a static qualifier. Private class methods may be in the same object, if they belong to the different classes. No two public class methods may be in the same object; in other words, class methods cannot be overridden. This also means final qualifier is semantically meaningless for class methods.

Fields [ edit | edit source ]

Each field is accessed based on a class. Consider the following.

class A < public int i = 2; >class B extends A

B b = new B (); A a = b; b.i++; // this would be 3 + 1 = 4 a.i++; // this would be 2 + 1 = 3

In other words, an access control modifier (none, public, private and protected) only affects if clients of the class can access a given field. This means that Java virtual machine may ignore the access flag, handling each field in the same manner.

References [ edit | edit source ]

Источник

Читайте также:  Php errors not displayed

Compilation and Execution of a Java Program

Java, being a platform-independent programming language, doesn’t work on the one-step compilation. Instead, it involves a two-step execution, first through an OS-independent compiler; and second, in a virtual machine (JVM) which is custom-built for every operating system.

The two principal stages are explained below:

Principle 1: Compilation

First, the source ‘.java’ file is passed through the compiler, which then encodes the source code into a machine-independent encoding, known as Bytecode. The content of each class contained in the source file is stored in a separate ‘.class’ file. While converting the source code into the bytecode, the compiler follows the following steps:

Step 1: Parse: Reads a set of *.java source files and maps the resulting token sequence into AST (Abstract Syntax Tree)-Nodes.

Step 2: Enter: Enters symbols for the definitions into the symbol table.

Step 3: Process annotations: If Requested, processes annotations found in the specified compilation units.

Step 4: Attribute: Attributes the Syntax trees. This step includes name resolution, type checking and constant folding.

Step 5: Flow: Performs dataflow analysis on the trees from the previous step. This includes checks for assignments and reachability.

Step 6: Desugar: Rewrites the AST and translates away some syntactic sugar.

Step 7: Generate: Generates ‘.Class’ files.

Principle 2: Execution

The class files generated by the compiler are independent of the machine or the OS, which allows them to be run on any system. To run, the main class file (the class that contains the method main) is passed to the JVM and then goes through three main stages before the final machine code is executed. These stages are:
These states do include:

Let us discuss all 3 stages.

The main class is loaded into the memory bypassing its ‘.class’ file to the JVM, through invoking the latter. All the other classes referenced in the program are loaded through the class loader.
A class loader, itself an object, creates a flat namespace of class bodies that are referenced by a string name. The method definition is provided below illustration as follows:

Illustration:

// loadClass function prototype Class r = loadClass(String className, boolean resolveIt); // className: name of the class to be loaded // resolveIt: flag to decide whether any referenced class should be loaded or not.

There are two types of class loaders

The primordial class loader is embedded into all the JVMs and is the default class loader. A non-primordial class loader is a user-defined class loader, which can be coded in order to customize the class-loading process. Non-primordial class loader, if defined, is preferred over the default one, to load classes.

After the bytecode of a class is loaded by the class loader, it has to be inspected by the bytecode verifier, whose job is to check that the instructions don’t perform damaging actions. The following are some of the checks carried out:

  • Variables are initialized before they are used.
  • Method calls match the types of object references.
  • Rules for accessing private data and methods are not violated.
  • Local variable accesses fall within the runtime stack.
  • The run-time stack does not overflow.
  • If any of the above checks fail, the verifier doesn’t allow the class to be loaded.
Читайте также:  Нахождение всех простых делителей числа питон

This is the final stage encountered by the java program, and its job is to convert the loaded bytecode into machine code. When using a JIT compiler, the hardware can execute the native code, as opposed to having the JVM interpret the same sequence of bytecode repeatedly and incurring the penalty of a relatively lengthy translation process. This can lead to performance gains in the execution speed unless methods are executed less frequently.

The process can be well-illustrated by the following diagram given above as follows from which we landed up to the conclusion.

Conclusion: Due to the two-step execution process described above, a java program is independent of the target operating system. However, because of the same, the execution time is way more than a similar program written in a compiled platform-dependent program.

Implementation:

Consider simple printing program is written somewhere on the local directory in a machine.

Источник

Compiler Construction Using Java, JavaCC, and Yacc

Compiler Construction Using Java, JavaCC, and Yacc Front Cover

Broad in scope, involving theory, the application of that theory, and programming technology, compiler construction is a moving target, with constant advances in compiler technology taking place. Today, a renewed focus on do-it-yourself programming makes a quality textbook on compilers, that both students and instructors will enjoy using, of even more vital importance. This book covers every topic essential to learning compilers from the ground up and is accompanied by a powerful and flexible software package for evaluating projects, as well as several tutorials, well-defined projects, and test cases.

Table of Contents

Chapter 1 Strings, Languages, and Compilers
Chapter 2 Context-Free Grammars, Part 1
Chapter 3 Context-Free Grammars, Part 2
Chapter 4 Context-Free Grammars, Part 3
Chapter 5 Chomsky’s Hierarchy
Chapter 6 Top-Down Parsing
Chapter 7 LL(1) Grammars
Chapter 8 Table-Driven Stack Parser
Chapter 9 Recursive-Descent Parsing
Chapter 10 Recursive-Descent Translation
Chapter 11 Assembly Language
Chapter 12 SI—A Simple Compiler
Chapter 13 JavaCC
Chapter 14 Building on S2
Chapter 15 Compiling Control Structures
Chapter 16 Compiling Programs in Functional Form
Chapter 17 Finite Automata
Chapter 18 Capstone Project: Implementing Grep Using Compiler Technology
Chapter 19 Compiling to a Register-Oriented Architecture
Chapter 20 Optimization
Chapter 21 Interpreters
Chapter 22 Bottom-Up Parsing
Chapter 23 yacc

Appendix A Stack Instruction Set
Appendix B Register Instruction Set

Источник

Оцените статью