structure Parser = struct structure T = Tokens fun parseItem (tokens, grid) = case tokens of T.L_BRACE :: T.INT x :: T.INT y :: T.INT ex :: T.INT ey :: T.INT r :: T.INT g :: T.INT b :: T.INT a :: T.R_BRACE :: tl => let val colour = {r = r, g = g, b = b, a = a} val grid = ParseGrid.applyItem (grid, x, y, ex, ey, colour) in SOME (tl, grid) end | _ => NONE (* note to be careful of: * - startParseItems returns NONE if there are no items found, * because we have not found a single item yet. * * - loopParseItems returns SOME if there are no items found, * because this function is called after we have parsed at least one item. * *) fun loopParseItems (tokens, grid) = case parseItem (tokens, grid) of SOME (tokens, grid) => loopParseItems (tokens, grid) | NONE => SOME (tokens, grid) fun startParseItems (tokens, grid) = case parseItem (tokens, grid) of SOME (tokens, grid) => loopParseItems (tokens, grid) | NONE => NONE fun parseLayer (tokens, canvasWidth, canvasHeight, tree, counter) = case tokens of T.L_BRACKET :: tl => let val grid = ParseGrid.make (canvasWidth, canvasHeight) in case startParseItems (tl, grid) of SOME (T.R_BRACKET :: tl, grid) => let val tree = LayerTree.insert (counter, grid, tree) in SOME (tl, tree) end | SOME _ => NONE | NONE => NONE end | _ => NONE fun parseLayerLoop (tokens, canvasWidth, canvasHeight, tree, counter) = case parseLayer (tokens, canvasWidth, canvasHeight, tree, counter) of SOME (tl, tree) => parseLayerLoop (tl, canvasWidth, canvasHeight, tree, counter + 1) | NONE => SOME (tokens, tree) fun startParseLayer (tokens, canvasWidth, canvasHeight, tree) = case parseLayer (tokens, canvasWidth, canvasHeight, tree, 1) of SOME (tl, tree) => parseLayerLoop (tl, canvasWidth, canvasHeight, tree, 2) | NONE => NONE fun parse string = case Lexer.scan string of SOME tokens => (case tokens of T.INT canvasWidth :: T.INT canvasHeight :: T.L_BRACE :: tl => let val maxSide = Int.max (canvasWidth, canvasHeight) val tree = LayerTree.init maxSide in case startParseLayer (tl, canvasWidth, canvasHeight, tree) of SOME ([T.R_BRACE], tree) => SOME (canvasWidth, canvasHeight, tree) | SOME _ => NONE | NONE => NONE end | _ => NONE) | NONE => NONE end