Hello and welcome to part two of implementing operator predecessors.
Let's go to parse the dot C and just scroll all the way to the top here and we're going to say extern
op presidents.
So we're basically referencing this.
Okay.
And it's going to be the structure of.
Our Presidents group.
And we can see that there's also an array size of total operator groups.
So we're just going to do that.
We're going to need to put some stuff in the header file here.
So all I wants to do is copy and paste this and we're going to remove it and just put it in compilers
h.
Just like that.
So now that we've put these in the header file, they'll be located in paths a dot C and expression
object C.
So obviously by making it extern, we're not actually defining the memory and parse dot C, we're just
referencing the memory in expression of dot C.
So that's all good.
So any access to here will actually be accessing the array in expression object C.
Perfect.
Okay.
Let's just scroll down to where we parse our expressions so you can see the paths expression normal.
If you remember the last lecture where we edited this, I explained how we need to reorder the expressions.
Okay, so what we're going to do, which is going to call this function, parse, reorder expression
and we're just going to go ampersand expression node.
We now need to create this function.
This function here will reorder the expression node that we've parsed here, flipping the operators
where necessary.
So just by here, we're going to say void, parse or reorder expression, struct node.
And remember that's a double pointer there node and we're going to call this node out actually.
So all I want us to do now is is go struck node node equals asterisk node out that will give us direct
access to the node pointer.
We now want to check if it's not an expression because if it's not an expression, we can't deal with
it.
So we just return.
But we also care that the children of both the left and right node of the expression node are also expressions.
And if they're not, then again we can't deal with it.
So we're just going to say if node expression left type.
So it's not equal node type expression and we have a right node and that right node.
Type also does not equal no type expression.
Then we're going to return.
So essentially.
If our lymph node is not an expression and we have a right node and that right node is also non expression.
Then return.
We can't do it.
So in this scenario, we have no expressions.
So that means there's nothing to do, right?
Because the left node and the right node are not expressions.
So in this particular scenario, someone might have passed 50 plus 20 to us.
Okay.
And since there's no other expressions, there's nothing to change.
So we're now going to check to see if the left is not an expression.
And we have a right expression,
then
this means as possible, some reordering is required.
So the first thing we're going to do is we're going to get the write up.
So at this point in time, if you imagine it, we kind of have like on the left node, no expression,
so it'll be like a number or something like that.
Yeah.
And then we have our expression here on the right node.
Now that doesn't necessarily have to be any brackets at all.
Right.
Parenthesis and just demonstrating how the node sees this.
And in fact, just to demonstrate that further, we're going to put an E there, just to represent that
it's an expression rather than parentheses.
So we can see on our left node we have just a 50, but on our right node, we have an expression that
contains another expression that has a left of 50 and a right of 20.
So before we can finish this function, we need to implement some more functions.
So first things first.
We need a function that tells us which operators have priority.
Okay, that's pretty important.
Is it the root operator of Plus or the sub operator of plus?
Now we know that they have equal priority, but if that was multiplication, then it would have priority
over the plus.
Right.
So we need a function to tell us this.
So we're just going to go static ball.
Parsa left AAP has priority concern Shah OP left can't operate.
So obviously this function will return true if the left operator has priority over the right operator.
So we now just need to create a function that returns the president's right.
So we're going to do static in it.
Pause to get precedence
for operator punch up struct expression level.
Oppressed and screwed up so we can just copy and paste that there because it is hard to spell out to
group out.
Okay, nice.
So we're just going to go ask this group out.
Equals no.
So what we're doing there is someone who calls.
This function will pass in the expression a lot precedence group and then we will basically set it.
And that should be a double pointer there.
Not a single pointer.
My bad.
Okay.
So we basically set the pointer to NULL.
So a lot of these functions might be better in expression of all that, see?
But for now, we're just going to keep them in positive, just for simplicity.
We might move them later on if it's appropriate.
So what will this function do that we're writing now?
It will basically return the precedence for the operator we provide.
So all we're going to say is we're going to say French equals zero ie below total operator groups.
I plus plus four in it b equals zero up precedence.
I thought operators b, b plus, plus.
So we're basically saying go through the groups.
If we do not reach a null, then we're still processing this operator group.
Okay.
That's basically what this says, because if this is zero, then the clause will fail and the follow
will end.
Right?
Because remember, we have a null at the end of each group, that's why.
So we know when to stop.
So we're going to say const char underscore all up equals up precedence.
I operators.
B
if s equals.
OP.
Then we found that operator and we're simply going to go asterisk group out equals ampersand or precedence
and now we return.
A Because that's our precedence.
Because our precedence is the group that it's in, right?
So Group zero.
Group one.
Group two.
Group three.
Group four.
They are presidents, right.
Okay.
So just by here, we return minus one.
And that means we couldn't find the operator in the presidents table.
Okay, so now we're ready to continue parse the laptop has priority.
And just to let you know, presidents is one of the hardest parts about making a compiler presence and
expressions.
So once you've done those things will be somewhat straightforward from there.
So here we're going to say struct expression, double op precedence group, and I'm just going to copy
and paste it just in case I made a spelling mistake, which I did.
And we're going to say group left equals null and then we're going to do it again for group, right.
I'm going to set that to NULL as well.
And now we're going to check if they're the same operator, the ones they provided us, because if they
are then left, does not have priority because they're equal.
Right.
So we just return false.
Now we're going to say in it precedence left equals parse gap precedence for operator upper left ampersand
group left.
I'm going to do the same for precedence.
Right.
Parse that gap precedence for operator operate ampersand group.
Right.
So after calling these functions, these pointers appear.
Group left and group right will be set.
To the press and scoop for that operator that we got the precedence for.
As you can see by here on line 97, we do that.
So now we're going to say if group left has an associated entity.
Of right to left.
Then we return false because we can't handle that here.
So left does not have priority because it's a right to left a social activity, whereas this function
is dealing with left or right sensitivity.
So now we just return.
Precedence left below.
Equal precedence.
Right.
And that will tell us if the left operator has priority.
Okay.
So if we pass in multiplication here and plus here, this will return.
True, because multiplication has higher priority than addition.
So that's a nice little function for working with the reorder function.
So let's go back to the reorder function.
So here we're going to say if Parsa left up, has priority note expression op and just rename op to
write up.
And then we're going to put right up by here.
So in this scenario, remember that our left operand here is not an expression, it's a number 50.
So we're grabbing the plus operator of that root expression and we're putting it here.
So we saw a plus goes here, and then we're grabbing our 50 plus 20.
Let's change that to 50 multiplied by 20.
So we're grabbing that 50 multiplied by 20.
We'll grab in the multiplication operator, we're putting it in the right up.
So then this will return false because addition does not have a greater priority than multiplication.
So let me just explain to you what we've done so far.
Firstly, change this 50 in this comment to a multiplication from an addition and just change that to
30 in a plus.
So let me break this problem down for you.
I left node of this node expression is not an expression that's important for this statement.
We also have a right node and it is an expression.
This code doesn't run without that.
Okay.
So let me break down this problem a little more.
So you understand.
So this is actually 50 times expression and even that is an expression in itself.
So it looks like this.
Now, our root expression will call it as a left operand of number, which is 50 and I right operand
of expression.
So what is our right operand of expression?
It contains a left operand of 30 and a right upper end of 20.
OC So back to our Bob mass scenario.
Our 50 multiplied by expression has priority over addition.
So what we really want to end up with is an expression which basically turns this input here into basically
50 times 30 plus 20 because Barb mass knows the multiplication has higher priority.
And in addition, so this is what this code is going to do.
We're going to shift the operator to the left.
Okay.
So that explains what I'm trying to accomplish here with you.
So passive left up has priority that returns true.
So what do we need to do?
We need to shift the Trojan to the left.
We haven't created a function that does that yet, but we're going to create that soon.
So let's just pretend it exists.
So we're going to say pause the node, shift children left and we're going to pass in the node.
So just as an example, let's pretend we have something like 50 times E for expression 20 plus 121.
This function's called we'll end up with expression 50 times 20 plus 120.
So as that makes sense, we've shifted it.
We've shifted it out of its own expression into the left operand, which results in the left becoming
its own expression and the right becoming a number.
That's what this function will do.
But we're not quite done when we've done that because we've just changed the syntax tree.
So we now need to call this reorder function on itself so it can go through it again and reorder if
necessary, because we've made a change that might affect the rest of the tree.
Right?
So we just go parse the re order expression, ampersand, node expression, dot left pause of reorder
expression, ampersand, node expression de right.
And that ensures that any change we've made that's changed the operator order will not be affected because
we'll call reorder expression again and that will call reorder expression again and that will call will
expression again until everything has been resolved.
So we now need to create the paths and node shift chosen left.
So just by here we're going to say voy parse the node shift children left
struck node node.
And the first thing we're going to do, we're going to assert that the node is a node type expression
so there's no bugs or anything.
Yeah, it's better to catch the bugs with assertions guides.
If you don't put the assertions, you're going to have compiler bugs because everyone makes mistakes.
So we're also going to check that the right is also an expression.
So we're checking if the node provided to us is an expression and the right node of that node is also
an expression.
So we're just going to go const char right up equals node expression to write the expression up.
And that'll be a pointer access there like that struct node new expression left node equals node expression
left struck node new expression right node equals node expression dot right dot expression dot left.
And remember I said a dot there.
I meant this because we're accessing the pointer there of the right node.
Okay?
And then we're going to say make expression node new expression, left node new expression, right node,
node expression dot up.
So that creates our new node.
So essentially the new expression left now will be this nodes left expression.
The new expression right node will be the left node of the right node.
Because remember, we're shifting the children, as I showed you here.
Right?
We're shifting the children one space to the left.
Right.
So we want to result in this.
But the only way to do that is to basically create a new expression, right?
Because we're parsing.
So to shift it to the left, this is the right nodes left node, which is 20, and this is the nodes
left node, which is 50.
So we've basically just created a new expression of 50 multiplied by 20.
That's what we've done in this code so far.
We're not done.
We now need to go struct node new left operand equals no pop struct node new right operand
equals node expression dot right expression right.
Okay.
So now we're popping off what we've just created here, this 50 multiplied by 20 that I just described
to you or popping that off and we're creating that the new as the new left operand.
So we end up with something like 50 times 20.
Yeah.
And then we're getting the new right operand as the right operand of the right expression, which is
120 by here.
So that's 120.
And now we're just going to go node expression dot left equals new left operand node expression dot
right equals new right operand
node expression dot arp is equal to the right up.
So now this has successfully reordered that node that they passed to us and we now have 50 times 20
plus 120 with 50 times 20 being the priority.
So that's all nice.
So there's two other things.
Just scroll to the top and include certain age since we use the assert function just now and scroll
down.
And I made a slight mistake here.
It needs to be.
And our president's I because we're accessing an array index.
So just do that.
And now just go to the terminal and we're going to do make clean, make.
We can see that that compiles absolutely fine.
Awesome.
So that concludes this lecture.
On the next lecture, we're going to test this operator precedence and see if it works.
Thanks for watching.