Skip to content

Commit f53fc44

Browse files
author
Fabian Sundholm
committedMay 18, 2018
initial commit
0 parents  commit f53fc44

21 files changed

+567
-0
lines changed
 

‎.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.stack-work/
2+
functional-parsing.cabal
3+
*~

‎ChangeLog.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Changelog for functional-parsing
2+
3+
## Unreleased changes

‎LICENSE

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
Copyright Author name here (c) 2018
2+
3+
All rights reserved.
4+
5+
Redistribution and use in source and binary forms, with or without
6+
modification, are permitted provided that the following conditions are met:
7+
8+
* Redistributions of source code must retain the above copyright
9+
notice, this list of conditions and the following disclaimer.
10+
11+
* Redistributions in binary form must reproduce the above
12+
copyright notice, this list of conditions and the following
13+
disclaimer in the documentation and/or other materials provided
14+
with the distribution.
15+
16+
* Neither the name of Author name here nor the names of other
17+
contributors may be used to endorse or promote products derived
18+
from this software without specific prior written permission.
19+
20+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

‎README.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# functional-parsing

‎Setup.hs

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import Distribution.Simple
2+
main = defaultMain

‎app/Main.hs

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module Main where
2+
3+
import Lib
4+
5+
main :: IO ()
6+
main = someFunc

‎package.yaml

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: functional-parsing
2+
version: 0.1.0.0
3+
github: "githubuser/functional-parsing"
4+
license: BSD3
5+
author: "Author name here"
6+
maintainer: "example@example.com"
7+
copyright: "2018 Author name here"
8+
9+
extra-source-files:
10+
- README.md
11+
- ChangeLog.md
12+
13+
# Metadata used when publishing your package
14+
# synopsis: Short description of your package
15+
# category: Web
16+
17+
# To avoid duplicated efforts in documentation and dealing with the
18+
# complications of embedding Haddock markup inside cabal files, it is
19+
# common to point users to the README.md file.
20+
description: Please see the README on GitHub at <https://github.com/githubuser/functional-parsing#readme>
21+
22+
dependencies:
23+
- base >= 4.7 && < 5
24+
25+
library:
26+
source-dirs: src
27+
28+
executables:
29+
functional-parsing-exe:
30+
main: Main.hs
31+
source-dirs: app
32+
ghc-options:
33+
- -threaded
34+
- -rtsopts
35+
- -with-rtsopts=-N
36+
dependencies:
37+
- functional-parsing
38+
39+
tests:
40+
functional-parsing-test:
41+
main: Spec.hs
42+
source-dirs: test
43+
ghc-options:
44+
- -threaded
45+
- -rtsopts
46+
- -with-rtsopts=-N
47+
dependencies:
48+
- functional-parsing

‎src/CoreParser.hs

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
module CoreParser(Parser, char, return, fail, (#), (!), (?), (#>), (>->),
2+
Parse, parse, toString, fromString) where
3+
import Prelude hiding (return, fail)
4+
infixl 3 !
5+
infixl 7 ?
6+
infixl 6 #
7+
infixl 5 >->
8+
infixl 4 #>
9+
10+
class Parse a where
11+
parse :: Parser a
12+
fromString :: String -> a
13+
fromString cs =
14+
case parse cs of
15+
Just(s, []) -> s
16+
Just(s, cs) -> error ("garbage '"++cs++"'")
17+
Nothing -> error "Nothing"
18+
toString :: a -> String
19+
20+
type Parser a = String -> Maybe (a, String)
21+
22+
char :: Parser Char
23+
char []= Nothing
24+
char (c:cs) = Just (c, cs)
25+
26+
return :: a -> Parser a
27+
return a cs = Just (a, cs)
28+
29+
fail :: Parser a
30+
fail cs = Nothing
31+
32+
(!) :: Parser a -> Parser a -> Parser a
33+
(m ! n) cs = case m cs of
34+
Nothing -> n cs
35+
mcs -> mcs
36+
37+
(?) :: Parser a -> (a -> Bool) -> Parser a
38+
(m ? p) cs =
39+
case m cs of
40+
Nothing -> Nothing
41+
Just(r, s) -> if p r then Just(r, s) else Nothing
42+
43+
(#) :: Parser a -> Parser b -> Parser (a, b)
44+
(m # n) cs =
45+
case m cs of
46+
Nothing -> Nothing
47+
Just(a, cs') ->
48+
case n cs' of
49+
Nothing -> Nothing
50+
Just(b, cs'') -> Just((a, b), cs'')
51+
52+
(>->) :: Parser a -> (a -> b) -> Parser b
53+
(m >-> b) cs =
54+
case m cs of
55+
Just(a, cs') -> Just(b a, cs')
56+
Nothing -> Nothing
57+
58+
(#>) :: Parser a -> (a -> Parser b) -> Parser b
59+
(p #> k) cs =
60+
case p cs of
61+
Nothing -> Nothing
62+
Just(a, cs') -> k a cs'

‎src/Dictionary.hs

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module Dictionary (T, empty, lookup, insert) where
2+
import Prelude hiding (lookup)
3+
import qualified Prelude
4+
5+
newtype T a b = Dictionary [(a, b)] deriving (Show)
6+
7+
empty :: (Eq a, Ord a) => T a b
8+
empty = Dictionary []
9+
10+
lookup :: (Eq a, Ord a) => a -> T a b -> Maybe b
11+
lookup a (Dictionary dict) = Prelude.lookup a dict
12+
13+
insert :: (Eq a, Ord a) => (a, b) -> T a b -> T a b
14+
insert pair (Dictionary dict) = Dictionary (pair:dict)

‎src/Expr.hs

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
module Expr(Expr, T, parse, fromString, value, toString) where
2+
3+
{-
4+
An expression of type Expr is a representation of an arithmetic expression
5+
with integer constants and variables. A variable is a string of upper-
6+
and lower case letters. The following functions are exported
7+
8+
parse :: Parser Expr
9+
fromString :: String -> Expr
10+
toString :: Expr -> String
11+
value :: Expr -> Dictionary.T String Int -> Int
12+
13+
parse is a parser for expressions as defined by the module Parser.
14+
It is suitable for use in parsers for languages containing expressions
15+
as a sublanguage.
16+
17+
fromString expects its argument to contain an expression and returns the
18+
corresponding Expr.
19+
20+
toString converts an expression to a string without unneccessary
21+
parentheses and such that fromString (toString e) = e.
22+
23+
value e env evaluates e in an environment env that is represented by a
24+
Dictionary.T Int.
25+
-}
26+
import Prelude hiding (return, fail)
27+
import Parser hiding (T)
28+
import qualified Dictionary
29+
30+
data Expr = Num Integer | Var String | Add Expr Expr
31+
| Sub Expr Expr | Mul Expr Expr | Div Expr Expr
32+
deriving Show
33+
34+
type T = Expr
35+
36+
var, num, factor, term, expr :: Parser Expr
37+
38+
term', expr' :: Expr -> Parser Expr
39+
40+
var = word >-> Var
41+
42+
num = number >-> Num
43+
44+
mulOp = lit '*' >-> (\_ -> Mul) !
45+
lit '/' >-> (\_ -> Div)
46+
47+
addOp = lit '+' >-> (\_ -> Add) !
48+
lit '-' >-> (\_ -> Sub)
49+
50+
bldOp e (oper,e') = oper e e'
51+
52+
factor = num !
53+
var !
54+
lit '(' -# expr #- lit ')' !
55+
err "illegal factor"
56+
57+
term' e = mulOp # factor >-> bldOp e #> term' ! return e
58+
term = factor #> term'
59+
60+
expr' e = addOp # term >-> bldOp e #> expr' ! return e
61+
expr = term #> expr'
62+
63+
parens cond str = if cond then "(" ++ str ++ ")" else str
64+
65+
shw :: Int -> Expr -> String
66+
shw prec (Num n) = show n
67+
shw prec (Var v) = v
68+
shw prec (Add t u) = parens (prec>5) (shw 5 t ++ "+" ++ shw 5 u)
69+
shw prec (Sub t u) = parens (prec>5) (shw 5 t ++ "-" ++ shw 6 u)
70+
shw prec (Mul t u) = parens (prec>6) (shw 6 t ++ "*" ++ shw 6 u)
71+
shw prec (Div t u) = parens (prec>6) (shw 6 t ++ "/" ++ shw 7 u)
72+
73+
value :: Expr -> Dictionary.T String Integer -> Integer
74+
value (Num n) _ = error "value not implemented"
75+
76+
instance Parse Expr where
77+
parse = expr
78+
toString = shw 0

‎src/Lib.hs

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module Lib
2+
( someFunc
3+
) where
4+
5+
someFunc :: IO ()
6+
someFunc = putStrLn "someFunc"

‎src/Makefile

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
default:
2+
@echo nothing done
3+
4+
clean:
5+
rm -f .BAK.* *~
6+
7+
zip: clean
8+
cd ..; zip -r ass3 clean_parser_assignment

‎src/Parser.hs

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
module Parser(module CoreParser, T, digit, digitVal, chars, letter, err,
2+
lit, number, iter, accept, require, token,
3+
spaces, word, (-#), (#-)) where
4+
import Prelude hiding (return, fail)
5+
import Data.Char
6+
import CoreParser
7+
infixl 7 -#, #-
8+
9+
type T a = Parser a
10+
11+
err :: String -> Parser a
12+
err message cs = error (message++" near "++cs++"\n")
13+
14+
iter :: Parser a -> Parser [a]
15+
iter m = m # iter m >-> cons ! return []
16+
17+
cons(a, b) = a:b
18+
19+
(-#) :: Parser a -> Parser b -> Parser b
20+
m -# n = error "-# not implemented"
21+
22+
(#-) :: Parser a -> Parser b -> Parser a
23+
m #- n = error "#- not implemented"
24+
25+
spaces :: Parser String
26+
spaces = error "spaces not implemented"
27+
28+
token :: Parser a -> Parser a
29+
token m = m #- spaces
30+
31+
letter :: Parser Char
32+
letter = error "letter not implemented"
33+
34+
word :: Parser String
35+
word = token (letter # iter letter >-> cons)
36+
37+
chars :: Int -> Parser String
38+
chars n = error "chars not implemented"
39+
40+
accept :: String -> Parser String
41+
accept w = (token (chars (length w))) ? (==w)
42+
43+
require :: String -> Parser String
44+
require w = error "require not implemented"
45+
46+
lit :: Char -> Parser Char
47+
lit c = token char ? (==c)
48+
49+
digit :: Parser Char
50+
digit = char ? isDigit
51+
52+
digitVal :: Parser Integer
53+
digitVal = digit >-> digitToInt >-> fromIntegral
54+
55+
number' :: Integer -> Parser Integer
56+
number' n = digitVal #> (\ d -> number' (10*n+d))
57+
! return n
58+
number :: Parser Integer
59+
number = token (digitVal #> number')
60+

‎src/Program.hs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module Program(T, parse, fromString, toString, exec) where
2+
import Parser hiding (T)
3+
import qualified Statement
4+
import qualified Dictionary
5+
import Prelude hiding (return, fail)
6+
newtype T = Program () -- to be defined
7+
instance Parse T where
8+
parse = error "Program.parse not implemented"
9+
toString = error "Program.toString not implemented"
10+
11+
exec = error "Program.exec not implemented"

‎src/Statement.hs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
module Statement(T, parse, toString, fromString, exec) where
2+
import Prelude hiding (return, fail)
3+
import Parser hiding (T)
4+
import qualified Dictionary
5+
import qualified Expr
6+
type T = Statement
7+
data Statement =
8+
Assignment String Expr.T |
9+
If Expr.T Statement Statement
10+
deriving Show
11+
12+
assignment = word #- accept ":=" # Expr.parse #- require ";" >-> buildAss
13+
buildAss (v, e) = Assignment v e
14+
15+
exec :: [T] -> Dictionary.T String Integer -> [Integer] -> [Integer]
16+
exec (If cond thenStmts elseStmts: stmts) dict input =
17+
if (Expr.value cond dict)>0
18+
then exec (thenStmts: stmts) dict input
19+
else exec (elseStmts: stmts) dict input
20+
21+
instance Parse Statement where
22+
parse = error "Statement.parse not implemented"
23+
toString = error "Statement.toString not implemented"

‎src/TestExpr.hs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{- Test for Expr-}
2+
module TestExpr where
3+
4+
import qualified Dictionary
5+
import Expr
6+
7+
dict = Dictionary.insert ("x", 1) $
8+
Dictionary.insert ("y", 2) $
9+
Dictionary.empty
10+
11+
testValue string = value (fromString string) dict
12+
13+
n1 = testValue "1"
14+
n2 = testValue "x"
15+
n3 = testValue "x+y"
16+
n4 = testValue "x-y-y"
17+
n21 = testValue "1/(2-y)" {- Expr.value: division by 0 -}
18+
n31 = testValue "2+z" {- Expr.value: undefined variable z -}
19+
20+

0 commit comments

Comments
 (0)
Please sign in to comment.