-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathParser.hs
More file actions
151 lines (136 loc) · 6.1 KB
/
Parser.hs
File metadata and controls
151 lines (136 loc) · 6.1 KB
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
module Parser
(
parse
)
where
import Data.List (tail)
import Tokens (Token, Token(..))
import Ast (
Exp, Exp(..),
Exp', Exp'(..),
Term, Term(..),
Term',Term'(..),
Factor, Factor(..),
Atom, Atom(..),
ArithOp, ArithOp(..))
parse :: [Token] -> Maybe Exp
parse tokens
| null remainingTokens = exp
| otherwise = Nothing
where (exp, remainingTokens) = parseExp tokens
parseExp :: [Token] -> (Maybe Exp, [Token])
parseExp [] = (Just TrivialExp,[])
parseExp tokens@(lookahead : rest)
| (Operator op) <- lookahead = parse' op
| (Tokens.Number num) <- lookahead = parse' 'n'
| OpenParens <- lookahead = parse' '('
| otherwise = (Nothing, tokens)
where parse' look | look == '+' = (liftIntoExp term exp', resultRest)
| look == '-' = (liftIntoExp term exp', resultRest)
| look == '(' = (liftIntoExp term exp', resultRest)
| look == 'n' = (liftIntoExp term exp', resultRest)
| otherwise = (Nothing, tokens)
where (term, termRest) = parseTerm tokens
(exp', resultRest) = parseExp' termRest
liftIntoExp :: Maybe Term -> Maybe Exp' -> Maybe Exp
liftIntoExp (Just term) (Just exp') = Just exp
where exp = NontrivialExp {
expTerm = term,
expExp' = exp'
}
liftIntoExp _ _ = Nothing
parseTerm :: [Token] -> (Maybe Term, [Token])
parseTerm [] = (Nothing, [])
parseTerm tokens@(lookahead : rest)
| (Operator op) <- lookahead = parse' op
| (Tokens.Number num) <- lookahead = parse' 'n'
| OpenParens <- lookahead = parse' '('
| otherwise = (Nothing, tokens)
where parse' look | look == '-' = (liftIntoTerm factor term', resultRest)
| look == 'n' = (liftIntoTerm factor term', resultRest)
| look == '(' = (liftIntoTerm factor term', resultRest)
| otherwise = (Nothing, tokens)
where (factor, factorRest) = parseFactor tokens
(term', resultRest) = parseTerm' factorRest
liftIntoTerm :: Maybe Factor -> Maybe Term' -> Maybe Term
liftIntoTerm (Just factor) (Just term') = Just term
where term = NontrivialTerm {
termFactor = factor,
termTerm' = term'
}
liftIntoTerm _ _ = Nothing
parseExp' :: [Token] -> (Maybe Exp', [Token])
parseExp' [] = (Just TrivialExp', [])
parseExp' tokens@(lookahead : rest)
| (Operator op) <- lookahead = parse' op
| CloseParens <- lookahead = (Just TrivialExp', tokens)
| otherwise = (Nothing, tokens)
where parse' look | look == '+' = (liftIntoExp' Add term exp', resultRest)
| look == '-' = (liftIntoExp' Sub term exp', resultRest)
| otherwise = (Nothing, tokens)
where (term, termRest) = parseTerm rest
(exp', resultRest) = parseExp' termRest
liftIntoExp' :: ArithOp -> Maybe Term -> Maybe Exp' -> Maybe Exp'
liftIntoExp' op (Just term) (Just exp') = Just exp''
where exp'' = NontrivialExp' {
exp'Op = op,
exp'Term = term,
exp'Exp' = exp'
}
liftIntoExp' _ _ _ = Nothing
parseTerm' :: [Token] -> (Maybe Term', [Token])
parseTerm' [] = (Just TrivalTerm', [])
parseTerm' tokens@(lookahead : rest)
| (Operator op) <- lookahead = parse' op
| CloseParens <- lookahead = (Just TrivalTerm', tokens)
| otherwise = (Nothing, tokens)
where parse' look | look == '+' = (Just TrivalTerm', tokens)
| look == '-' = (Just TrivalTerm', tokens)
| look == '*' = (liftIntoTerm' Mul factor term', resultRest)
| look == '/' = (liftIntoTerm' Div factor term', resultRest)
| otherwise = (Nothing, tokens)
where (factor, factorRest) = parseFactor rest
(term', resultRest) = parseTerm' factorRest
liftIntoTerm' :: ArithOp -> Maybe Factor -> Maybe Term' -> Maybe Term'
liftIntoTerm' op (Just factor) (Just term') = Just term''
where term'' = NontrivialTerm' {
term'Op = op,
term'Factor = factor,
term'Term' = term'
}
liftIntoTerm' _ _ _ = Nothing
parseFactor :: [Token] -> (Maybe Factor, [Token])
parseFactor [] = (Nothing, [])
parseFactor tokens@(lookahead : rest)
| (Operator op) <- lookahead = parse' op
| (Tokens.Number num) <- lookahead = parse' 'n'
| OpenParens <- lookahead = parse' '('
| otherwise = (Nothing, tokens)
where parse' look | look == '-' = (liftIntoNegativeFactor factor, factorRest)
| look == 'n' = (liftIntoAtomicFactor atom, atomRest)
| look == '(' = (liftIntoAtomicFactor atom, atomRest)
| otherwise = (Nothing, tokens)
where (factor, factorRest) = parseFactor rest
(atom, atomRest) = parseAtom tokens
liftIntoNegativeFactor :: Maybe Factor -> Maybe Factor
liftIntoNegativeFactor (Just factor) = Just NegativeFactor { innerFactor = factor }
liftIntoNegativeFactor Nothing = Nothing
liftIntoAtomicFactor :: Maybe Atom -> Maybe Factor
liftIntoAtomicFactor (Just atom) = Just AtomicFactor { innerAtom = atom }
liftIntoAtomicFactor Nothing = Nothing
parseAtom :: [Token] -> (Maybe Atom, [Token])
parseAtom [] = (Nothing, [])
parseAtom tokens@(lookahead : rest)
| (Tokens.Number value) <- lookahead = parse' 'n'
| OpenParens <- lookahead = parse' '('
| otherwise = (Nothing, tokens)
where parse' look | look == 'n' = (liftIntoNumericAtom value, rest)
| look == '(' && expRest /= [] = (liftIntoExpAtom exp, tail expRest)
| otherwise = (Nothing, tokens)
where (exp, expRest) = parseExp rest
(Tokens.Number value) = lookahead
liftIntoNumericAtom :: Double -> Maybe Atom
liftIntoNumericAtom value = Just NumericAtom { number = value }
liftIntoExpAtom :: Maybe Exp -> Maybe Atom
liftIntoExpAtom (Just exp) = Just ExpAtom { innerExp = exp }
liftIntoExpAtom _ = Nothing