-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathParseGrammar.hs
67 lines (56 loc) · 1.28 KB
/
ParseGrammar.hs
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
module ParseGrammar where
import Text.ParserCombinators.Parsec
import System.Environment
import Data.Char
import FirstFollow
{-
This is the simple grammar for representing grammars. The grammar itself almost
represents itself, but I am using some helpful constructs like the '+' to mean
one or more, and '*' to mean zero or more.
<Grammar> -> +(<Rule>)
<Rule> -> <NT> -> <SF> *(| <SF>)
<SF> -> <SF><SF> | <NT> | <T> | <Epsilon>
<NT> -> [A-Z]
<T> -> [a-z]
<Epsilon> -> '_'
-}
epsilon :: Parser Node
epsilon = do
char '_'
return Epsilon
nonterminal :: Parser Node
nonterminal = do
nt <- oneOf ['A'..'Z']
return $ N $ [toUpper nt]
terminal :: Parser Node
terminal = do
t <- oneOf ['a'..'z']
return $ T $ [toLower t]
parseSF :: Parser [Node]
parseSF = many1 (nonterminal <|> terminal <|> epsilon)
parseRHSLast :: Parser [Node]
parseRHSLast = do
char '|'
spaces
r <- parseSF
spaces
return r
parseRHS :: Parser [[Node]]
parseRHS = do
first <- parseSF
spaces
rest <- option [] $ many1 $ parseRHSLast
return $ first : rest
parseRule :: Parser Rule
parseRule = do
lhs <- nonterminal
spaces
char '-'
char '>'
spaces
rhs <- parseRHS
return $ Rule{lhs=lhs, rhs=rhs}
parseGrammar :: Parser Grammar
parseGrammar = do
g <- many1 parseRule
return $ Grammar g