1 (* Modified by Vesa Karvonen on
2007-12-18.
2 * Create line directives
in output
.
4 (* ML
-Yacc Parser
Generator (c
) 1991 Andrew W
. Appel
, David R
. Tarditi
*)
6 structure Absyn
: ABSYN
=
9 = CODE
of {text
: string, pos
: Header
.pos
}
15 | LET
of decl list
* exp
20 | PAPP
of string * pat
22 | PLIST
of pat list
* pat option
26 and decl
= VB
of pat
* exp
27 and rule
= RULE
of pat
* exp
29 fun idchar #
"'" = true
31 | idchar c
= Char.isAlpha c
orelse Char.isDigit c
33 fun code_to_ids s
= let
35 |
g(a
as (h
::t
),r
) = if Char.isAlpha h
then f(t
,[h
],r
) else g(t
,r
)
36 and f(nil
,accum
,r
)= implode(rev accum
)::r
37 |
f(a
as (h
::t
),accum
,r
) =
38 if idchar h
then f(t
,h
::accum
,r
) else g(a
,implode (rev accum
) :: r
)
42 val simplifyRule
: rule
-> rule
= fn (RULE(p
,e
)) =>
43 let val used
: (string -> bool) =
44 let fun f(CODE s
) = code_to_ids (#text s
)
45 |
f(EAPP(a
,b
)) = f a @ f b
46 |
f(ETUPLE l
) = List.concat (map f l
)
50 (List.concat (map (fn VB(_
,e
) => f e
) dl
)) @ f e
51 |
f(SEQ(a
,b
)) = f a @ f b
54 in fn s
=> List.exists (fn a
=>a
=s
) identifiers
56 val simplifyPat
: pat
-> pat
=
59 of (PVAR s
) => if used s
then a
else WILD
63 | pat
' => PAPP(s
,pat
'))
64 |
(PLIST (l
, topt
)) =>
66 val topt
' = Option
.map f topt
67 fun notWild WILD
= false
70 SOME WILD
=> if List.exists notWild l
' then
73 | _
=> PLIST (l
', topt
')
77 in if List.exists(fn WILD
=>false | _
=> true) l
'
90 val simplifyExp
: exp
-> exp
=
91 let fun f(EAPP(a
,b
)) = EAPP(f a
,f b
)
92 |
f(ETUPLE l
) = ETUPLE(map f l
)
93 |
f(FN(p
,e
)) = FN(simplifyPat p
,f e
)
95 LET(map (fn VB(p
,e
) =>
96 VB(simplifyPat p
,f e
)) dl
,
98 |
f(SEQ(a
,b
)) = SEQ(f a
,f b
)
102 in RULE(simplifyPat p
,simplifyExp e
)
105 fun printRule (say
: string -> unit
, sayln
:string -> unit
, fmtPos
) r
= let
106 fun flat (a
, []) = rev a
107 |
flat (a
, SEQ (e1
, e2
) :: el
) = flat (a
, e1
:: e2
:: el
)
108 |
flat (a
, e
:: el
) = flat (e
:: a
, el
)
109 fun pl (lb
, rb
, c
, f
, [], a
) = " " :: lb
:: rb
:: a
110 |
pl (lb
, rb
, c
, f
, h
:: t
, a
) =
111 " " :: lb
:: f (h
, foldr (fn (x
, a
) => c
:: f (x
, a
))
114 fun pe (CODE
{text
, pos
}, a
) =
115 " (" :: fmtPos (SOME pos
) :: text
:: fmtPos NONE
:: ")" :: a
116 |
pe (EAPP (x
, y
as (EAPP _
)), a
) =
117 pe (x
, " (" :: pe (y
, ")" :: a
))
118 |
pe (EAPP (x
, y
), a
) =
121 " " :: Int.toString i
:: a
122 |
pe (ETUPLE l
, a
) = pl ("(", ")", ",", pe
, l
, a
)
125 |
pe (FN (p
, b
), a
) =
126 " (fn" :: pp (p
, " =>" :: pe (b
, ")" :: a
))
127 |
pe (LET ([], b
), a
) =
129 |
pe (LET (dl
, b
), a
) =
130 let fun pr (VB (p
, e
), a
) =
131 " val " :: pp (p
, " =" :: pe (e
, "\n" :: a
))
132 in " let" :: foldr
pr (" in" :: pe (b
, "\nend" :: a
)) dl
134 |
pe (SEQ (e1
, e2
), a
) =
135 pl ("(", ")", ";", pe
, flat ([], [e1
, e2
]), a
)
140 |
pp (PAPP (x
, y
as PAPP _
), a
) =
141 " " :: x
:: " (" :: pp (y
, ")" :: a
)
142 |
pp (PAPP (x
, y
), a
) =
143 " " :: x
:: pp (y
, a
)
145 " " :: Int.toString i
:: a
146 |
pp (PLIST (l
, NONE
), a
) =
147 pl ("[", "]", ",", pp
, l
, a
)
148 |
pp (PLIST (l
, SOME t
), a
) =
149 " (" :: foldr (fn (x
, a
) => pp (x
, " ::" :: a
))
153 pl ("(", ")", ",", pp
, l
, a
)
156 |
pp (AS (v
, PVAR v
'), a
) =
157 " (" :: v
:: " as " :: v
' :: ")" :: a
158 |
pp (AS (v
, p
), a
) =
159 " (" :: v
:: " as (" :: pp (p
, "))" :: a
)
160 fun out
"\n" = sayln
""
163 case simplifyRule r
of
164 RULE (p
, e
) => app
out (pp (p
, " =>" :: pe (e
, ["\n"])))