-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLexer.hs
More file actions
129 lines (111 loc) · 3.23 KB
/
Copy pathLexer.hs
File metadata and controls
129 lines (111 loc) · 3.23 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
-- Matt's Typechecker: Lexer datatype and associated functions
-- (C) Matt Teichman, 2019
-- Note: this module uses the ReadP library, whereas LambdaParse does
-- not. LambdaParse hand-rolls a version of the ReadP library so that
-- it can make use of additional functions that reach into the
-- under-the-hood machinery of ReadP.
module Lexer where
-- standard modules
import Control.Applicative
import Data.Char
import Text.ParserCombinators.ReadP as R
-- lexeme datatype
data Lexeme =
XLambda
| XString String
| XAtomicType Char
| XColon
| XDot
| XLeftP
| XRightP
| XLeftA
| XRightA
| XWhitesp
| XEqDef
| XLineBrk
| XNull
deriving (Show, Eq)
-- lookup table for significant characters in my DSL
chr_lex :: Char -> Lexeme
chr_lex chr =
case chr of
'\\' -> XLambda
':' -> XColon
'.' -> XDot
'(' -> XLeftP
')' -> XRightP
'<' -> XLeftA
'>' -> XRightA
'\n' -> XLineBrk
'=' -> XEqDef
'E' -> XAtomicType 'E'
'K' -> XAtomicType 'K'
'S' -> XAtomicType 'S'
'T' -> XAtomicType 'T'
_ -> XNull
-- retrieve a string from a string lexeme
xgetString :: Lexeme -> String
xgetString (XString str) = str
xgetString _ = ""
-- predicate for string lexemes
isXString :: Lexeme -> Bool
isXString (XString _) = True
isXString _ = False
-- string lexer
lexString :: ReadP Lexeme
lexString = fmap XString (munch1 isAlpha)
-- whitespace lexer
lexWhitesp :: ReadP Lexeme
lexWhitesp = fmap (const XWhitesp) (munch1 $ \chr -> chr == ' ')
-- significant character lexer
lexChar :: Char -> ReadP Lexeme
lexChar chr = fmap chr_lex (char chr)
-- arbitrary symbol lexer
lexSymbol :: ReadP Lexeme
lexSymbol = lexChar '\\' <|>
lexChar ':' <|>
lexChar '.' <|>
lexChar '(' <|>
lexChar ')' <|>
lexChar '<' <|>
lexChar '>' <|>
lexChar '=' <|>
lexChar '\n' <|>
lexChar 'E' <|>
lexChar 'K' <|>
lexChar 'S' <|>
lexChar 'T'
-- whitespace/symbol/string lexer
lexItem :: ReadP Lexeme
lexItem = lexWhitesp <++
lexSymbol <++
lexString
-- pull result out of a 'many parser' parser
cleanUpMany :: [([Lexeme], String)] -> Maybe [Lexeme]
cleanUpMany lst =
case filter (\(x,y) -> y == []) lst of
[] -> Nothing
[([],_)] -> Nothing
pair:[] -> Just $ fst pair
_ -> Nothing
-- map a string to a list of lexemes representing that string
lambdaLex :: String -> Maybe [Lexeme]
lambdaLex str = cleanUpMany $
filter (\(x,y) -> y == []) $
readP_to_S (R.many lexItem) str
-- predicate for lexeme lists with balanced angle brackets
balanced_A :: [Lexeme] -> Bool
balanced_A lst =
let countParens acc [] = acc
countParens acc (XLeftA:xs) = countParens (acc + 1) xs
countParens acc (XRightA:xs) = countParens (acc - 1) xs
countParens acc (_:xs) = countParens acc xs
in countParens 0 lst == 0
-- predicate for lexeme lists with balanced parentheses
balanced_P :: [Lexeme] -> Bool
balanced_P lst =
let countParens acc [] = acc
countParens acc (XLeftP:xs) = countParens (acc + 1) xs
countParens acc (XRightP:xs) = countParens (acc - 1) xs
countParens acc (_:xs) = countParens acc xs
in countParens 0 lst == 0