 I started today now that you don't have to see a purple screen. Actually, on the way over here, I made a note on my phone to buy a new adapter when I get back. But I clearly didn't buy it yet. But luckily, plenty of you have this problem of meeting adapters because your stupid laptop doesn't have all the connected to you. Really fun. OK, any questions before we start on the homework or projects? Homework 1, project 2? No questions? So you want harder homeworks and harder projects? Easier. Easier? Well, you don't have any questions, which means that it must be going fine. And I had one person in office hours yesterday. Also means it's going fine, right? Yeah, office hours. Sure. Are you in office hours again after class right after today? No. Whenever it's on my schedule, the TA has office hours today. OK. So yeah, on the website, I think all five days a week we have office hours. If he has Monday, Wednesday, Friday, I have Tuesday, Thursday. So this is why you need to start early, right? Because if you have any problems after Friday, you're going to be on the homework. You're going to be kind of on your own until Saturday. I may, maybe your other students will help you out. Maybe I can help you out. But really, this is why you've got to start these things early so that that way we can answer all questions and help you out and make sure you're successful. Cool. All right, so this is where we left off, right? Oh, I thought I was going to do this wrong. So what? Oh, no. OK, let's try to recap and get us back to where we were. So what do we call these things that I've written here? Or some of the terminology here that we've been using. What is it? Production. Production, yeah, the production rules. Production rules of what? Tokens. Context free. Context free grammar. Yeah, exactly. A grammar, right? Specifically a context free grammar. What does context free mean? Doesn't have context. Yes, very good. How did you come to that conclusion? Genius? Popped into your head. Yes, very good. Yeah, so the idea is the difference between context free and not context free grammars, it has to do with the thing on the left. So the idea is if we, I don't know, if we maybe chose a different rule depending on where S was, if S was here or if S was here, something like that. So this would be where the rule we choose is dependent on the context that S appears in. So depending on the context, we would choose different rules. But talking about context free grammars, we're actually going to have to worry about that. Know that that's what it is. It is kind of weird to talk about something as being free of context without understanding what it means to have context, right? OK, so I want to find out a possible string that this can generate. So what do I do to try to create one of those strings? Pick a rule to start with. Yeah, so I start with E, right? So I start with the starting non-term, the starting non-term, which in this case is E. I choose a rule. So choose a rule between one and two. E times E. E times E, do you say times? It's a lot harder to write a time symbol than it is. That's why I was letting you get it out of the way early. Sweet. No, you just have to write it a single time now. Now what do we do? Now you apply choosing a rule to each of these on the other side. So choose an E, which E? Say, take this E. Let's first E, and let's go with E plus E. Plus times E, something like that. It makes it really bad today. It's because it's cold. I'll play it on that. OK, and let's choose another E. Let's choose the middle E. Let's take that to a number, let's say. We have E plus num times E. And then which one? Let's just make it all numbers. So we'll do it step by step. We'll do E plus num times num. And then we'll do num plus num. OK, simple enough. So what did we just do? What's this process called? Good guess. It's a good app description, I guess, of what's happening. It's Russian or something. Oh, it was the D word, it's something that D. Derivation, yeah, we're deriving, right? We're deriving a string that's in the language described by the context regrammer by starting with the starting non-term rule and simply applying one of these production rules over and over again until we end up with all terminal symbols here in our resulting string. All right, so one of the different types of derivations that we've talked about. Leftmost, rightmost. So is this a leftmost derivation? No, no. We started in the left, and then we went in the middle. This step here? So it's not a leftmost derivation? Is it a rightmost derivation? No, no, it's a derivation. Right, yeah. So this is just an example that a derivation doesn't have to be either leftmost or rightmost. They can be neither, yeah. In programming wonders, just do they choose one or the other, or does it flip flop? Or does it do both? That's a very good question. We're going to come back to that. So derivations, to me, are actually a little bit easier to understand for humans, right? So it's pretty easy to see exactly what things, what rules were chosen at each step. Programming languages, though, want to do the reverse, essentially. A programming language doesn't start with a non-terminal. It doesn't start with a starting non-terminal. The programming language, when we get in our compiler, gets in a sequence of tokens. So it's actually starting here at the string and trying to go backwards, in essence. But we need to know how to do this to understand how can we generate strings. So if I say, if we want to answer the question, hey, is num plus star num, does that exist in the language described by, let's say, that context for grammar g? Does it? No, it's not possible to derive that string applying the rule starting with a starting non-terminal and applying those rules. Yeah, so it definitely doesn't apply. But yeah, hold that thought. We'll come back to that. OK, because the idea is, right? We actually want, what we really want is we want to think about it in terms of parse trees. Because if we go back to what we talked about when we started all this, we said, OK, our lexer gets in bytes, right, bytes. And the lexer, using tokens, which are defined using regular expressions, is able to essentially group those random bytes into tokens. And then that sequence of tokens is fed into the parser, which then is going to create a parse tree from that. That's what we'll look at, a parse tree. Let's change our language a little bit. I'm kind of tired of that example. A goes to a B or a C. And B goes to a little B. All right, was it farming? Or so how do we read that rule? Big A equals A capital B or C. Yeah, so it's essentially two rules, right? So there's two rules there. A can either go to A can produce little A big A or A can produce little C, as little C. OK, so we can quickly do a fast derivation here, right? We can go S goes to, we only have one choice, right? Small A big A. And then we have, we can expand, let's just expand A to C. So we have A, C. And then we're done. That's a string that's in our grammar. OK, let's try to think about, how can we represent this derivation in a different way? How can we represent that in a different form? So let's think about, let's start at S, right? Let's think about a tree. So what are the important properties of a tree? Branches? Parents and children. Parents and children? So you have basically what? Nodes and edges, yeah, nodes and edges. You can't have any cycles that's going to go from the top down, right? You just have a root. So the root of our tree will make sense to think we're starting from the starting on terminal S. And then let's apply S goes to a little A big A. So what would my children of S be? Little A is 1. Yeah, why? Because little A is a terminal, and that's going to end the big A. It's going to end the big A. Yeah, so we're just applying this rule. Exactly, we're applying the S. And we say, S can be turned into a little A big A, right? And then we say, so are we done here? Is this a complete tree? Does it represent the string that this S could possibly generate? Why not? Because A can also be AB 4C. Exactly, right? Because we have a leaf. What does a leaf in a tree mean? Falls to the ground. Do you write poetry about it? It's the F. It's a last node. Has no children. Exactly, the node that has no children. But here, well, this A, we said S can be something. So we represent that something as its children. Here, A can be something. So let's do the same example. So let's choose the rule A goes to S. So what would the child of AB be? C, AB. C. Yeah, I said S, but you're correct. S. So can I expand this out? Can I expand this out? So then once I have this tree structure, that represents my derivation here, now what happens if I take all the leaves and concatenate them together in order? I get the string. Yeah, I get the string AC that's in the, that is the string that's generated by this grammar. I do it again. Let's see. So let's draw another tree. So do I have any choice here? No. So how many children is the S node going to have? Two. Little A. And write it like this? No. Why? Because A comes first. Technically, you can as long as you're consistent about it being backwards. I guess. It's like saying, yes, as long as I'm constantly wrong all the time, if you just take the opposite and not whatever I do, then I'm right all the time. Yes, theoretically, yes, you could if we were drawing trees like this. But it doesn't make sense intuitively, because at the end, we want to take all the leaves and go left to right as they appear in the tree and to be able to create that string. Unless you come from a culture that reads right to left. Which we do not. I mean, maybe you do. It's totally cool, obviously. But we, as a culture speaking English right now as the dominant language that I'm teaching you in, we're going to go left to right. That way, there's no question. I don't think you like this. All right, A goes to, so let's choose a different rule here, right? So how many children would I give A to? What's the left child? A. The right child? Big B. Big B. Am I done? Nope. Big B's can be not a term. So then what's the string here? A. Let's look at it with expressions. It's very quickly. And hopefully, this will show some of the benefits of, you know, I'm going to be, I'm just going to call this adopt, I think that's a lot better. And I'm also going to get rid of num because num is too many words, so I'll just do one. All right, we'll start at E. So how many children is E going to have if I choose rule 1? 3. 3? 3? Why 3? You're the tiebreaker. Because the plus is going to be 1? Right. The plus is a terminal in this language, right? It's a symbol in the language. So the left child is going to be an E, right? What's the middle child going to be? The plus. And the right child? Awesome. OK, let's expand this out by applying rule 2. So how many children is this E going to have? All right, do I expand this? Does this have any children? Nope. Why not? Because it's a plus sign. It's a terminal. A terminal. Yes, a terminal, exactly. OK, so think about a tree, right? Does the order that I add children on here make any difference to the final tree? Right, so when I'm done, so when do I know what I'm done first? When you have all leaves or terminals. When all leaves or terminals, yeah. So I know I'm done when all leaves or terminals. So then I can decide, OK, let's create this one. So what's this going to go to? Well, let's stop. So let's say this goes to 1. So how many children is it going to have? 1. 1 with the number 1. All right, let's just do this one and this one. So how many derivations can we do that results in the string here 1 times 1 plus 1? So this we can easily see, right? This is the resulting string. So the string that this represents is 1.1. How many derivations are there of that string? I can say at least two. At least two? Yeah, you could do a leftmost derivation or a rightmost derivation. I think we also showed that you can do it with neither, right? So there's probably at least three, maybe more. Probably a lot more depending on which way you switch. When you get to two E's at each point, you can choose one way to the left or one way to the right. Are there any other ways to write this tree? Our current context for grammar doesn't have a way of representing grouping. Like parentheses, brackets, curly braces. So there's not really an order of operation. Yes. OK, that's definitely true. We're going to hold that. We're going to get to that, I think, today. The key thing I want to point out here is that there are multiple derivations of the string. But there's only a few ways we can do. Like you can do a leftmost derivation and a rightmost derivation. And both of them are going to be the same tree. So if we start with this, we can say, OK, we start with E. Then we apply E plus E. And leftmost, which one am I going to apply? Put the E times E. Put it on the left. Yeah, so it'll be E dot E plus E. Thank you. Then we do leftmost, which would be that one. 1 times E plus E. I'm going to do this again. We'll do leftmost dot 1 plus E. I'm going to do this again. Finally, we get 1 plus dot 1 plus 1. And we can do the same thing with rightmost. And we'll end up with two different derivations, leftmost and rightmost, but one parse tree from that. Let's look at some more examples. Goes by a little quicker. So this is our example. So we have the expression. We have expression plus in here. I'm just using a different color for the terminal symbols. And we can expand this out, as we've seen, kind of in whatever way, just as long as at every place, just that every leaf in the tree is a terminal symbol. And then we know we're done. We've finished parsing. And obviously, as long as the parent-child relationships respect the rules, that was the other thing. OK, let's look at why we want to use a parse tree. So let's talk about that. Let's get into this idea of precedence. So if I ask you, if I say, OK, this is a mathematical equation. This tree represents the mathematical formula, some kind of mathematical operations. What would you compute? What makes sense to compute? Seven. Walk us through. What's the first thing you do? First character is two. Two? Second character is a multiplication sign. Multiplication sign. Third character is a three. And so I would compute those. OK, two times three, which is? Six. Sorry to put you on the spot. So if you're doing math right there, it's. And plus one, I have to do this in front of everyone, so it's really terrible. That's why I like you guys to do it. OK, so six plus one, what about if I wrote the tree like this? So the first thing, right, is this a parse tree? Yes. Each layer, we're applying one of the rules. All the leaf nodes are terminals, right? Verify, yes, terminal, terminal, terminal, terminal, terminal. Is it the same string? So what's the string of this that both of these trees represent? Two times three plus one. Yeah, the tree looks a lot different, though, right? So if you're going to compute this tree and use this tree to perform the operations, how would you do it? What kind of information is it essentially encoded in this tree? It's three plus one times two instead of two. Which would be eight instead of seven. Why three plus one first? Why are you doing three plus one first? Because that's just how the expressions break down. That follows the order of operation. What about the tree? What about the tree? Yeah, the closest one. I would say the closest one, the closest operator, the top. This one? Yes. So two times three. So look at this, right? We just looked at this sub-tree in isolation. Would you know how to compute that? If I looked at this expression in isolation, this sub-tree, would you know how to calculate that? Two. If you look at this sub-tree in isolation, would you know how to compute that? Two plus one, yeah. So then if I could look at this whole tree, how would you compute that using what we just said? Two plus two times four. Two times the result of three plus one. Yeah. Whereas this one is? The result of six plus one. Exactly. Two times three plus one. And see, it's encoded in the tree structure, right? Farther down here, each sub-tree represents a specific thing. This says, hey, this expression is a three plus of one. And this expression is the expression two times the expression three plus one. So just expanding on this. So in a partial tree, in a proper partial tree, like down the line, would the partial tree automatically adjust it or create itself in a way that it follows order of operations? Yes, we will get into that. There are lots of ways you can do that. That's not cool. Yes, it is. It's very cool. Yeah, the point is, well, actually we're going to see grammars in a second. We're talking about grammars in a bit. So for now, if I give you either of these trees, you can compute. So you can compute whatever expression is no matter how complicated or how far this thing goes down. So this is why the goal of the parser is to take in the string. So the parser doesn't get this. But the rest of the program sure would like a partial tree, because then it can perform some computation. It's structured. It's very clear what things are children of other things. All these issues of order of operations or whatever have already been dealt with so that everything else is simplified. So we can say, OK, if I know how to just evaluate an expression, then I can evaluate this tree of expressions. Because everyone is just, I know how to evaluate a sub-expression. Expression is either a single number or an expression is another expression added to another expression or an expression multiplied by another expression. So the goal of parsing, what we want to do with parsing is our input is this string. So what we know, we know 2 times 3 plus 1. We also know our grammar. Our goal is to create a tree from this input string of tokens. Does that make sense? Parsing, that's all we want to do here. And this is part of the reason why I really like talking about compilers from a software engineering perspective is all these problems are broken down in the distinct components that each do one thing. So the lexer just gets tokens from the bytes. But it's cool because it uses regular expressions and it uses all the regular expression and language theory stuff here. And here, when we're doing parsing, we take the input as a series of tokens and then we're going to create this tree out of them using the context-free grammar and all those types of things. So yeah, our goal, we want to get to that parse tree. And so parsing is essentially determining either the derivation, but really derivations are for us to think about trying to understand how these grammars work. Really, our end goal is we want a parse tree because as we've seen, we can compute something on it. We can compute. There's two major parsing problems. So one is the thing we've just seen. If the grammar that we just defined, if we have two times plus one, there's two possible parse trees that can be generated from that. Equally valid based on our context-free grammar. What else do we care about a lot of times with programs or parts of, this is something, your compiler, your interpreter, is something you use every single day. Every time you compile or if it's an interpreter, every time you interpret and execute your program, it's running and going through all these steps. So you want it to be super slow? Would you be super stoked if it took like a day to compile your code? Would you ever finish your projects? No. Or you'd learn how to be a much better programmer, I guess, or maybe you'd move into hardware because it talks to hardware people and that's what they say is the big problem, that you design this whole thing, you get to it and you're like, oh, it doesn't work. I'm gonna go back and change things. So we want it to be efficient. So these are the two problems and the two questions we're gonna ask ourselves to drive why does it work like this? How does it work like this? What kind of things can we pull from the grammar? Can we do some kind of cheats? Do we wanna accept every context-free grammar and be able to parse it? Are there some way we can window that down so that we're only thinking about efficient grammars, grammars that we're able to efficiently parse? Okay, so we looked at ambiguity, right? So this is pretty much the exact same example. So here's two derivations, each with different strings. So this is the definition of an ambiguous grammar. So an ambiguous grammar means that there are either two leftmost or two rightmost derivations or two parse trees, all those things are equivalent. So you can take a leftmost derivation, you can turn it into rightmost derivation, you can take either of those and turn them into a parse tree. So just like we looked at, right? Both of these trees represent that string, one plus two times three. When we're thinking about execution, right, and we're thinking about interpreting that tree, what is the tree on the left compute? Which is? It's three, nine. Nine? What about the tree on the right, somebody else? Close it? Seven. Seven? Two times three and then plus one. Two times three, six plus one, seven? Yeah, exactly, right? But because of the way our language is written, both of these parse trees are valid for that string, right? If you only have that string, trying to derive, you could derive either of these parse trees. Okay, so the formal definition, right, is if there exists two different leftmost derivations or two different rightmost derivations or two different parse trees for any string in the grammar. So is English ambiguous? Absolutely. Absolutely? How do you say absolutely? They are there and they are. Okay. So if you think about written English, right, that's, I don't remember the word for it, but it's when words sound the same. It would be ambiguous, verbally or auditorily. You got it right, homophone. Homophone, that's what it is, yeah, sweet. That's good. What about just grammar-wise? I mean, the sentences has some things that it's supposed to contain, subject to verb, but there's all these exceptions that's the problem. Rules and exceptions. Naturally. So is this, is this sentence ambiguous? Yes. Saw a man on a hill with a telescope. Seems pretty straightforward, right? What's this straightforward interpretation? You saw the telescope. Yeah, so like, I'm there. I'm off the hill. I saw a man on a hill with a telescope, with my telescope. I use my telescope to see the man on the hill. The question is, does the man have a telescope or does the hill have a telescope? Why is that a question? Because the helmets are placed. Right, so what are the other interpretations? Let's go through this. I like this exercise, it's a lot of fun. Yeah. I saw the man on a hill with a telescope. So you saw him, you saw him in half. That's the first one you went to. With the telescope. With the telescope. With the telescope. Break it in half to maybe get a little jagged edge so it can help you with your song endeavors. It's not in the sentence. It's not in the sentence. Yes, very true. What else, yeah. Could it be like you're on a hill looking at someone or you're looking at a man on a hill? Yeah, so like you could be on the hill. I saw a man while I was on the hill with the telescope. Right? What else? It's a fun game. Yeah. You could see the man on the hill and he has a telescope. Yeah, right, does that change the definition? Yes. Yeah, it changes the idea you're trying to convey. Just like if I were to tell the computer one plus two times three and it gave back nine instead of seven, that completely changes everything. Telescope. Maybe the hill has a telescope, maybe the hill. Is a telescope somehow or something, right? It's like a secret evil layer and it's like a little stove coming out of the hill. Are there anything else? We could go back to the, you know, and you can all do all kinds of combinations, right? You can go back to the actually sawing a person in half. Like you're sawing them in half and the man has a telescope. He's like holding on to it for your life. Or you saw him with the telescope. Right, yeah, or you saw him with the telescope. Yeah, exactly. Or you saw him with the saw on a hill that has a telescope. Yes, also that option as well. Or you saw him with the telescope. Yeah, he has a break in half or something. Don't anybody go out and saw anybody with the telescope, please. I feel like that's not the tool for the job. All right, we're gonna leave the dexter ideas for later. All right, so do we want this in a programming language? No. Why not? Because for that exact reason you never know what you're actually trying to convey to the computer. Right, yeah, this is why natural language processing is so difficult and it's such, we're just now kind of making strides in that direction, but does stupid Siri understand me all the time? No, or Cortana, whatever the thing is, right? Like it frequently misunderstands you or gets, and that's audio, right? But even text parsing, that kind of stuff, right? But, you know, we're not talking about that. We're talking about programming. So why don't you want that in your programming language? What's so special about programming? We do it, right? We're humans. I think society's kind of functioned fairly well with us speaking this ambiguous language. Like unfortunately a computer isn't as versatile as like, you know, we understand what you do. Yeah, so part of what I can do, right, what we can do, right, when I make like a joke about dexter or something, right, I'm using our shared cultural knowledge, and I'm assuming that you'll be able to know what I mean or refer what I mean based on, you know, our context and our common sense and our shared experiences. Yeah, language kind of leaves all that out. It would be, I don't know if you think about communicating with a human as if without any ambiguity, go crazy, right? And it probably would have no jokes. Or maybe it would be funny because you're explaining the jokes. What else, is that the only reason why? Because you don't want the computer deciding, well what does a programmer mean today? You want repeatability and get the same result every time. Yeah, so what if you compiled it today and then tomorrow the computer decides, I actually think they meant something else, so I'll compile it differently. Yeah, right, so think about like the compiler every time it's like, oh, did you mean this or this? You're like, oh, I guess that would be, I don't even know if that's, I don't know if that's worse than it just deciding or let's give me the option to choose. Yeah, it's probably to choose at once. Yeah, so basically, we don't want the compiler to have to try to read our minds, right? I think somebody briefly mentioned that the computer is fundamentally stupid, right? It's a stupid butler that can do things very, very, very, very, very fast, much faster than we can, right? But it only does exactly what we tell it to do, right? So remember that when you're working on projects and it doesn't work, you're trying to pull out your hair why, right? It's only doing what you told it to do or actually it's more like you and the thousands and thousands of other programmers that went into all layers of the computing stack between you and the CPU, but still, it's mostly you. So let's think about, we'll deal with the ambiguity stuff a little bit later. So we have a string A, B, B, B, B, B. So now in the parser, we have this input string. It's not really a string, it's a sequence of tokens but you can represent a sequence of tokens as a string, right? So I wanna turn this into a parse tree. How do I do that? What are some ways you could think about trying to do that? See if one of the roles, one of the characters you have, there's only one way to get it. So like with that little A at the beginning, we can only get that through S. That's the only way that we're gonna get it. That's what we're gonna say. Yeah. But how do we create that into a tree? What would, what would we do? You know that one of the, yeah, that's not gonna help me a whole lot. It can help, but it's not gonna get you. Right, end goal tree. Yeah. You can start at the leaves if you work your way up. So we can start at the leaves, so what does that mean? So we get here, kind of how would that work? We do things. Get here and say, okay, it's got to be, so yeah, essentially kind of what you're saying is we can start something like this, these as nodes. What's the easy way, right? So on a programming interview, usually when they ask you a question, your first thought should be, what's the stupidest, simplest way to solve this problem? What's the simplest way to answer the question or to create a parse tree from this? What's usually the stupidest, simplest way? Group force. Group force. How would you group force this? It's a tram or possible solution. Yeah. Right, please. Yeah. Load up these rules, start generating and cranking out parse trees until you get a parse tree that matches this and then you found the string, right? Job done, yeah. And oftentimes, you know, in the real world, those solutions really work because you only have 10 things to iterate over. So it doesn't matter that your solution isn't doing it and log in, right? It just matters that you're actually doing something that's correct but does what it needs to do, right? So the first thing, that's what you could do, right? You just, let's, we know how to create parse trees from the grammar, right? We just choose rules and we can iterate over all possible strings. What's the downside there? It's kind of getting something. Computationally expensive. Yeah, computationally expensive. It may never finish. How do you decide that you're actually exploring all of the space? It could be the very last string that you find. And it's clearly, it violates one of our properties we want from our parse tree, right? Fast. Fast, efficient, exactly. So now we're looking at the leaves, right? Can we build the tree from these leaves? How do we do that? Let's do it. Start with the very last V. I want to make that one into a V. You want to make this one into a G? How do you know how to do that, though? Why don't you choose? It's the only way you can get to it. Because of magic. Because of magic. So let's go down magic and erase your magic. So let's look at this A, right? We can look at this A. A can only be gotten from the big S, so it has to go up to a big S. So there's only one way to produce an A here, right? And that's if its parent is an S. If its parent is an S, then what does that mean about its sibling? It has to be an uppercase A. It has to be an uppercase A, exactly. So then what do we know about this little B? So we've started, we've found S, right? So what does that mean about our tree and all the nodes in this tree from S? They're all children of A. They all have to be, so first they all have to be children of S, right? We start from the start, right? Every node in our tree has to be a child of S. And we look here and we say, okay, well, this A, so all the rest of the nodes in this tree must be a child of that A, right? Because there's nothing else here possible in this tree, right? There's no other nodes in this tree that we know about. We know that for this string to actually, for this parse tree to generate a string that starts with A, the first thing has, and the first thing has to be a small A, then everything else has to be Bs. So then what would be maybe the next rule after this? Or how can we connect this big A to the small B? Well, big A can be little B, big B, so there's your first little B, that's the second, especially because A only has one child, one potential, yeah, one potential, that makes perfect for more seconds. Right, yeah, so it has to be, yeah, right? We don't have a choice, there's no or there. Whenever we see an A, it has to be a little B and a big B. So what if this had been, what if this had been an A? Yeah, right? We'd say this doesn't parse. There's no possible way that we could generate a string, a parse tree from this input string. Now, this B, what could be the children of this B? Little B and another big B. Why not, what about this? Can we do that? Yeah, because it's a problem with your B. Bang, we're done, not done here? We just do this? Go home? No, because we still have to extra B. No, because we still have more class. Looks like you can't go home. That's it. That's it. All right, so yeah, so we can choose this one, we can go little B and big B here. And then for this one, which one do I choose? The exact same thing over again? And now what about for this one? Just for little B. Little B, yeah. I don't like that tree either. I don't like that tree either. And I don't want to redraw it, it's the problem. If you think about it, if you pull the S up, you'll get a better tree, everything will kind of fall out a little bit better. Maybe someday one of you can create some software so that as I write this tree, I can like drag them and move them so that way that it knows that it's nodes and it'll know the lengths between them so that I can just drag it and move the tree and it will do that. It should do that at some point, that's cool. I'm fairly certain that already exists somewhere. It's probably a JS library. Ah, but as I write it, that's the thing. I want it to interpret and understand my writing and as I create this tree, then be able to move it and treat it as one object. Yeah, I know people, there's actually some people that do it on whiteboards, which is super cool. Guy Newet, you see Santa Barbara was doing that where you record, like camera record this and then as you're drawing it, you could draw like an NFA or a DFA like an automata and then it would understand that and interpret it and then you could press a play button to start the automata and it would like move throughout it and parse strings and all that kind of stuff. Neither here nor there, but very cool. Okay, so here we kind of started. So in this approach, right, we kind of started from, I wanna make it terrible too, right? So on the tree, where did we start? We started from the bottom, right? Now we're here. Now we're coming up. Okay. Sorry, I had to do that. That's okay. Thank you. Okay, but we have this string. What's the other way we could start if we're not starting from the bottom? On the top, we can start born rich. We know, what's the one thing that we know about a tree? A few things that we know about this tree. We can know how many leaf nodes we have. We know how many leaf nodes we gotta have. Yeah, exactly. We definitely know that based on our string. We also know what? That has to follow those rules. It has to follow those rules and so what does that mean about the root of the tree? It has to be S. It has to be S, right? It has to be our starting non-terminal, right? If I had a parse tree that was this, like B goes to little b, right? Is that something that language can generate? Does context-free grammar can generate? No. No, right? It has to start with S. Exactly, so one way to do it, we could start with S at the top and then we can try to draw down, essentially down the tree to see if we can match our input. So first we can use the fact that we have how many choices for S? One, how many choice, well I guess okay, we have one choice. We have no choice to make, I guess, right? So we have to always be this rule. Whenever we have an S, we have to have a little a and a big a, right? And then what about for this a? How many choices? Just one, right? We can do little b, big b. And we can see we've actually started generating non-terminal, right? So we've got this a, we've got this b. Now we have a choice, right? So now it's rule that we choose and why? The question is why? Not just what, but why? Big b, little b, so we can get all the bs into research, little b, big b. Right, little b, big b, because we know there's more into the strength, right? If this was for some reason the last b here, and we try to look and see, look ahead and say, okay, we're at the end, so it can't be, it can't be big b little, or little b, big b, it has to be little b. So what about this b? So I've parsed up to here. Little b, big b. What's that? And now what about this last rule? Can I do this again, little b, big b? No, just do a little b. No, just do a little b, because you want to end on a terminal. So here we have a nicer tree, right? So the purpose of this is to show that they're in different parsing methods. They all have pros and cons in various strengths. We saw bottom up where we started from the leaves and tried to grow the tree up. Top down parsing is where we start from the starting on terminal, and we're going to try to work our way down, essentially trying to get to the strength, yeah. Is one way more efficient than the other, or is it dependent on what you're trying to do? It's dependent on the language. They each have different approaches based on what types of context-free grammars they will efficiently parse, so they have different rules there. So for this, you know, we're trying to learn this stuff. The ideas here are very similar. So we're going to focus exclusively on top-down parsing. So this is the only thing we're going to talk about. And so, there we'll kill it, and when we come back, we're going to see what techniques we need to develop to actually do this efficiently. And actually it's really cool. We'll be able to develop some algorithms to look at a context-free grammar and make some claims about it, about what symbols it can generate, what, which will help us in our parsing.