aboutsummaryrefslogtreecommitdiff
path: root/SmurfParse.icl
blob: bf59b643939c15e1484538483a3b9d5eadc7aaea (plain) (blame)
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
implementation module SmurfParse

from StdFunc import o, flip
import StdArray
import StdChar
import StdList
import StdMisc
import StdFile
import StdTuple
import StdString

from Data.Func import $
import Data.Maybe
import Control.Applicative
import Control.Monad

import Smurf

eToVarChars :: Expr -> [VarChar]
eToVarChars (Lit s)         = map Char $ fromString s
eToVarChars (Var v)         = [VarString v]
eToVarChars (ECat a b)      = eToVarChars a ++ eToVarChars b
eToVarChars (EHead (Var v)) = abort "head of var\n"
eToVarChars (EHead a)       = [hd $ eToVarChars a]
eToVarChars (ETail (Var v)) = abort "tail of var\n"
eToVarChars (ETail a)       = tl $ eToVarChars a
eToVarChars (EQuotify a)    = [Quoted a]

parse :: ![Char] -> Maybe Program
parse cs = parsev $ map Char cs

parsev :: ![VarChar] -> Maybe Program
parsev []            = pure []
parsev [Char '"':cs] = parseString cs >>= \(s,cs`) -> append (Push s) $ parsev cs`
parsev [Char 'i':cs] = apparse Input cs
parsev [Char 'o':cs] = apparse Output cs
parsev [Char '+':cs] = apparse Cat cs
parsev [Char 'h':cs] = apparse Head cs
parsev [Char 't':cs] = apparse Tail cs
parsev [Char 'q':cs] = apparse Quotify cs
parsev [Char 'p':cs] = apparse Put cs
parsev [Char 'g':cs] = apparse Get cs
parsev [Char 'x':cs] = apparse Exec cs
parsev [Char c:cs]   = if (isSpace c) (parsev cs) empty
parsev [Quoted e:cs] = apparse (Push e) cs
parsev _             = empty

apparse :: Stm -> [VarChar] -> Maybe Program
apparse stm = append stm o parsev

append :: a (m [a]) -> m [a] | Monad m
append x mx = mx >>= \xs -> pure [x:xs]

parseString :: ![VarChar] -> Maybe (Expr, [VarChar])
parseString cs = pS [] cs
where
	pS :: ![VarChar] ![VarChar] -> Maybe (Expr, [VarChar])
	pS _ []             = empty
	pS s [Char '"':cs]
		= pure (toExpr $ reverse s, cs)
	pS s [Char '\\':Char 'n':cs]  = pS [Char '\n':s] cs
	pS s [Char '\\':Char 'r':cs]  = pS [Char '\r':s] cs
	pS s [Char '\\':Char 't':cs]  = pS [Char '\t':s] cs
	pS s [Char '\\':Char '\\':cs] = pS [Char '\\':s] cs
	pS s [Char '\\':Char '"':cs]  = pS [Char '"':s] cs
	pS s [c:cs]                   = pS [c:s] cs

	toExpr :: [VarChar] -> Expr
	toExpr cs = simplify $ te cs
	where
		te :: [VarChar] -> Expr
		te []               = Lit ""
		te [VarString v:cs] = ECat (Var v) (te cs)
		te [Char c:cs]      = ECat (Lit {c}) (te cs)
		te [Quoted e:cs2]   = ECat e (te cs2)
		
		simplify :: Expr -> Expr
		simplify (ECat a b) = case (simplify a, simplify b) of
			(Lit x, Lit y) = Lit $ x +++ y
			(x, y)         = ECat x y
		simplify e = e