aboutsummaryrefslogtreecommitdiff
path: root/SmurfParse.icl
blob: 385747cdab02070f522fa67954498b39d98985e6 (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
82
83
84
85
86
87
88
89
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 a)       = case eToVarChars a of
	[Char c:cs] = [Char c]
	[VarString s:cs] = [VarString (s % (0,0))]
	[Quoted e:_] = abort "head of quoted\n"
eToVarChars (ETail a) = case eToVarChars a of
	[Char _:cs] = cs
	[VarString s:cs] = [VarString (s % (1,size s - 1)):cs]
	[Quoted e:_] = abort "tail of quoted\n"
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 "", Lit y) = Lit y
			(Lit x, Lit "") = Lit x
			(Lit x, Lit y)  = Lit $ x +++ y
			(x, y)          = ECat x y
		simplify (EHead a) = EHead $ simplify a
		simplify (ETail a) = ETail $ simplify a
		simplify e = e