 So, this is how the symbol table was looking just to express your memories. So, we have a symbol table for a scope which is at the highest level. So, this is the program I will come to the program later. So, this is one of the scope and then whenever I have declaration of a procedure of function then I just make this entry and this gives me a pointer to the symbol table of the scope which is nested inside this. And then again I can go for any level of nesting and if I need to go back to the parent node then I also have a link to the parent's indicator. So, this is how a symbol table was looking and then we looked at the declarations and then we said that to begin with we will start with an offset of 0. So, we are trying to generate relocatable board and this says that in each scope my offset is 0 to begin with and how do I change this variable global variable. Every time I assign some width in the variable that means some number of bytes to variable I just add this value to the offset and this ensures that whenever I have a new variable to be entered in the symbol table I am going to enter the new offset. So, for the first variable I am going to enter offset 0 here but suppose this variable takes 4 bytes then the next variable will be new and here I have offset of 4 from the space value. This is what we were discussing and then we started looking at little more complex things. So, for arrays and for points and so on. Now, what we want to do is we want to go for nesting that means now it is possible that in addition to having a program which has some declarations followed by a statement. I can also say that a procedure is nothing but a declaration at this point of time I am not interested in looking at the body of the procedure. So, body of the procedure will tell me that if I call a procedure what is the code which is going to get taken. But if I just look at I treat this also a procedure declaration then what will happen that because of this nesting. So, suppose what may happen is that I may have say. So, some let us say scope 1 and here I may have some string of local variables and once I have the string of local variables then I may have procedure p 1. Now, as soon as I have a procedure p 1 what I need to do is I need to create a table for p 1. So, I can this I am going to treat as a different scope. So, this scope is inside scope 1. So, what will happen is that I will have this simple table for scope 1 which will have declarations corresponding to l 1, l 2 and l n and then I have this declaration of p 1 which gives me a pointer to the symbol table of scope 2 and then it should have its own local variables. Now, first thing that you must realize is that when I start with the variable like offset with l 1 with an offset of 0. I will process it up to this point and as soon as I encounter p 1 and it has its own local variables what will be the offset I again have to set it back to 0. Because within this scope I am again generating variables which are starting with an offset of 0. But when I come back here now after this if I come back here and suppose I have a variable and l n plus 1 then its offset must be computed with respect to the offset of l n. So, I must keep track of this information of offset of each of the source and as we mentioned in the previous class that stack perhaps is the best data structure. What I can do is I can create now a stack on which I keep offset on the top and when I reach this particular scope which gives me a new symbol table I push now one more offset on top of whatever my stack was and say that this is now offset of scope p 1 which will be 0 here. I will keep on incrementing and when I come back then I will pop this value and I will have the offset of l n on top and then I can start processing from there. Now two kind of scenarios where I say that in this I must have all the declarations together and then all the procedure declarations. But there are some languages which say that I can have declarations and procedure declarations of internals. So, I am looking at general scenario where I can take care of both these situations. So, this first problem definition here what we are trying to do before I start getting into the implementation in the code. Yes, no, this problem definition here or not? Not sure. Why don't you ask questions if it is not clear. Yes, suppose we have two classes. We need to keep track of this inventory one of those classes in the file which has not yet been processed. But according to this scheme then once we go back to the previous offset the new offset that we had seen or is destroyed. So, first we have to define what is the language you have. When you say you have two classes what does that mean? So, normally if you look at object oriented languages also we are not dealing with object oriented languages here and we are assuming that I have only one class. What will happen here that you will have a class definition and then you will have another class definition. Either it will be nested or it will be disjoint. So, you have a situation where I have a class definition and something will start from here and this will finish and this will go on. There are two different. There are two different scopes right. But suppose I call. It is not a wait wait wait. I am not calling at this point of time right. I am only creating I am doing compilation I am not executing at this point of time. We have to manage it on time. Even if I am doing type checking. So, suppose there is a declaration. We are mixing several things. First we have time to build this table. So, type checking will start only once I have symbol table right. Here once we have completed a symbol table. I mean we have completed the scope of which we have built the So, I am only pushing information about offset on the stack, symbol table is separate, so I am saying that if I have a declaration sequence of declarations where I start with some scope and then suppose I have nesting it, so let me give you an example right away, let us take this program. So, what I have here is I am starting with a program sort here which is the main program then I have some variables which are local to sort, then within sort I have a nesting of procedure called read array which has its own local variable and I have as I told you that I have eliminated all the code information in this point of time I am not interested in that, within that I have a procedure exchange which takes two arguments i and j but has no local variable and then I have another procedure with sort which has two arguments and which also has its local variable and within this I have function r t j, now what I am trying to do at this point of time is I am only trying to create a symbol table such that at the top I have a symbol table corresponding to sort which has variables a and x and which also has variables read array, exchange and fit sort but these three variables point to symbol tables, three different symbol tables and then from these symbol tables I also have a pointer which is pointing that to the sort right, so I am keeping all the symbol tables I am not throwing anything what I am trying to remember here is that when I say that a is the first variable I encounter and therefore I have to look at certain space for this, this is going to be at an offset of 0 because that is the first variable and then I will compute how many bytes this is going to take, so if I say that this is going to take, integer takes 4 bytes and this is of size n, this is going to take 4 n bytes and therefore x integer must be at an offset of 4 n, now that is the information I will remember and as soon as I encounter this function I will say now this 4 n plus whatever was this integer, so 4 n plus 4 gets pushed on the stack and then offset for I becomes 0 once again, so I am not throwing any information all this is going to be part of the symbol table, so now this one to revise your question or this your doubt is clear, clear, so this is the kind of program we have now, so let us see that how do I create a symbol table, so for this program I want to create a symbol table which is of this form, this is what I want to create, so this is my output and what I showed you the program as input, so now I want to write code which is syntax directed definition which will make sure that when I process that program by outcome in a single table like this, that is the problem definition, so is problem definition clear, so if problem definition is clear we want to now find out how to solve this problem, so the way we will solve this is that if I do not have Nascate Scopes and I have only one scope then we already looked at it saying that I will start with an offset of 0 and whenever I have a declaration I will enter this information in the symbol table which will say that I have an identifier of certain type with an offset right and then for rest of the variables how do I modify this, I will say that offset is assigned offset plus whatever is the width of this particular type and then for rest of the type declarations I just say what is my type and what is my width, now if you recall type information I already had, so when I was doing all the type checking this information was already being used, only additional thing that has come now is the width here and some information about the offset and this line which says offset has to be recomputed every time you enter some information in the symbol table, there is only additional thing that has happened so far, rest of the information we have already processed here, so what we do now is we keep track of local information and what we assume now is that our program consists of declarations as I said at this point of time I do not even care about the code and out of my declarations look, declaration can be a sequence of declarations, it can be declaration of a local variable or it can be declaration of a procedure or function and what is the declaration of a procedure and function, there is an ID for each procedure and function, it has its own local declarations and it has a set of statements, again I will not tell you any information about set of statements I will not even worry about it, I will just ignore it for the time but now you can see that I have recursive definition here, that means I can have another procedure being declared inside this procedure and I need to keep track of all these codes and therefore, whenever I encounter a procedure declaration like this I need to create a new symbol table, because if I do not create a symbol table I will keep anchoring it in the same symbol table, so now things you must remember is that I need to create symbol tables, this is one thing I need to do, what are the other things I need to do for nested codes, I need to recompute offset for each of the scopes, I also need to remember the scope of the offset of the previous scope, anything else I need to do, need to do not move, so you also need to remember when I say create a symbol table and I have this declaration, so let us say I have a declaration like this, it says DIT, do I now need to say in which symbol table this information should be entered, because now I have multiple symbol tables, so I need to give this information saying that enter this particular name of this type, this offset in symbol table and how do I remember symbol table with symbol table, so I just need to have a pointer, so when I say create a symbol table, if I have a pointer to the symbol table all I can say is push this information in this particular symbol table, so that means when I say create a symbol table that means remember the pointer to the symbol table and if I need to remember the pointer for the symbol table, I also need to remember the pointer to the pk symbol table, because when this scope finishes for example, when this scope finishes and I say that the local variables of p1 must be entered in this symbol table, but variable ln plus 1 must be entered in the symbol table here, that means you also need to remember the pointer to the pk symbol table. Now you can immediately see that when I am talking about creating a symbol table having a pointer, remembering the old pointer, recomputing the offset and remembering the offset, I can just have two stacks on one, I will keep the pointer to the current symbol table and on one I will keep the offset to the current variable in that particular scope and whenever this symbol table finishes that means this particular scope finishes and I come back, I just need to pop this pointer and I need to then remove the offset and continue processing from there, this is exactly what I am going to do. So now we will say that when I have this listed scope, we will say that entry for d1 are created in the new symbol table and the name is represented id which is local to the enclosing procedure. So this id which is name of this procedure is a local variable to this program, but these declarations are going to be inside id which is in this symbol table, I still see lot of blank faces, something is not there, something is telling me wrong. So I need to remember the pointer to the symbol table, I need to remember the offset in that particular symbol table, that is the only thing, you want to push it in one stack with two entries like the stack of these structures which is fine, I mean how does it matter, information is the same right. So let us go through the code and if you still have doubts then we will come back. So this is the code, this is what we want to create. So let us see how do we create symbol table, so I have a function which says create a table and this also gives me pointer to the previous table, that means if I am now creating a table for this, it returns just a pointer. So create a new symbol table and return a pointer to the new table and this one I will remember and argument previous points to the enclosing procedure. So what I am saying is now, so when I say that I want to create a symbol table for p1, I will say pass to this function which says create this table pointer to this particular symbol table, so that when I put this pointer back, I will remember that one field of this symbol table will have to point to this particular symbol table. So this is what I need to do, so now I say that my enter function is going to be, I will say name type offset but I will also say that enter in particular symbol table. So additional information that has come is now symbol table, so this says create a new entry and then I will also say that and width which says table width, so what I am keeping here is, so if you recall one of the fields I had at the top, one was going a pointer to the parent nodes but I left this field undefined and this really keeps the cumulative width of all the symbols in the scope. So for example if for some particular scope I have to keep this, so this information I also want to keep ready with me, so this gives me the cumulative width of all the entries in the symbol table, not of the enclosing functions but only the local variables there and that information becomes useful when I start designing my functions. So let's see in presence of these functions how will I do that and I have one more function which says now enter procedure name, so this says that within this table enter a name and a pointer to the new symbol table. So when I say that in this function either I am going to add a variable or I am going to add a variable of type function and say that this must have a pointer to the new symbol table, these are the four functions I need. So let's quickly go over the board and then see how it helps me and we are able to understand this. So when I start now processing my program first thing I say is create a symbol table with nil as a pointer it has no parent and it is returning a pointer p to me. So this is saying that the symbol table I am creating for the current scope does not have a parent node and the pointer to the symbol table is nil and then I say that I now have a stack in which I remember which is my current symbol table. So table pointer is a stack in which I am going to keep this information which says that p is the current pointer. So basically what will happen is something like this that if I now encounter my same program and I first say that the sort is the program at the top level what will happen that I will say create a symbol table for sort. So this gives me a pointer and then I have this stack which is table pointer and this has this entry corresponding to sort. So basically this is nothing but an entry in it. This is what I have done by this function that I created a symbol table and then I have pushed this into the table pointer. And then what do I do? Now I say push 0 on the offset. So I have another stack in which I keep information about the offset and I push 0 here. So earlier offset was a global variable and now offset is just going on the stack. And then after this initialization what do I do? I have processed all the declarations corresponding to local declarations corresponding to this particular scope and after I have finished this what do I say? That I am going to add width of all these declarations into the symbol table which is 0.2 by top and whatever is on the top of offset. So what happens is that as I keep entering variables in this this offset will keep changing. And whatever is this final value, suppose I had 5 variables in that. So I had a variable which was array and I had local variable which was integer so together that was giving me 44 bytes. And therefore at that point of time this offset must have become 44 and I am going to enter this information now 44. So basically this is saying that add width whatever is being pointed to by this particular entry and this is the value to be entered. That will happen after I have processed all the declarations and then I will say now pop this and when I pop this I have finished creating symbol table and I am going to pop the pointer, I am going to pop the offset and I will continue from there. So this is from the outermost scope but what happens to the inner scopes? So for inner scopes what happens is that I have a declaration which is of type procedure. So now suppose within sort program I have redirect. Now when I encounter redirect what will I do? When I say proc id what are the action I need to take? I need to create a symbol table so I need to create a symbol table and push the pointer here. So I will now create a symbol table which is corresponding to redirect and this entry will be pointing to the symbol table of redirect. And then once I have done this I will now say that I am going to push this T on the table pointer and I am going to push 0 on the offset. So I am going to push 0 here. And after that what will happen? I will look at the local declarations. So D1 are all the local declarations of this procedure but once I have finished processing this what will I say that? Now T is again this variable will be copied into variable T. So I will again say that T now is a pointer which is pointing to this symbol table. And then I will say that at which T and whatever is the offset. So whatever was the offset of the local variables of this particular scope that will get entered here. And then I will say that now both offset and table pointer. So that means I am going to pop this and I am going to pop this. That means this particular pointer will be lost. But I still need to remember pointer to this symbol table. So what will I do? Now I need to make an entry in this symbol table where T will be copied. So this is what I do next. I say that now enter a procedure entry into whatever is pointed to by top of the table pointer. Now this top of table pointer is pointing to sort. So now I will say that in this symbol table make an entry which says that whatever is id name and what is the id name here procedure id. So this is name of the procedure and what is the second point? Second point says that T. So T is now this particular pointer so it will start pointing to this. So only additional thing that has happened is that now I can look at not just one scope but I can look at multiple scopes. Multiple scopes by using these two steps. So now suppose I have more variables in sort. What will happen? I will have this pointer and I will have this offset at the top and I can keep on adding more and more variables to sort. So if next variable is of type procedure then I will create a symbol table if next variable is not of type procedure then I will enter it here and then I will keep on changing my offset. Make sense? So this is what happens here. Now what about this? When I say that I have now encountered a variable of type T. What is the function call I am going to make now? Now I need to remember that corresponding to this id this is the type information and where is the offset? Offset is in this stack and with symbol table I make an entry into whatever is the top. So then what will happen? Now I say enter into the symbol table which is 0.52 by the stack this id name this type and whatever is the offset of top of the stack. So instead of global variable now I have put the same global variable on stack and corresponding to each of the scopes I have a global variable and a pointer to that symbol table. That is the only additional thing I need to do to create symbol table for nested scopes. Now this is making sense everything is falling in place. So these are the only things and then obviously once I have finished this I also need to now change my width. So earlier it was offset being assigned offset plus T width. I will say offset is in the stack and therefore top of offset is being assigned top of offset plus T. And that is top of the information is going to be exactly same. So yes, any questions on this? On how to create now nested symbol tables? So I have taken care of both kind of languages where you can have local variables and functions and procedure definitions intermushed or you only have local variables followed by procedures both will work in this case. In the second case you will find that you will only keep on talking that is what is known as tail reversion. At the end there will be nothing left. Everything will just keep on talking any questions on this? Tail recursion normally is when your recursion happens in the last statement. That is also standard definition of tail recursion. So after recursion when the control returns in the parent scope you only keep on returning. You do not execute anything. So what I am going to do now is I am going to stop here today and quickly return your with some answer scripts and we will also discuss briefly tell you the grading scheme and the solutions.