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