never executed always true always false
1 module HelVM.HelMA.Automata.FALSE.Parser (
2 parseSafe,
3 parse,
4 charToSimpleInstruction,
5 ) where
6
7 import HelVM.HelMA.Automata.FALSE.Expression
8
9 import HelVM.HelMA.Automaton.API.IOTypes
10 import HelVM.HelMA.Automaton.Instruction
11 import HelVM.HelMA.Automaton.Instruction.Groups.IOInstruction
12 import HelVM.HelMA.Automaton.Instruction.Groups.SMInstruction
13 import HelVM.HelMA.Automaton.ReadPExtra
14
15 import HelVM.HelMA.Automaton.Instruction.Extras.Constructors
16
17 import HelVM.HelIO.Control.Safe
18 import HelVM.HelIO.Extra hiding (runParser)
19 import HelVM.HelIO.ReadText
20
21 import Data.Char
22
23 import Text.ParserCombinators.ReadP hiding (many)
24
25 parseSafe :: Source -> Safe ExpressionList
26 parseSafe = parse
27
28 parse :: MonadSafe m => Source -> m ExpressionList
29 parse = runParser vlParser
30
31 vlParser :: ReadP ExpressionList
32 vlParser = many (skipSpaces *> valueParser) <* skipSpaces
33
34 valueParser :: ReadP Expression
35 valueParser = lambdaParser <|> commentParser <|> writeStringParser <|> constParser <|> refParser <|> simpleParser
36
37 lambdaParser :: ReadP Expression
38 lambdaParser = Lambda <$> (char '[' *> vlParser <* char ']')
39
40 commentParser :: ReadP Expression
41 commentParser = Comment <$> (char '{' *> many (notChar '}') <* char '}')
42
43 writeStringParser :: ReadP Expression
44 writeStringParser = Str <$> stringParser
45
46 constParser :: ReadP Expression
47 constParser = Inst . consI . fromIntegral <$> naturalParser
48
49 refParser :: ReadP Expression
50 refParser = refFromChar <$> letterAscii
51
52 simpleParser :: ReadP Expression
53 simpleParser = fromJustWithText "imposible" . charToSimpleInstruction <$> oneOf simpleInstructionChars
54
55 simpleInstructionChars :: String
56 simpleInstructionChars = "$%\\@`+-*/_&|~<=!?#:;^,.ß"
57
58 charToSimpleInstruction :: Char -> Maybe Expression
59 charToSimpleInstruction '$' = inst dupI
60 charToSimpleInstruction '%' = inst discardI
61 charToSimpleInstruction '\\' = inst swapI
62 charToSimpleInstruction '@' = inst rotI
63 charToSimpleInstruction '`' = inst copyTI
64
65 charToSimpleInstruction '+' = inst addI
66 charToSimpleInstruction '-' = inst subI
67 charToSimpleInstruction '*' = inst mulI
68 charToSimpleInstruction '/' = inst divI
69 charToSimpleInstruction '_' = inst negI
70
71 charToSimpleInstruction '&' = inst $ binary BAnd
72 charToSimpleInstruction '|' = inst $ binary BOr
73 charToSimpleInstruction '~' = inst $ unary BNot
74
75 charToSimpleInstruction '<' = inst $ binary LGT
76 charToSimpleInstruction '=' = inst $ binary LEQ
77
78 charToSimpleInstruction '!' = pure Exec
79 charToSimpleInstruction '?' = pure Cond
80 charToSimpleInstruction '#' = pure While
81
82 charToSimpleInstruction ':' = pure Store
83 charToSimpleInstruction ';' = pure Fetch
84
85 charToSimpleInstruction '^' = inst $ sio InputChar
86 charToSimpleInstruction ',' = inst $ sio OutputChar
87 charToSimpleInstruction '.' = inst $ sio OutputDec
88 charToSimpleInstruction 'ß' = pure Flush
89
90 charToSimpleInstruction _ = Nothing
91
92 inst :: Instruction -> Maybe Expression
93 inst = pure . Inst
94
95 -- | Extra
96
97 refFromChar :: Char -> Expression
98 refFromChar c = Ref $ fromIntegral $ ord (toLower c) - ord 'a'
99
100 naturalParser :: ReadP Natural
101 naturalParser = naturalLiteralParser <|> ordCharLiteralParser
102
103 naturalLiteralParser :: ReadP Natural
104 naturalLiteralParser = readUnsafe <$> many1 digit
105
106 ordCharLiteralParser :: Integral a => ReadP a
107 ordCharLiteralParser = fromIntegral . ord <$> (skipSpacesAndChar '\'' *> anyChar)
108
109 stringParser :: ReadP String
110 stringParser = skipSpacesAndChar '"' *> many (notChar '"') <* char '"'
111
112 skipSpacesAndChar :: Char -> ReadP Char
113 skipSpacesAndChar c = skipSpaces *> char c