 Okay, guess we'll get started now. Welcome everyone, this is a state-lead state machines with Rachel, thanks for coming to my talk. I guess I have a couple to choose from, so I appreciate that. I'm a little jet lagged, so if I seem like I don't know what I'm talking about, that's probably why. Who here has heard of Rachel before? I worked with it just so I know who's gonna go online. Okay, do it. Okay, all right, we'll just get started. So the goals for this talk are to convince you that Rachel's worth trying if you haven't used it before, and to give you some intuition about how it works and to show you how to set it up so that you can kind of do some basic parsing with it. Just a little bit about me, my name is Ian Duggan. I'm into a lot of different things. I play hockey several times a week. This is Storvey the Pig, where I come from North Carolina. Pig's mean hockey. I play guitar. I play banjo, mandolin, ukulele. I'm a fiddle, but gathering dust, and my cats actually appreciate that. Sometimes I fly. I've got a Cessna 120 that I fly out of Hayward, California. It's got a whopping 85 horsepower, but it's fun to put around the bay in the valley with that. And I love my cats. A couple, you know, gotta have cat pictures in a presentation, so here they are. This is Purrington, we call him Bufus. This is Minnie. She's a goofball. She likes to wear outfits. She doesn't care. She thinks they're fun. This cat likes being cozy. These ones are dopey. Jill. Minnie likes to sit in strange places. So I'm a software guy. I code things. I code the internet and the Googles. I'm a recovering technology entrepreneur. Been in and out of startup institutions for many years now. My current status is that I work for Twitch. We do online streaming, social video games. Obviously we're hiring. We have lots of Ruby, the whole front end of this Ruby on Rails. The back end is getting redeveloped and to go for a lot of our services, because we just need a performance. I've been using Ruby for quite some time now. I started on the 1.6 days, a friend of mine gave me a 1.6 book and I was kind of playing around with it. I thought it was a pretty cool language. So I don't know when the transition happened, but I've just kind of stuck with it since. But enough about me. This talk is about Rachel. Rachel's is a really cool tool and it's used in a lot of sort of high performance text parsing areas and some people seem to have discovered it and are using it for stuff like that. And there's a lot of other use cases where people are kind of fighting with regular expressions where I think Rachel could be really helpful. It's got a lot of features that allow you to do some kind of really cool tricks with it. And if you don't have it in your bat belt, I'm hoping that you'll add it to that. As I mentioned, there are many projects that use Rachel. Mongrel Unicorn and Puma are kind of the ones that people know about the most. Zed Shaw I think kind of popularized it about 10 years ago when he rewrote the Mongrel HTTP protocol parsing API with it. There's a really cool gem called Whitecork which actually parses Ruby using Rachel. The male gem, Redcloth, Hverkot, Kirk, and they all kind of make use of it. So just really quickly, what does Rachel look like before we jump into it? It says DSL, you can kind of define some actions and then you've got some ways of converting different terms into other terms. So that's kind of what it looks like and we'll get into the details here shortly. So most people are familiar with regular expressions. Regular expressions are easy for the most part. People understand them. It's kind of the basic stuff that we all understand. Matching, grouping, alternation, matching zero, one or more, end times, end times, et cetera. Ruby has really great tools for regular expressions because it has a heritage from Perl as Zed and Locke which relied heavily on this. So you can do fancy things like match stuff and in a block, match some more stuff and in a block replace something that's three regular expressions down. So you can get pretty fancy with them. But at some point, they can become irregular expressions. So if you've ever opened up a file and stared at something like this, then Rachel might be something worth considering for you. They have their place, but there are better tools. Sometimes you want more control and I posit that this means you want some sort of automaton. So just a little bit about automatons. Like finite automata, they're basically these devices. They have states and transitions. Many people probably see these. You've got circles and arrows and some input comes in that cause you to transition to another state. There are two kind of basic types. There's a deterministic finite automata and non-deterministic finite automata. It's just kind of an academic distinction. Deterministic means it can just be in one state at a time, non-deterministic means you can be simultaneously in two different states. However, you could map those multiple states as super states or the single states and convert that into a deterministic finite automata. So in academia, they talk about this equivalence of regular expressions NFAs and TFA's. So all this stuff that you're doing with crazy regular expressions you can kind of do with these other tools. So you should choose the tool that kind of makes the job easiest for you at that point in time. Excuse me. So, as a superset, these are all state machines. State machines are an important tool in computer programming. Rachel's a wonderful tool for creating them. And state machines are everywhere. And they're in your stoplight. Yeah, green, the timer goes to yellow, goes to red, goes to green, goes to yellow, goes to red, goes to green. Round and around forever. They run your CPU. If you imagine your computer like every single bit that's in it as kind of a definition of a state then every piece of input causes it to transition to another state, your computer is one gigantic state machine. There's some kind of non-state machine-ish stuff that happens on the edge when inputs come in asynchronously and stuff. But for the most part, you can think of it like that. It's a big working state machine. And there's other examples everywhere. So I've watched it as vending machines, I've mentioned traffic lights already, barcode scanners, pretty much any piece of machinery these days that isn't analog. Has any kind of computing device in it? It's gonna be a state machine or something. So I think they're the cat's meow. I think they're great for many reasons. They're simple to understand and there's a great deal of research around finite automaton state machines. With the right approach, they can also produce code that is faster, easier to maintain and correct, more correct than that's most secure. They're very specific about what inputs are accepted and what aren't. And it's harder to get it to parse something correctly than it is for it to admit something that doesn't parse. Which can be very useful. If you're still not convinced, you should probably just spend some time looking at what they are. So let's go over some vocabulary. So state machines, they all have something called a start state. It's usually designated as zero. This is as it sounds like the first state that the state machine starts at. They also have kind of on the other side an accept state or a final state. They can have multiples of these just depending on what they are. And this, when the machine transitions to this state, it is said to have accepted the string. Excuse me. So within a state machine, to go from state one to state two. In this case, when an H is received, you go from state one to state two. It's called a transition. It's usually an arrow in the diagram. It's labeled with an arrow. Sorry, it's an arrow in the slip. There's a special kind of transition called an epsilon transition. This allows you to go from one state to another without taking any input. So this can be useful to wire like the out. You can take two state machines, stick them together, and basically it works like a concatenation like you don't need input to go from one to the next. So with what we know so far, we've got a couple of simple state machines that we can build. So like if you think about a regular expression and how it's parsing things, this is kind of what it looks like. So A star will take any number of A's and just kind of keep mapping on it as long as the first one was an A. The second machine just maps a single A and then you're done. This next one needs an A and then as many A's as you want after that point. So that's A plus. And from that we can get more complicated. So this is a machine that will match zero or more hellos. So the start state is actually a final state. So that's acceptable. But once we've taken an H, we need an ELLO before we can get back to a final state again. So whenever this isn't a final state, it's accepting the input. So you may be asking, what's the big deal? I mean these just look like regular expressions. I've done this before. I don't really need this. So what is Rachel exactly? Rachel is a finite state machine compiler with output support for C, C plus plus, C sharp, objective C, D, Java, O, Camel, Go, and Ruby. So if you're doing stuff across projects, it's really useful. It also supports a generation of several different ways of working its way around the states. And it's really useful for building electrical analyzers and protocol definitions, et cetera. So I talked about state machine generation. So another unique feature of it is that with these states and with these transitions, you can attach arbitrary code at any point in time. So as you're moving around the state machine, you can pull things in and out of the input and jump around in the state machine. And these are the features of Rachel that make it really different than just a regular expression. The regular expression, you can match a string or you can't. With Rachel, you can match half the string, jump to the end of the string, do some stuff, jump to the beginning of the string, give it some more data, download something, upload it to YouTube, and come back. You can do that all inside Rachel if you want to. Not sure I would recommend that though. So I'm actually wasn't sure how to pronounce it. I've been saying Rachel forever. Right, some people say Regal, there's Rajul, there's a bunch of different ways to do it. So you can get the answer from the horse's mouth because Adrian Thurston who created it, actually, I guess sent an email, some time ago. And he said that it's actually Rajul, which is not at all how I guessed. He said it was based on his R and L for regular language and his nickname was Aj, even though it was Adrian or maybe Aj, I don't know. So maybe it's Rachel, maybe it's Rajul. If he's Aj, it would be Rajul, but he wrote Rajul, so I still don't know that. But if you can help, please let me know. So darn, I've been pronouncing it wrong for quite some time. So on a more basic level, Rachel is a DSL for creating these state machines, and it's especially useful, as I mentioned, for parsing protocols, data formats. It's incredibly powerful. It allows you to do this in sort of a EBNF kind of format. So you get this really declarative approach to parsing text as opposed to kind of while loops and for loops and function calls and returns. So let's just take a look at the DSL, get a better idea of it. So the general structure of a Rachel file it'll be written in the host language, so if you're in Ruby, it'll be mostly Ruby, and they'll have some sections in there which kind of call out pieces that are Rachel. So this is a machine which matches Fuba. You can name several machines and refer to them inside your file. There are definitions and instantiations. So this defines a piece of state machine that you can use and you can compose it into a bigger state machine. And to actually generate states, you need to have an instantiation of some sort. This is done with colon equals. And like any kind of programming system that you can include and import and do things like that. There's some slight symmetric differences in terms of what those mean, so you can refer to the manual for more details. White space is ignored. Coddles are started with a pound just like in Ruby. There's different kinds of literals. There are straight literals, regular expression literals, grouping literals. Got kind of standard escape characters that we're familiar with. And if you need to jump, if you're inside a Rachel section, you need to jump out to the host language you kind of put inside braces like this. Numbers can be specified as either integers or hexadecimal, which is useful because when you're parsing in Rachel, you're actually looking at the binary value. So if you're looking at an A, it's actually a capital A, it's actually 65. So you'd be aware of that. You know, it's got a couple of keywords. So these are kind of first section here. This is the stuff that is more like a regular expression. So this matches the word simple. So nothing too fancy there. We can have unix expressions similar to regular expressions. We have zero length matches. We have numerical literals, as I mentioned before, like this is matching 42. So this would be the ASCII character represented by the number 42. And you can have regular expressions inside Rachel, which is, could be a little bit line bending, but regular expressions actually compile down into state machines. So this is actually pretty obvious when you think about it. We have range expressions. So if we want to match A to Z, same as regular expression A to Z. This is where we kind of start to jump out of what you can do in regular expression. Here you can kind of name something called secret code and refer to it in a different place inside the regular expressions. You can name it once. It'll be used in five or six different places. And there are a bunch of sort of built in character classes. Any ASCII extend printable and control graph. So if you, for basic stuff, you can just reach to one of these. You don't have to define it all in front. So at this point, we sort of have the basic building blocks for building more complicated machines. These are like levers, wedges, wheels, pulleys. These are like the simple machines that mankind has built. And on top of that, we built rocket ships and got to the moon. So that's what we're gonna do next. Here's another cat picture. So when I was first learning about Rachel, I kind of heard it was useful. I wasn't quite sure why. I was reading through the user manual. That's like, if you really want to understand how it works, that's the best way to do it. There's a really good PDF online about that. But it has this really interesting thing where you can take a really complex machine and add it to another machine or subtract it or do an intersection or a difference or a union. And it will do the math to kind of add or subtract the state so that it does what you expect. This is kind of my blog when you see it in process. Compositional operators are the things I just mentioned. Union, intersection, difference, strong difference, concatenation, things start. And we'll go and check it in detail in a second here. So a union, you would take, this string up top could be matching, this could have a thousand states in it, one on the bottom could have a thousand states in it. The state machine will traverse both machines at the same time and enter a final state. But it does this by adding, like adding together all the states and lining up the final results. Sorry, the final states inside it. Bugging my slide here, simple union examples, which are on it. But we have an intersection. So that should be, matches any string that would be in both machines. So this is an example of that. It's taken the machine on the left here and the machine on the right. And it is merging together into kind of one mega machine. So we can do a difference. So this would take any string, the first machine matches, minus any string in the second machine matches. This is the state machine that you get from that expression. So as you can see, it's pretty complicated. And coming up with that yourself would be a mess and trying to do that code would probably be a mess. But it's actually pretty simple here in the DSL. You have a notion of a strong difference. This will match any string in the first machine, sorry, any string of the first machine that does not have any string of the second machine as a substring. So one example would be I want to match any character except control character turn line feed. Character turn line feed is a compound string. So you have concatenation and this is just taking the epsilon states out of one machine. Setting up epsilon states which come out of the final states of the first machine into the second machine creates like a global machine. Concatenation example. And you have other things that relate it to regular expressions like the clear start. This is more basic repetition. We've got the optional operator, optional example. So this would admit any string that the machine doesn't match. Negation example, sorry, I'll give you a second. Special form of character level negation. If you just need to get negate on a single character, there's a special operator for that, that's this. When you go through the work of putting these machines together and feeding them into Rachel, it does a kind of final process called state machine minimization where it does some optimizations of the states within the state machine and at any of them that are redundant it can kind of subtract out. So you may have a thousand, you may initially have a thousand states that you've kind of added together that could subtract it down to like 250 equivalent. So I mentioned before, like one of the powerful things you can do with Rachel is attach user actions to different parts inside the state machine. So this is some examples how you would do that. You can define an action statement inside the DSL and then attach them to the transitions. So there are different kinds of transitions, they're entering transitions, so I'm going into a state. You can attach there, you can attach to a finishing transition which is coming out of state. You can attach to every single transition or you can attach to just the leaving transition and you would do this, you would choose based on kind of what you're doing which one of these you want to do. And the embedding operators can get really fancy, there's like two or three pages in the manual about how to do this. I need more details, I just suggest you check there. One of the problems you can come up with is this notion of non-determinism. So you may have two machines that are stuck together and you can't get out of the first state to match on the beginning of the second. You can't get out of the first machine to match on the beginning of the second machine because they're matching the same characters. So an example would be this machine here. So the new line and the new line in white space will prevent the final new line from matching. So the solution is to exclude it from the beginning. There's also ambiguity problems. Like if you're trying to match, if you're trying to match like a C comment for example, you might say, okay, match slash star, give me anything and then give me slash star. But you'll never match the slash star because you're matching on any. And you can do things like, okay, match on anything except slash star and kind of add things together like this but that gets up late. Rachel fortunately gives us some tools that are easier to reason about. So you don't have to kind of do the second stuff. The way it does this is it allows you to set priorities on the states. So you could say that I want the transitions like going to the second machine to have higher priority. So one of the techniques it gives you is a special notation called guarded operations and these are called guarding concatenations. So an example of the one we just looked at, how do I match say on a C comment? When you use this kind of colon greater, greater, this causes the slash star in this final machine to match more strongly. So I'm going to match on any as long as it's not a star slash and then it'll kind of come out of the machine. So we've got, there's a couple of different forms of that whether like kind of the right machine is stronger or the left machine is stronger. Or if you want to along this match but you don't want to kind of stay inside it. So one of the things that you, so that's kind of for simple matching but a lot of times we're trying to build a scanner. Like we want to scan a file we just want to recognize tokens in it like one after another after another after another and have it keep going. So Rachel has a notion of a scanner and this will keep matching on the input and it will take the longest match that it can and recognize that time after time. So an example of that right here would be like, so if you're kind of like this is like parsing headers. So right here we're saying a header, like within a header I can match on a word, a space or a new line and this is what I'm going to do for each of those. So it's going to keep matching on a word. There's a space that's going to ignore it. There's a new line that's going to effort which is actually kind of coming back to work on an F call. So as I mentioned it's really useful for protocol parsing. This is what ZXA did and that's what Puma uses it for. So if you want like a good detailed example of how to like parse HTTP using Rachel Puma I think is the best resource. And up to this point we kind of been thinking sort of on the level of regular expressions but on the lower level these are just states of transitions and Rachel actually lets you kind of go down into what it calls the assembly language of state machines which is just saying I want these states, I want these transitions, I want these characters to go from one to the next. So you can also define those. So this is an example of parsing XMLC data body. So this actually defines three states start one and two and some to transitions based on what it's matching to go from one state to the next. And you can use F call and F return to kind of set up function calls within Rachel which is useful as well. When you start parsing some of the Rachel you're probably gonna reach for it like instead of running a scanner or Alexa you're gonna say oh maybe I can use Rachel. One of the problems with it is parsing recursive structures. Regular expressions are not good for that and Rachel's equipment to regular expression more or less. So how can you do that? The trick is to take advantage of these actions that you can embed and when you recognize within your parse that you are looking at sort of a nested construct you can in your host language set up like a stack push a context to that and jump out and jump back and look at your stack when you need to. So because you've got these embedded actions you can like step outside of what regular expressions allow. You can also implement look ahead. So the trick here is you would match on a couple of characters farther than you want and then you can call F hold which will kind of back the parser up for each time you call it backs it up one character. So internally when you're working with Rachel it has all these variables that you're gonna interact with and they represent the state. So there's data which is a buffer which is where you kind of store your strength. So we'll see in a second here like when you call Rachel you basically set up data in a buffer you set a variable called p which points to the front of the data pe which points to the end and then you just tell Rachel to go and it'll match on everything between pe and pe. When more data comes in you kind of tack it on to the end move pe and pe and like tell it to go again. So if you want to match one character at a time you can just line up pe and pe and you can kind of move them along. And when you're inside a scanner it's actually uses some other variables ts and te because it's in order to do the scanning and do a longest match it actually looks ahead and stores some state on a stack and backtracks what it leads to. So roughly you know you start at state zero you feed it data it runs the exact loop the characters move through the state you consume this p to pe data and it's done if your current state matches a final state which gives you a list of them means that you've admitted this drill. For scanners it's similar except it uses ts te and a stack. The way you extract a string when you're so this is like as you're moving through the scanner like you'll use this kind of slash mark that marks the beginning of something you're interested in and this percent would say like I'm leaving the transition that's what I want to admit. So when I enter I store where I was so data p and then when I leave I store data p I store from my mark to my pe I pull that out and I store it into my things or a for example. As I mentioned there's a bunch of different post language languages and coding styles. One of the nice things you can do with Rachel is you can write a generic parser and just refer to all these actions by name and you can have multiple other files that you would include so I could have one definition of HTTP and then my actions I can have my actions defined as C and my actions defined in Java and that's actually what Pima does. You can also prototype something in Ruby you get it working how you want and then go convert it to C pretty easily because you have most of your logic inside Rachel. So the director is that you need to put in your file or in a net which sets up kind of all the state. Data which has all the states and transitions and exec is actually causes it to run that loop that I was describing. So this is an example of some of the code that that generates. So installing it on a Mac it's really simple just brew install Rachel and to generate the Ruby from like a Rachel file you just say Rachel-R for Ruby simple.rl would be the Rachel file in this example and you give it the output. So this will build your Ruby file and we'll take a look at it in a second and debugging these things it's kind of hard to do visually or it can't be hard to do visually so Rachel actually lets you emit these out to a graph is dot file which you can then kind of make an SVG or PNG out of and kind of look at all the states so I'll show you in a second. So this is an example of calling it from Ruby so this would parse the data so take the data we have to unpack it into the binary format that I mentioned from characters. We set the EOF as a variable that Rachel uses to know when it gets to the end. Tokens is our variable where we're storing things call init, call exact and that's gonna process everything that you put inside data. So somewhere in the actions it's actually pulling things out and storing them and the tokens are right here. So I created a tool here for kind of doing some visualization is, I'm gonna pull it up to figure out how to get onto the screen. Can you see that? And I actually can't see it so I'm gonna put it around here. That's done called as mirror displays, right? Where is my cursor? Lost a window here. So this is actually a little app that I built in Volt which is pretty cool framework. You guys haven't used Volt so you can go to check but it allows me to kind of experiment here and kind of see what these graphs are. So normally to build these I would have to run a couple of command line commands but I just kind of set it up in here so I can do stuff like this. So I've got examples of like the different machines in here. So this is a machine that matches on simple. Oops, sorry, I got an auto update. So this is an example of the state machines that are being created by this. So if I want to match on sim or PLD it would look like that. Or if I want to zero more of those. Let's say I want to one more of those. So I can kind of build these things up and play with it. I have the code for this like referenced here. Pre-sensation window here. So if I want to kind of create a new machine here so I'll just call this new machine. Let's take a look at some examples here. Everybody see that? All right. So this is an example of the machine I, well it's like the machine I showed earlier where it was matching on, this isn't the machine I showed earlier, it's matching on zero more than those. So I've set up sort of a regional parser base here. I'm actually going to take a look at that. So in parser base I have, I'm setting up some variables manually here. I have a way of feeding a data. I have a way of asking if I'm in a final state. I have a way of pulling out the current match. And I just sort of, I have it, I'm putting some debugging data here which I'll show you on the console in a second. But I just have this set up so that it'll read from standard in so I can use it for experimentation. So this is a hello, this is hello parser. And this is, this is the file, this is what the file you work with looks like. And then we take a look at like the generated file. I'm sorry, the hello rb. So this is the generated file and Rachel's doing all this work for you. So this is setting up all the states up top here. This is a pretty simple state machine so there's not much going on here. But this is the init that we saw. This is the perform method and this is the exact that was buried inside of it. So it's setting up all the states. It's doing go-tos and jumps and matches and et cetera. So all this really nasty code which is heavily optimized, so that's why it's so fast. So this particular example here, I'm gonna run this one in a second. One small mark, let's try that next one. Oh, let's comment it out on this one. So I typed h, you can kind of see that it's in current state one now. p is at one and pe is at one. And we have one piece of data at h. I say e, l, l. Our final state here at the bottom is still false. So we're not in a final state, we're gonna press o. We've now entered a final state, so we've matched on hello. And I press h again and we're not matching. e, l, l, but proceeding on that character, I'm gonna step outside of what it knows. I'm not in error state, I'll never match again. So that's an example of sort of a basic example. I have some arg parsers defined here. So there's, I mentioned state charts and not using state charts, so I've one defined here using sort of standard approach. So this is the main part of my parser and I'm just saying I wanna match on an arg, dash and flags or dash, dash, long opt. Long opt, I have defined as a bunch of alphas. Flags would be a bunch of alphas as well. And what this is gonna do is this parser is gonna go around and around in a loop and when it sees some dash, dash, long opt it's gonna call saw long opt. So the Ruby code is actually pretty simple there. And these are the actions up here. So I call mark arg when it took out of Marcos sort of it. Not really, can't see no. How do I change the color? Yeah, that's what I did. How do I do that? What's that? Okay. Where's my system preferences? Accessibility? Where are colors? There you go. Is that more legible? Okay. So what I'm doing here in the code is when an alpha is matched for its first time I'm kind of marking the beginning of the argument, marking the beginning of the flags, marking the long opts. And then when I get to saw arg, which is what the scanner calls, I'll use that previously marked thing to kind of pull out what was there. So I can do dash, a, s, d, f and see it. And I'll put in flags, s, d, f, so that means I'm not showing that there. So now I can do like a long one. I can say long opt. So matched on long opt. So that's just an example of kind of doing basic argument parsing there. And then I have an example of this in the sort of state chart for it as well. So state chart is a little bit more complicated when you draw it out of paper. It's simple and you can operate, you can do the dot biz visualization of this as well. But I start in a start state here. If I see a dash, I'll go to pre flag. If I see a quote, I'll jump to quoted value. And if I see anything else, I'm gonna kind of start a value arg. So as an example, this is what I'm calling. Val arg is just kind of a word. Quoted v could be a quoted word. Flags would be this and like a long, long flag would be that. So the basic idea here is that you create some buffers and as you match or kind of go around in a circle in a state, I'll keep it pending to that buffer. And then when I leave the state, I'll admit what I want, looking up what I've stored. And, oops, sorry, the Ruby code for this again is very simple. Most of the work is being done up inside the parser. So as an example, the same thing, but you know, I can say, you know, ASDF and then val arg and I got a val arg. I can say quote, quote v and I got a quoted value. Space brings me back to start. I can say dash dash long equals, I got a long quote, quoted and I got a quoted. So I have links to all this code. So after the presentation, you guys wanna like pull it up and kind of like dig through here, figure out what's going on. It's in there. Let me go back to the presentation here, if I can find it in this color. You got an invert, the presentation got closed. So while I'm looking for this, does anyone have any questions? I'm not familiar with what, so TreeTop's all in Ruby, right? Yeah, so TreeTop is, it may be similar, like presumably they may be doing kind of similar techniques under the covers. I'm not super familiar with how TreeTop does things, but this is like super highly optimized. For the C version, it can actually, actually one of the versions compiles it down into just jumps within a while. So like it'll go to the bottom, it'll go to, it'll go to, it'll go to, it'll go to. It's almost like optimized assembly. So I'd be surprised if it wasn't faster, but it probably really depends on this case. No, definitely. It allows you to, it allows you to do chunking. So you can kind of think about your problem in smaller pieces and unit test those and then compose them together. So like as I mentioned, the composition is, like it's two main things that make it really cool. The composition is one of them. Like that's kind of mind blowing. And then the fact that you got these actions. So I can not be in a programming language and then suddenly be in a programming language. Okay. Right, right. Yeah. I mean, if you're, if, does TreeTop do other languages as well? Okay. Yeah. So if you, if you were writing an HTTP parser, you wanted it to work like, you know, quickly on J Ruby, so you wanted it down in Java and also like in C Ruby. So you wanted it down in C. Then this would be a good choice. Yeah. Right. Yeah. So the question is like, how do you know, this is using instance variables and kind of local variables. And so how would you like turn this into kind of like a composable unit? Yeah. So that's, that's actually kind of what I, what I tried to demonstrate here. So I created this Rachel parser base and I have, I have several parses which kind of inherit from it. The default is to use local variables, which obviously it's kind of painful. Part of the DSL, you probably can't see it again. So we invert this. Yeah. So this is, since I, it depends on where you put these, it depends on where you put like these things. So right, I put these inside this object that I've created. So when it, when it refers to app, it's going to be in the context of this object inside the context of this method. And you can remap what it does. So normally it'll just refer to P. I have it referring to app P, because I set up the stuff up here. Hey, there it is. So I showed the demos and that was it. So I've got these resources here. I have the slides up and I've got the, I got the playground code up there. Had some other features I wanted to add to it, but I kind of ran out of time. So I hope that was useful. Sorry if I drowned on.