 So, on the mailing list, we announced Project 2, so Project 2 is due, what is it, next Tuesday? Is that right? Yeah. So, 2-2 is next Tuesday. Before midnight. Any questions on that? Okay. So, there's basically two goals for Project 2. So, the first goal is we want you to need to practice being able to read and understand other people's code. So, you're going to read and understand our code because we're going to give you a lexer and your job is to use the APIs provided by that lexer in order to do something. So, that's the first goal. The second goal is to get you, let's say, reactivated to C and the specifics in C. And the important part there is we're going to give you other lexers, other code in C. And so, as the project goes on, you don't want to be stumbling over, how do I do, what is this linked list structure in C? Or what does this mean when a struct has a field that's also a struct? So, that's the purpose of this assignment. So, this shouldn't be, so this, honestly, you should use this assignment as sort of a self-assessment, right? So, it shouldn't be crazy difficult. The actual logic and programming logic here is not difficult. But, if it's very difficult for you, you should rethink taking this class now versus waiting and taking it later. Because the other assignments are going to be a lot more difficult than this one. But, that doesn't mean if you're spending time getting familiar with C and structs and reactivating yourself to all that, I think that's time well spent. That should be good. Okay, so the idea is you're going to be given a lexer. You're going to write, you can write your program in either C or C++. And you're going to be calling the getToken function of the lexer. So, what is the getToken function return? From where? Yeah, from the input, from the input program, right? The exact same getToken semantics that we've been talking about in class. So, the lexer when you call getToken is going to parse from standard input and try to get as much, uses the longest prefix matching rule to get the longest token and returns that. So, yeah, read over lexer.C so you understand how it works. You know, it's important stuff in there. If you have questions, feel free to ask in the mailing list. We can talk about it. There's some interesting or maybe slightly tricky stuff in there. Okay, so the lexer defines two big functions. GetToken, which exactly we said, reads the next token from standard input. If the token is an ID, a num, if, while, do, then, or print, then the actual token is stored in a global variable called currentToken. So, your code, because it's including the lexer file, can access this global variable. So, this, the last part here gets back to what we talked about, I think, on Monday. We're talking about what happens when we get to the end of the input string, right? What is the lexer return? So, here we have two special tokens that are returned. End of file. So, why doesn't it return EOF, the pop quiz? Yeah, EOF is a macro that's already defined in standardlib.h, maybe? I don't actually know exactly where it's defined. You know, we want to make sure that there's a difference between those two. And then error if there's an error. There's an unrecognized character in the input string. Okay. So, ungetToken. So, basically what ungetToken is a way for you to essentially push back the last token so that the next call to getToken will return that same token and won't advance the input. Why would you want to do that? The text that's on the screen? I'll talk about words that we haven't talked about yet. In general, why would that be useful? Yeah. So, that if you need to go backwards. Yeah. Yeah, maybe that we want to peek and look at the next token, but maybe we don't want to deal with it yet, right? Maybe we want to peek and then depending on what that token is, then we'll maybe parse the function definition versus parsing some other thing. So, that's the idea here. It's not, it doesn't stack. So, this is one of the things you should look at how ungetToken actually works so you understand it. It doesn't stack and you can't just call ungetToken to keep pushing things back so you can't go back infinitely. You can only go back one token essentially. Yeah. So, we'll see it's going to be a useful function later on. Okay. Four variables in lexer.h. So, what's a h file define? Header. Header? So, what's a header used for? Define the function. Yeah. Define the interface. So, it defines all the variables and all the functions. So, that way when you're including a C file, you don't care how it's actually implemented. You just care about the definitions. So, what are the definitions of the functions that were defined? And so, the token type is also stored in a global variable called t type. It'll be the same thing that's returned by getToken. Current token is going to be a character array. So, a car pointer or a car star, a C string. So, it will be a zero-terminated sequence of characters that is the token value in there. So, why is this useful? Is it not useful? There's stuff in here to make it more complicated. Yeah. You want to do anything with the token? Yes. Are you getting identified? So, what's an ID? What do we define like an ID as? A variable name. A variable name, a function name, right? But just ID by itself. Okay. So, it's important because it distinguishes it between the other tokens, right? We know it's an identifier, an ID. We want to know what that actually is so we can understand what function it's calling or what variable it's named, right? So, that's how we are able to get that. The length, the length of the string is stored here. Line has the current line number. I'm sure you need this here, but maybe you didn't find the following thing. So, yeah. Here's some hints, stuff, how to use. Okay. So, that's basically the interface. So, this is, we're defining this other, you know, this piece of code and you have to call specific functions within that. So, what you're going to do, this is your main goal. So, you're going to use the lexer, read all the tokens from input by repeatedly calling get token. When should you end? And you get to the end of the file. Yeah, exactly. And you're going to store certain things in a linked list. As we'll see later, specifically C-style linked list with a struct with a field that points to itself. If you don't know what that means, you need to look it up. You have to understand how to do linked lists and C. So, what token strings and additional data are you going to store in this linked list? If the token's of type num, you're going to want to store that. But we'll see what you have to print out so that'll influence what you store. If the token's of a number or if the token's an ID and the actual token, right, so what does it mean, the actual token? Yeah, the value, the string that the token matched, right, is either CSE340 programming or language. So how do we compare strings and C? SCRCMP string compare. So that's the function you should use to compare these. All right. So then you're going to store that string and some other information in a node on a linked list. So you're going to store, yeah, here's where we use the line. So you're going to store the token type, the token value, and the line number where you read in that token. It seems pretty simple, right? Making a linked list, storing input, creating data. So we should just create some record that has a link. Yes. You need to create a struct that has this data and then a fourth field which would be a link to itself, right? So that would be the next pointer in your linked list. Cool. All right. So then you have to do something with that. So once you read all the tokens from input and I'm hitting things, you go over the link list, print out the information in reverse order from where the token was encountered. So basically you go from the end of the list to the beginning of the list, printing that out. So for each, you print out the line number that you found it on, the token type as a string. So it says here either the string ID or the string num, and then the token value, the token value to print out. Yeah. It doesn't have to be though, right? No. It could be a previous linked list instead of a next linked list, right? You could have just a one-way backwards link. It's possible, but yeah. That's part of what you're doing is deciding how to build your data structures to solve the problem, so that's the key. Yeah. Is there only one in that part of that? Oh, you mean in the output like this? Yes. We're trying to identify the line. Exactly. There are multiple lines, but it'll be in the order that your lexer encounters them. So if there's two tokens on the same line, like an ID followed by a number, the number would be printed first because it's the last one in that line, right? So just whatever order the lexer gives it to you in. Yeah. So like the token type, it's going to be, you know, a type depth, so it's going to be the number. Yes. So you need to translate. Okay, so you need to translate. Exactly. So that's okay to be like, okay. Absolutely. Yeah, so you should write a little function, right, that takes in a token type, which is an enum, and then returns a string based on whichever token type it is, right? These little switch statements. Other questions? So yeah, it should be one value for line, output at all. You need to write all your code so you can't modify lexer.c or lexer.h, right? Remember, this is your interface that you're programming to, so you can't change that. You just have to write your code to use that, right? It's just like using a library, like trying to change the C standard library, right? You can't do that. You have to use them. So if you're in C, this is how you would write it. Should you write all of your code in your main method like this? Probably not. Probably not? Why probably not? Because it's kind of messy. On the back? It's very difficult to read and even more difficult to debug. Yes. Yes. So say future you some headaches. I had some people last semester who read a God method for one of the projects, and you look at it and it's just huge. I didn't know the term. That was the term that this person used. It was this huge function that did everything. So it's like, okay, well, where's the problem? Well, I don't know. First it's doing this, right? So there's no, just a huge function. Anything can go wrong. So if you break your functions up into smaller pieces, they can be a lot more easier to understand and to test because you can try to test that function in isolation. I have a story. I wish I could remember the person who I heard it, that it was about. But let's say an old famous C programmer or whatever, they say, well, how do you know when a function is too long? Like when should you make it smaller? It's like, oh, I use my head. It's like, oh, so you just think about it. He's like, no, no, I put my head up to the screen. And if the code is longer than my head, then I need to refactor it. Another way to think about it. All right, C plus plus. So this is how you do it. This is how you do it in C plus plus. This specifies that the lecture H file that you're including is C code. So the C plus plus compiler needs to know that when it's so it can link properly to that object file. Make sure you do that. This is going to cause problems. So make sure you do that. Say that again. If you want to code in C plus plus, you can do that. You can use C and C out for an output, whatever you want. I don't really care. The only thing you can't do is use Vector, any of those other C plus plus classes, STL classes. The whole point of the assignment is to get used to C structs for linked lists. So that's the data structure you have to use, and that's what we want to see when you're doing your code here. But if you're doing it in C plus plus, you have to include basically this boilerplate to include the lecture dot H file. All right. And then a little stuff in here about how to compile it. Make sure it's compiled the exactly the same way. We're going to download by that. So here's an example input. So this was the input to your application. Right? So let's see. If we go backwards, what are the things that it's going to just print out? What's it supposed to print out? The CSE 40. Backwards. I can't see past your head. Should I say something more? OK. So the backwards. So is it going to print out the if? Yes. No. What are the conditions for printing? CSE 40 programming. ID or number. Right. Exactly. And if it's an ID, there's additional constraints. So it's going to print out the number 200. It's going to go, go, go. It's going to print out 100. So we can see here that yes, it prints out four num 200, line three num 100, line three num 340. Why isn't this, why isn't this an ID called CSE 340? Because it's space. Spaces. Yes. 340. We don't print out CSE because it's not on our list. Programming. We print out on line two an ID called programming. And print out 456, 123, CSE 340 ID. So if you go backwards, that should be exactly. It should be clear. OK. Testing. So this is important. The opportunity you should take to, like the first project, right, was to set up your environment. The second project part of it is understanding how the grading system works and how all the test cases are run so that you can test it on your own machine locally before you submit so you know how you're doing it. So this is the same testing infrastructure that's going to be used on all projects in the class. So take the time, get familiar with this section, set it up so you can run these self-tests and not have to rely on the server. OK. So I'm going to kind of briefly go over this. The basic idea is there's a bunch of test cases. The inputs have the .txt extension. The output have .txt.expected. Basically the idea is if we give your program a .txt, then we should expect the output in the text.expected. Yeah. So this talks about redirection, how to do that. You should read all of this. This is really good stuff. I won't go over all of it. We provide a shell script that will actually run all of the test cases in a given directory against your program. So this is the exact same way that your tests are evaluated on the server. So you have the exact operating system environment, the exact compiler, and now you have the exact scripts to run to test. OK. I can't remember for this one, but in general, so we give you some of the test cases. So why don't we give you all of the test cases? So that we don't hard code. So you don't hard code? Yeah, that's one reason. Yeah. Yeah, it could be, we want you to do things differently, right? If you see everything about all the test cases, maybe you'll code a certain way and it'll bias you. Any other reasons? Remain and evil? You don't always know how your software is going to be used, so giving us all the test cases is an unfair advantage. I guess it depends on your perspective. I do appreciate that unfair advantage from my perspective. Your coach would be robust to take in any employee. Yes. That's a huge, huge thing, right? So if you think about, so I'll draw a little diagram I was playing on this, but I think this is good. So if you think about a program, right? So a program, so you have to write some program to some specification, right? So it should do something, right? There's behaviors that it should fill. So if the thing that you actually write is kind of like this, is that a correct program? No. No. Right? So how do you even know that your program actually successfully does everything it's supposed to do? Test. Test. You guys, test. If you think about tests are kind of just points in the circle, right? So part of being a good software developer is learning how do I write my own test cases to test my own code to make sure it does what it's supposed to do. So if we were just to give you something that looks like this, you could draw a circle around that pretty easily and be like, bang, did the project, I'm awesome. But if we give you a lot fewer test cases, right? Now it's up to you to decide, OK, how should the program operate? What should I do? What are the boundary conditions? What things should it do? What things shouldn't it do? And you should be creating these other test cases to try to define and understand your own program. And this is a really key issue because it's going to help you progress and develop as a software developer because writing correct software that does what it's supposed to do is the key to what we're doing, right? That's why hopefully somebody's going to pay you a lot of money when you graduate to do this, right? So we'll give you feedback on what test cases you passed so you'll know right away. But I don't know. I want to get this out now. As much as it may hurt, right? I'm not going to tell you the test cases because if it doesn't pass on the test cases, it means your code isn't correct, right? Maybe for these three cases in here, right? Maybe they all had input, right? And one of the test cases is testing what happens if there's no input or what happens if there's no tokens that match, right? Does your program crash? That's not a good, it's not a robust program, right? It shouldn't crash. So basically given all possible input, your program shouldn't crash or fail or do anything like that. So does this make sense? All right, let's see. Evaluation, yeah, test cases, and then you got to use a C-style link list. So we'll look through your projects just to, I guess, make sure you did this, but I don't know. I don't want to have to deal with any of this, so just make sure you do that. Then you can submit on this project website and that's where you'll find all the files, the lexer. I think, let's see. Oh, my thing doesn't fill in there. Okay, can't check. Any questions? Cool, you should get started in less than a week. So what we've been talking about so far, and what we want to understand, okay, so we've been trying to say, hey, let's use regular expressions to understand if the tokens that we're receiving from the program are correct. But what did we find out? They're not expressive enough. They can't express simple things like one plus two plus three, or at least naturally in this way. There could be a way you do that, but not in the way you want. Let's go a little bit pro and let's say how would this is not the right slide. You guys want to learn about even it? Okay, so let's go. So how to write a regular expression to match parentheses. So what kind of strings do I want my regular expression to match? Open parentheses, followed by what, a closed parentheses? Is it like that? No. What else? What if I do left to left? So how many do I need on the other side? What if I do even something like this? So how would I write the regular expression R? Are we just assuming all of the parentheses are empty? Yeah, we'll do that. Balance empty parentheses. So the key thing is balance. So that every left parentheses is matched by every right parentheses. When you're checking for parentheses, your program, that's like the basic thing it needs to do. Your compiler should tell you, hey, your parentheses don't match. So we'll get rid of all the stuff in between and just say, can we detect balanced set of left parentheses and right parentheses? Any number of open parentheses is followed by the same number of closed parentheses. And we may need to escape these just to make sure their characters symbol but we kind of know what we need, right? Yeah. So this is, so... It's closer. It's close. What's the problem with this? There's no way to define that it's the same amount. Exactly, there's no way to define that they have the same amount, right? And that's, it all falls apart right here. So we cannot express this language. We can't write a regular expression that captures this language in regular expressions. Yeah? We also do multiple parentheses within a parentheses. You mean something like... like that? Well, another open parentheses on the left side and one on the right side. Oh, like this? Okay, so you mean if they're next to each other? So like you have one open parentheses and another open parentheses and then a closed parentheses and then another open and then a closed parentheses. Oh, yeah, yeah, exactly. Yeah, that would be another one too, right? So, yeah, this would be in our set. So does this match this string? Does it match this string? Yeah, it matches this one. It matches this one. But the problem is, right, we have to think about what... Does it also match that it's not in LR that we want? So what are some other strings that this regular expression could match? No left parentheses and then number of right ones. Yeah. So it's one and then two and then three and then nothing, right? So these are not balanced parentheses. It also includes just... Yeah, the epsilon, the empty string too, right? Which is also not what we want, but we could fix that, right? We could say the base case. So can we just write? Okay, well, R is equal to this or this or this. Can we do that? If you want to take the rest of your life doing that. If you want to take the rest of your life doing it. Yeah, I don't want to do that. I have better things to do, I guess, than write a regular expression. But the point is, you can never finish writing this regular expression, right? Regular expressions have to be finite and this is an infinite regular expression. And it doesn't even capture the things we want to capture like this string here. So yeah, so this is just another example to bring home that regular expressions express very significant programming constructs that we want. So matching regular expressions, right? This should be simple. But regular expressions can't do it. Okay, so this leads us to context-free grammars, just a little differently. So we're going to find something new. So we're going to talk about context-free grammars. And the idea here is saying, okay, let's rethink. Instead of using regular expressions, let's define what we want the language to look like from a grammar perspective. You can think of it kind of from the top down in some sense. Similar to how we actually did the regular expressions, wrote the regular expressions here. We said a program is one or more statements or zero more statements. It's either of these things. So we're going to start from the top. So why don't we be super lazy and call the starting rule S? Because that's what we do. So we can say, okay, S. So let's think about the parentheses, right? So we can say S. So what do we want any matching parentheses? Kind of what should it look like? All by the same number of parentheses. Right. So we want left parentheses and right parentheses. Let's say now we can do a self-referencing definition. With S in the middle. With S in the middle. So every time I see an S, I can expand it to a left parentheses, a right parentheses, and a middle S. What's the problem here, though? Recursive. Exactly. I'm never going to stop. I really do this. So why don't we just add another rule that says, hey, I can stop. So what would, when would I be able to stop? Epsilon. Epsilon. Yeah, exactly, right? So if, hmm, is that epsilon? Yeah. No? Yep. It is? Kind of? More like this? Yeah. I think that's, it suddenly looked very weird to me. So I would say creek to me, but, anyway, yeah, that's it. Okay. So the idea is if we take this, we'll define this context-free grammar. Well, let's call it G, this grammar. And it's composed of these rules. So I'm using, I don't know, this notation here. It's just to say that these are rules. We're actually, we're not going to define context-free grammars formally. We're not going to say that they're, you can define them in terms of sets and rules and symbols and terminals and non-terminals. That doesn't add too much to our discussion because really the intuition behind how to use that is much more important. So the idea is by defining a grammar here and I say, okay, then what are, what's the language described by this grammar, this context-free grammar G? So we'll use this as in the same way to say this is all the strings that this grammar could possibly generate. Yeah, so starting from here, so what's, what would be the first one? One set of parentheses? And epsilon, yeah, right? So epsilon is the first one in this set, right? Because, so the whole idea is we start from the top, so to generate this set S, we start from the top and we choose every possible combination of rules, right? So the first time, let's say we choose the second rule here and we generate an epsilon. Right, so that'll just be epsilon. We've stopped. So the second time, let's say we take S and we apply rule one. And what do we get as a result? Left parentheses, S, right parentheses, so is this in our set? S still has to be something. Exactly, S is not a, S is, so remember, I didn't write it here, but here sigma, right, our alphabet, what's our alphabet here? Parentheses, yeah, I think, I was talking with someone, I don't necessarily think you put epsilon in this set, sigma, but I don't, it doesn't matter too much. So we have left and right parentheses, right? Do we have S in here? No, because S is just a symbol that matters in our grammar, right? It's something we're using to say, okay, every string that G represents starts with S. So we apply it once, we get left parentheses, S, right parentheses, yeah. In regards to the grammar, we also want S to be able to be SS so that we have the two parentheses next to each other. Yeah, we'll get rid of that in a second. I realize that adds more complication to what we're going over here. But let's just do the balanced parentheses, right? Equal number of lefts followed by equal number of rights. So we take S, we apply the first rule, we get left parentheses, S, right parentheses. So can we stop? Is that in here? No, right? Because S is not in our symbol. Yeah, so we can't stop here, right? We still have an S in here. So we can apply this one more time. Which rule do you want to apply? The second one. So what's left parentheses and epsilon can coordinate with right parentheses? So in this string, left parentheses, right parentheses is in our set, right? So is that it? Are we done? Done all the strings. So let's do another. So let's start with S. Which rule do you want to apply? The first one. Top one. So can we stop? No. Okay, let's apply it again. Then which rule do you want to apply? Top one. Then the bottom one. Then the bottom one. Then the bottom one. And that's the same thing as, if I reach the end here. So if we think of the language, right, that this grammar defines, how would you describe all of these strings? So are we done here? Could we keep going? Yeah. Repeating sets of strings. Exactly, yeah. So every time we have, right, every time we have, we have two choices of rules. We can either choose the first choice or the second choice. And we can keep doing that, right? So we can keep applying that. Starting, remember, we think top down. So we start from S. And we can keep applying rules to S to try to generate resulting string. Okay, now we need to give names to some things. Right, because, I don't know, we just have this G, we can talk about S. So S. So when we think about anything on the left-hand side, we're going to call a terminal. All right, sorry. All right, this is when you guys have to be vigilant, because I often mistake these two terms. This is called a non-terminal. Why do you think it's called that? It expands. Yeah, you can never stop with an S. You have to, you always, so when you're, we're going to see, this is called kind of deriving a string from the grammar, but every time, you know, you want to break down one of these rules, every time you see a non-terminal, you can't stop. You have to keep applying a rule until you finally get a string. And so we've called these symbols, right? They're symbols in our alphabet. In the grammar, we're going to call these terms like, well, I guess it should be, right? This is a non-terminal. These would be the opposite of a non-terminal. A terminal, yes. It's not a trick question. So we'll call the other symbols terminals. Right, and that makes sense too, because when we apply this rule, S goes to left parentheses, S right parentheses. Can we try to change this left parentheses? No, because we applied one rule. We're done. Any questions on this? We'll go back to the slides and kind of go a little bit more in depth, but I'm trying to build up some intuition behind what these context-free grammars are. Okay, so a little bit more syntax stuff. So each rule, right, we defined each rule. We're going to call them a production, which I guess is not like a theatrical production. It's like more of in the sense of something that generates or something that produces something. So you have the left-hand side. The non-terminal on the left-hand side produces the symbols on the right-hand side. So this is an important key, and maybe we'll look at it in a second. Non-terminals always on the left. So you have single non-terminals by themselves on the left, which define this non-terminal, this symbol s always produces this other thing. A right arrow, and then we have non-terminals and terminals both on the right, which is what we saw. This is kind of a convention for all the examples going forward. Non-terminals are going to start with uppercase as much as possible, and terminals will be lowercase. So this will just help everyone when you're looking at stuff. We don't have to keep defining sigma. We don't have to define our language. You can tell just from looking at the grammar. And remember, going back to what our goal is, all of the terminals are actually tokens. So if we think about a left-paren token and a right-paren token, that's exactly what we want there. And s will typically be the starting non-terminal unless we specifically say otherwise. Okay, so the matching parentheses? Yeah, so the signal wasn't right. I got it in my head wrong. So do we want to... Every time do we want to write this two separate rules of productions for s? It's kind of a pain, right? What if we have multiple, like four or five? Then when you want to see what things you can do to s, you can write five different rules. So we're going to actually reuse the concept, the bar operator from regular expression. What was the bar operator again? Or, right? It meant or. So we're just going to use that here. We're going to say, okay, we can write it on one line by saying s goes to left parentheses, s right parentheses, or s goes to epsilon. So these two are exactly equivalent. So there's absolutely no difference between these two rules. It's just like a syntactic shortcut for us. So what we've been doing is we've been actually, when we wanted to say, okay, what strings can this context-free grammar generate? Or what strings are in the language defined by this context-free grammar? We actually were doing derivation. So we were saying, okay, start with s and then do a double bar symbol and say, apply one of the rules. So take s, apply one of the rules. So here we're taking s, right? We're applying epsilon and say, okay, s goes to epsilon. We can take this, right? We did s goes to left parentheses, s right parentheses. We can take the second rule here and go s goes to epsilon. And then go there. Same with, you know, we can do this as many times as we want. And every resulting string is in the language defined by this context-free grammar. So, now when we get to, let's say we have something like this. What's one difference between what we've seen before? Other symbols. We're using other symbols. We're using symbols and not their ways from the flexible and the star. The star here is multiplication. Right, the star here is multiplication, not regular expression. We represent the star as a token, right? We also don't have an s starting non-terminal. So what symbol, what non-terminal do we have up here? Expression, right? It's pretty clear it's expression because there are no other non-terminals. Alright, so let's say we wanted to derive expression. So how do we do that? How do we want to start generating strings that this grammar defines? Yeah, it could be a number. Let's choose the second one, since that's what the example says. Let's choose the second one. So we say expression goes to expression star expression, right? So now, what choices do we have? So before we had the choice of which production do we choose? Now, what choice do we have? Right choices. Yeah, six. Why six? Where does that two come from? This is two. Exactly, so we generated this and now we have two non-terminals here, right? So do we do the left one first, the right one first? How's left to right? That's me. I agree. Unless you're going to have right to left, right in culture, right, and then you'd say right. Yeah. Although then it would be going this way, so maybe it would still be that way. Well, doesn't either read left or right? In this case, read left or right? It's tricky. I don't know how to answer that. The direction and arrows are pointing. Or the arrow direction. Which one of those? Two. Yes, and we could apply one of the rules to it. Even when we started this, right, we had one non-terminal expression. So we just have to decide which of these three rules we apply. Isn't it the first one listed like before? That's what we have to define. So yeah, that's the thing is it, yeah. Or does it follow the order of operation? Yeah, keep that in mind. So the short answer is it depends. So, you know, you could actually, when you're just doing a derivation, and you could do it both ways. The resulting string, right, so we think, why are we doing derivations? Because they help us understand things, but what's the ultimate goal of deriving? What am I going to get when I finish this? A string, exactly. A string that is an expression in our language, right? So if I... So, at the end of the day, if I just want to get a string and I want to get all strings, what kind of strings do I choose? Is that going to affect the strings that I get? No, I should choose... At some point, right, you're going to kind of choose both, because there's no order here, right? So it says we can do whichever one we want, and then we can apply whatever rule to any non-terminal. And it doesn't matter that these are both the same non-terminal, they could be different ones, right? We still have the choice of which one to expand. So let's say we do the right one. There should be none here, and then let's say the left one. So now do what choice do we have of non-terminal to expand? Just one, right? We have expression. Yeah, so the non-terminal, we just have expression. And then for the rule, we have one, two, and three. So let's do one. So we do expression plus star three, and then we can expand. Now we have a choice, so we do the left one or the right one. Let's do the right one again. So we have expression plus two times three, and then we do the left one, and we have one plus two times three. So the idea is we can do it kind of randomly and do whatever we want. So, but yeah, so there's rules. So we can determine, okay, we want to always do either a left hand, always do the left most non-terminal, or always do the right most non-terminal. So this is the names derived obviously from operation, left most derivation. You can always do the left most symbol, right most derivation, means the right most. So this means that we if we have these rules right, so we can ask a question, right? Like, is this a left most derivation? No. Why? Which step specifically? How do we number steps? Between, we'll say, one, two, three, between what, two and three? Yes. Right, why? Because you evaluated the right one. Right, we evaluated the not, or actually it's not the right one, but we evaluated the not left most. Correct. Not left most non-terminal here. What about this? That appears to be doing it properly. So what rule did we apply to where on between steps here, between steps two and three? Left expression that's turning into an expression plus expression. Right, so does everybody see how we got there? So you just expanded it or? Yeah, so we, so the idea is we were deriving expression, right? And we said expression goes to expression, star expression. And then, now we, remember we want to do a left, we're asking is this a left most derivation? So then we have to derive the left most expression. Then the idea is why did we choose rule one to expand here? Is it because it was listed first? No, it's not quite. Because one of the same solution is the one above. Solution, very close. Or, same expression as the one above. Still, very close. So that's where the string, the resulting string of our derivation. Yeah, exactly, same similar things, right? But, you know, so yeah, so we wanted to derive the same string, right? Both derivations derive the string one plus two times three, right? It's just the derivate, steps of the derivation happen in a different order. So, the idea is if your goal is to try to derive the string one plus two times three, then, and you say, derive the string with the left most derivation, right? At this step you have to, if you do it like this, right? If your first step is the multiplication, then your next step has to be the plus to get that in there. Why might I want to ask the question of can this grammar derive this string? What does that mean? Based off of the expression where the grammar that was given can you come up with this string basically? Exactly, right? Exactly. Is this string in the language defined by the grammar? And if it is, then that means a string, that's a string that the grammar can produce and how you prove that is you show me a derivation. One of the ways you do that is you show me a derivation. You show me exactly how the rules are applied and if that every step in this derivation a proper rule was applied, then that string is in the language defined by this grammar. So I know that this expression, right? This grammar defines the string one plus two times three. Alright, what would be the opposite of a left most derivation? Right most. Always expand the right most symbol. So is this a right most derivation? Let's take it step by step. So is this derivation right most? Yes. Does it also apply one of the rules? That would be the other check, right? How is it the right most? This one? The first step, so which in the starting with the expression what's the right most non-terminal? Exactly, there's only one, right? So it's both the left most and the right most non-terminal. So the other way to think about it, so if you just think about the expression right, any other non-terminal to its right? No, there's nothing to its right. Exactly. So this is the right most non-terminal, then we expand that and the other step would be okay, is it actually a derivation? Did we correctly apply one of these rules? Then we say, okay, which one of these is the right most? The one on the right, the expression, yeah. So we expand that out to num and then we look at the, so now which one of these is the num has already been fulfilled? So there's the expression on the left which is the right most non-terminal. Right most non-terminal is the important thing here, which is expression, yeah, three is terminal and the star is terminal. So we take expression, we apply rule one, we get expression plus expression times three, now which one is the right most one here? The one on the right. The expression on the right in between the plus and the multiplication, that transforms into the num and then we only have one choice of non-terminal, so it's this one, you can see we have derivation, right? That still gets the exact same string, both right most and left most derivations. Cool? All right. You just happened to pick star. What happened to here? Why did you start with star and not plus? That's actually a good point. We'll get into that later. That's why I got confused. That was my question. Yeah, the very first step, you have a choice of which one you choose to get to the same string. You can still do, there could be multiple derivations that all get to the same string. Oh, so you chose that one for right most derivation because that's the one that works for right most derivation to get you that same string. Actually both would work. We're actually going to get to it. Yeah. It's so easy to do. It's something I've missed. I won't do it retrospectively.