Skip to content

Commit a98f9f8

Browse files
committed
fix(docs/11): cleanup question mark
1 parent 36d39b8 commit a98f9f8

File tree

1 file changed

+27
-12
lines changed

1 file changed

+27
-12
lines changed

docs/11-parser.md

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,16 @@ let symbol: Lexer[Char] = pchar(fn{
8484
let whitespace : Lexer[Char] = pchar(fn{ ch => ch == ' ' })
8585
```
8686

87-
The `map` function can convert the result upon successful parsing. Its parameters include the parser itself and a transformation function. At the end of line 3, we use the question mark operator `?`. If parsing succeeds and the value is non-empty, the operator allows us to directly access the tuple containing the value and remaining string; otherwise, it returns the empty value in advance. After obtaining the value, we apply the transformation function. Utilizing this, we can map the characters corresponding to arithmetic operators and parentheses into their corresponding enum values.
87+
The `map` function can convert the result upon successful parsing. Its parameters include the parser itself and a transformation function. After obtaining the value, we apply the transformation function. Utilizing this, we can map the characters corresponding to arithmetic operators and parentheses into their corresponding enum values.
8888

8989
```moonbit
9090
fn map[I, O](self : Lexer[I], f : (I) -> O) -> Lexer[O] {
9191
Lexer(fn(input) {
9292
// Non-empty value v is in Some(v), empty value None is directly returned
93-
let (value, rest) = self.parse(input)?
93+
let (value, rest) = match self.parse(input) {
94+
Some(v) => v
95+
None => return None
96+
}
9497
Some((f(value), rest))
9598
},) }
9699
@@ -109,13 +112,19 @@ let symbol : Lexer[Token] = pchar(
109112
},)
110113
```
111114

112-
Let's look at other combinators. We've seen other pattern matching rules like matching `a` followed by `b`, `a` or `b`, zero or more occurrences of `a`, etc. Each combinator is simple to implement, and let's do it one by one. For matching `a` and then `b`, we first use `self` for parsing, as shown in line 3. After obtaining the value and the remaining string with the question mark operator `?`, we use another parser to parse the remaining string, as shown in line 4. The two outputs are returned as a tuple. Then, for matching `a` or `b`, we will pattern match the result of parsing using `self`. If empty, we use the result of another parser; otherwise, we return the current result.
115+
Let's look at other combinators. We've seen other pattern matching rules like matching `a` followed by `b`, `a` or `b`, zero or more occurrences of `a`, etc. Each combinator is simple to implement, and let's do it one by one. For matching `a` and then `b`, we first use `self` for parsing, as shown in line 3. After obtaining the value and the remaining string, we use another parser to parse the remaining string, as shown in line 7. The two outputs are returned as a tuple. Then, for matching `a` or `b`, we will pattern match the result of parsing using `self`. If empty, we use the result of another parser; otherwise, we return the current result.
113116

114117
```moonbit
115118
fn and[V1, V2](self : Lexer[V1], parser2 : Lexer[V2]) -> Lexer[(V1, V2)] {
116119
Lexer(fn(input) {
117-
let (value, rest) = self.parse(input)?
118-
let (value2, rest2) = parser2.parse(rest)?
120+
let (value, rest) = match self.parse(input) {
121+
Some(v) => v
122+
None => return None
123+
}
124+
let (value2, rest2) = match parser2.parse(rest) {
125+
Some(v) => v
126+
None => return None
127+
}
119128
Some(((value, value2), rest2))
120129
},) }
121130
@@ -312,13 +321,19 @@ fn recursive_parser[E : Expr]() -> Parser[E] {
312321
}
313322
// Put things together
314323
fn parse_string[E : Expr](str: String) -> Option[(E, String, @immut/list.T[Token])] {
315-
let (token_list, rest_string) = tokens.parse(str)?
316-
let (expr, rest_token) : (E, @immut/list.T[Token]) = recursive_parser().parse(token_list)?
324+
let (token_list, rest_string) = match tokens.parse(str) {
325+
Some(v) => v
326+
None => return None
327+
}
328+
let (expr, rest_token) : (E, @immut/list.T[Token]) = match recursive_parser().parse(token_list) {
329+
Some(v) => v
330+
None => return None
331+
}
317332
Some(expr, rest_string, rest_token)
318333
}
319334
```
320335

321-
Thus, we only need to define different implementations and specify which one to use in MoonBit. The former involves defining different methods for the data structure to meet the requirements of the interface, such as the `number` method in lines 4 and 5. The latter specifies the return type of functions to indicate the specific type parameter, as shown in lines 8 and 10. In line 8, we will obtain the expression tree constructed from enums, while in line 10 we can directly obtain the result. You can also add other interpretations, like converting an expression into a formatted string by removing extra parentheses and whitespaces.
336+
Thus, we only need to define different implementations and specify which one to use in MoonBit. The former involves defining different methods for the data structure to meet the requirements of the interface, such as the `number` method in lines 4 and 5. The latter specifies the return type of functions to indicate the specific type parameter, as shown in lines 8 and 12. In line 8, we will obtain the expression tree constructed from enums, while in line 12 we can directly obtain the result. You can also add other interpretations, like converting an expression into a formatted string by removing extra parentheses and whitespaces.
322337

323338
```moonbit no-check
324339
enum Expression { ... } derive(Show) // Implementation of syntax tree
@@ -328,14 +343,14 @@ fn BoxedInt::number(i: Int) -> BoxedInt { BoxedInt(i) }
328343
fn Expression::number(i: Int) -> Expression { Number(i) }
329344
// Parse
330345
test {
331-
inspect((parse_string_tagless_final("1 + 1 * (307 + 7) + 5 - 3 - 2") :
346+
inspect!((parse_string("1 + 1 * (307 + 7) + 5 - 3 - 2") :
332347
Option[(Expression, String, @immut/list.T[Token])]), content=
333348
#|Some((Minus(Minus(Plus(Plus(Number(1), Multiply(Number(1), Plus(Number(307), Number(7)))), Number(5)), Number(3)), Number(2)), "", @immut/list.T::[]))
334-
)? // Get the syntax tree
335-
inspect((parse_string_tagless_final("1 + 1 * (307 + 7) + 5 - 3 - 2") :
349+
) // Get the syntax tree
350+
inspect!((parse_string("1 + 1 * (307 + 7) + 5 - 3 - 2") :
336351
Option[(BoxedInt, String, @immut/list.T[Token])]), content=
337352
#|Some((BoxedInt(315), "", @immut/list.T::[]))
338-
)? // Get the calculation result
353+
) // Get the calculation result
339354
}
340355
```
341356

0 commit comments

Comments
 (0)