All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javax0.jamal.builtins.For Maven / Gradle / Ivy

package javax0.jamal.builtins;

import javax0.jamal.api.*;

import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Define the {@code for} looping macro. The syntax of the macro is
 *
 * 
 *     {#for var in (a,b,c,d)= var is either a, b, c or d
 *     }
 * 
*

* The default separator is {@code ,} (comma), but it can be redefined assigning a value to the user defined * macro {@code $forsep}. */ public class For implements Macro { private static final Pattern pattern = Pattern.compile("\\s+(\\w[\\w\\d_$]*)\\s+in\\s*\\((.*?)\\)\\s*=(.*)", Pattern.DOTALL); @Override public String evaluate(Input input, Processor processor) throws BadSyntax { Matcher matcher = pattern.matcher(input); if (!matcher.matches()) { throw new BadSyntax("use macro has bad syntax '" + input + "'"); } final String loopVariable = matcher.group(1); final String values = matcher.group(2); final String content = matcher.group(3); final Optional optionalForSepMacro = processor.getRegister().getUserMacro("$forsep"); final String splitter = optionalForSepMacro.isPresent() ? optionalForSepMacro.get().evaluate() : ","; final String[] valueList = values.split(splitter); final StringBuilder output = new StringBuilder(); final Segment root = new Segment(null, content); root.split(loopVariable); for (final String value : valueList) { for (Segment segment = root; segment != null; segment = segment.next()) { output.append(segment.content().orElse(value)); } } return output.toString(); } private static class Segment { Segment nextSeg; String text; Segment(Segment nextSeg, String text) { this.nextSeg = nextSeg; this.text = text; } private static void split(final Segment root, final String parameter) { Segment it = root; //noinspection StatementWithEmptyBody while ((it = splitAndGetNext(it, parameter)) != null) ; } private static Segment splitAndGetNext(final Segment it, final String parameter) { final int start = it.text.indexOf(parameter); if (start < 0) { return null; } final Segment textSeg = new Segment(it.nextSeg, it.text.substring(start + parameter.length())); it.nextSeg = new Segment(textSeg, null); it.text = it.text.substring(0, start); return textSeg; } Optional content() { return Optional.ofNullable(text); } Segment next() { return nextSeg; } void split(String parameter) { split(this, parameter); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy