Files
sml-projects/functional-core/file/parse-file.sml

136 lines
2.9 KiB
Standard ML
Raw Normal View History

signature PARSE_FILE =
sig
val parseLine: string -> AppType.triangle option
end
structure ParseFile :> PARSE_FILE =
struct
datatype triangle_token =
X
| Y
| R
| G
| B
| COORD of Real32.real
| UNKNOWN of string
val zero: Real32.real = 0.0
fun extractTriangle lst =
case lst of
[ X
, COORD x1
, Y
, COORD y1
, X
, COORD x2
, Y
, COORD y2
, X
, COORD x3
, Y
, COORD y3
] =>
(* file format not specifying any colours *)
SOME
{ x1 = x1
, y1 = y1
, x2 = x2
, y2 = y2
, x3 = x3
, y3 = y3
, r = zero
, g = zero
, b = zero
}
| [ X
, COORD x1
, Y
, COORD y1
, X
, COORD x2
, Y
, COORD y2
, X
, COORD x3
, Y
, COORD y3
, R
, COORD r
, G
, COORD g
, B
, COORD b
] =>
(* file format specifying rgb *)
SOME
{ x1 = x1
, y1 = y1
, x2 = x2
, y2 = y2
, x3 = x3
, y3 = y3
, r = r
, g = g
, b = b
}
| _ => NONE
fun tokeniseString str =
if str = "x" then
X
else if str = "y" then
Y
else if str = "r" then
R
else if str = "g" then
G
else if str = "b" then
B
else
case Real32.fromString str of
SOME num => COORD num
| NONE => UNKNOWN str
fun helpParseLine (line, pos, acc, wordStartPos) =
if pos = String.size line then
List.rev acc
else
let
val chr = String.sub (line, pos)
in
if Char.isSpace chr then
if pos > 0 andalso Char.isSpace (String.sub (line, pos - 1)) then
(* if previous character is space, just proceed to next character *)
helpParseLine (line, pos + 1, acc, wordStartPos)
else
let
(* current character is space, but previous character is not,
* which means we have some text to substring and tokenise
* before proceeding to next character *)
val strToken =
String.substring (line, wordStartPos, pos - wordStartPos)
val token = tokeniseString strToken
in
helpParseLine (line, pos + 1, token :: acc, pos)
end
else if pos > 0 andalso Char.isSpace (String.sub (line, pos - 1)) then
(* previous character was space but current character is not,
* meaning that we have hit the start of a new word *)
helpParseLine (line, pos + 1, acc, pos)
else
(* just proceed to next character *)
helpParseLine (line, pos + 1, acc, wordStartPos)
end
fun parseLine line =
let val lst = helpParseLine (line, 0, [], 0)
in extractTriangle lst
end
end