/* e.g. overlay <- ScreenOverlay bounds <- rightScreenBounds overlay bounds bounds overlay show */ sclass GazelleV_LeftArrowScript > SimpleLeftToRightParser { new Script script; new LinkedHashSet knownVars; interface Evaluable { public O get(VarContext ctx); } sclass Script extends ArrayList { void run(VarContext ctx) { main forEach(this, step -> step.get(ctx)); } } sclass Assignment is Evaluable { settable S var; Evaluable expression; public O get(VarContext ctx) { ctx.set(var, expression.get(ctx)); } } srecord noeq NewObject(Class c) is Evaluable { public O get(VarContext ctx) { ret callConstructor(c); } } srecord noeq GetVar(S var) is Evaluable { public O get(VarContext ctx) { ret ctx.get(var); } } srecord noeq Const(O value) is Evaluable { public O get(VarContext ctx) { ret value; } } srecord CallMethod(Evaluable target, S methodName, L args) { public O get(VarContext ctx) { ret call(target.get(ctx), methodName, mapToArray(args, arg -> arg.get(ctx))); } } Script parse() { while (mainLoop()) { S t = token(); if (isIdentifier(t) && eq(token(1), "<") && eq(token(2), "-")) { next(3); script.add(Assignment(t, parseExpr())); knownVars.add(t); } else script.add(parseExpr()); } ret script; } Evaluable parseExpr() { if (atEndOrLineBreak()) null; S t = tpp(); if (knownVars.contains(t)) ret parseCall(new GetVar(t)); O o = findExternalObject(t); if (o == null) fail("Unknown object: " + o); else if (o cast Class) ret new NewObject(o); else ret parseCall(new Const(o)); } L parseExpressions() { ret collectWhileNotNull(-> parseExpr()); } Evaluable parseCall(Evaluable target) { if (atEndOrLineBreak()) ret target; S methodName = tpp(); var args = parseExpressions(); ret new CallMethod(target, methodName, args); } swappable O findExternalObject(S name) { null; } }