 A few days ago, I merged the audit rewrite thing that's been going on with Stringear back into the Mastery branch, and I'd like to just talk a little bit about what the plans are from here since I said the tutorial videos are holding off to a 2.0 release. The stuff I've already got done, the way the project had developed originally was just as extensions, and some of those extensions wound up turning into just the entire parsing engine, literally by accident. I didn't really mean for that to happen, but I could kind of tell where it was going partway through. When I added the alternator, the one or the other, that was the big one where I'm like, oh well, I've already got this in the wrong namespace. Shit. Because if you're doing extensions, it's generally viewed as fine to populate an existing namespace, one of the namespaces that's part of the core libraries. But you're really not supposed to add new ones, because there's always the possibility that there's going to be a namespace collision down the road. So, yeah, don't do that. And since it was starting out as an extension, that's fine. But it didn't stay that way. That's been fixed. The extensions that were there when the project first started are still in the system and system.txt namespaces, like you would expect. You just install the NuGet package. Well, not even really install, you just say you're dependent on it and it pulls it down. And you've got the extensions, boom, you don't need to add any namespace. It's just there, because they're extension methods. The pattern engine, the parser engine, whatever you want to call it, that's in its own namespace, like it should be, that's stringing your dot patterns now. So there's a little bit of a migration thing with that. But for the most part, everything should drop in, which is good. I wanted to fix that, but I wanted there to be as little issue with migrating as possible. I'd also migrated all of the tests to be exclusively an F-sharp. And the reason for that is I noticed some of the F-sharp support was not up to the standards that I really wanted, not up to the standards that I expected out of myself. So that's done. The reason for it is the F-sharp code has to call the C-sharp code, so you effectively get better code coverage that way. But it also means that everything in the actual implementation library is guaranteed to be covered that way, since there's nothing being added by the F-sharp stuff. It's just a wrapper, basically, just to provide a more functional feeling interface to all the code. Since the actual core stuff is CLS-compliant anyways, it's all there. If you want to just stick with that, it's still there. It's just kind of a user experience benefit. You get to work in the environment that you're much more familiar with. If you're doing an F-sharp project, it's probably because you want a functional programming environment, and this just kind of adds that on top. So yeah, forcing myself to test everything through F-sharp happens to also force myself to make sure that there's always good F-sharp support. And like I said, the actual core libraries get tested anyways. There is still some stuff to do, despite the fact that I merged it. The merge happened because I was happy with the results of the audit, not that the work is done. Basically, that was an audit rewrite branch. And then there's still some work that needs to be done for the 2.0 release, but it's not much at this point. I had planned, and they are actually kind of implemented, but I'll talk a little bit about it, for factory functions for generating common patterns. Kind of like a generic thing, but you can't have an initialized generic that's not making a whole lot of sense because it's not a thing. But the factory functions, you just pass in the little bits of information it needs to provide the full pattern, and it outputs the full pattern. So an example of that is like line comments. Line comments in basically every language work the same way, so you can provide a nice generic form and just specify the delimiter that the line comments begin with, and you'll get the full pattern for that. A similar thing already exists for string literals, including escapes within string literals. Anybody who's done a decent amount of regex stuff knows that the regex for that is a little wonky. And just because of some of the features I was able to provide with the string here, it's a little bit better, but this just abstracts away all of that. You just specify what the delimiter is, and if there's an escape, you specify that too. And it just outputs the proper pattern for it. I had originally specified that as a requirement for the version 2.0. I've changed that into an epic instead. And the reason for that is really, there's no point in which you fully implemented factory functions, since they're just a matter of convenience, as you recognize more patterns that might as well be done through these factory functions. You just keep adding new factory functions, just as a convenience. So another thing that could be done is globally aware phone numbers, since that's something that you'd often want to validate. And then you'd just specify the your locale code, and it could spit out the pattern for whatever the phone numbers are for that locale. Obviously, that's quite a bit more of an undertaking, since there's a lot of different variations for that. Why are you barking? Huh? Why are you barking? I think he's lonely. He's kind of attached to the hip. He's a little cry baby too. He probably wants to come out here with me. Nope, he's, yeah, he's weird. I guess he is coming. Lastly, I've pretty much narrowed down what I want to do with the jumper target system. For those who don't know what I'm talking about, basically, with the approach I'm taking, since it's based on a decision graph, it's actually really, really easy to implement left recursion and mutual recursion. And I'm just trying to find the most optimal way to actually do that. And I've pretty much narrowed it down. So that's coming soon. That's one of the big holdups for the 2.0 release. Especially in academic circles, they really like to see left recursion supported by a system, even if it's a hacky approach. Like a lot of your parser generators, they're also called compiler compilers sometimes. Some of the approaches, some of the parsing algorithms they use, don't always play nice with left recursion, but they've sometimes figured out ways to introduce a new algorithm in the instance that left recursion is used. And then just use that algorithm instead to support left recursion. I don't need to mess around with any of that. The approach just supports it. It's just a matter of directing the flow the appropriate direction. Like I said, just I know this works. It's just figuring out the most optimal way. But I basically have that. And another thing I've been doing around the time I was working on this, it wasn't really clear that Quantex Fparsec is really seems to be abandoned. It became more clear towards the end of it. And I made some comments about that in the introductory video. That's not meant to disparage Fparsec. It's actually an amazing thing. They worked out a lot of the performance problems that parser combinators have, because yes, they actually do have parser performance problems. Um, performance is really good in many regards, like really, really good in many regards, but they face some difficulties in certain areas. And the guys working on Fparsec solved a lot of them. But they're testing it was awkward because due to some problems with the last package they ever uploaded, uh, part of it was only built in debug mode. So that causes performance problems when you benchmark against it, forcing you to use the, I think they call it like the big data addition or something, which was only built for the .NET framework, not .NET Core, which really everybody should be migrating to. And it didn't work on Mono either, which I don't know why you'd be doing tons of parsing on a mobile device. But I'm sure there's some need for that somewhere. I know there are people playing around with compilers and shit on the phone and probably more as like a prototyping quick edit thing, but it's still nice to be able to say you support that, especially when it's not any additional work. But because of that, I couldn't profile it against my main benchmark set. So I had to maintain two benchmark sets. And because Fparsec is very F sharp specific, and had to maintain benchmarks in two different languages, and just decided to drop that for many reasons. But I still want a benchmark against parser combinators, because that's a major parser approach. So what I'm, what I did, this is already done, is I took one of the supposedly quite good parser combinator libraries called Pigeon, which is actually CLS compliant. It's mostly targeting C sharp, but because it's CLS compliant, it will work on F sharp and other things. Pigeon seems to need a lot of work. Like I'm sorry, guys at Stack Overflow, but I'd stop the, honestly, I would stop the project and contribute to either Sprock or Superpower. That being said, I don't have benchmarks against Sprock or Superpower yet. But from what I've seen from other sources, they seem to be just absolutely great. Because Superpower is ultimately based on Sprock, I intend to add benchmarks just to Superpower. But it's not the easiest thing to use. Pigeon happens to be one of the easier parser combinators to use. So it does have that going for it. But even then, there are some quirks just because I really don't think functional programming is the right way to go with this. Like object oriented is actually really good for this kind of thing. But whatever. So I need to add that in. But I do have benchmarks against Pigeon. I also found somebody, well, because I've been looking for another regex implementation that works on .NET, whether a toy or a binding or whatever, just so that I can compare it against another regex implementation and also compare regex implementations. I did not find any native .NET implementations, but I did find that somebody made bindings to PCRE, which is an excellent regex implementation. So just today, I went through and added the PCRE stuff to all of the benchmarks that I had. And I'm sort of finishing up migrating all the benchmarks over to the new stuff. I can definitely say now that I've seen the benchmarks, for more complex patterns, PCRE does a really good job. For simpler stuff, MX regex seems to do the better job. So if you're doing something that has to use regex, or you just need an easier migration path because you're trying to get some performance, but don't have a manager approval to a more sophisticated approach like parser combinators or what I'm doing, consider looking into the PCRE binding. It seems to be quite good for more complex stuff, but always benchmark. Don't just take my word for it. There's always edge cases. There's always things that one does better than the other benchmark and actually make the decision based on the good hard evidence. Specific to your case. Not generalized stuff, just specific to your case. That being said, the 2.0 release is basically almost done. I don't have a huge feature set requirement just because the features that I've already added by this point are basically already there. It's really just rounding stuff out at this point. I'm trying to remember the issues I put up, but I think it's basically just waiting on the target jumper thing at this point. There's some other minor one, but it's a minor one. Something I can knock out in a few hours. Now that being said, I said that just the last time, so that's awkward. I did realize today that there's really not a whole lot of educational content as far as this kind of stuff goes, just text processing in general, but even like parser frameworks. We'll call the entire collective just parser frameworks. So I think I'd like to cover that a little bit to give a little explanation on like what the different components of these are, like what's a lexer, what's a parser, what do they mean by like an analyzer or a synthesizer when they talk about compilers, stuff like that. Because I'll notice some interesting stuff. I focus primarily when we talk about language stuff. I focus primarily on the analyzers, which I see a lot of people just assume that that means like, oh, you write stuff that, you know, like determines the the code complexity or the slot. And kind of, but there's an actual thing called an analyzer. And that's my thing. Yeah. But you just kind of give a easier to understand explanation on what a lot of these algorithms are and that kind of stuff. So expect some of those videos somewhat soon. I'll get some presentations made up for that. Until then, have a good one, guys.