Bottom-Up Parsing in Compiler Design

Bottom-Up Parsing

A bottom-up parsing constructs the parse tree for an input string beginning from the bottom (the leaves) and moves to work towards the top (the root). Bottom-up parsing is a parser that reduces the string to the start symbol of the grammar.  During the reduction, a specific substring matching the right side or body of the production will be replaced by a non – terminal at the head of that production. Bottom-up parsing constructs rightmost derivation in reverse order while scanning the input from left to right.

Shift – Reducing Parser

It is a type of bottom-up parser. In this parser, a stack holds the grammar symbol, and an input buffer holds the rest of the string that is set to be parsed. 

The symbol $ denotes the bottom of the stack and also the input's right side. While discussing the bottom-up parsing, we generally represent the top of the stack on the right-hand side. In the beginning, the stack is empty, and the string a is on the input side, as shown below:

                                         STACK                                     INPUT

                                              $                                              a$ 

This parsing generally performs two action shifts and reduce. But there are four possible actions that this parser can perform: shift, reduce, accept, error.

1) Shift – Shift operation shifts the input symbol onto the top of the stack.

2) Reduce – The top of the stack must hold the right end of that string, which is set to be reduced. It finds the left end of the string within the stack and decides which non – terminal can replace the string.

3) Accept – When we are only left with the start symbol in the stack, then the parsing action is called as Accept state.

4) Error – It detects the error and try to recover it.

Example:

Grammar:

A => A + A

A => A – A

A => (A)

A => a

input string:

a1-(a2+a3)

Parsing Table:

StackInputAction
$  a1- (a2+a3)$Shift a1
$a1  -(a2+a3)$Reduce by A => a
$A  -(a2+a3)$Shift -
$A-   (a2+a3)$Shift (
$A-(    a2+a3)$Shift a2
$A-(a2    +a3)$ Reduce by A => a
$A -(A     +a3)$Shift +
$A -(A +      a3)$Shift +
$A -(A +a3      ) $Reduce by A =>a
$A -(A + A      ) $Shift )
$A -(A + A)     $Reduce by A => A +A
$A - (A)     $Reduce by A => (A)
$A – A     $Reduce by A => A - A
$A    $Accept

Table1: Configuration of shift-reduce parser on input a1-(a2+a3)

Operator Precedence Parser

A grammar that is used to generate or define the mathematical expression with some restrictions on it is known as operator precedence grammar. Any grammar can be operator precedence grammar if it follows two properties:

  • No two-variable should be adjacent.
  • It should not have a null production.

Example:

E => E + E/ E * E/id

This is operator precedence grammar because there are no two adjacent variables, and there is no null production on the right side of the grammar.

Operator precedence parser ignores the non – terminal. It can only be established between the terminal of grammar. Only operator precedence grammar accepts ambiguous grammar.

Operator precedence relation

If a ? b, it means that terminal b has lower precedence than terminal a.

If b ? a, it means that terminal b has higher precedence over terminal a.

If a=b, it means that terminal a and terminal b have the same precedence.

An identifier has higher precedence than any other symbol, and the symbol $ has the lower precedence.

If two operator has the same precedence, then we will decide by checking the associativity of the operator.

Precedence Table

 +*()id$
+ ??????
*??????
(??? =?X
)??X?X?
Id??X?X?
$???X?X

Parsing Action

  • Adds symbol $ at both ends of the input string
  • Scans the input symbol from left to right until the ? encounter.
  • Scan towards leftover all the equal precedence until the first left-most ? is encountered.
  • Everything between the left-most ? and rightmost ? is a handle.
  • $ on $ means parsing is successful.

Example:

Grammar:

E => EAE |id

A => + | x

String:

id + id x id.

Depict the operator precedence parser and parse the given input string.

Solution:

Firstly, we will convert the given grammar into an operator precedence grammar.

The equivalent operator precedence grammar is as follows:

                                                  E => E + E | E x E | id

The terminal symbols in the given grammar are = (id, +, x, $)

We will construct the operator precedence table as:

 Id+x$
Id 
+
X
$ 

String to be parsed is given as id + id x id.

We will follow the given steps to parse the given input string:

The symbol $ will be added at both ends of the given input string:

                                                                  $ id + id x id $

Now insert the precedence operators between the string symbol as:

                                                                 $ < id > + < id > x < id > $

Now let's process the string with the help of the given precedence table:

$ < id > + < id > x < id > $

$ E + < id > x < id > $

$ E + E x < id > $

$ E + E x E $

$ + x $

$ < + < x > $

$ < + > $

$ $


Related Topics

LR Parser in Compiler Design

LR Parser The most popular type of bottom-up parsing is LR(K) parsing. The LR() parser scans the input from left – to – right, which is the actual abbreviation of L...

2 minutes read.

CLR Parsing Compiler Design

CLR Parsing CLR parsing refers to the canonical lookahead. We will use the canonical collection of LR(1) items for the construction of the CLR(1) parsing table. Generally, CLR(1) parsing has more...

6 minutes read.

Symbol Table Compiler Design

Symbol Table It is an important data structure used by the compiler. It stores information about various entities such as object, class, variable names, functions name, interfaces, procedure, literals, string etc.  The...

3 minutes read.

Parsing in Compiler Design

Parsing is the term used to describe the process of converting data between different formats. The parser can carry out this operation. The parser is a part of the translator...

4 minutes read.

Machine-Independent Optimizations in Compiler Design

Machine-Independent Optimizations The main aim of machine-independent optimization is to improve the generated intermediate code so that compiler can get better target code. Eliminating unwanted code from the object code or replacing...

8 minutes read.

Regular Expression | Compiler Design

Regular Expression A regular expression is a set of patterns that can match a character or string. It can also match alternative characters or strings. The grammar defined by the regular...

3 minutes read.

LEX

LEX Lex is a tool/computer program that generates a Lexical analyzer. Lex is developed by Vern Paxson in C around 1987. Lex works together with the YACC parser generator. It allows...

3 minutes read.

Ambiguity Elimination Compiler Design

Ambiguity Elimination Ambiguity elimination makes the sentence clear and readable. A sentence is grammatically ambiguous if it can produce more than one parse tree for a particular grammar. In this article,...

3 minutes read.

Storage Allocation

Storage Allocation The storage allocation represents memory management. The allocation of memory can be done in the following ways: Static AllocationStack AllocationHeap Management Static Allocation: It is a procedure used for the allocation of...

1 minute read.

Evolution of Programming Languages in Compiler Design

The Evolution of Programming Languages The first computer came in the 1940s and was programmed in a binary language that told the computer what operations are to be performed and in...

4 minutes read.

Basic Blocks and Flow Graphs in Compiler Design

Basic Blocks and Flow Graphs In this section, we are going to learn how to work with basic block and flow graphs in compiler design. Basic Block The basic block is a set...

3 minutes read.

Lexical Analysis in Compiler Design

Lexical Analysis It is the first phase of the compiler. As we know, it is also known as a scanner. The input for lexical analysis is source code. After taking source...

2 minutes read.

Syntax Analysis Compiler Design

Syntax Analysis This article will describe the parsing method used in the compiler. The grammatical rule of programming language can be constructed with the help of context-free grammars or BNF (Backus–Naur...

3 minutes read.

Compiler Design Tutorial

Our compiler design tutorial will provide all the information about compiler from basic to advanced level. This compiler tutorial will help the student for their semester as well as for...

3 minutes read.

Code Generation

Code Generation The last phase of the compiler is code generation. It is the compiler's back-end that makes multiple passes over the IR before generating the target program. The code generator's...

4 minutes read.

Derivation and Parse Tree in Compiler Design

Derivation and Parse Tree In this article, we will learn Derivation and Parse Tree. Derivations The parse tree can be constructed by taking a derivational view in which production is treated as rewriting...

4 minutes read.

Errors in Compiler Design

Introduction Errors in compiler design refer to mistakes or issues that arise during the process of execution of the program. A compiler is a program that translates source code written in...

4 minutes read.

Target Machine

Target Machine A target machine is a byte-addressable machine. This machine has n general-purpose registers, R0, R1,.....Rn-1. A Simple Target Machine Model has three-address instruction. A full-edged assembly language would have...

3 minutes read.

Run-Time Environments

Run-Time Environments Storage Organization Every target program has its own logical address, and an executable program runs in it. The logical address space has the location for each program value. The...

2 minutes read.

Translation of Array References in Compiler Design

Translation of Array References We can access the elements of an array stored in consecutive blocks very easily and quickly. In a programming language like C and Java, the size of...

2 minutes read.