org.xdef.impl.compile.XScriptMacro Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xdef Show documentation
Show all versions of xdef Show documentation
X-definition 4.2 (Open Source Software)
package org.xdef.impl.compile;
import org.xdef.msg.XDEF;
import org.xdef.sys.ArrayReporter;
import org.xdef.sys.ReportWriter;
import org.xdef.sys.SBuffer;
import org.xdef.sys.SParser;
import org.xdef.sys.StringParser;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/** Provides model of macro definition used in X-definitions script.
* @author Vaclav Trojan
*/
public final class XScriptMacro {
private final String _name;
private final String _value;
private final List _paramNames;
private final String[] _paramValues;
private int[] _references;
/** Create the new object ScriptMacro.
* @param name name of macro.
* @param defName name of X-definition.
* @param params table with macro parameters.
* @param body source of macro body.
* @param reporter reporter where errors are recorded (if this parameter
* is null then an runtime exception is thrown when an error
* occurs).
*/
public XScriptMacro(final String name,
final String defName,
final Map params,
final SBuffer body,
final ReportWriter reporter) {
SBuffer ibody = body == null ? new SBuffer("") : body;
ReportWriter rwi =
reporter == null ? new ArrayReporter() : reporter;
_name = (defName != null ? defName + '#' + name : name).intern();
int numParams = params.size();
_paramNames = new ArrayList<>(params.keySet());
_paramValues = new String[numParams];
for (int i = 0, j = _paramNames.size(); i < j; i++) {
_paramValues[i] = params.get(_paramNames.get(i));
}
_references = new int[0];
StringParser p = new StringParser(ibody.getString(), rwi);
int lastPos = p.getIndex();
StringBuilder sb = new StringBuilder();
while (p.findTokenAndSkip("#{")) {
if (p.getIndex() > 2 && p.getCharAtPos(p.getIndex() - 3) == '\\') {
continue;
}
sb.append(p.getBufferPart(lastPos,p.getIndex() - 2));
if (!isName(p)) {
//Reference to macro parameter is not integer
p.error(XDEF.XDEF490);
break;
}
String paramName = p.getParsedString();
int index = _paramNames.indexOf(paramName);
if (!p.isChar('}')) {
p.error(XDEF.XDEF491);//Incorrect reference to macro parameter
break;
}
lastPos = p.getIndex();
if (index < 0) {
p.error(XDEF.XDEF492); //Incorrect macro parameter index
break;
} else {
//add reference of parameter
int len = _references.length;
if (len > 0) {
int[] w = _references;
_references = new int[len + 2];
System.arraycopy(w, 0, _references, 0, len);
_references[len] = sb.length();
_references[len + 1] = index;
} else {
_references = new int[] {sb.length(), index};
}
}
}
if (lastPos < p.getEndBufferIndex()) {
sb.append(p.getBufferPartFrom(lastPos));
}
_value = sb.toString();
if (rwi.errors() && reporter == null) {
rwi.checkAndThrowErrors();
}
}
private boolean isName(final StringParser p) {
char c;
if ((c = p.isLetter()) == SParser.NOCHAR) {
if (p.isChar('_')) {
c = '_';
} else {
return false;
}
}
StringBuilder sb = new StringBuilder(String.valueOf(c));
for (;;) {
if ((c = p.isLetterOrDigit()) == SParser.NOCHAR) {
if (p.isChar('_')) {
sb.append('_');
} else {
p.setParsedString(sb.toString());
return true;
}
} else {
sb.append(c);
}
}
}
@Override
/** Returns hash code of the object. */
public int hashCode() {
return _name.hashCode();
}
@Override
/** This enables to use the method indexOf(anObject).
* @param anObject The object to be compared with this one.
* @return true if and only if the object is considered to be
* equal with this one.
*/
public boolean equals(final Object anObject) {
return (anObject instanceof XScriptMacro) ?
((XScriptMacro) anObject)._name.equals(_name) : false;
}
/** Expand macro reference
* @param params parameters of macro reference.
* @return string with expanded macro.
*/
public final String expand(final String... params) {
if (_references.length == 0) {
return _value; // no parameters
}
StringBuilder sb = new StringBuilder();
int lastPos = 0;
for (int i = 0; i < _references.length;) {
sb.append(_value.substring(lastPos, lastPos=_references[i++]));
sb.append(params[_references[i++]]);
}
if (lastPos < _value.length()) {
sb.append(_value.substring(lastPos));
}
return sb.toString();
}
/** Get macro name.
* @return macro name.
*/
public String getName() {return _name;}
/** Get list of names of macro parameters.
* @return list of names of macro parameters.
*/
public final List getParamNames() {return _paramNames;}
/** Get array with values of parameters,
* @return array with values of parameters,
*/
public final String[] getParamValues() {return _paramValues;}
/** Get string with value of macro.
* @return string with value of macro.
*/
public final String getParamValue() {return _value;}
}