0% found this document useful (0 votes)
89 views13 pages

CD Unit 4 Complete Notes Topic Wise

The document discusses symbol tables, which are data structures used by compilers to store information about identifiers and other elements in source code. A symbol table stores entries with a name, type, and attributes. It allows compilers to check scopes, declarations, and assignments. Symbol tables can be implemented as linear lists or hash tables and support operations like insertion and lookup. The document also discusses code generation, memory allocation, and lexical errors.

Uploaded by

abcmsms432
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
89 views13 pages

CD Unit 4 Complete Notes Topic Wise

The document discusses symbol tables, which are data structures used by compilers to store information about identifiers and other elements in source code. A symbol table stores entries with a name, type, and attributes. It allows compilers to check scopes, declarations, and assignments. Symbol tables can be implemented as linear lists or hash tables and support operations like insertion and lookup. The document also discusses code generation, memory allocation, and lexical errors.

Uploaded by

abcmsms432
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 13

Unit-4 Symbol Tables

Symbol table is an important data structure used in a compiler.

Symbol table is used to store the information about the occurrence of various entities
such as objects, classes, variable name, interface, function name etc. it is used by both
the analysis and synthesis phases.

The symbol table used for following purposes:

o It is used to store the name of all entities in a structured form at one place.
o It is used to verify if a variable has been declared.
o It is used to determine the scope of a name.
o It is used to implement type checking by verifying assignments and expressions
in the source code are semantically correct.

A symbol table can either be linear or a hash table. Using the following format, it maintains
the entry for each name.

<symbol name, type, attribute>

For example, suppose a variable store the information about the following variable
declaration:

static int salary

then, it stores an entry in the following format:

<salary, int, static>

The clause attribute contains the entries related to the name.

Implementation
The symbol table can be implemented in the unordered list if the compiler is used to
handle the small amount of data.

A symbol table can be implemented in one of the following techniques:

o Linear (sorted or unsorted) list


o Hash table
o Binary search tree

Symbol table are mostly implemented as hash table.

Operations
The symbol table provides the following operations:

Insert ( )
o Insert () operation is more frequently used in the analysis phase when the tokens
are identified and names are stored in the table.
o The insert() operation is used to insert the information in the symbol table like
the unique name occurring in the source code.
o In the source code, the attribute for a symbol is the information associated with
that symbol. The information contains the state, value, type and scope about
the symbol.
o The insert () function takes the symbol and its value in the form of argument.

For example:

int x;

Should be processed by the compiler as:

insert (x, int)

lookup ( )
In the symbol table, lookup() operation is used to search a name. It is used to
determine:

o The existence of symbol in the table.


o The declaration of the symbol before it is used.
o Check whether the name is used in the scope.
o Initialization of the symbol.
o Checking whether the name is declared multiple times.

The basic format of lookup() function is as follows:


lookup (symbol)

This format is varies according to the programming language.

Data structure for symbol table


o A compiler contains two type of symbol table: global symbol table and scope symbol
table.
o Global symbol table can be accessed by all the procedures and scope symbol table.

The scope of a name and symbol table is arranged in the hierarchy structure as shown
below:

int value=10;
void sum_num()
{
int num_1;
int num_2;
{
int num_3;
int num_4;
}
int num_5;
{
int_num 6;
int_num 7;
}
}
Void sum_id
{
int id_1;
int id_2;
{
int id_3;
int id_4;
}
int num_5;
}
The above grammar can be represented in a hierarchical data structure of symbol
tables:

The global symbol table contains one global variable and two procedure names. The
name mentioned in the sum_num table is not available for sum_id and its child tables.

Data structure hierarchy of symbol table is stored in the semantic analyzer. If you want to
search the name in the symbol table then you can search it using the following algorithm:

o First a symbol is searched in the current symbol table.


o If the name is found then search is completed else the name will be searched in the
symbol table of parent until,
o The name is found or global symbol is searched.
Representing Scope Information
In the source program, every name possesses a region of validity, called the scope of
that name.

The rules in a block-structured language are as follows:

1. If a name declared within block B then it will be valid only within B.


2. If B1 block is nested within B2 then the name that is valid for block B2 is also valid for
B1 unless the name's identifier is re-declared in B1.

o These scope rules need a more complicated organization of symbol table than a list of
associations between names and attributes.
o Tables are organized into stack and each table contains the list of names and their
associated attributes.
o Whenever a new block is entered then a new table is entered onto the stack. The new
table holds the name that is declared as local to this block.
o When the declaration is compiled then the table is searched for a name.
o If the name is not found in the table then the new name is inserted.
o When the name's reference is translated then each table is searched, starting from the
each table on the stack.

For example:
int x;

void f(int m) {

float x, y;

int i, j;

int u, v;
}
}
int g (int n)
{
bool t;
}
Fig: Symbol table organization that complies with static scope information rules

Storage Organization
o When the target program executes then it runs in its own logical address space in which
the value of each program has a location.
o The logical address space is shared among the compiler, operating system and target
machine for management and organization. The operating system is used to map the
logical address into physical address which is usually spread throughout the memory.

Subdivision of Run-time Memory:


o Runtime storage comes into blocks, where a byte is used to show the smallest unit of
addressable memory. Using the four bytes a machine word can form. Object of
multibyte is stored in consecutive bytes and gives the first byte address.
o Run-time storage can be subdivide to hold the different components of an executing
program:

1. Generated executable code


2. Static data objects
3. Dynamic data-object- heap
4. Automatic data objects- stack

Activation Record
o Control stack is a run time stack which is used to keep track of the live procedure
activations i.e. it is used to find out the procedures whose execution have not been
completed.
o When it is called (activation begins) then the procedure name will push on to the stack
and when it returns (activation ends) then it will popped.
o Activation record is used to manage the information needed by a single execution of
a procedure.
o An activation record is pushed into the stack when a procedure is called and it is
popped when the control returns to the caller function.

The diagram below shows the contents of activation records:


Return Value: It is used by calling procedure to return a value to calling procedure.

Actual Parameter: It is used by calling procedures to supply parameters to the called


procedures.

Control Link: It points to activation record of the caller.

Access Link: It is used to refer to non-local data held in other activation records.

Saved Machine Status: It holds the information about status of machine before the
procedure is called.

Local Data: It holds the data that is local to the execution of the procedure.

Temporaries: It stores the value that arises in the evaluation of an expression

Storage Allocation
The different ways to allocate memory are:

1. Static storage allocation


2. Stack storage allocation
3. Heap storage allocation

Static storage allocation


o In static allocation, names are bound to storage locations.
o If memory is created at compile time then the memory will be created in static area
and only once.
o Static allocation supports the dynamic data structure that means memory is created
only at compile time and deallocated after program completion.
o The drawback with static storage allocation is that the size and position of data objects
should be known at compile time.
o Another drawback is restriction of the recursion procedure

Stack Storage Allocation


o In static storage allocation, storage is organized as a stack.
o An activation record is pushed into the stack when activation begins and it is popped
when the activation end.
o Activation record contains the locals so that they are bound to fresh storage in each
activation record. The value of locals is deleted when the activation ends.
o It works on the basis of last-in-first-out (LIFO) and this allocation supports the recursion
process.

Heap Storage Allocation


o Heap allocation is the most flexible allocation scheme.
o Allocation and deallocation of memory can be done at any time and at any place
depending upon the user's requirement.
o Heap allocation is used to allocate memory to the variables dynamically and when the
variables are no more used then claim it back.
o Heap storage allocation supports the recursion process.

Example:

fact (int n)
{
if (n<=1)
return 1;
else
return (n * fact(n-1));
}
fact (6)

The dynamic allocation is as follows:

Lexical Error
During the lexical analysis phase this type of error can be detected.

Lexical error is a sequence of characters that does not match the pattern of any token.
Lexical phase error is found during the execution of the program.

Lexical phase error can be:

o Spelling error.
o Exceeding length of identifier or numeric constants.
o Appearance of illegal characters.
o To remove the character that should be present.
o To replace a character with an incorrect character.
o Transposition of two characters.

Example:

Void main()
{
int x=10, y=20;
char * a;
a= &x;
x= 1xab;
}

In this code, 1xab is neither a number nor an identifier. So this code will show the
lexical error.

Syntax Error
During the syntax analysis phase, this type of error appears. Syntax error is found
during the execution of the program.

Some syntax error can be:

o Error in structure
o Missing operators
o Unbalanced parenthesis

When an invalid calculation enters into a calculator then a syntax error can also occurs.
This can be caused by entering several decimal points in one number or by opening
brackets without closing them.

For example 1: Using "=" when "==" is needed.

16 if (number=200)
17 count << "number is equal to 20";
18 else
19 count << "number is not equal to 200"

The following warning message will be displayed by many compilers:


Syntax Warning: assignment operator used in if expression line 16 of program
firstprog.cpp

In this code, if expression used the equal sign which is actually an assignment operator
not the relational operator which tests for equality.

Due to the assignment operator, number is set to 200 and the expression number=200
are always true because the expression's value is actually 200. For this example the
correct code would be:

16 if (number==200)

Example 2: Missing semicolon:

int a = 5 // semicolon is missing

Compiler message:

ab.java:20: ';' expected


int a = 5

Example 3: Errors in expressions:

x = (3 + 5; // missing closing parenthesis ')'


y = 3 + * 5; // missing argument between '+' and '*'

Semantic Error
During the semantic analysis phase, this type of error appears. These types of error are
detected at compile time.

Most of the compile time errors are scope and declaration error. For
example: undeclared or multiple declared identifiers. Type mismatched is another
compile time error.

The semantic error can arises using the wrong variable or using wrong operator or
doing operation in wrong order.

Some semantic error can be:


o Incompatible types of operands
o Undeclared variable
o Not matching of actual argument with formal argument
Example 1: Use of a non-initialized variable:

int i;
void f (int m)
{
m=t;
}

In this code, t is undeclared that's why it shows the semantic error.

Example 2: Type incompatibility:

int a = "hello"; // the types String and int are not compatible

Example 3: Errors in expressions:

String s = "...";
int a = 5 - s; // the - operator does not support arguments of type String

You might also like