some small fixes
[cc1516.git] / spl.icl
1 module spl
2
3 import StdFile
4 import StdBool
5 import StdMisc
6 import StdFunc
7 import StdTuple
8 import StdList
9 import StdString
10 import Data.Either
11 import Data.Maybe
12 import Data.Func
13 import System.CommandLine
14 import GenPrint
15 from Text import class Text(concat), instance Text String
16
17 import parse
18 import lex
19 import AST
20 from yard import :: Error, instance toString Error
21
22 :: Opts = {
23 version :: Bool,
24 program :: String,
25 lex :: Bool,
26 parse :: Bool,
27 fp :: Maybe String,
28 help :: Bool}
29
30 derive gPrint TokenValue
31
32 Start :: *World -> *World
33 Start w
34 # (args, w) = parseArgs w
35 # (stdin, w) = stdio w
36 | args.version
37 # stdin = stdin
38 <<< "spl 0.1 (17 march 2016)\n"
39 <<< "Copyright Pim Jager and Mart Lubbers\n"
40 = snd $ fclose stdin w
41 | args.help
42 # stdin = stdin
43 <<< "Usage: " <<< args.program <<< " [OPTION] [FILE]\n"
44 <<< "<spl> ::= <spl> <parser> <lexer>\n"
45 <<< "Lex parse and either FILE or stdin\n"
46 <<< "\n"
47 <<< "Options:\n"
48 <<< " --help Show this help\n"
49 <<< " --version Show the version\n"
50 <<< " --[no-]lex Lexer output(default: disabled)\n"
51 <<< " --[no-]parse Parser output(default: enabled)\n"
52 = snd $ fclose stdin w
53 # (contents, stdin, w) = readFileOrStdin stdin args.fp w
54 = case contents of
55 (Left cs) = snd $ fclose (stdin <<< cs) w
56 (Right cs)
57 # lexOut = lexer cs
58 # stdin = if (not args.lex) stdin (case lexOut of
59 (Right toks) =
60 stdin <<< "//LEXER\n" <<< printTokens toks <<< "//LEXER\n"
61 _ = stdin)
62 # parseOut = parser lexOut
63 # stdin = if (not args.parse) stdin (case parser lexOut of
64 (Right ast) =
65 stdin <<< "//PARSER\n" <<< toString ast <<< "//PARSER\n"
66 (Left parse) = stdin <<< toString parse)
67 = snd $ fclose stdin w
68 where
69 printTokens :: [Token] -> String
70 printTokens ts = concat $ flatten $ map pt ts
71 where
72 pt ({line,col},token) = [toString line, ":",
73 toString col, ": ", printToString token, "\n"]
74
75 parseArgs :: *World -> (Opts, *World)
76 parseArgs w
77 # ([p:args], w) = getCommandLine w
78 = (pa args {
79 program=p,
80 version=False,
81 lex=False,
82 parse=True,
83 fp=Nothing,
84 help=False}, w)
85 where
86 pa :: [String] Opts -> Opts
87 pa [] o = o
88 pa ["--help":r] o = pa r {o & help=True}
89 pa ["--version":r] o = pa r {o & version=True}
90 pa ["--lex":r] o = pa r {o & lex=True}
91 pa ["--no-lex":r] o = pa r {o & lex=False}
92 pa ["--parse":r] o = pa r {o & parse=True}
93 pa ["--no-parse":r] o = pa r {o & parse=False}
94 pa [x:r] o = pa r {o & fp=Just x}
95
96 readFileOrStdin :: *File (Maybe String) *World -> *(Either String [Char], *File, *World)
97 readFileOrStdin stdin Nothing w
98 # (cs, stdin) = readEntireFile stdin
99 = (Right cs, stdin, w)
100 readFileOrStdin stdin (Just fp) w
101 # (b, fin, w) = fopen fp FReadText w
102 | not b = (Left "Unable to open file", stdin, w)
103 # (cs, fin) = readEntireFile fin
104 # (b, w) = fclose fin w
105 | not b = (Left "Unable to close file", stdin, w)
106 = (Right cs, stdin, w)
107
108 readEntireFile :: *File -> *([Char], *File)
109 readEntireFile f
110 # (b, c, f) = freadc f
111 | not b = ([], f)
112 # (cs, f) = readEntireFile f
113 = ([c:cs], f)