Skip to content

Commit 48dc59a

Browse files
committed
make some progress on the parsing
1 parent 01db992 commit 48dc59a

5 files changed

Lines changed: 370 additions & 36 deletions

File tree

Main.hs

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
module Main where
2+
3+
import System.Environment
4+
import Debug.Trace
5+
import Parser
6+
import Control.Monad
7+
import Data.List
8+
import System.Exit
9+
import Data.Char
10+
import Data.Word
11+
import Data.Maybe
12+
13+
{-
14+
NOOP
15+
ADD ACC, Mem[Addr]
16+
SUB ACC, Mem[Addr]
17+
NOT ACC
18+
AND ACC, Mem[Addr]
19+
CMP ACC, Mem[Addr]
20+
LB ACC, Mem[Addr]
21+
LBI ACC, Mem[Mem[Addr]]
22+
SB Mem[Addr], ACC
23+
SBI Mem[Mem[Addr]], ACC
24+
IN Mem[Addr], IO_BUS
25+
JA Addr
26+
J Offset
27+
JEQ Offset
28+
JNE Offset
29+
DS
30+
-}
31+
32+
data Reg = ACC deriving Show
33+
data IOBus = IOBus deriving Show
34+
newtype Addr = Addr Word8
35+
newtype AddrAddr = AddrAddr Word8
36+
newtype Offset = Offset Word8
37+
38+
instance Show Addr where
39+
show (Addr x) = "M["++show x++"]"
40+
41+
instance Show AddrAddr where
42+
show (AddrAddr x) = "M[M["++show x++"]]"
43+
44+
instance Show Offset where
45+
show (Offset x) = "±"++show x
46+
47+
data Opcode = NOOP
48+
| ADD Reg Addr
49+
| SUB Reg Addr
50+
| NOT Reg
51+
| AND Reg Addr
52+
| CMP Reg Addr
53+
| LB Reg Addr
54+
| LBI Reg AddrAddr
55+
| SB Addr Reg
56+
| SBI AddrAddr Reg
57+
| IN Addr IOBus
58+
| JA Addr
59+
| J Offset
60+
| JEQ Offset
61+
| JNE Offset
62+
| DS
63+
deriving Show
64+
65+
-- ordered after opcode in binary
66+
opcodes = [
67+
"NOOP",
68+
"ADD",
69+
"SUB",
70+
"NOT",
71+
"AND",
72+
"CMP",
73+
"LB",
74+
"LBI",
75+
"SB",
76+
"SBI",
77+
"IN",
78+
"JA",
79+
"J",
80+
"JEQ",
81+
"JNE",
82+
"DS"
83+
]
84+
85+
upperLowerToken :: Parser String
86+
upperLowerToken = do xs <- some alphanum
87+
guard (all isUpper xs || all isLower xs)
88+
space
89+
return xs
90+
91+
opcode :: Parser String
92+
opcode = do xs <- upperLowerToken
93+
guard (map toUpper xs `elem` opcodes)
94+
return xs
95+
96+
reg :: Parser Reg
97+
reg = do r <- upperLowerToken
98+
if map toUpper r == "ACC"
99+
then return ACC
100+
else error "unknown reg"
101+
102+
readHex :: String -> Int
103+
readHex = sum . zipWith (*) [1,16..] . reverse . ys
104+
where
105+
ys = map (\x -> if x `elem` ['0'..'9'] then
106+
ord x - ord '0'
107+
else
108+
ord x - ord 'a' + 10)
109+
110+
--hex = do { string "0x"; xs <- some (sat (`elem` (['0'..'9']++['a'..'f']) . toLower)); return (readHex xs)}
111+
--bin = do { string "0b"; nat }
112+
113+
addr :: Parser Addr
114+
addr = (Addr . fromIntegral <$> do { char 'M'; space; char '['; space; n <- nat; space; char ']'; space; return n })
115+
<|> Addr . fromIntegral <$> nat
116+
-- <|> Addr . fromIntegral <$> hex
117+
118+
addraddr :: Parser AddrAddr
119+
addraddr = AddrAddr . fromIntegral <$> nat
120+
121+
offset :: Parser Offset
122+
offset = Offset . fromIntegral <$> nat
123+
124+
ioBus :: Parser IOBus
125+
ioBus = do b <- upperLowerToken
126+
if map toUpper b == "IO_BUS"
127+
then return IOBus
128+
else error "unknown IO_Bus"
129+
130+
newline :: Parser Char
131+
newline = do { space; char '\n' }
132+
133+
noop = return NOOP
134+
add = do { r <- reg; space; char ','; space; ADD r <$> addr; }
135+
sub = do { r <- reg; space; char ','; space; SUB r <$> addr; }
136+
nott = NOT <$> reg
137+
andd = do { r <- reg; space; char ','; space; AND r <$> addr; }
138+
cmp = do { r <- reg; space; char ','; space; CMP r <$> addr; }
139+
lb = do { r <- reg; space; char ','; space; LB r <$> addr; }
140+
lbi = do { r <- reg; space; char ','; space; LBI r <$> addraddr; }
141+
sb = do { a <- addr; space; char ','; space; SB a <$> reg; }
142+
sbi = do { a <- addraddr; space; char ','; SBI a <$> reg; }
143+
inn = do { a <- addr; space; char ','; IN a <$> ioBus; }
144+
ja = JA <$> addr
145+
j = J <$> offset
146+
jeq = JEQ <$> offset
147+
jne = JNE <$> offset
148+
ds = return DS
149+
150+
lineComment :: Parser String
151+
lineComment = do space
152+
c <- string "//"
153+
xs <- many (sat (/= '\n'))
154+
return (c++xs)
155+
156+
lineWithComment = do x <- line
157+
some newline <|> (do {lineComment; newline; return " "})
158+
return (Just x)
159+
<|> do {lineComment; newline; return Nothing}
160+
<|> do {space; newline; return Nothing}
161+
162+
163+
line :: Parser Opcode
164+
line = do op <- opcode
165+
case map toUpper op of
166+
"NOOP" -> noop
167+
"ADD" -> add
168+
"SUB" -> sub
169+
"NOT" -> nott
170+
"AND" -> andd
171+
"CMP" -> cmp
172+
"LB" -> lb
173+
"LBI" -> lbi
174+
"SB" -> sb
175+
"SBI" -> sbi
176+
"IN" -> inn
177+
"JA" -> ja
178+
"J" -> j
179+
"JEQ" -> jeq
180+
"JNE" -> jne
181+
"DS" -> ds
182+
op -> error "hello"
183+
184+
main = do
185+
args <- getArgs
186+
when (null args) (die "No input file provided.")
187+
188+
contents <- readFile (head args)
189+
--let line = head (lines contents)
190+
print contents
191+
print . catMaybes . fst . head $ parse (many lineWithComment) contents
192+
print $ parse (many lineWithComment) contents
193+
194+

Parser.hs

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
{-# LANGUAGE LambdaCase #-}
2+
module Parser (module Parser, module Control.Applicative) where
3+
4+
import Control.Monad
5+
import Control.Applicative
6+
import Data.Char
7+
8+
-- | A parser for things is a function from strings to list of pairs of things and strings.
9+
-- The empty list of of results denotes failure of parsing.
10+
newtype Parser a = Parser (String -> [(a, String)])
11+
12+
parse (Parser p) = p
13+
14+
item :: Parser Char
15+
item = Parser (\case
16+
"" -> []
17+
(c:cs) -> [(c,cs)])
18+
19+
instance Functor Parser where
20+
fmap = liftM
21+
-- fmap g p = P (\inp -> case parse p inp of
22+
--[] -> []
23+
--[(v,out)] -> [(g v, out)])
24+
25+
instance Applicative Parser where
26+
pure a = Parser (\cs -> [(a,cs)])
27+
(<*>) = ap
28+
29+
instance Monad Parser where
30+
p >>= f = Parser (\inp -> concat [parse (f a) out | (a,out) <- parse p inp])
31+
32+
-- ======================= Choice combinators =======================
33+
34+
instance Alternative Parser where
35+
empty = Parser (const [])
36+
p <|> q = Parser (\cs -> case parse p cs of
37+
[] -> parse q cs
38+
res -> res)
39+
40+
-- | Keep only one first parsing successfully result,
41+
-- throw away other ways the parsing could succeed when making a choice
42+
(+++) :: Parser a -> Parser a -> Parser a
43+
p +++ q = Parser (\cs -> case parse (p <|> q) cs of
44+
[] -> []
45+
(x:xs) -> [x])
46+
47+
sat :: (Char -> Bool) -> Parser Char
48+
sat p = do c <- item
49+
guard (p c) -- fail if predicate doesn't hold
50+
return c
51+
52+
char :: Char -> Parser Char
53+
char c = sat (c ==)
54+
55+
-- ======================= Recursion combinators =======================
56+
57+
-- | Parse a specific string
58+
string :: String -> Parser String
59+
string "" = return ""
60+
string (c:cs) = do { char c; string cs; return (c:cs); }
61+
62+
-- | Parse repeated applications of a parser p;
63+
-- the many combinator permits zero or more applications of p
64+
-- `many`
65+
66+
-- | Parse repeated applications of a parser p;
67+
-- the some combinator permits one or more applications of p
68+
-- `some`
69+
70+
-- | Parse repeated applications of a parser p, separated by applications
71+
-- of a parser sep whose result values are thrown away. Permits zero applications
72+
sepBy :: Parser a -> Parser a -> Parser [a]
73+
p `sepBy` sep = (p `sepBy1` sep) +++ return []
74+
75+
-- | Parse repeated applications of a parser p, separated by applications
76+
-- of a parser sep whose result values are thrown away. Permits one or more applications
77+
sepBy1 :: Parser a -> Parser a -> Parser [a]
78+
p `sepBy1` sep = do a <- p
79+
as <- many (do {sep; p})
80+
return (a:as)
81+
82+
-- | Parse repeated applications of a parser p, separated by applications of a parser
83+
-- op whose result value is an operator that is assumed to associate to the left,
84+
-- and which is used to combine the results from the p parsers
85+
-- Can be applied zero or more times.
86+
chainl :: Parser a -> Parser (a->a->a) -> a -> Parser a
87+
chainl p op a = (p `chainl1` op) +++ return a
88+
89+
-- | Parse repeated applications of a parser p, separated by applications of a parser
90+
-- op whose result value is an operator that is assumed to associate to the left,
91+
-- and which is used to combine the results from the p parsers.
92+
-- Can be applied one or more times.
93+
chainl1 :: Parser a -> Parser (a->a->a) -> Parser a
94+
p `chainl1` op = do { a <- p; rest a}
95+
where
96+
rest a = do f <- op
97+
b <- p
98+
rest (f a b)
99+
+++ return a
100+
101+
-- chainr and chainr1 can be implemented simmiliarly
102+
103+
104+
-- ======================= Lexical combinators =======================
105+
106+
digit :: Parser Int
107+
digit = do x <- digitChar
108+
return (ord x - ord '0')
109+
110+
letter :: Parser Char
111+
letter = sat isLetter
112+
113+
digitChar :: Parser Char
114+
digitChar = sat isDigit
115+
116+
lower :: Parser Char
117+
lower = sat isLower
118+
119+
upper :: Parser Char
120+
upper = sat isUpper
121+
122+
alphanum :: Parser Char
123+
alphanum = sat isAlphaNum
124+
125+
nat :: Parser Int
126+
nat = do x <- some digitChar
127+
return (read x)
128+
129+
-- | Parse a string of spaces, tabs, and newlines
130+
space :: Parser String
131+
space = many (sat (\c -> c == '\t' || isSeparator c))
132+
133+
-- | Parse an identifier, starting with a lowercase and zero or more alphanumerics.
134+
identifier :: Parser String
135+
identifier = do x <- lower
136+
xs <- many alphanum
137+
return (x:xs)
138+
139+
-- | Parse a token using a parser p, throwing away any trailing space
140+
token :: Parser a -> Parser a
141+
token p = do a <- p
142+
space
143+
return a
144+
145+
-- | Parse a symbolic token
146+
symbol :: String -> Parser String
147+
symbol cs = token (string cs)
148+
149+
-- | Apply a parser p, throwing away any leading space
150+
apply :: Parser a -> String -> [(a,String)]
151+
apply p = parse $ do { space; p }
152+
153+
-- ======================= Example =======================
154+
{-
155+
expr :: Parser Int
156+
addop :: Parser (Int -> Int -> Int)
157+
mulop :: Parser (Int -> Int -> Int)
158+
159+
expr = term `chainl1` addop
160+
term = factor `chainl1` mulop
161+
factor = digit +++ do { symbol "("; n <- expr; symbol ")"; return n }
162+
163+
addop = do { symbol "+"; return (+) } +++ do { symbol "-"; return (-) }
164+
mulop = do { symbol "*"; return (*) } +++ do { symbol "/"; return div }
165+
166+
res :: Int
167+
res = fst . head $ apply expr " (1 - 2*3)+4 " -- -1
168+
169+
-}

main.hs

Lines changed: 0 additions & 7 deletions
This file was deleted.

0 commit comments

Comments
 (0)