 Good Monday everyone, we had a relaxing weekend, maybe? The giant one? Wow, weird. Not that weird that they won, weird that we had a giant today in the audience, I guess. Cargill's almost won, cool, some things we don't talk about, okay, I understand. I'm a 49er fan, so, I feel good. Alright, cool, so before we get started, today we're going to talk about calculating first sets, and I think we're going to be able to get into calculating follow sets, which as you all know because you reviewed Project 3's description, this is Core 2 Project 3. And to further motivate you into how important Project 3 is and to start early, these are the scores from last semester of everybody's Project 3. So you can see there's actually a good amount of people who did, got over 100%, there's a little bit of extra credit if you're really grading there carefully. But you can see how quickly it goes down. It keeps going. The line's just a page on the note. The line doesn't mean anything. It goes, I don't want this to be you. This is why I want you to start now. So you're going to be all good, you're going to start early, you're going to come to office hours, you're going to come to undergrad TA hours, you're going to come to recitation sections, and you're going to destroy this project in a good way. Some other statistics, so if you want to see it in a, so here's kind of the distribution, it's kind of just kind of weird, right, these are just all grades plotted highest to lowest, kind of on scatterplot in here. Which end do you want to be in? The left? The left end. Yeah. Alright, to further break it down, I got some stats. The average is 53.9%. And so you think, well there's a ton of zeros here, right? And actually some of those people who drew from the class or weren't involved or whatever. And so even taking out those zeros, the average is still 67.39%. And I dug down some more, and I figured out based on people's final grades, what was the average of what they got. So people who got an A minus or higher, the average is 101%, which makes sense, right? You get 105% of this project, it's a lot easier to get A in the class. The B's were the average was 70%, the C's the average was 38%, and the not passing grades were 14%. So this is also why this sets you up very good for the rest of the semester. It's a good gradient project, 3 makes it a lot easier to pass the class and do really well. So questions on this and the importance of project 3? I won't take individual like project 3 description questions, that's going to happen in recitation sections, yeah. Did you get A pluses? Yes, but you have to score very high. I think 5 students got it last semester out of 126 or something like that. So yeah, I think it's on the website, right, on the syllabus. It's like over 97%. It's hard to get. Any other questions? I saw there was like another hand over there. Some people, yes. It's a variety of reasons, some people definitely ran out of time. There's people who came to me and talked to me and said that they ran out of time on project 3 and that's why they did so poorly on it. So that's definitely part of it. Another thing is people, you have to kind of fight that feeling of not getting help. So starting early helps because you get stuck and then you go get help. Getting unstuck and then you keep going. So that's why I encourage people to come to office hours and do all that stuff because it can definitely help you if we can help get you on the right track if you're getting on the wrong track. But if you just like sit in your room or in the lab or whatever working on it and don't get any help from anyone just they're stuck for days at a time and you have a tough time. Something I've been wondering about is we are able to get it all up and running and then we submit it and then we get some immediate feedback from the system. Yes. But I'm assuming our grade is also based on the actual source that we submitted. If somebody's going to be going through it and we're going to make sure that we people have our own link list, things like that. For project 2, yes. We're going to be looking at your code. It's only going to adjust your grade very slightly, but we want to give you feedback on what you're doing well or not well. But for projects, for the rest of the projects, we're really treating this kind of as an input output project. So I don't care how you implement it from here on out. Basically, projects 1 and 2 are to get you developing the skills that you need to be successful on projects 3, 4, and 5. And that's why we do things like making link lists with straps because in project 5 you have to do that a lot or to find bugs in projects which I know these bugs in these projects and they're happening in 3, 4, and 5. Or doing code coverage. Learning how to debug code, all those kinds of things will help you. So that's why from here on out it's going to be, there's a long specification. You have to understand and interpret that specification. The specification has very specific input-output requirements. And so if you satisfy those, you're all good. If you don't, you don't get great. If you give me a thousand lines of code that don't work and don't pass any test cases and don't compile, it's still a zero. I don't know, it's actually hard to tell because people find out that this project day was draw. So by the time you project 5 comes around, some of the people are gone that didn't do well on projects 3 or 4, who may not do well on project 5. But there are still people who, I looked it up, some people passed with a zero on project 3, so it's definitely possible depending on how you do any other ones. Anecdotally from students, I've heard some people think project 3 is the hardest, some people think project 5 is the hardest. I don't kind of depend on the person, I think. So the good news is this isn't just to scare you, right? The good news is this chunk of the top, right? It's possible and you can do it. I'm not going to curb it or anything. It comes out that all of you get in 105, besides looking for accurate integrity violations, I'll be super stoked. I don't want to give out any zeros, all right? I don't want you to get a zero, but, you know, we got a set standard exam. It's probably in the document, but it'll be the same automated system like all of our code instance feedback on this project. It's already up there now, so. Everything's good for you to go. Anything else, briefly? We've got to get to the stuff if you're able to do those projects. Okay, all right. So last week, on Friday, we started out basically developing our own intuition of first sets. So what are first sets? So from an input-output functional standpoint, what was the first set? What was the input? Yeah. Tell us the terminal or terminals, the context-free grammar. Yes. More specifically, what's the input to a first set? What kind of sentence? A sequence of terminal and non-terminal. Yes. A sequence of terminal and non-terminal, right? Exactly. So like this alpha represents a sequence of terminals and non-terminal. And then so what's that with? A set of... Close it around. Terminals. It can't have any non-terminals, right? Because you can't have a string to start with a non-terminal, right? Because every non-terminal's going to be broken down eventually into targets. So it's going to be set in terminals and what? Possibly up to one. And possibly up to one. Exactly, cool. So we have a function. We're taking in a list, a sequence of terminals and non-terminals, and it's going to output either... It's going to output a set containing terminals or non-terminals in the set, I guess. Could it ever be empty? I don't know. Maybe. It's interesting. Okay. Alright, so we saw and watched. So the very first part of this process, right? This calculation is we start out with empty first sets for all non-terminals in the grammar. So why do we do this? I would already use on a half, but yes. It depends on the way how you're using half. If you mean like a cool half, then yes. It's just a way of starting an algorithm, right? So we start with knowing nothing. Right? We know nothing. So that this way we don't have to worry about the first set of this, the first set of this, the first set of this. No. We'll just start with the first set of all non-terminals in the grammar is the empty set. So we start with that and then we go through... In this case, we care about the non-terminals. So we're going to apply these following five rules that we derived on Friday and we're going to apply them for every non-terminal in the grammar and we're going to do this until the first sets don't change. So what was... Somebody give me a rule. It could be the first rule or not. Think of the base cases. So what are the base cases of these calculated first sets? So wait. Oh, so terminal. So yeah, so what's the first set of a terminal? Yeah, the set containing that terminal. Exactly. So this should be the first rule. So the first set of X, if X is a terminal, is the set containing X. Right? First rule. It makes sense. Terminal, it stops. Cool. What about the other case? So what's the other base case condition? Epsilon. Epsilon. Yeah. So if we have the rule... So what's that? All right. So the first of epsilon is the set containing epsilon. Right? Then we have our three rules. So these are... When you think of it as a... You know, these are the base cases here. They're going to be a terminal or an epsilon. And then we have to say, okay, how do we pull apart this alpha? Alpha's going to be a sequence of terminals and non-terminals. So we have... So this is slightly different from the way we looked at it before, but it's basically the same. So we have... If we have a production rule, A produces B alpha. Right? So alpha here, sequence of terminals, non-terminals. If it's a production rule, we're going to add the first of B minus epsilon to first of A. Right? So what does this say kind of in English if you were to translate this? We don't. So what this says is we add the first of B. So we take the first symbol on the left hand... on the right hand side. So the left-most symbol on the right hand side, calculate its first set, subtract epsilon, and then add that to the first of A. This one? Yes. Yeah. So we don't even worry about that in this case. You just say for everything, right? For every rule that's in this form, we always do this. We add the first of B to the first... the first of B minus epsilon to the first of A. So then do we care if there's an epsilon in first of B? First of B. Yeah, but that's the nice rule. Let's go on to worry about that. Just for this rule. So you're talking about... For this rule, do we care if there's an epsilon in the first of B? No. So this one, we don't care. We just know we always have to take out epsilon, right? If it's there, we're doing set difference here. And so we add that and we're talking about set, so we add it to a set, right? It's going to add it to the first of A. Cool. Now we have to deal with the case of what if there is an epsilon in the first of B? All right. So it's going to look complicated. But it's not... Well, once we pull it apart I'm just doing this to forget. So we know intuitively, right? So what do we know? So if there's an epsilon in the first of B, then what do we do? Right. We add the first of alpha to first of A. Right? So this is just saying, okay, let's pick apart alpha and let's say alpha is composed of B's from index zero to I and then from I to K. Right? So all this means is let's say there's epsilon in the first of B zero, B1, B2, all the way up to B I. Right? So the I's represent epsilons. They're going to be epsilon in all those first sets. Then we add the next one first of B I plus one minus epsilon to the first of A. So add the next one. Right? So we have B zero through B I because epsilon in all those first sets then we add first of B I plus one minus epsilon. So what does this say about B I plus one, the first set of B I plus one? So that's the important thing to note about the way we write this rule. All we're saying that must have epsilon in it is B zero through B I. We're not saying anything about what comes after it. What we're saying is we take the first set of whatever comes after it minus epsilon from it and add it to the first of A. But we don't have to worry about B I plus one. And so, if you think about it in this case, let's assume there is epsilon in B zero through I. Does this apply with, let's say, I is equal to one or I, let's say I equals zero. So if I is equal to zero, is there an epsilon in first of B zero? Assuming this is true? Yes. It has to be. So then what should we add to the first of A? The first of B one minus epsilon to the first of A. And then we would say, is epsilon in the first of B zero and the first of B one? In this case, yes. Then add the first of B two minus epsilon to the first of A. So you see how this definition essentially allows us to iterate over all of the elements of alpha from zero all the way to the end and says this applies for all, if there's epsilon in the first of that symbol, you can move on to the next one. Yeah. Exactly. Yeah. As soon as this is false, where we get to some D in between i and k, let's say j, to some j that does not have an epsilon in its first set, then we don't go any further because this condition no longer holds and it doesn't hold. You don't have an epsilon in the first one. None of this applies. So the fifth case, so when we developed our intuition, what is the fifth case to take care of? They all have epsilon. Yeah. What happens if every single token here, terminal, non-term, well, it won't be a terminal in this case, but every single non-term all has epsilon in its first set, then we add epsilon to first of A. So if throughout all the symbols, so when you think about this programmatically, right, what you're doing is you're saying the third rule says you always take the first symbol here, whatever it is, add the first of that to the first of A. The first of that minus epsilon to the first of A. And then you say, is there an epsilon in that B zero's first set? If there is, then add the next ones minus epsilon to the first of A. And then check that. Is there an epsilon there? If it is, add the next one. And you go through and if you went through every single symbol on the right-hand side, there is epsilon in all those first sets. The fifth rule applies and you add epsilon back. Questions on the formalism, the formal rules, and the linkage to the intuition we talked about on Friday? They're pretty clean. They're basically exactly the same. This is just more formally defined. And a little bit more exact. Example time? Example. Walked on an example of calculating first sets. So we have a grammar. S goes to A, B, C, D. A goes to C, D, or little A, big A. B goes to little B. C goes to little C, big C, or epsilon. D goes to little D, big B, or epsilon. So we're going to do, just like we did when we were calculating these by hand, I mean, we're still going to calculate these by hand, but even with the rules, we're going to basically make a table and say, oh, that's weird. We're not going to say that at the start. We're going to first initialize the first sets of all non-terminals in the grammar to the empty set. S, A, B, C, D. That's how we start. This is exactly how your program should start. You don't have to do it now because we're talking about how to calculate this. So calculating this by hand is critical. You can't write a program to do this if you don't know how to do it yourself. Seems an obvious statement, but that's important. But later on, when you come back to this and you're thinking about how to program this, you should think about what things do I need to implement this in my program based on this mathematical algorithm. I must have some ways to distinguish between terminals and non-terminals. I have some ways to represent epsilon. I need to represent things as sets. So I need to have a set class and know how to do set operations. I need to have a set difference operation to subtract out epsilon. I need to be able to add one set to another set. You can use whatever you want as long as it's not anybody else's code. I mean, in here's code or in previous years. So all the CS330 or 340s you can stretch it back in time. Yeah, you're free to use whatever you have to get to compile and run on that operating system. But yeah, you can, whatever's built into the C++ standard library you're welcome to use. You can use third-party libraries if you want to include them in your code. All that stuff's good to go. It's difficult enough as is without writing. I mean, you can do this, I mean, well, people do it in C without sets. You can do some basic set operations yourself in C you just have to do a little more work. Anyway. Okay. So we go through and then we say we're calculating first of S. So which rule applies? Is S a terminal? It's a terminal? It's a terminal. Oh. So the rule one doesn't apply. Is it epsilon? No. Rule two doesn't apply. Are there any rules with S on the left-hand side where S goes to something? One. Yeah. Just the one. Perfect. So then we have rule three which says that if we have this production rule, so the other way to look at this is when you're calculating the first of S, you go through the rules where S is on the left-hand side. Right? That's what you're looking for and only looking at those rules. We don't care for calculating first of S. We don't care about any of this, anything else. We only look at the rules where S is on the left-hand side. Okay. So then we take the... So what's the left-most symbol on the right-hand side of this rule? A. A. So what's the first A? Empty set. Empty set. Perfect. Empty set minus epsilon is the empty set. And we add that to the first of S which is the empty set. Yay. No progress made. Then we look at A. So we want to calculate first of A. So we know A is not on the terminal, not epsilon. So in rule three, you want to check that applies. So if A goes to B, alpha, then we add the first of the left-most symbol on the right-hand side. So what do we have to pick first? Is alpha, in this case, CD bar little a big A? No, right? The important thing to remember is that bar is just shorthand for two rules. A goes to CD and A goes to little a big A. Okay. So we first, well, so we first add, okay, let's see. We first add the first set of C which is empty set to the minus epsilon to the first of A which doesn't change it. And then we look at the next rule. And then we would also say is epsilon in the first set of C? No, so we don't move on. Then we look at the next rule and say, okay, we take the first of this left-most symbol. The left-most symbol is little a, so it is the first of the second-taining A. So the first of A right now is the second-taining A. First of B, what's it gonna be? Second-taining B. Second-taining little B, yeah, cool. All right, first of C. So it'll be by rule three. It'll be C, right? We have this little C and then by rule two with the other rule it'll be epsilon, right? So we'll have C epsilon here and what about for D? Yeah, D epsilon, the same thing. Cool. Are we done? We go home? Is that because there's three more columns to do? That knows. It does help. There won't be that on any midterms or anything. So, yeah. But we know, we can see we've made a change, right? Cool. But then I'm gonna tell you I would be really mean and give you a super large chart just to mess with me. It's actually not that hard to grade these because you're just having curly braces with an arrow and it's easy to see when you mess up. I mean, if. First of S now so we go again through our rules. So we say rule three implies so we add the first of A which is second-taining A and then there's no epsilon in the first of A so we say stop we don't move on anymore. So now we do first of A so now we look at this rule and we say, okay first of C minus epsilon add that to first of A so now first of A we'll have C little C and then do we get to move on? So now rule four applies because there's an epsilon in the first of C so now we add the first of D minus epsilon to the first of A which is gonna be little D so now we have little A or little C little D and then do we add the next thing after D does rule four apply again? There is nothing after so it doesn't make sense to talk about adding the next thing afterwards so there is no I plus one here we've reached the end but then we have rule five and so do all the symbols in the right-hand side of this rule have epsilon in the first set yes epsilon epsilon so then we have the first of A and then we would go and check this other rule and add the first of little A to the first of big A so we have C D epsilon little A which I guess all the rules are here A C D epsilon and you can actually do this whichever way you want you can start with because you're only ever adding information here so you can start with the second tiny A and then add C D epsilon and then add A back in or you can even start with the empty set and this could be a good self-check that you better have what you had before in it in the next step otherwise you can calculate something wrong first of B is going to remain the same first of C is also going to remain the same first of D is going to remain the same are we done? no so you see it's kind of cool that the information is kind of propagating throughout all of these first sets based on the rules and their relationships and how they appear in the grammar right so like before well we got to C we got to A we didn't know anything about C and D so we didn't get that much information but now that we know more about C and D we can understand that oh actually the first of A can be a lot of things A, C, D and epsilon and as probably as you can see here this is going to impact S and change what we do with S okay so first of S we do rule number three and we say we add the first of A minus epsilon and then do we go on does rule four apply yes so what what's first set do I add B so there is an epsilon in the first of A so I add the first of B minus epsilon to S so this is going to be B and then do I apply rule four again and add the first of C no no there's no epsilon there and this makes sense based on the grammar right so A can go to C, D and both of those can go to nothing so there is a chance that A that this A basically disappears and doesn't produce anything in the resulting string but this capital B will always produce this lowercase B right so strings that S generate have to at least start with either an A, C, D or B we do first of A again we'll see that it's the same we'll do first of B C and D are we done we got more information about first of S right so we run through it again and we'll see that they don't change and then we say are we done yes we are done this is the first set of every grammar questions on this so there's two really cool things that I like about this A I mean we practice it by hand but it's mechanical right and you're just applying an algorithm doing a process and this is why you can write a program that can do this exact same thing so it doesn't matter how this grammar looks like or what this grammar does you can still calculate first sets for every non-terminal grammar yeah does it always top down say that again is it always going to be like top down so we have to work out first as first as an A which term which non-terminal you start with yeah doesn't matter yeah it would converge quicker right where we get to this point where we're not adding any more information in this specific case it will work so that's why it doesn't work it really doesn't matter I just like always starting in kind of in order that the non-terminals are hitting it's a little bit easier to read and understand test questions where going the wrong way may take maybe take longer cool I have questions on first sets sweet okay so why are we trying to calculate the first sets in the first place project three why are we doing first sets for project three for project three for class all true things is yeah going back we wanted to be able to see whatever that is the whole reason why we wanted to talk about these is so that when we're in this situation S goes to A or B and we have A goes to A or C and B goes to little B big B or epsilon or something, right? So why do we want this? Yeah, we need to decide which rule. So what do we use? So now we have the first set. So we have the first set of, let's see, S, A, and B. And A is going to be AC, B is going to be the epsilon, and so S will be ACB epsilon. So why can we always tell in this specific example, why can I always choose if I read one token or one terminal, why can I choose if I'm parsing an A or parsing a B? So can you choose? Let's go with that. So let's say, go back to how we were writing the parse S method, right? I go to T side, get token. So now when I check, how do I go? I should call parse A. If it's in the first of A, yeah, or one, or C, right? Because we have A goes to A or C. So if T side, I'm going to make really terrible syntax, is A or C. I'll just write a language so that I can do this, right? And I do this, so I know basically this is the rule S goes to A, produce this output, and what else am I checking, was it, B? Yeah, if B, so let's say there was, let's say I changed this grammar to be like this, and this was the first S. Now, can I tell by looking at one character? No. So then how do I use the first set to create a rule that says if I know the first set's long non-term of the grammar, I can say that I can always distinguish between these rules. So what is it about the first sets of A and B? Yeah, there's no element in common of their first sets, right? So something like, I'm going to get rid of all this, I don't actually need this right now. And why is there a reason for this? So they say if I have a rule S goes to alpha and S goes to beta. So if the first of alpha intersects with the first of beta, it should be Y. It's equal to the empty set, yeah, exactly. This means that if I take the elements in common to both sets, there should be none. No elements in common. This way I can actually tell which one should go. Does that make sense? We're going to come back to this later, but remember we just invented this. Is it like if the intersection is 05, then we can't parse it? Correct. Well, we can't parse it efficiently, right? We can always do the incredibly brute force way of parsing it and try every possible combination. So yeah, we can try parsing it with A and then try parsing it with B if that failed and then say either it could be parsed or it could not be parsed. To parse it efficiently by only looking at one token in advance, which is where we're going with all of this. So it's predicting the recursive descent parsers, but we'll get to that in a bit. But I want to build up a little bit before we're talking about follow sets. I mean, it's talking about why we need follow sets. And so this is kind of where we're leaving here. Can we look at one or more next terminals and decide? Say that again. Currently we are only one. Correct. Maybe then we can decide with production to use. I think in general, yes. But then calculating second is a lot more difficult than just calculating first. So right now we're just focusing on specific types of grammars that we can easily distinguish based on one token. But yeah, there's infinite types of grammars. So you have these grammars where you can look two tokens or three tokens or four tokens. But we're trying to avoid that. General compilers have only one look ahead. Say it again. Normal compilers like C or whatever. They have only one look ahead and they have multiple look ahead. It depends on the specific language. I will actually see an example that's taken from real parsing. So I'll share that with you in a second. Good question though. I'll bring my C-book. Does anybody have that C-book that I recommended? You got it? Okay, maybe later. But in the background of the book it has the whole context free grammar of the C language. So everything that you need in there. I don't know whether it's this way or not. It's interesting. Probably. I have a question about the finger we just did earlier. First set? The table. Sure. For example, say B actually was like B and epsilon. Would S end in epsilon? Because we already have C and B. Like we won't point to the next C or maybe we already have it. Or would it actually store C and then B again? You would do it again. So if there was B or epsilon here, you would add the first of A minus epsilon to the first of S. And you'd say, is there an epsilon first of A? Yes. So you add the first of B minus epsilon to the first of S. And then you'd say, is there an epsilon first of B? Yes. Then you'd say, then add the first of C minus epsilon to the first of S. Is there an epsilon on the first of C? Yes. Then add the first of D minus epsilon to the first of S. Yes. And then you'd say, is there an epsilon on all these symbols? Yes. Then finally add epsilon. I think it would be the same but with epsilon. They'll just say ACDG and then epsilon? Yeah. So the epsilon won't point like at the C after that again because it just stops there since we already had a C and D already in the thing. No, no, it doesn't stop anywhere. So it only, the fact that A can go to C, D basically means that C and D's first sets are already in the first of A, which means we add them to first of S. So really we're not adding any additional information by doing this, but in general, you don't know that for a certain, so you should just do it every time. And because that information's already there, you're not changing the first of S. Right, so you're just adding it's set, it's set union and set it, right? So you're adding it to this set, you can't have more elements of a certain thing in a set, so. Or B, okay, let's use this as an example for this right as well. S, A, and B. Okay, so first of A, B, B, epsilon. Oh, this still doesn't show exactly what I want to show. Okay, so by our first rule, right, so our rule here, so there's S goes to A or S goes to B, so is there any intersection between these first sets? Okay, let's think. So if I have an A, I have S goes to A here. So do I actually know that this A came from here? So parts S, I can parse S, S goes to A, little bit to B, little A. So can I tell? So if I get an A, get token as an A, should it always be parts A? If B is a little B, say it again? It is a little B. Erase the little B? Oh, this definitely wouldn't, but then this changes the first set, right? The first set, so actually this is a good example. So I start out with all empty sets. All right, let's start with B, start from the bottom. Okay, so I apply rule three to this rule, and E goes to big B, little A. And so then I say add the first of B to the first of B. Our first of B minus epsilon to the first of B, what's the first set of B? Empty set, yeah, empty set, minus there's an empty set. Do I move on and add first of A? Not yet, because there is no epsilon first of A, the first of B, exactly, cool. Then I add here, so this is the epsilon. Then I add first of A. So by rule one, that's gonna give me first set containing A, and then S. So A is gonna give me A, and B is gonna give me epsilon. So let's think about exactly how this happens, right? So I have an A epsilon, right? Let's think about exactly how this happens, right? And it's important to think this way because this is the way the program should operate, right? So by rule three, we have the rule S goes to B. So by rule three, it should add the first of B, what? Minus epsilon, so the first of B minus epsilon to S. So the first set of B is the second containing epsilon, so we take out epsilon, it's the empty set. So we add the empty set to S, so where did this epsilon and S come from? Yeah, rule five, right? So we say, does rule four apply? There's nothing after it, so it can't apply. But then we say, okay, rule five. Is there epsilon in the first sets of all symbols here? Yes, there is, then we add epsilon to the first set of S. And this is an important distinction because when you're doing this mentally, it's clear that the first set of this S goes to B means we add epsilon to the first of S. It's important to understand how exactly that happens by precisely using our rules so that when you program it, you can make sure that this is happening in the same way. Cool, okay, we're on the down, we're starting at B. So now I add the first of B minus epsilon to the first of B. So the first of B is second containing epsilon, so we add the empty set, but then I say rule four. Does rule four apply? Yeah, so we add the next one, the first of the next thing to the first of B. So what's the first, the next thing after it? A, so we're gonna add A. And so we say, does rule four apply again? No, because there's no epsilon here and there's nothing after. Does rule five apply here? Is there epsilon in the first set of all the symbols of this right hand rule? No, yeah, we're just being thorough. Start going from the bottom up just because of the conversation we had earlier. Yep, just because. And so B goes to epsilon, adds epsilon. Yeah, there's no difference. You can start with whatever order you want. A is still gonna be A. S is going to be A, which is A, B, which is also A, and epsilon. So can we distinguish between S goes to A or B by those two rules, right? Because the first of A is A and the first of epsilon is A, epsilon, right? So this is, so we actually can't so this grammar will see as not predictive. Cool, all right, we'll stop here at this good side of the point. On Wednesday, the attack will follow sets.