5
5
6
6
The development of the Imp language in `Imp . lidr` completely ignores issues of
7
7
concrete syntax -- how an ascii string that a programmer might write gets
8
- translated into abstract syntax trees defined by the datatypes `aexp` , `bexp` ,
9
- and `com` . In this chapter, we illustrate how the rest of the story can be
10
- filled in by building a simple lexical analyzer and parser using Idris's
11
- functional programming facilities.
8
+ translated into abstract syntax trees defined by the datatypes \ idr{ AExp } ,
9
+ \ idr{ BExp }, and \ idr{ Com } . In this chapter, we illustrate how the rest of the
10
+ story can be filled in by building a simple lexical analyzer and parser using
11
+ Idris's functional programming facilities.
12
12
13
13
It is not important to understand all the details here (and accordingly, the
14
14
explanations are fairly terse and there are no exercises). The main point is
@@ -26,9 +26,6 @@ very end to get the punchline.
26
26
27
27
=== Lexical Analysis
28
28
29
- > isLowerAlpha : (c : Char) -> Bool
30
- > isLowerAlpha c = isLower c || isDigit c
31
- >
32
29
> data Chartype = White | Alpha | Digit | Other
33
30
>
34
31
> classifyChar : (c : Char) -> Chartype
@@ -100,10 +97,9 @@ more convenient.
100
97
>
101
98
> Applicative OptionE where
102
99
> pure = SomeE
103
- > (SomeE f) <*> (SomeE x) = SomeE (f x)
104
- > (SomeE _ ) <*> (NoneE e2) = NoneE e2
105
- > (NoneE e1) <*> (SomeE _ ) = NoneE e1
106
- > (NoneE e1) <*> (NoneE e2) = NoneE (e1 ++ " ;" ++ e2)
100
+ > (SomeE f) <*> (SomeE x) = SomeE (f x)
101
+ > (SomeE _ ) <*> (NoneE e) = NoneE e
102
+ > (NoneE e) <*> _ = NoneE e
107
103
>
108
104
> Alternative OptionE where
109
105
> empty = NoneE " "
@@ -145,14 +141,15 @@ A parser that expects a particular token:
145
141
> expect : (t : Token) -> Parser ()
146
142
> expect t = firstExpect t (\ xs => SomeE (() , xs))
147
143
>
144
+
148
145
==== A Recursive - Descent Parser for Imp
149
146
150
147
Identifiers :
151
148
152
149
> parseIdentifier : Parser Id
153
150
> parseIdentifier [] = NoneE " Expected identifier"
154
151
> parseIdentifier (x:: xs) =
155
- > if all isLowerAlpha (unpack x)
152
+ > if all isLower (unpack x)
156
153
> then SomeE (MkId x, xs)
157
154
> else NoneE (" Illegal identifier:'" ++ x ++ " '" )
158
155
>
@@ -306,85 +303,26 @@ Parsing commands:
306
303
307
304
== Examples
308
305
309
- `` `coq
310
- (*
311
- Compute parse "
312
- IF x == y + 1 + 2 - y * 6 + 3 THEN
313
- x := x * 1;;
314
- y := 0
315
- ELSE
316
- SKIP
317
- END " .
318
- ====>
319
- SomeE
320
- (IFB BEq (AId (Id 0 ))
321
- (APlus
322
- (AMinus (APlus (APlus (AId (Id 1 )) (ANum 1 )) (ANum 2 ))
323
- (AMult (AId (Id 1 )) (ANum 6 )))
324
- (ANum 3 ))
325
- THEN Id 0 ::= AMult (AId (Id 0 )) (ANum 1 );; Id 1 ::= ANum 0
326
- ELSE SKIP FI , [])
327
- * )
328
-
329
- (*
330
- Compute parse "
331
- SKIP;;
332
- z:=x*y*(x*x);;
333
- WHILE x==x DO
334
- IF z <= z*z && not x == 2 THEN
335
- x := z;;
336
- y := z
337
- ELSE
338
- SKIP
339
- END;;
340
- SKIP
341
- END;;
342
- x:=z " .
343
- ====>
344
- SomeE
345
- (SKIP ;;
346
- Id 0 ::= AMult (AMult (AId (Id 1 )) (AId (Id 2 )))
347
- (AMult (AId (Id 1 )) (AId (Id 1 )));;
348
- WHILE BEq (AId (Id 1 )) (AId (Id 1 )) DO
349
- IFB BAnd (BLe (AId (Id 0 )) (AMult (AId (Id 0 )) (AId (Id 0 ))))
350
- (BNot (BEq (AId (Id 1 )) (ANum 2 )))
351
- THEN Id 1 ::= AId (Id 0 );; Id 2 ::= AId (Id 0 )
352
- ELSE SKIP FI ;;
353
- SKIP
354
- END ;;
355
- Id 1 ::= AId (Id 0 ),
356
- [])
357
- * )
358
-
359
- (*
360
- Compute parse "
361
- SKIP;;
362
- z:=x*y*(x*x);;
363
- WHILE x==x DO
364
- IF z <= z*z && not x == 2 THEN
365
- x := z;;
366
- y := z
367
- ELSE
368
- SKIP
369
- END;;
370
- SKIP
371
- END;;
372
- x:=z " .
373
- =====>
374
- SomeE
375
- (SKIP ;;
376
- Id 0 ::= AMult (AMult (AId (Id 1 )) (AId (Id 2 )))
377
- (AMult (AId (Id 1 )) (AId (Id 1 )));;
378
- WHILE BEq (AId (Id 1 )) (AId (Id 1 )) DO
379
- IFB BAnd (BLe (AId (Id 0 )) (AMult (AId (Id 0 )) (AId (Id 0 ))))
380
- (BNot (BEq (AId (Id 1 )) (ANum 2 )))
381
- THEN Id 1 ::= AId (Id 0 );;
382
- Id 2 ::= AId (Id 0 )
383
- ELSE SKIP
384
- FI ;;
385
- SKIP
386
- END ;;
387
- Id 1 ::= AId (Id 0 ),
388
- []).
389
- * )
306
+ `` `idris
307
+ λΠ> parse " IF x == y + 1 + 2 - y * 6 + 3 THEN x := x * 1;; y := 0 ELSE SKIP END"
308
+ SomeE (CIf (BEq (AId (MkId " x" )) (APlus (AMinus (APlus (APlus (AId (MkId " y" )) (ANum 1 )) (ANum 2 )) (AMult (AId (MkId " y" )) (ANum 6 ))) (ANum 3 )))
309
+ (CSeq (CAss (MkId " x" ) (AMult (AId (MkId " x" )) (ANum 1 ))) (CAss (MkId " y" ) (ANum 0 )))
310
+ CSkip ,
311
+ []) : OptionE (Com , List String )
312
+
313
+ λΠ> parse " SKIP;; z:=x*y*(x*x);; WHILE x==x DO IF z <= z*z && not x == 2 THEN x := z;; y := z ELSE SKIP END;; SKIP END;; x:=z"
314
+ `` `
315
+
316
+ \ todo[inline]{This one is repeated twice in the book for some reason}
317
+
318
+ `` `idris
319
+ SomeE (CSeq CSkip
320
+ (CSeq (CAss (MkId " z" ) (AMult (AMult (AId (MkId " x" )) (AId (MkId " y" ))) (AMult (AId (MkId " x" )) (AId (MkId " x" )))))
321
+ (CSeq (CWhile (BEq (AId (MkId " x" )) (AId (MkId " x" )))
322
+ (CSeq (CIf (BAnd (BLe (AId (MkId " z" )) (AMult (AId (MkId " z" )) (AId (MkId " z" )))) (BNot (BEq (AId (MkId " x" )) (ANum 2 ))))
323
+ (CSeq (CAss (MkId " x" ) (AId (MkId " z" ))) (CAss (MkId " y" ) (AId (MkId " z" ))))
324
+ CSkip )
325
+ CSkip ))
326
+ (CAss (MkId " x" ) (AId (MkId " z" ))))),
327
+ []) : OptionE (Com , List String )
390
328
`` `
0 commit comments