From b5f34c03cfec59625135deb725788392433c2102 Mon Sep 17 00:00:00 2001
From: AidenRushbrooke <72034940+AidenRushbrooke@users.noreply.github.com>
Date: Mon, 13 Dec 2021 01:09:03 +0000
Subject: Added to chapter 3 of the report

---
 report/esoteric_project_report.tex | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

(limited to 'report/esoteric_project_report.tex')

diff --git a/report/esoteric_project_report.tex b/report/esoteric_project_report.tex
index be12b46..4ab77e5 100644
--- a/report/esoteric_project_report.tex
+++ b/report/esoteric_project_report.tex
@@ -114,13 +114,20 @@ Esolangs are programming languages designed to be jokes or proof of concept lang
 \section{Example - Shakespearian Programming Language}
 The Shakespeare Programming Language is esoteric code parodied on extracts from Romeo and Juliet. Here, code is written so it reads like how a script would, such as \texttt{[Enter Juliet]} where \texttt{Juliet} may be a variable name. Other examples include using \texttt{Acts} or \texttt{Scenes} as GOTO statements, where the interpreter can jump to a certain point in the code and read from there. Otherwise, these are ignored similar to the title or character descriptions. Other examples include LOLCODE, Hodor or White Space. This serves the purpose of writing code in a different manner to usual, sometimes for humour. The aim is to replace typical language features so that it can still be read by a compiler or interpreter but also look and read very differently by the user.  
 
-\chapter{The Structure of our Programming Language}
-\section{The Lexar (Lexical Analysis)} 
-In the field of linguistics or computer programming language design, lexical analysis is the process of converting a sequence of characters (such as a computer program) into a sequence of tokens. 
-This process is also known as tokenisation, particularly in the field of natural language processing (NLP).
-When designing a programming language, the task of lexical analysis or tokenisation is performed by a lexer. 
-The actual matching of tokens is often performed using regular expressions, defined in the design stage in order to reliably match all tokens in the language. 
-
+\chapter{Compiler Design and Methodology}
+This chapter will discuss how compilers work, and the design behind them. The goal of a compiler is to convert the source code into an from which the CPU can execute. As mentioned in chapter 2, a compiler works by converting the entire source code in one go, then executing, unlike a interpreter which executes each line at a time. However, before the code can be executed a number of steps have to be taken.
+\section{The Lexer (Lexical Analysis)}
+The first step for a compiler is to convert the initial source code into groups of characters which the computer can understand, generally known as tokens. This process is also known as tokenisation, particularly in the field of natural language processing (NLP). When designing a programming language, the task of lexical analysis or tokenisation is performed by a lexer or scanner. This lexer looks through each character and creates equivalent tokens based on the character values. For example, the character '+' may be converted into the token "plus", which in a programming language would likely represent addition. Some tokens may also be multiple lines long, such as strings, identifiers and keywords like "if" or "int". This stage can also detect some syntax errors, for any unrecognised characters. The end result of lexical analysis is a series of tokens representing the starting source code.
+\section{The Parser}
+The second stage of the compiler is to try and understand how the tokens link together to form a a program.  The parser uses the list of tokens created and compares it to the language grammar. This allows it to understand how the tokens are linked, and can then use this information to create abstract syntax trees (AST), which represents the code in a logical fashion. The parser can also detect any syntax errors  in the initial source code when comparing against the language grammar. 
+
+The specific parser we have chosen is a recursive descent parser, a Top-Down parser where each rule in the grammar maps to a specific function in the parser implementation. A recursive descent parser works by starting at the first rule in the grammar, then working downward, finding each statement or expression. We chose this parser design as it is both simple to implement and gives a lot of control to how the parser functions and error reporting compared to parsers created through a parser generator and grammar table. Many compiler implementations also use recursive descent parsers, such as GCC \cite{GCCParser} and Clang. 
+\section{Optimization}
+This step involves making a variety of optimizations to the current program to speed up processing. This may involve simplifying loops, or pre-calculating complicated expressions which only contain constants. However, this step is not vital to the function of an effective compiler, with some deciding to ignore optimization entirely.
+\section{Code Generation}
+At this stage, the code is converted into a form which can be executed by the CPU, such as machine code. However, due to the complexity of converting directly to machine code, an alternative is commonly done. Here, the compiler writes to a alternate form designed to run on a created virtual machine. This form is known as bytecode. Java is a well known example which uses this method, where java programs are compiled to run in the Java virtual machine.
+
+One other method is to compile into another, existing programming language. This method is known as a source-to-source compiler. Here, instead of writing to machine code or bytecode, the compiler creates a string of valid source code for the language being targeted, based on the initial source code for the main compiler. This can then be executed using other, pre-existing compilers. One common use of these compilers is for web browsers, where many languages compile to javascript.
 
 \chapter{Grammar}
 
-- 
cgit v1.2.3

