File: ExprParser.lhs

package info (click to toggle)
ghc-cvs 20040725-2
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 68,484 kB
  • ctags: 19,658
  • sloc: haskell: 251,945; ansic: 109,709; asm: 24,961; sh: 12,825; perl: 5,786; makefile: 5,334; xml: 3,884; python: 682; yacc: 650; lisp: 477; cpp: 337; ml: 76; fortran: 24; csh: 18
file content (92 lines) | stat: -rw-r--r-- 1,848 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
>{-# OPTIONS -farrows #-}

> module ExprParser where

> import Data.Char

> import Control.Arrow
> import Control.Arrow.Transformer.Error

> import Parser

Expressions

> data ESym = LPar | RPar | Plus | Minus | Mult | Div | Number | Unknown | EOF
>	deriving (Show, Eq, Ord)

> instance Symbol ESym where
>	eof = EOF

> type ExprParser = Parser ESym String (->)
> type ExprSym = Sym ESym String

The grammar

> expr :: ExprParser () Int
> expr = proc () -> do
>		x <- term -< ()
>		expr' -< x

> expr' :: ExprParser Int Int
> expr' = proc x -> do
>		returnA -< x
>	<+> do
>		symbol Plus -< ()
>		y <- term -< ()
>		expr' -< x + y
>	<+> do
>		symbol Minus -< ()
>		y <- term -< ()
>		expr' -< x - y

> term :: ExprParser () Int
> term = proc () -> do
>		x <- factor -< ()
>		term' -< x

> term' :: ExprParser Int Int
> term' = proc x -> do
>		returnA -< x
>	<+> do
>		symbol Mult -< ()
>		y <- factor -< ()
>		term' -< x * y
>	<+> do
>		symbol Div -< ()
>		y <- factor -< ()
>		term' -< x `div` y

> factor :: ExprParser () Int
> factor = proc () -> do
>		v <- symbol Number -< ()
>		returnA -< read v::Int
>	<+> do
>		symbol Minus -< ()
>		v <- factor -< ()
>		returnA -< -v
>	<+> do
>		symbol LPar -< ()
>		v <- expr -< ()
>		symbol RPar -< ()
>		returnA -< v

Lexical analysis

> lexer :: String -> [ExprSym]
> lexer [] = []
> lexer ('(':cs) = Sym LPar "(":lexer cs
> lexer (')':cs) = Sym RPar ")":lexer cs
> lexer ('+':cs) = Sym Plus "+":lexer cs
> lexer ('-':cs) = Sym Minus "-":lexer cs
> lexer ('*':cs) = Sym Mult "*":lexer cs
> lexer ('/':cs) = Sym Div "/":lexer cs
> lexer (c:cs)
>	| isSpace c = lexer cs
>	| isDigit c = Sym Number (c:w):lexer cs'
>	| otherwise = Sym Unknown [c]:lexer cs
>		where (w,cs') = span isDigit cs

> run parser = runError (runParser parser)
>	(\(_, err) -> error ("parse error: " ++ err)) . lexer

> t = run expr