Main.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
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
import Orchid.Tokenizer (runTokenizer) import Orchid.Parser (runParser) import Orchid.Data (Token(..), renderToken, describeToken, Statement(..)) import qualified Data.Text.IO.Utf8 as Text.IO import Data.Text (Text) import qualified Options.Applicative as Options import Options.Applicative ((<**>)) import qualified System.IO import qualified Text.Colour.Chunk as Colors import qualified Text.Colour.Capabilities as TerminalCapabilities data Arguments = TokenizeArguments { sourceFile :: Maybe String, outputFile :: Maybe String } | ParseArguments { sourceFile :: Maybe String, outputFile :: Maybe String } makeArgumentParser :: Options.ParserInfo Arguments makeArgumentParser = Options.info (parseArguments <**> Options.helper) (Options.fullDesc <> Options.progDesc "Transforms an Orchid source file into another form" <> Options.header "orchid-cli: The Orchid language command-line interface") parseArguments :: Options.Parser Arguments parseArguments = do let tokenize = do sourceFile <- parseSourceFile outputFile <- parseOutputFile return TokenizeArguments { .. } let parse = do sourceFile <- parseSourceFile outputFile <- parseOutputFile return ParseArguments { .. } Options.hsubparser ( Options.command "tokenize" (Options.info tokenize (Options.progDesc "Tokenize an Orchid source file")) <> Options.command "parse" (Options.info parse (Options.progDesc "Parse an Orchid source file"))) parseSourceFile :: Options.Parser (Maybe String) parseSourceFile = Options.optional $ Options.strArgument (Options.metavar "SOURCE_FILE" <> Options.help "The source file to process") parseOutputFile :: Options.Parser (Maybe String) parseOutputFile = Options.optional $ Options.strOption (Options.short 'o' <> Options.long "output-file" <> Options.metavar "OUTPUT_FILE" <> Options.help "The output file to process") main :: IO () main = do arguments <- Options.execParser makeArgumentParser runOrchidToolchain arguments runOrchidToolchain :: Arguments -> IO () runOrchidToolchain (TokenizeArguments sourceFile outputFile) = do source <- readSourceFile sourceFile let result = runTokenizer (filenameOf sourceFile) source case result of Left e -> putStrLn e Right tokens -> renderTokens outputFile tokens runOrchidToolchain (ParseArguments sourceFile outputFile) = do source <- readSourceFile sourceFile let result = runParser (filenameOf sourceFile) source case result of Left e -> putStrLn e Right statements -> renderStatements outputFile statements filenameOf :: Maybe String -> String filenameOf (Just filename) = filename filenameOf Nothing = "<standard input>" readSourceFile :: Maybe String -> IO Text readSourceFile (Just sourceFile) = Text.IO.readFile sourceFile readSourceFile Nothing = Text.IO.getContents renderTokens :: Maybe String -> [Token] -> IO () renderTokens outputFile tokens = do outputHandle <- case outputFile of Just path -> System.IO.openFile path System.IO.WriteMode Nothing -> return System.IO.stdout mapM_ (Text.IO.hPutStrLn outputHandle . displayToken) tokens System.IO.hClose outputHandle renderStatements :: Maybe String -> [Statement] -> IO () renderStatements outputFile statements = do outputHandle <- case outputFile of Just path -> System.IO.openFile path System.IO.WriteMode Nothing -> return System.IO.stdout mapM_ (Text.IO.hPutStrLn outputHandle . displayStatement) statements System.IO.hClose outputHandle displayToken :: Token -> Text displayToken token = "> " <> description <> ": " <> colorRepresentation representation where representation = renderToken token description = describeToken token displayStatement :: Statement -> Text displayStatement _ = "placeholder" colorRepresentation :: Text -> Text colorRepresentation text = Colors.renderChunkText TerminalCapabilities.With8Colours colored where colored = Colors.fore Colors.cyan chunk chunk = Colors.chunk text