package com.github.czyzby.lml.parser.impl.tag.macro; import com.github.czyzby.lml.parser.LmlParser; import com.github.czyzby.lml.parser.impl.tag.macro.util.Equation; import com.github.czyzby.lml.parser.tag.LmlTag; /** Calculates passed equation and assigns its result to an LML argument. The first macro attribute has to be tag's * name. The rest of attributes is merged into an equation - so spaces are allowed. Alternatively, equation can be * passed with data between macro tags. Supported operators: * * <ul> * <li>+: adds ints and floats; concats Strings. * <li>-: subtracts ints and floats; uses {@link String#replace(CharSequence, CharSequence)} (replacing with empty * string) on first string, removing occurrences of the second. * <li>=: compares booleans, ints and floats; uses {@link String#equalsIgnoreCase(String)} on strings. * <li>==: works like =, except uses regular equals method on strings. * <li>!=, !==: negated equality operators. * <li><, <=, >, >=: compares ints and floats; compares strings's lengths. If one of the strings is an int, * compares numeric int value to the other's length. For example, "string>t" returns true, as "string" is longer than * "t", but "string>9" returns false, because "string" has less characters than 9. Since > is also the char that * closes the tag it cannot be used directly - alias for > is {@literal >}. < does not have to be escaped, so * there's no alias. * <li>^: {@link java.lang.Math#pow(double, double)} on numbers; XOR on booleans. * <li>&, &&, |, ||: logical "and" and "or" on booleans. Bit "and" and "or" on ints. * <li>%: modulo on ints and floats. * <li>!: negates booleans, ints and floats. Clears strings to empty string. Negates operators (!= becomes "not equals", * !< becomes >, etc). * <li>~: negates booleans. Bit negation on ints. * <li>--, ++: increments or decrements numbers. Has to appear BEFORE the value to modify: will have no effect or throw * exception otherwise. Has similar effect to +1 or -1, but is evaluated before most other operators; for example, --3^2 * returns 4, while 3-1^2 returns 2. If you want to simulate -- or ++, use parenthesis: (3-1)^2 returns 4. * </ul> * * For example: * * <blockquote> * * <pre> * <:calculate meaningOfLife 40+2/> * </pre> * * </blockquote>This will assign "42" to {meaningOfLife} attribute. * * <blockquote> * * <pre> * <:calculate shouldContinue>{loop:index}^2==4</:calculate> * </pre> * * </blockquote>This will assign "true" boolean value to {shouldContinue} if squared "loop:index" argument value equals * 4. * * <blockquote> * * <pre> * <:calculate concat should+be+joined+{index}/> * </pre> * * </blockquote>Will merge the arguments, assigning "shouldbejoinedN" (where N is the current value of "index") to * {concat} argument. * * <blockquote> * * <pre> *<table> * <:loop 4> * <:calculate makeRow {loop:index}%2==1/> * <label row={makeRow}>@bundleLine{loop:index}</label> * </:loop> *</table> * </pre> * * </blockquote> * * This makes 4 labels (with text extracted from i18n bundle lines: bundleLine0-bundleLine3). Since the calculation * result is a boolean, it can be easily used as an actor attribute. In this example, when loop index is not even (1, * 3), it adds a table row thanks to "row=true" attribute. {makeRow} will take these values: false (0 iteration), true * (1), false (2), true (3). * * <p> * {@link com.github.czyzby.lml.parser.LmlSyntax#getEquationMarker() Equation marker} is a simplified alternative to * this macro. * * <p> * This macro can also be used with named attributes: <blockquote> * * <pre> * <:calculate key="meaningOfLife" value="40+2"/> * </pre> * * </blockquote> * * @author MJ */ public class CalculationLmlMacroTag extends AssignLmlMacroTag { public CalculationLmlMacroTag(final LmlParser parser, final LmlTag parentTag, final StringBuilder rawTagData) { super(parser, parentTag, rawTagData); } @Override protected String processArgumentValue(final CharSequence argumentValue) { return new Equation(getParser(), getActor()) .getResult(replaceArguments(argumentValue, getParser().getData().getArguments())); } }