Skip to content
This repository was archived by the owner on Jun 15, 2023. It is now read-only.

Commit fdfd959

Browse files
committed
Parse iflet expressions
1 parent a682fbe commit fdfd959

File tree

3 files changed

+163
-3
lines changed

3 files changed

+163
-3
lines changed

src/napkin_core.ml

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3014,7 +3014,7 @@ and parseElseBranch p =
30143014
Parser.expect Rbrace p;
30153015
blockExpr;
30163016

3017-
and parseIfBody startPos p =
3017+
and parseIfCore startPos p =
30183018
let conditionExpr = parseIfCondition p in
30193019
let thenExpr = parseIfBranch p in
30203020
let elseExpr = match p.Parser.token with
@@ -3040,6 +3040,49 @@ and parseIfBody startPos p =
30403040
let loc = mkLoc startPos p.prevEndPos in
30413041
Ast_helper.Exp.ifthenelse ~loc conditionExpr thenExpr elseExpr
30423042

3043+
and parseIfLet startPos p =
3044+
let pattern = parsePattern p in
3045+
Parser.expect Equal p;
3046+
let conditionExpr = parseIfCondition p in
3047+
let guard = parsePatternGuard p in
3048+
let thenExpr = parseIfBranch p in
3049+
let elseExpr = match p.Parser.token with
3050+
| Else ->
3051+
Parser.endRegion p;
3052+
Parser.leaveBreadcrumb p Grammar.ElseBranch;
3053+
Parser.next p;
3054+
Parser.beginRegion p;
3055+
let startPos = p.Parser.startPos in
3056+
let elseExpr = match p.token with
3057+
| If ->
3058+
Parser.next p;
3059+
parseIfBody startPos p
3060+
| _ ->
3061+
parseElseBranch p
3062+
in
3063+
Parser.eatBreadcrumb p;
3064+
Parser.endRegion p;
3065+
elseExpr
3066+
| _ ->
3067+
Parser.endRegion p;
3068+
let startPos = p.Parser.startPos in
3069+
let loc = mkLoc startPos p.prevEndPos in
3070+
Ast_helper.Exp.construct ~loc (Location.mkloc (Longident.Lident "()") loc) None
3071+
in
3072+
let loc = mkLoc startPos p.prevEndPos in
3073+
Ast_helper.Exp.match_ ~loc conditionExpr [
3074+
Ast_helper.Exp.case pattern ?guard thenExpr;
3075+
Ast_helper.Exp.case (Ast_helper.Pat.any ()) elseExpr;
3076+
]
3077+
3078+
and parseIfBody startPos p =
3079+
match p.Parser.token with
3080+
| Let ->
3081+
Parser.next p;
3082+
parseIfLet startPos p
3083+
| _ ->
3084+
parseIfCore startPos p
3085+
30433086
and parseIfExpression p =
30443087
Parser.beginRegion p;
30453088
Parser.leaveBreadcrumb p Grammar.ExprIf;

tests/parsing/grammar/expressions/__snapshots__/parse.spec.js.snap

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,45 @@ let ifElseIfThen =
503503
if foo = bar
504504
then f ()
505505
else if foo = bar2 then f1 () else if foo = bar3 then f2 () else f3 ()
506-
let x = (if true then 1 else 2) + (if false then 2 else 3)"
506+
let x = (if true then 1 else 2) + (if false then 2 else 3)
507+
;;match foo () with | Some x -> doSomethingWithX x | _ -> ()
508+
;;match foo () with | Some x -> doSomethingWithX x | _ -> doSomethingElse ()
509+
;;match foo () with
510+
| Some x -> doSomethingWithX x
511+
| _ ->
512+
(match bar () with
513+
| Some y -> doSomethingWithY y
514+
| _ -> doSomethingElse ())
515+
;;match foo () with
516+
| Some x -> doSomethingWithX x
517+
| _ -> if n > 10 then doSomethingWithForN () else doSomethingElse ()
518+
;;if n > 10
519+
then doSomethingWithForN ()
520+
else
521+
(match foo () with
522+
| Some x -> doSomethingWithX x
523+
| _ -> doSomethingElse ())
524+
;;if n > 10
525+
then ((doSomethingWithForN ())[@aa ])
526+
else
527+
(match ((foo ())[@dd ]) with
528+
| ((Some ((x)[@cc ]))[@bb ]) -> ((doSomethingWithY x)[@ee ])
529+
| _ -> ((doSomethingElse ())[@ff ]))
530+
;;match foo () with | Some x when x > 10 -> doSomethingWithX x | _ -> ()
531+
;;match foo () with
532+
| Some x when x > 10 -> doSomethingWithX x
533+
| _ ->
534+
(match bar () with
535+
| Some y when y > 10 -> doSomethingWithY y
536+
| _ ->
537+
(match baz () with
538+
| Some z when z > 10 -> doSomethingWithZ z
539+
| _ -> ()))
540+
;;match foo () with
541+
| Some (Thing (With { many = Internal [|Components;q|] })) as p when
542+
isValid q -> doSomethingWithE e
543+
| _ -> ()
544+
let a = match foo () with | Some x when x > 10 -> x | _ -> 123"
507545
`;
508546
509547
exports[`infix.js 1`] = `

tests/parsing/grammar/expressions/if.js

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ let ifThenElse = if foo {
1414
lala
1515
} else {
1616
doStuff(x, y, z,)
17-
}
17+
}
1818

1919
let ifElseIfThen =
2020
if foo == bar {
@@ -28,3 +28,82 @@ let ifElseIfThen =
2828
}
2929

3030
let x = if true { 1 } else { 2 } + if false { 2 } else { 3 }
31+
32+
// Basic
33+
if let Some(x) = foo() {
34+
doSomethingWithX(x)
35+
}
36+
37+
// Else branch
38+
if let Some(x) = foo(){
39+
doSomethingWithX(x)
40+
} else {
41+
doSomethingElse()
42+
}
43+
44+
// Else-if support
45+
if let Some(x) = foo(){
46+
doSomethingWithX(x)
47+
} else if let Some(y) = bar(){
48+
doSomethingWithY(y)
49+
} else {
50+
doSomethingElse()
51+
}
52+
53+
// Mixed conditions, pattern start
54+
if let Some(x) = foo(){
55+
doSomethingWithX(x)
56+
} else if n > 10 {
57+
doSomethingWithForN()
58+
} else {
59+
doSomethingElse()
60+
}
61+
62+
// Mixed conditions, condition start
63+
if n > 10 {
64+
doSomethingWithForN()
65+
} else if let Some(x) = foo() {
66+
doSomethingWithX(x)
67+
} else {
68+
doSomethingElse()
69+
}
70+
71+
// Maintains attrs correctly
72+
if n > 10 {
73+
@aa
74+
doSomethingWithForN()
75+
} else if let @bb Some(@cc x) = @dd foo() {
76+
@ee
77+
doSomethingWithY(x)
78+
} else {
79+
@ff
80+
doSomethingElse()
81+
}
82+
83+
// pattern guards are allowed
84+
if let Some(x) = foo() when x > 10 {
85+
doSomethingWithX(x)
86+
}
87+
88+
if let Some(x) = foo() when x > 10 {
89+
doSomethingWithX(x)
90+
} else if let Some(y) = bar() when y > 10 {
91+
doSomethingWithY(y)
92+
} else if let Some(z) = baz() when z > 10 {
93+
doSomethingWithZ(z)
94+
}
95+
96+
97+
// full destructioning
98+
if let Some(Thing(With({
99+
many: Internal([Components, q]),
100+
}))) as p = foo() when isValid(q) {
101+
doSomethingWithE(e)
102+
}
103+
104+
105+
let a = if let Some(x) = foo() when x > 10 {
106+
x
107+
} else {
108+
123
109+
}

0 commit comments

Comments
 (0)