/* e.g. overlay <- ScreenOverlay bounds <- rightScreenBounds overlay bounds bounds overlay show Can separate commands with ";" also. */ sclass GazelleV_LeftArrowScriptParser > SimpleLeftToRightParser { replace Toolbox with GazelleV_LeftArrowScript. delegate Script to Toolbox. delegate Evaluable to Toolbox. replace const with _const. new Script script; new LinkedHashSet knownVars; // object can be a class srecord MethodOnObject(O object, S method) {} Script parse(S text) { setText(text); while (mainLoop()) { if (is(";")) continue with next(); S t = token(); if (isIdentifier(t) && eq(token(1), "<") && eq(token(2), "-")) { next(3); knownVars.add(t); script.add(new Toolbox.Assignment(t, parseExpr())); } else addUnlessNull(script, parseExpr()); } ret script; } Evaluable parseOptionalExpression() { if (lineBreak()) null; ret parseExpr(); } Evaluable const(O o) { ret new Toolbox.Const(o); } Evaluable parseExpr() { if (atEnd()) null; if (is(";")) null; S t = tpp(); if (isInteger(t)) ret const(parseInt(t)); if (was("true")) ret const(true); if (was("false")) ret const(false); if (was("null")) ret const(null); if (knownVars.contains(t)) ret parseCall(new Toolbox.GetVar(t)); O o = findExternalObject(t); if (o == null) fail("Unknown object: " + t); else if (o cast Class) { L args = null; if (!atCmdEnd() && is("new")) { next(); args = parseExpressions(); } ret new Toolbox.NewObject((Class) target, args); } else if (o cast MethodOnObject) ret new Toolbox.CallMethod(const(o.object), o.method, parseExpressions()); else ret parseCall(const(o)); } L parseExpressions() { ret collectWhileNotNull(-> parseOptionalExpression()); } bool atCmdEnd() { ret atEndOrLineBreak() || is(";"); } Evaluable parseCall(Evaluable target) { if (atCmdEnd()) ret target; S methodName = tpp(); var args = parseExpressions(); ret new Toolbox.CallMethod(target, methodName, args); } // can return MethodOnObject swappable O findExternalObject(S name) { null; } void allowTheWorld(Class... functionContainers) { findExternalObject = name -> { try object findClassThroughDefaultClassFinder(name); try object findClassInStandardImports(name); fOr (container : functionContainers) if (hasMethodNamed(container, name)) ret new MethodOnObject(container, name); null; }; } }