@@ -24,20 +24,22 @@ import Language.PureScript.CST.Utils
24
24
import qualified Language.PureScript.Names as N
25
25
}
26
26
27
+ %expect 75
28
+
27
29
%name parseKind kind
28
30
%name parseType type
29
31
%name parseExpr expr
30
32
%name parseModuleBody moduleBody
31
33
%partial parseModuleHeader moduleHeader
32
34
%partial parseDoStatement doStatement
33
- %partial parseDoBinder doBinder
34
35
%partial parseDoExpr doExpr
35
36
%partial parseDoNext doNext
36
- %partial parseGuardBinder guardBinder
37
37
%partial parseGuardExpr guardExpr
38
38
%partial parseGuardNext guardNext
39
+ %partial parseGuardStatement guardStatement
39
40
%partial parseClassSuper classSuper
40
41
%partial parseClassNameAndFundeps classNameAndFundeps
42
+ %partial parseBinderAndArrow binderAndArrow
41
43
%tokentype { SourceToken }
42
44
%monad { Parser }
43
45
%error { parseError }
@@ -343,7 +345,7 @@ exprBacktick :: { Expr () }
343
345
344
346
expr2 :: { Expr () }
345
347
: expr3 { $1 }
346
- | ' -' expr3 { ExprNegate () $1 $2 }
348
+ | ' -' expr2 { ExprNegate () $1 $2 }
347
349
348
350
expr3 :: { Expr () }
349
351
: expr4 { $1 }
@@ -439,10 +441,10 @@ guardedExpr(a) :: { GuardedExpr () }
439
441
-- productions to parse it, so we' d have to maintain an ad-hoc handwritten
440
442
-- parser which is very difficult to audit.
441
443
--
442
- -- As an alternative we introduce some backtracking. Using %partial parsers,
443
- -- we can encode the state transitions and use the backtracking `tryPrefix`
444
- -- combinator. Binders are generally very short in comparison to expressions,
445
- -- so the cost is modest.
444
+ -- As an alternative we introduce some backtracking. Using %partial parsers and
445
+ -- monadic reductions, we can invoke productions manually and use the
446
+ -- backtracking `tryPrefix` combinator. Binders are generally very short in
447
+ -- comparison to expressions, so the cost is modest.
446
448
--
447
449
-- doBlock
448
450
-- : ' do' ' \{ ' manySep (doStatement, ' \; ' ) ' \} '
@@ -459,24 +461,24 @@ guardedExpr(a) :: { GuardedExpr () }
459
461
-- : expr0
460
462
-- | binder ' <-' expr0
461
463
--
462
- doBlock
464
+ doBlock :: { DoBlock () }
463
465
: ' do' ' \{ '
464
466
{%% revert $ do
465
467
res <- parseDoStatement
466
468
when (null res) $ addFailure [$2] ErrEmptyDo
467
469
pure $ DoBlock $1 $ NE.fromList res
468
470
}
469
471
470
- adoBlock
472
+ adoBlock :: { (SourceToken, [ DoStatement ()]) }
471
473
: ' ado' ' \{ '
472
474
{%% revert $ fmap ($1 ,) parseDoStatement }
473
475
474
- doStatement
476
+ doStatement :: { [ DoStatement ()] }
475
477
: ' let' ' \{ ' manySep(letBinding, ' \; ' ) ' \} '
476
478
{%^ revert $ fmap (DoLet $1 $3 :) parseDoNext }
477
- | error
479
+ | {- empty -}
478
480
{%^ revert $ do
479
- stmt <- tryPrefix parseDoBinder parseDoExpr
481
+ stmt <- tryPrefix parseBinderAndArrow parseDoExpr
480
482
let
481
483
ctr = case stmt of
482
484
(Just (binder, sep), expr) ->
@@ -486,37 +488,33 @@ doStatement
486
488
fmap ctr parseDoNext
487
489
}
488
490
489
- doBinder
490
- : binder ' <-' {%^ revert $ pure ($1 , $2 ) }
491
-
492
- doExpr
491
+ doExpr :: { Expr () }
493
492
: expr {%^ revert $ pure $1 }
494
493
495
- doNext
494
+ doNext :: { [ DoStatement ()] }
496
495
: ' \; ' {%^ revert parseDoStatement }
497
496
| ' \} ' {%^ revert $ pure [] }
498
497
499
498
guard :: { (SourceToken, Separated (PatternGuard ())) }
500
- : ' |'
501
- {%% revert $ do
502
- (binder, expr) <- tryPrefix parseGuardBinder parseGuardExpr
503
- fmap (($1 ,) . Separated (PatternGuard binder expr)) parseGuardNext
504
- }
499
+ : ' |' {%% revert $ fmap (($1 ,) . uncurry Separated) parseGuardStatement }
505
500
506
- guardBinder :: { (Binder (), SourceToken) }
507
- : binder ' <-' {%^ revert $ pure ($1 , $2 ) }
501
+ guardStatement :: { (PatternGuard (), [(SourceToken, PatternGuard ())]) }
502
+ : {- empty -}
503
+ {%^ revert $ do
504
+ grd <- fmap (uncurry PatternGuard) $ tryPrefix parseBinderAndArrow parseGuardExpr
505
+ fmap (grd,) parseGuardNext
506
+ }
508
507
509
508
guardExpr :: { Expr () }
510
509
: expr0 {%^ revert $ pure $1 }
511
510
512
511
guardNext :: { [(SourceToken, PatternGuard ())] }
513
- : ' ,'
514
- {%^ revert $ do
515
- (binder, expr) <- tryPrefix parseGuardBinder parseGuardExpr
516
- fmap (($1 , PatternGuard binder expr) :) parseGuardNext
517
- }
512
+ : ' ,' {%^ revert $ fmap (\(g, gs) -> ($1 , g) : gs) parseGuardStatement }
518
513
| {- empty -} {%^ revert $ pure [] }
519
514
515
+ binderAndArrow :: { (Binder (), SourceToken) }
516
+ : binder ' <-' {%^ revert $ pure ($1 , $2 ) }
517
+
520
518
binder :: { Binder () }
521
519
: binder0 { $1 }
522
520
| binder0 ' ::' type { BinderTyped () $1 $2 $3 }
0 commit comments