Summary Files Commits Branches @commit @diff @stats
diff options
context:
space:
mode:
Commit70a5c36c26987847d2e0952e215943645c6d3452 (patch)
Author
 Syndamia <kamen@syndamia.com>
2023-04-15 10:34:12 +0300
Committer
 Syndamia <kamen@syndamia.com>
2023-04-15 10:34:12 +0300
Files571be888e48badce2125026f45eb51e6431f0a91
syndamia.com-70a5c36c26987847d2e0952e215943645c6d3452.tar
syndamia.com-70a5c36c26987847d2e0952e215943645c6d3452.tar.gz
syndamia.com-70a5c36c26987847d2e0952e215943645c6d3452.zip
Parent786343ae5bccfd6415e48298bc3b59ae73891d8b (diff)
[blog/seoc] Changed number to state in LR explanations
1 files changed, 44 insertions, 45 deletions
-rw-r--r--src/blog/sane-explanation-of-compilers/part-1.md89
diff --git a/src/blog/sane-explanation-of-compilers/part-1.md b/src/blog/sane-explanation-of-compilers/part-1.md
index 1682807..1ddaab4 100644
--- a/src/blog/sane-explanation-of-compilers/part-1.md
+++ b/src/blog/sane-explanation-of-compilers/part-1.md
@@ -456,10 +456,10 @@ It all boils down to using a whole bunch of conditional statements and tracing w
S -> F | (S + F)
```
- We need to track "how the current string looks", because if we read an "a", it could either be from the left handside of the "a + a" or from the right handside.
- We're going to track where we came from with numbers, which I will define like this:
+ We need to track the current state of the string, because imagine we've just read an "a", it could either be from the left or right handside of "a + a", and that changes what character to expect next.
+ We're going to track the state with different numbers, defined like this:
- |Number|Current expression ends with|
+ |State (number)|Current expression ends with|
|------|---------------|
|0 |Nothing; this is the start|
|1 |The name `S`; the final number should be this|
@@ -471,72 +471,72 @@ It all boils down to using a whole bunch of conditional statements and tracing w
|7 |"(S + F"|
|8 |"(S + F)"; this is the one before the final|
- You can think of every number as the valid, but "unfinished" state of the current string.
- For now don't think about how I've defined those numbers, it'll make sense later.
- But you could make a table for literally every valid state: "(", "(a", "(F", "(S", ..., there is no problem.
+ You can think of every state number as the valid, but "unfinished" state of the current string.
+ For now don't think about the way this table is defined, it'll make sense later.
+ But you could make a state for literally every valid string composition: "(", "(a", "(F", "(S", ....
Keep in mind that the way I'll show the algorithm step by step isn't really correct, but will suffice for the current moment.
- We'll be working with a string, where reading a character from the input means putting the latest one in the String:
+ Reading a character from the input means appending it to the right of String:
```
String : (
- Number : 0
+ State : 0
```
- We're reading "(", so our string "ends" on a "("
+ We've read "(", so our string "ends" on a "(".
```
String : (a
- Number : 3
+ State : 3
```
We've read "a", our string "ends" on an "a".
```
String : (a
- Number : 4
+ State : 4
```
- Here comes the clever bit, for certain numbers, we'll stop reading forward and do something else.
- If we're on the number 4, our string ends on an "a", so we're going to go backward and replace it with an F, meaning now the number is 2.
+ Here comes the clever bit, for certain states, we'll stop reading forward and do something else.
+ If we're on state 4, our string ends on an "a", so we're going to go backwards and replace it with an F, meaning the current state should be 2.
```
String : (F
- Number : 2
+ State : 2
```
- Here is another such rule, if our number is 2, our string ends with an "F" and we replace it with an S, now the number is 5.
- That's why we have a different number for "(S + F", if we didn't, our number would become 2 and we would make "(S + S", which isn't valid.
+ Here is another such rule, if our state is 2, our string ends with an "F" and we replace it with an S, now the state is 5.
+ That's why we have a different state for "(S + F", if we didn't, our state would become 2 and we would make "(S + S", which isn't valid.
So, think of 2 as "this is the first F".
```
String : (S
- Number : 5
+ State : 5
```
- We have a different number for "(S", because if we didn't, we would've gone to number 1, and could've ended the algorithm then and there, without reading the rest of the input.
- Otherwise, we continue as normal, we read the `+` and the spaces around it, going to number 6.
+ We have a different state for "(S", because if we didn't, we would've gone to state 1, and could've ended the algorithm then and there, without reading the rest of the input.
+ Otherwise, we continue as normal, we read the `+` and the spaces around it, going to state 6.
```
String : (S + a
- Number : 6
+ State : 6
```
- Now, our string ends with an "a", it's tempting to change our number to 4, but we shouldn't, this would remove our progress so far!
- Better yet, this number will also be special, if we have a 6 and we end with "a", rather than going to 4, we'll substitute "a" with F now and change number to 7.
+ Now, our string ends with an "a", it's tempting to change our state to 4, but we shouldn't, this would remove our progress so far!
+ Better yet, this state will also be special, if we have a 6 and we end with "a", rather than going to 4, we'll substitute "a" with F now and change state to 7.
```
String : (S + F
- Number : 7
+ State : 7
```
- And now it's trivial, we read ")", so we go to number 8.
- But if we're at number 8, don't continue reading, replace with number 1.
- Now that we're at number 1, if we read any character (including end of string), we'll say the string upto now matches and we're done!
+ And now it's trivial, we read ")", so we go to state 8.
+ But if we're at state 8, don't continue reading, replace with state 1.
+ Now that we're at state 1, if we read any character (including end of string), we'll say the string upto now matches and we're done!
It's also helpful to put what we do in different situations in another table:
- |Number|If ends on|Change number to|Also do|
+ |State|If ends on|Change state to|Also do|
|------|----------|----------------|-------|
|0 |"(" |3 | |
|1 | | |Nothing, we matched|
@@ -548,20 +548,20 @@ It all boils down to using a whole bunch of conditional statements and tracing w
|7 |")" |8 | |
|8 | |1 |Replace "(S + F)" with "S"|
- where, if there is a value in "If ends on", we read the next character, while otherwise we don't and we just execute "Change number to" and "Also do".
+ where, if there is a value in "If ends on", we read the next character, while otherwise we don't and we just execute "Change state to" and "Also do".
-- You're probably wondering why the table works so weird, like why on number 3 we don't directly replace "a" with "S" and change to number 5 for example.
+- You're probably wondering why the table works so weird, like why on state 3 we don't directly replace "a" with "S" and change to state 5 for example.
The reason is that the way I showed the algorithm isn't exactly how it normally works.
- Rather than tracing the current number in a variable, we trace it with a [stack](https://en.wikipedia.org/wiki/Stack_%28abstract_data_type%29).
+ Rather than tracing the current state in a variable, we trace it with a [stack](https://en.wikipedia.org/wiki/Stack_%28abstract_data_type%29).
- When you read a character and have to go to another number, the number is added to the stack (this operation is called "shift").
- When we have to change characters from String (without reading anything), with a string (expression) of length j, we remove the last j added numbers and do a normal shift from the last number and character in String (this operation is called "reduce").
+ When you read a character and have to go to another state, the state is added to the stack (this operation is called "shift").
+ When we have to change characters from String (without reading anything), with a string (expression) of length j, we remove the last j added states and do a normal shift from the last state and character in String (this operation is called "reduce").
-- Let's look at the same example, done with shift and reduce operations (without me showing the table):
+- Let's look at the same example, done with shift and reduce operations (without me showing the proper table), where pushing and popping items from the stack is done from the right side of the array:
```
String : (
- Number : [0]
+ State : [0]
```
We've read "(", add 3 on top of the stack aka shift(3).
@@ -569,35 +569,35 @@ It all boils down to using a whole bunch of conditional statements and tracing w
```
String : (a
- Number : [0, 3, 4]
+ State : [0, 3, 4]
```
With 4 we'll do a reduction, "a" gets replaced by F, 4 is removed:
```
String : (F
- Number : [0, 3]
+ State : [0, 3]
```
- If last number is 3 and last character is "F", we're doing shift(2).
+ If last state is 3 and last character is "F", we're doing shift(2).
```
String : (F
- Number : [0, 3, 2]
+ State : [0, 3, 2]
```
Now, we'll be doing a reduction, where F is replaced by S:
```
String : (S
- Number : [0, 3]
+ State : [0, 3]
```
- If last number is 3 and last character is "S", we're dong shift(5).
+ If last state is 3 and last character is "S", we're dong shift(5).
And so on, we continue.
As you can see, we go back and forth, from 3 to 4, back to 3, then to 2, back to 3, then to 5.
- This way we avoid doing different things on different numbers.
+ This way we avoid doing different things on different states.
Additionally, in the real world nobody makes this table by hand, it is generated by a program, and this method makes table generation easier.
- As for the complete table, you can view it on the [Context Free Grammar Checker](https://smlweb.cpsc.ucalgary.ca/lr0.php?grammar=S+-%3E+F+%7C+%28+S+%2B+F+%29.%0AF+-%3E+a.&substs=) by [](TODO),
@@ -612,12 +612,11 @@ It all boils down to using a whole bunch of conditional statements and tracing w
To read the table, remember that:
- - our numbers are formally called states
- on every row you have each state
- on every column you have each possible value in the string and "$" which signifies the end of the string
- - with sr or shift (or just with a number) you go to another state
- - with r or reduce you make the substitution in the current string and go back one state
- - acc or accept means you've reached the end
+ - with `sr` or `shift` (or just with a number) you go to another state
+ - with `r` or `reduce` you make the substitution in the current string and go back one state
+ - `acc` or `accept` means you've reached the end and the string is valid
##### LR's family