···11-#lang plait
22-(require "utilities.rkt")
33-(require "types.rkt")
44-55-;----- Parser 'a applicative -----;
66-; The following applicative implementations for (Parser 'a) were taken
77-; from the prelude implementation of haskell at:
88-; https://hackage.haskell.org/package/base-4.19.1.0/docs/src/GHC.Base.html
99-; Creates a parser that parses (x) regardless of input
1010-(define (pure [x : 'a]) : (Parser 'a)
1111- (λ (input)
1212- (ok (pair input x))))
1313-1414-; Creates a parser out of two parsers that will sequence the application of the
1515-; first parser with the second parser. First it parses the same input with both
1616-; parsers then applies the function contained within the first parser to the
1717-; parsed result of the second parser. This is usually referred to as <*> in
1818-; Haskell.
1919-(define (seq-ap [p1 : (Parser ('a -> 'b))] [p2 : (Parser 'a)]) : (Parser 'b)
2020- (λ (input)
2121- (type-case (ParseResult ('a -> 'b)) (p1 input)
2222- [(ok f) (do (p2 input)
2323- (λ (y) (p-result (fst y) ((snd f) (snd y)))))]
2424- [(err) (err)])))
2525-2626-;----- Parser Combinators -----;
2727-; Creates a parser that runs the entire list of parsers through an input and
2828-; returns an (ok) variant if any of them succeed
2929-(define (or/p [ps : (Listof (Parser 'a))]) : (Parser 'a)
3030- (λ (input)
3131- (let ([res1 ((first ps) input)])
3232- (foldr alt res1 (map (λ (p) (p input)) (rest ps))))))
3333-3434-; Creates a parser out of two parsers that will sequence them.
3535-(define (seq/p [p1 : (Parser 'a)] [p2 : (Parser 'b)]) : (Parser ('a * 'b))
3636- (λ (input) (do (p1 input)
3737- (λ (res1) (do (p2 (fst res1))
3838- (λ (res2) (p-result (fst res2) (pair (snd res1) (snd res2)))))))))
3939-4040-; Creates a parser that parses either (p1) or (p2)
4141-(define (alt/p [p1 : (Parser 'a)] [p2 : (Parser 'a)]) : (Parser 'a)
4242- (λ (input) (alt (p1 input) (p2 input))))
4343-4444-; Creates a parser that will parse the input 0 or more times. Like using "*" in
4545-; a RegEx.
4646-(define (many/p [p : (Parser 'a)]) : (Parser (Listof 'a))
4747- (alt/p (many1/p p) (pure '())))
4848-4949-; Creates a parser that parses the input 1 or more times. Like using "+" in a
5050-; RegEx.
5151-(define (many1/p [p : (Parser 'a)]) : (Parser (Listof 'a))
5252- (λ (input) (type-case (ParseResult 'a) (p input)
5353- [(ok first) (type-case (ParseResult (Listof 'a)) ((many/p p) (fst first))
5454- [(ok rest) (ok (pair (fst rest) (append (list (snd first)) (snd rest))))]
5555- [(err) (err)])]
5656- [(err) (err)])))
5757-5858-; Creates a parser out of two parsers that sequentially applies them. But will
5959-; only return the result of the first parser with the rest of the input from the
6060-; second parser.
6161-(define (left/p [l : (Parser 'a)] [r : (Parser 'b)]) : (Parser 'a)
6262- (λ (input) (do (l input)
6363- (λ (result1) (do (r (fst result1))
6464- (λ (result2) (p-result (fst result2) (snd result1))))))))
6565-6666-; Creates a parser out of two parsers that sequentially applies them. But will
6767-; only return the result of the second parser.
6868-(define (right/p [l : (Parser 'a)] [r : (Parser 'b)]) : (Parser 'b)
6969- (λ (input) (do (l input)
7070- (λ (result1) (do (r (fst result1))
7171- (λ (result2) (ok result2)))))))