Files
sml-projects/dotscape/fcore/parser/parser.sml
Humza Shahid f3a4e15ed5 Add 'dotscape/' from commit 'f306501a68a51b634e895c5fdac70788ae899d75'
git-subtree-dir: dotscape
git-subtree-mainline: 6b91d64fc3
git-subtree-split: f306501a68
2026-04-24 00:30:08 +01:00

83 lines
2.7 KiB
Standard ML

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