Syntactic analysis is the process of checking whether a program is syntactically correct.
The compilation process consists of:
- Lexical analysis: programs decomposed into tokens
- Parsing: tokens checked to ensure they form a word in the prog. language

Parsing
A parser reads a sequence of tokens and builds a parse tree (or derivation tree), outputting an abstract syntax tree.
A parse tree shows the step-by-step process of building the AST.

Abstract Syntax
Abstract Syntax describes the syntax trees, to which semantics is associated.
Link to original
Top-Down parsing: Recursive descent parsing (RDP)
In top-down parsing, (starting from the start symbol) search for a rule that rewrites the non-terminals to yield terminals consistent with the input.
There are two problems with RDP:
- left recursion
- repeated terminal checking
A grammar is suitable for RDP if, wherever there is a choice, the parser can select the correct alternative by looking at the current symbol. If this is not the case, we end up backtracking a lot which is inefficient (each token is examined several times). We can make it less expensive by left factoring the grammar: expand rules to expose the common part and factor it out.
Left recursion can cause an RDP to get stuck in an infinite loop. A grammar is left-recursive if it has a non-terminal such that there is a derivation for some string .
To eliminate left recursion from any rule, we can apply the following substitution:
We can also run into infinite loops if the grammar is indirectly left-recursive.
We can rewrite indirect left-recursion as an equivalent direct left-recursion by using the substitution rule below: (and then eliminate left-recursion as before)
Example RDP 1
Let’s say we have the grammar:
stat -> begin statlist | S statlist -> end | stat ; statlistAssume that the input is derived from start symbol
stat, examine each alternative rule forstat. Compare first unmatched token with first symbol on RHS of each alternative rule forstat. If a matching production is found, use it to rewritestat. Repeat, using next input token to determine the rule used for next non-terminal. If no match, try a rule that begins with a non-terminal, e.g.stat;statlist.
Example RDP 2
Given the following definition: Use top-down parsing to determine if
crabis valid.
Example of left factoring
Given the grammar:
stmt -> while exp do stmt | assign | call assign -> ident = exp call -> ident ( arglist )Expand assign and call:
stmt -> ... | ident = exp | ident ( arglist )And then factor out ident:
stmt -> ... | ident rest rest -> = exp | ( arglist )
Example of left recursion
Given the definition: The parse tree ends up infinitely recursing:
Example of indirect left recusion
Bottom-up parsing: Shift-reduce parsing
In bottom-up parsing, we start from the input and compare it against right-hand side of the rules, to find where a string can be replaced by a non-terminal. Parsing succeeds when the whole input has been replaced by the start symbol of the grammar.
Shift-reduce is hard to do by hand but it’s efficient since we don’t have to rewrite the grammar.
A parser generator generates a parser from a given grammar.
- Generate a push-down automata to recognise language (shift and reduce transitions)
- Generate code in a chosen language
Example

Lexical Analysis
A lexer reads a string and converts it to a sequence of tokens. In practice it also removes white-space / tabs, comments, has some limited error detection / correction, and can do macro expansion.
Skipping slides 12-18
A regular expression denotes a language . (set of acceptable words) Formulation rules for regular expressions over alphabet :
- denotes
- denotes for any symbol
- Suppose and are regular expressions:
- denotes ; sometimes written as
- denotes
- denotes
- denotes , i.e.
- abbreviates Conventions: drop unnecessary parentheses, all operators are left-associative, precedence is then concatenation then , and use abbreviations incl. character classes e.g. .
A regular definition, over an alphabet , is a sequence of definitions: Where each is a distinct name and each is a regular expression over . Symbols in are called terminals. are called non-terminals.
Example


