 All right. Thank you, Mingning. So, yeah, an introduction. My name is Chiang. I work at Pocket Math. I'm on www.chiang.b. And yeah, past seeing expression grammar. So, it's actually this talk is started as one of the refactoring effort at our company that we just decided, okay, we should go a different route and then I had to present to our team and then I thought why not just share it to the Ruby community as well. And basically, I'm just beginning to learn this as well. So, I'm by no means an expert. Oops. All right. Yeah. So, I work at Pocket Math. We are an advertising programmatic advertising company. You can check out our product if you want to increase your conversion. Yeah. And again, it is claimed I'm not an expert in compiler design. It's just a sharing that I've learned over the past couple of weeks. And to start up, we'll set our objective to be implementing a DSL without using eval or instance eval in Ruby. DSL is basically domain specific language. Oops. Oops. Too fast. Too fast. An example, if you guys use Rails, a lot of people raise their hands so you would have seen this before. You declare resources articles, which has comments as it's nested resources. So, this is a form of domain specific language. Anyone knows what this is? Shout it out. Yeah. So, this is Rails in Rails, right? Another example, quite easy too. It's RSpec. It's also, to me, a domain specific language. So, if you read it, it is Ruby, but it's also in the language of testing, right? You say, okay, the subject here is going to be object. Before any of the tests, you have to do this. And it expects that this will equal to whatever you expect. So, it's a language. And for us, we had this feature that we call Rules, which you can read about at our blog post, which is a DSL that we designed for our customer to use our platform. So, one of the rules example is like this. Say, the customer will think of automatically changing a variable in the configuration of their campaign, right? One of it is, say, the publisher's cost per meal, right? CPM. So, they'll say, okay, if the publisher's impression is more than a thousand, then you set this CPM to this particular formula. This is just one example. You can do a ton of other things. You can, suddenly, you want to pause the order. You can want to start the order. You can save the publisher name to a particular list. So, yeah, you can find out more at the blog post here. So, this is the feature. We want to implement this without using eval. But now, I'm going to just focus on this last bit, which is the formula that will evaluate into a floating point number that we can set into our campaign configuration, right, to the publisher's CPM. So, the easiest way is just evaluate it. Just make sure before you evaluate, the publisher is there. Order is there. Impressions and win rate are the legal methods. And in the form, we just educate the user, okay, you have to call a publisher a spell like this. And you can only call win rate in a couple of other attributes, similarly for order. So, yeah, the validation is just tedious to do this. And when you see eval, this should be your reaction. It's just nasty, nasty things, right? Because it's easy, but then the responsibility to validate it, yeah, it's huge, right? Because there could be crazy things like that. And validation, though, is not trivial because, yeah, like I said, you have to educate the user, okay, hey, if you put anything other than impressions with a plural impression, and it doesn't work, we have to think about, because we don't do eval, right? So then we have to handle the operation precedence. If the bracket is there, you have to evaluate those first, things like that. So, it was difficult. And at the start, we just do regular expression and just pass and oh, okay, if the order is there, these other attributes should be allowed. Yeah, check that the operations multiply, addition, those things are there. But there are still abuses that can happen, right? And it's ugly. You see this block of code, you wouldn't want to read it, right? So that was just the formula. And if you think about the whole DSL, it's even harder to validate, right? If you need a condition there, and then you need to follow by then, so your reggags that will validate, all this is just going to be crazy. So, the way we go about it is we don't let the user actually write the language. We use UI to enforce most of the DSL, right? But essentially, the users here are doing their program, right? They're saying, okay, if the publisher impression is more than that, or else, and then you do something, blah, blah, blah. So this is sort of a program that we empower our user to do. But we still are stuck with the last one, right? You have to set the value to a formula. So today, and that's how we had to, okay, just find a better way. And then here I shall introduce PEG, Passing Expression Grammar. It's sort of like a more modern tool to attack this problem, right? More semi-formally, PEG describes languages, and it does so in a top-down manner. For example, the three lines there, pseudocode, it will describe a mathematical expression like you say an expression can be a term which can have an addition or subtraction with another term, and it can repeat zero more times. A term in turn is a factor which can be multiplied or divided by a different factor, and a factor is a bracket expression or a number. So with this, you can, not sure you can see here, you can describe things like this 23 plus 45 multiplied by 5 minus 1 can be passed, can be described by that language, and you can break it down into a tree, right? And it's top-down in the sense that it will try to match from the top, from the whole expression, and then at the end of each single one. So at the end of the day, you get a factor which is 23, and operation plus with another term here, which breaks down further. So here you can break down into a number, another operator, and then another number. So with these three lines, you can describe just purely numerical expression. So let's say we want to support variable, and we just say, okay, a factor on top of being a number or another expression, it can also be a variable, so which is a subject or an attribute, subject dot attribute, right? So and then subject, you can define further what are your legal subjects, what are your legal attributes for our example. Just now, the subject would be either publisher or order, and then attribute would be the impressions, the CPMs, and things like that. Yeah, so it's very easy to extend the language in this sense. Okay, later on, we'll sort of visit this again, and you'll see that if, in a case where there's an operator, we can, I'll call one the L term, the left term, the operator term, and the right term. So we'll come back to this later. And so that's PEG, and that was all pseudo code, right? And in Ruby, I've only explored two alternatives, two gems. So this is, yeah, unfortunately, those things that you just gem install and hope that life is peachy. So one is parsley, and another one is slightly older one, treetop. I didn't go all the way for the treetop gem. It looks much closer to the PEG pseudo expression, right? But it just doesn't feel very ruby-ish to me. So for parsley, you're basically just subclassing one of the gems class, and then you define the rule, and then at the end of it, you can use the parser and just pass a string. And one of the output from parsing it, so from here on out, I'll only be talking about parsley. One of the output, which is E, right, it's just a hash, which is in that sort of state. So let's say our expression here. We're about to break it down into a tree, which at the leaf node, you'll see that it's very recognizable. We can only have three shapes. It's either a variable, which will be a hash of a subject and an attribute. It'll be either a number or an L-O-R hash, right? So it's the left operation and the right. Yeah, so the right, it'll be one of the other two. So yeah, so suddenly our formula is very structured. And PEG sort of ends there. It's just this thing that describes languages and helps you pass out the structure. So the cool thing is that what we can do with PEG's output is supported by Parslet is to evaluate, to quickly collapse all those three back into one value, right? So you can define an evaluator, which will expect, let's say, the variable term previously. You know that it can have a subject and an attribute. So you just do some checks there and then subject, send attribute, just make sure they are symbols. And if it is a number, yeah, you can just make it cast it to string and then to rationale. You could do to float as well. And then if it's a left operation and right, yeah, you just, the left term, which will already be calculated into a number because each of these two terms, the leaf of the left right, will collapse into a float. And then with a float, you can send the addition sign with the right as the argument. So at the end of it, all of these three will evaluate into a number. And with the same class, you can evaluate, you can have your own evaluator, right, which is much safer. So you can't do any RM things here because immediately you'll put the string into your parser, which will raise an error if it doesn't match our language. And then, yeah, you can just apply passing in your order and publisher into it. So, yeah, it's much safer with your own evaluator. So the way that we can use eval now is, okay, we have an expression. We can just evaluate the expression itself, giving it the order and publisher instances. And we know what the error can come out at the passing step, et cetera. All right, so this is where we were previously. We used just UI to help the user go through that big part of the DSL, right? And then in the last bit, the formula, we just brute-force regress and ng-subbit. But after we moved to it, to PEG, it's just a way that I see that, okay, now rule, mapping from the rule in the user's head into the execution is a little bit easier to reason about. And then eventually, we can even remove the UI step and then enable a separate channel when we support the if and the then part of the rules. And yeah, I'll put a quote here by Donald Knuth. Let us change our traditional attitude to the construction of programs instead of imagining that our main task is to instruct a computer what to do. We should concentrate rather on explaining to other human beings what we want a computer to do. So the idea is that keep your code readable, because yeah, your teammates and yourself will thank your readable code later down the line. Yeah, so that's my presentation on PEG. Any questions? How do you keep the grammar and the UI fit in sync? Because the stuff that you need to, if you're generating, if you're generating statements, right, that you're then subsequently passing back, then I'm imagining you want to have a structured way to generate that UI fit to begin with. Yeah. So right now, we only do the PEG for the last bit. So the formula is, so it's just a textbook. And yeah, you're right. If we need to support this UI, the UI will have to evolve as the language that we support evolve as well. Yeah, which is a pain that we are facing now, like, because these rules is evolving very quickly. And we, it's just like every time we have to update, okay, we have to support another operation. For example, we had to support time range on each variable. And then suddenly we have to redo the whole form. And yeah, that's something we're still thinking about. It's library that your team is building. Is this a closed proprietary library or is it open source? Partslet is actually not our company's. It's an open source one. Right. Yeah, so what we do is, if you see this rules feature is, yeah, we just use this parcel thing so that when we evolve the rule languages, it's just easier to maintain the code. There's really no proprietary thing going on here. Any more questions? Okay. Thank you. Thank you.