mirror of https://github.com/octoleo/plantuml.git
refactor: prepare preprocessor error improvement (in progress)
https://github.com/plantuml/plantuml/pull/1668
This commit is contained in:
parent
436fb37f1a
commit
6329d9a8d5
|
@ -1,4 +1,4 @@
|
||||||
# Warning, "version" should be the same in gradle.properties and Version.java
|
# Warning, "version" should be the same in gradle.properties and Version.java
|
||||||
# Any idea anyone how to magically synchronize those :-) ?
|
# Any idea anyone how to magically synchronize those :-) ?
|
||||||
version = 1.2024.4beta2
|
version = 1.2024.4beta3
|
||||||
org.gradle.workers.max = 3
|
org.gradle.workers.max = 3
|
|
@ -143,7 +143,7 @@ public class BlockUml {
|
||||||
this.data = new ArrayList<>(strings);
|
this.data = new ArrayList<>(strings);
|
||||||
} else {
|
} else {
|
||||||
final TimLoader timLoader = new TimLoader(mode.getImportedFiles(), defines, charset,
|
final TimLoader timLoader = new TimLoader(mode.getImportedFiles(), defines, charset,
|
||||||
(DefinitionsContainer) mode);
|
(DefinitionsContainer) mode, strings.get(0));
|
||||||
this.included.addAll(timLoader.load(strings));
|
this.included.addAll(timLoader.load(strings));
|
||||||
this.data = timLoader.getResultList();
|
this.data = timLoader.getResultList();
|
||||||
this.debug = timLoader.getDebug();
|
this.debug = timLoader.getDebug();
|
||||||
|
|
|
@ -55,6 +55,7 @@ import net.sourceforge.plantuml.file.AParentFolder;
|
||||||
import net.sourceforge.plantuml.security.SFile;
|
import net.sourceforge.plantuml.security.SFile;
|
||||||
import net.sourceforge.plantuml.security.SecurityProfile;
|
import net.sourceforge.plantuml.security.SecurityProfile;
|
||||||
import net.sourceforge.plantuml.security.SecurityUtils;
|
import net.sourceforge.plantuml.security.SecurityUtils;
|
||||||
|
import net.sourceforge.plantuml.text.StringLocated;
|
||||||
import net.sourceforge.plantuml.tim.EaterException;
|
import net.sourceforge.plantuml.tim.EaterException;
|
||||||
import net.sourceforge.plantuml.tim.TMemory;
|
import net.sourceforge.plantuml.tim.TMemory;
|
||||||
import net.sourceforge.plantuml.tim.TVariableScope;
|
import net.sourceforge.plantuml.tim.TVariableScope;
|
||||||
|
@ -81,11 +82,11 @@ public class Defines implements Truth {
|
||||||
return new Defines();
|
return new Defines();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void copyTo(TMemory memory) throws EaterException {
|
public void copyTo(TMemory memory, StringLocated location) throws EaterException {
|
||||||
for (Entry<String, Define> ent : values.entrySet()) {
|
for (Entry<String, Define> ent : values.entrySet()) {
|
||||||
final String name = ent.getKey();
|
final String name = ent.getKey();
|
||||||
final Define def = ent.getValue();
|
final Define def = ent.getValue();
|
||||||
memory.putVariable(name, def.asTVariable(), TVariableScope.GLOBAL);
|
memory.putVariable(name, def.asTVariable(), TVariableScope.GLOBAL, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -114,10 +115,10 @@ public class Defines implements Truth {
|
||||||
final Defines result = createEmpty();
|
final Defines result = createEmpty();
|
||||||
result.overrideFilename(file.getName());
|
result.overrideFilename(file.getName());
|
||||||
result.environment.put("filedate", new Date(file.lastModified()).toString());
|
result.environment.put("filedate", new Date(file.lastModified()).toString());
|
||||||
if (SecurityUtils.getSecurityProfile() == SecurityProfile.UNSECURE) {
|
if (SecurityUtils.getSecurityProfile() == SecurityProfile.UNSECURE)
|
||||||
result.environment.put("dirpath",
|
result.environment.put("dirpath",
|
||||||
file.getAbsoluteFile().getParentFile().getAbsolutePath().replace('\\', '/'));
|
file.getAbsoluteFile().getParentFile().getAbsolutePath().replace('\\', '/'));
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,10 +127,10 @@ public class Defines implements Truth {
|
||||||
final Defines result = createEmpty();
|
final Defines result = createEmpty();
|
||||||
result.overrideFilename(file.getName());
|
result.overrideFilename(file.getName());
|
||||||
result.environment.put("filedate", new Date(file.lastModified()).toString());
|
result.environment.put("filedate", new Date(file.lastModified()).toString());
|
||||||
if (SecurityUtils.getSecurityProfile() == SecurityProfile.UNSECURE) {
|
if (SecurityUtils.getSecurityProfile() == SecurityProfile.UNSECURE)
|
||||||
result.environment.put("dirpath",
|
result.environment.put("dirpath",
|
||||||
file.getAbsoluteFile().getParentFile().getAbsolutePath().replace('\\', '/'));
|
file.getAbsoluteFile().getParentFile().getAbsolutePath().replace('\\', '/'));
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,9 +148,9 @@ public class Defines implements Truth {
|
||||||
|
|
||||||
private static String nameNoExtension(String name) {
|
private static String nameNoExtension(String name) {
|
||||||
final int x = name.lastIndexOf('.');
|
final int x = name.lastIndexOf('.');
|
||||||
if (x == -1) {
|
if (x == -1)
|
||||||
return name;
|
return name;
|
||||||
}
|
|
||||||
return name.substring(0, x);
|
return name.substring(0, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,11 +170,10 @@ public class Defines implements Truth {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isTrue(String name) {
|
public boolean isTrue(String name) {
|
||||||
for (String key : values.keySet()) {
|
for (String key : values.keySet())
|
||||||
if (key.equals(name) || key.startsWith(name + "(")) {
|
if (key.equals(name) || key.startsWith(name + "("))
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,9 +192,9 @@ public class Defines implements Truth {
|
||||||
}
|
}
|
||||||
|
|
||||||
private String method1(String line) {
|
private String method1(String line) {
|
||||||
for (Define def : values.values()) {
|
for (Define def : values.values())
|
||||||
line = def.apply(line);
|
line = def.apply(line);
|
||||||
}
|
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,18 +215,17 @@ public class Defines implements Truth {
|
||||||
|
|
||||||
private String method2(String line) {
|
private String method2(String line) {
|
||||||
final Set<String> words = words(line);
|
final Set<String> words = words(line);
|
||||||
if (magic == null) {
|
if (magic == null)
|
||||||
magic = getAll();
|
magic = getAll();
|
||||||
|
|
||||||
}
|
|
||||||
for (String w : words) {
|
for (String w : words) {
|
||||||
Collection<Define> tmp = magic.get(w);
|
Collection<Define> tmp = magic.get(w);
|
||||||
if (tmp == null) {
|
if (tmp == null)
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
for (Define def : tmp) {
|
for (Define def : tmp)
|
||||||
line = def.apply(line);
|
line = def.apply(line);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
@ -236,9 +235,9 @@ public class Defines implements Truth {
|
||||||
Pattern p = Pattern.compile(ID);
|
Pattern p = Pattern.compile(ID);
|
||||||
Matcher m = p.matcher(line);
|
Matcher m = p.matcher(line);
|
||||||
final Set<String> words = new HashSet<>();
|
final Set<String> words = new HashSet<>();
|
||||||
while (m.find()) {
|
while (m.find())
|
||||||
words.add(m.group(0));
|
words.add(m.group(0));
|
||||||
}
|
|
||||||
return words;
|
return words;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
package net.sourceforge.plantuml.preproc;
|
package net.sourceforge.plantuml.preproc;
|
||||||
|
|
||||||
public interface Truth {
|
public interface Truth {
|
||||||
|
|
||||||
public boolean isTrue(String name);
|
public boolean isTrue(String name);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,21 +139,21 @@ public class PreprocessorUtils {
|
||||||
if (StartDiagramExtractReader.containsStartDiagram(url, s, charset))
|
if (StartDiagramExtractReader.containsStartDiagram(url, s, charset))
|
||||||
return StartDiagramExtractReader.build(url, s, suf, charset);
|
return StartDiagramExtractReader.build(url, s, suf, charset);
|
||||||
|
|
||||||
return getReaderInclude(url, s.getLocation(), charset);
|
return getReaderInclude(url, s, charset);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Logme.error(e);
|
Logme.error(e);
|
||||||
throw EaterException.located("Cannot open URL " + e.getMessage());
|
throw EaterException.located("Cannot open URL " + e.getMessage(), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ReadLine getReaderInclude(SURL url, LineLocation lineLocation, Charset charset)
|
public static ReadLine getReaderInclude(SURL url, StringLocated s, Charset charset)
|
||||||
throws EaterException, UnsupportedEncodingException {
|
throws EaterException, UnsupportedEncodingException {
|
||||||
final InputStream is = url.openStream();
|
final InputStream is = url.openStream();
|
||||||
if (is == null)
|
if (is == null)
|
||||||
throw EaterException.located("Cannot open URL");
|
throw EaterException.located("Cannot open URL", s);
|
||||||
|
|
||||||
return ReadLineReader.create(new InputStreamReader(is, charset), url.toString(), lineLocation);
|
return ReadLineReader.create(new InputStreamReader(is, charset), url.toString(), s.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,7 +93,7 @@ public abstract class Eater {
|
||||||
final TokenStack tokenStack = new TokenStack();
|
final TokenStack tokenStack = new TokenStack();
|
||||||
addIntoTokenStack(tokenStack, false);
|
addIntoTokenStack(tokenStack, false);
|
||||||
if (tokenStack.size() == 0)
|
if (tokenStack.size() == 0)
|
||||||
throw EaterException.located("Missing expression");
|
throw EaterException.located("Missing expression", stringLocated);
|
||||||
|
|
||||||
return tokenStack;
|
return tokenStack;
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,7 @@ public abstract class Eater {
|
||||||
final public String eatAndGetQuotedString() throws EaterException {
|
final public String eatAndGetQuotedString() throws EaterException {
|
||||||
final char separator = peekChar();
|
final char separator = peekChar();
|
||||||
if (TLineType.isQuote(separator) == false)
|
if (TLineType.isQuote(separator) == false)
|
||||||
throw EaterException.located("quote10");
|
throw EaterException.located("quote10", stringLocated);
|
||||||
|
|
||||||
checkAndEatChar(separator);
|
checkAndEatChar(separator);
|
||||||
final StringBuilder value = new StringBuilder();
|
final StringBuilder value = new StringBuilder();
|
||||||
|
@ -142,7 +142,7 @@ public abstract class Eater {
|
||||||
while (true) {
|
while (true) {
|
||||||
char ch = peekChar();
|
char ch = peekChar();
|
||||||
if (ch == 0)
|
if (ch == 0)
|
||||||
throw EaterException.located("until001");
|
throw EaterException.located("until001", stringLocated);
|
||||||
|
|
||||||
if (level == 0 && (ch == ',' || ch == ')'))
|
if (level == 0 && (ch == ',' || ch == ')'))
|
||||||
return value.toString().trim();
|
return value.toString().trim();
|
||||||
|
@ -190,7 +190,7 @@ public abstract class Eater {
|
||||||
final protected String eatAndGetVarname() throws EaterException {
|
final protected String eatAndGetVarname() throws EaterException {
|
||||||
final StringBuilder varname = new StringBuilder("" + eatOneChar());
|
final StringBuilder varname = new StringBuilder("" + eatOneChar());
|
||||||
if (TLineType.isLetterOrUnderscoreOrDollar(varname.charAt(0)) == false)
|
if (TLineType.isLetterOrUnderscoreOrDollar(varname.charAt(0)) == false)
|
||||||
throw EaterException.located("a002");
|
throw EaterException.located("a002", stringLocated);
|
||||||
|
|
||||||
addUpToLastLetterOrUnderscoreOrDigit(varname);
|
addUpToLastLetterOrUnderscoreOrDigit(varname);
|
||||||
return varname.toString();
|
return varname.toString();
|
||||||
|
@ -199,7 +199,7 @@ public abstract class Eater {
|
||||||
final protected String eatAndGetFunctionName() throws EaterException {
|
final protected String eatAndGetFunctionName() throws EaterException {
|
||||||
final StringBuilder varname = new StringBuilder("" + eatOneChar());
|
final StringBuilder varname = new StringBuilder("" + eatOneChar());
|
||||||
if (TLineType.isLetterOrUnderscoreOrDollar(varname.charAt(0)) == false)
|
if (TLineType.isLetterOrUnderscoreOrDollar(varname.charAt(0)) == false)
|
||||||
throw EaterException.located("a003");
|
throw EaterException.located("a003", stringLocated);
|
||||||
|
|
||||||
addUpToLastLetterOrUnderscoreOrDigit(varname);
|
addUpToLastLetterOrUnderscoreOrDigit(varname);
|
||||||
return varname.toString();
|
return varname.toString();
|
||||||
|
@ -249,7 +249,7 @@ public abstract class Eater {
|
||||||
|
|
||||||
final protected void checkAndEatChar(char ch) throws EaterException {
|
final protected void checkAndEatChar(char ch) throws EaterException {
|
||||||
if (i >= stringLocated.length() || stringLocated.charAt(i) != ch)
|
if (i >= stringLocated.length() || stringLocated.charAt(i) != ch)
|
||||||
throw EaterException.located("a001");
|
throw EaterException.located("a001", stringLocated);
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
@ -299,7 +299,7 @@ public abstract class Eater {
|
||||||
}
|
}
|
||||||
|
|
||||||
final protected TFunctionImpl eatDeclareFunction(TContext context, TMemory memory, boolean unquoted,
|
final protected TFunctionImpl eatDeclareFunction(TContext context, TMemory memory, boolean unquoted,
|
||||||
LineLocation location, boolean allowNoParenthesis, TFunctionType type)
|
StringLocated location, boolean allowNoParenthesis, TFunctionType type)
|
||||||
throws EaterException, EaterExceptionLocated {
|
throws EaterException, EaterExceptionLocated {
|
||||||
final List<TFunctionArgument> args = new ArrayList<>();
|
final List<TFunctionArgument> args = new ArrayList<>();
|
||||||
final String functionName = eatAndGetFunctionName();
|
final String functionName = eatAndGetFunctionName();
|
||||||
|
@ -308,7 +308,7 @@ public abstract class Eater {
|
||||||
if (allowNoParenthesis)
|
if (allowNoParenthesis)
|
||||||
return new TFunctionImpl(functionName, args, unquoted, type);
|
return new TFunctionImpl(functionName, args, unquoted, type);
|
||||||
|
|
||||||
throw EaterException.located("Missing opening parenthesis");
|
throw EaterException.located("Missing opening parenthesis", stringLocated);
|
||||||
}
|
}
|
||||||
while (true) {
|
while (true) {
|
||||||
skipSpaces();
|
skipSpaces();
|
||||||
|
@ -320,7 +320,7 @@ public abstract class Eater {
|
||||||
if (peekChar() == '=') {
|
if (peekChar() == '=') {
|
||||||
eatOneChar();
|
eatOneChar();
|
||||||
final TokenStack def = TokenStack.eatUntilCloseParenthesisOrComma(this);
|
final TokenStack def = TokenStack.eatUntilCloseParenthesisOrComma(this);
|
||||||
def.guessFunctions();
|
def.guessFunctions(location);
|
||||||
defValue = def.getResult(getStringLocated(), context, memory);
|
defValue = def.getResult(getStringLocated(), context, memory);
|
||||||
// System.err.println("result=" + defValue);
|
// System.err.println("result=" + defValue);
|
||||||
} else {
|
} else {
|
||||||
|
@ -333,7 +333,7 @@ public abstract class Eater {
|
||||||
checkAndEatChar(")");
|
checkAndEatChar(")");
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
throw EaterException.located("Error in function definition");
|
throw EaterException.located("Error in function definition", stringLocated);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
skipSpaces();
|
skipSpaces();
|
||||||
|
@ -341,25 +341,25 @@ public abstract class Eater {
|
||||||
}
|
}
|
||||||
|
|
||||||
final protected TFunctionImpl eatDeclareReturnFunctionWithOptionalReturn(TContext context, TMemory memory,
|
final protected TFunctionImpl eatDeclareReturnFunctionWithOptionalReturn(TContext context, TMemory memory,
|
||||||
boolean unquoted, LineLocation location) throws EaterException, EaterExceptionLocated {
|
boolean unquoted, StringLocated location) throws EaterException, EaterExceptionLocated {
|
||||||
final TFunctionImpl result = eatDeclareFunction(context, memory, unquoted, location, false,
|
final TFunctionImpl result = eatDeclareFunction(context, memory, unquoted, location, false,
|
||||||
TFunctionType.RETURN_FUNCTION);
|
TFunctionType.RETURN_FUNCTION);
|
||||||
if (peekChar() == 'r') {
|
if (peekChar() == 'r') {
|
||||||
checkAndEatChar("return");
|
checkAndEatChar("return");
|
||||||
skipSpaces();
|
skipSpaces();
|
||||||
final String line = "!return " + eatAllToEnd();
|
final String line = "!return " + eatAllToEnd();
|
||||||
result.addBody(new StringLocated(line, location));
|
result.addBody(new StringLocated(line, location.getLocation()));
|
||||||
} else if (peekChar() == '!') {
|
} else if (peekChar() == '!') {
|
||||||
checkAndEatChar("!return");
|
checkAndEatChar("!return");
|
||||||
skipSpaces();
|
skipSpaces();
|
||||||
final String line = "!return " + eatAllToEnd();
|
final String line = "!return " + eatAllToEnd();
|
||||||
result.addBody(new StringLocated(line, location));
|
result.addBody(new StringLocated(line, location.getLocation()));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
final protected TFunctionImpl eatDeclareProcedure(TContext context, TMemory memory, boolean unquoted,
|
final protected TFunctionImpl eatDeclareProcedure(TContext context, TMemory memory, boolean unquoted,
|
||||||
LineLocation location) throws EaterException, EaterExceptionLocated {
|
StringLocated location) throws EaterException, EaterExceptionLocated {
|
||||||
final TFunctionImpl result = eatDeclareFunction(context, memory, unquoted, location, false,
|
final TFunctionImpl result = eatDeclareFunction(context, memory, unquoted, location, false,
|
||||||
TFunctionType.PROCEDURE);
|
TFunctionType.PROCEDURE);
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -53,7 +53,7 @@ public class EaterAffectation extends Eater {
|
||||||
if (scope != null) {
|
if (scope != null) {
|
||||||
skipSpaces();
|
skipSpaces();
|
||||||
if (peekChar() == '?' || peekChar() == '=') {
|
if (peekChar() == '?' || peekChar() == '=') {
|
||||||
// The variable itself is "local" or "glocal", which is not a good idea by the
|
// The variable itself is "local" or "global", which is not a good idea by the
|
||||||
// way
|
// way
|
||||||
scope = null;
|
scope = null;
|
||||||
} else
|
} else
|
||||||
|
@ -72,7 +72,7 @@ public class EaterAffectation extends Eater {
|
||||||
|
|
||||||
skipSpaces();
|
skipSpaces();
|
||||||
final TValue value = eatExpression(context, memory);
|
final TValue value = eatExpression(context, memory);
|
||||||
memory.putVariable(varname, value, scope);
|
memory.putVariable(varname, value, scope, getStringLocated());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ public class EaterAffectationDefine extends Eater {
|
||||||
// if (memory instanceof TMemoryLocal) {
|
// if (memory instanceof TMemoryLocal) {
|
||||||
// memory = ((TMemoryLocal) memory).getGlobalForInternalUseOnly();
|
// memory = ((TMemoryLocal) memory).getGlobalForInternalUseOnly();
|
||||||
// }
|
// }
|
||||||
memory.putVariable(varname, value, TVariableScope.GLOBAL);
|
memory.putVariable(varname, value, TVariableScope.GLOBAL, getStringLocated());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,9 +55,9 @@ public class EaterAssert extends Eater {
|
||||||
if (ch == ':') {
|
if (ch == ':') {
|
||||||
checkAndEatChar(':');
|
checkAndEatChar(':');
|
||||||
final TValue message = eatExpression(context, memory);
|
final TValue message = eatExpression(context, memory);
|
||||||
throw EaterException.located("Assertion error : " + message.toString());
|
throw EaterException.located("Assertion error : " + message.toString(), getStringLocated());
|
||||||
}
|
}
|
||||||
throw EaterException.located("Assertion error");
|
throw EaterException.located("Assertion error", getStringLocated());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,17 +35,16 @@
|
||||||
package net.sourceforge.plantuml.tim;
|
package net.sourceforge.plantuml.tim;
|
||||||
|
|
||||||
import net.sourceforge.plantuml.text.StringLocated;
|
import net.sourceforge.plantuml.text.StringLocated;
|
||||||
import net.sourceforge.plantuml.utils.LineLocation;
|
|
||||||
|
|
||||||
public class EaterDeclareProcedure extends Eater {
|
public class EaterDeclareProcedure extends Eater {
|
||||||
|
|
||||||
private TFunctionImpl function;
|
private TFunctionImpl function;
|
||||||
private final LineLocation location;
|
private final StringLocated location;
|
||||||
private boolean finalFlag;
|
private boolean finalFlag;
|
||||||
|
|
||||||
public EaterDeclareProcedure(StringLocated s) {
|
public EaterDeclareProcedure(StringLocated s) {
|
||||||
super(s.getTrimmed());
|
super(s.getTrimmed());
|
||||||
this.location = s.getLocation();
|
this.location = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -35,17 +35,16 @@
|
||||||
package net.sourceforge.plantuml.tim;
|
package net.sourceforge.plantuml.tim;
|
||||||
|
|
||||||
import net.sourceforge.plantuml.text.StringLocated;
|
import net.sourceforge.plantuml.text.StringLocated;
|
||||||
import net.sourceforge.plantuml.utils.LineLocation;
|
|
||||||
|
|
||||||
public class EaterDeclareReturnFunction extends Eater {
|
public class EaterDeclareReturnFunction extends Eater {
|
||||||
|
|
||||||
private TFunctionImpl function;
|
private TFunctionImpl function;
|
||||||
private final LineLocation location;
|
private final StringLocated location;
|
||||||
private boolean finalFlag;
|
private boolean finalFlag;
|
||||||
|
|
||||||
public EaterDeclareReturnFunction(StringLocated s) {
|
public EaterDeclareReturnFunction(StringLocated s) {
|
||||||
super(s.getTrimmed());
|
super(s.getTrimmed());
|
||||||
this.location = s.getLocation();
|
this.location = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -40,16 +40,16 @@ public class EaterException extends Exception {
|
||||||
|
|
||||||
private final String message;
|
private final String message;
|
||||||
|
|
||||||
private EaterException(String message) {
|
private EaterException(String message, StringLocated location) {
|
||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EaterException unlocated(String message) {
|
public static EaterException unlocated(String message, StringLocated location) {
|
||||||
return new EaterException(message);
|
return new EaterException(message, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EaterException located(String message) {
|
public static EaterException located(String message, StringLocated location) {
|
||||||
return unlocated(message);
|
return unlocated(message, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final String getMessage() {
|
public final String getMessage() {
|
||||||
|
|
|
@ -100,12 +100,12 @@ public class EaterFunctionCall extends Eater {
|
||||||
checkAndEatChar('=');
|
checkAndEatChar('=');
|
||||||
skipSpaces();
|
skipSpaces();
|
||||||
final TokenStack tokens = TokenStack.eatUntilCloseParenthesisOrComma(this).withoutSpace();
|
final TokenStack tokens = TokenStack.eatUntilCloseParenthesisOrComma(this).withoutSpace();
|
||||||
tokens.guessFunctions();
|
tokens.guessFunctions(getStringLocated());
|
||||||
final TValue result = tokens.getResult(getStringLocated(), context, memory);
|
final TValue result = tokens.getResult(getStringLocated(), context, memory);
|
||||||
namedArguments.put(varname, result);
|
namedArguments.put(varname, result);
|
||||||
} else {
|
} else {
|
||||||
final TokenStack tokens = TokenStack.eatUntilCloseParenthesisOrComma(this).withoutSpace();
|
final TokenStack tokens = TokenStack.eatUntilCloseParenthesisOrComma(this).withoutSpace();
|
||||||
tokens.guessFunctions();
|
tokens.guessFunctions(getStringLocated());
|
||||||
final TValue result = tokens.getResult(getStringLocated(), context, memory);
|
final TValue result = tokens.getResult(getStringLocated(), context, memory);
|
||||||
values.add(result);
|
values.add(result);
|
||||||
}
|
}
|
||||||
|
@ -119,9 +119,9 @@ public class EaterFunctionCall extends Eater {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (unquoted) {
|
if (unquoted) {
|
||||||
throw EaterException.located("unquoted function/procedure cannot use expression.");
|
throw EaterException.located("unquoted function/procedure cannot use expression.", getStringLocated());
|
||||||
}
|
}
|
||||||
throw EaterException.located("call001");
|
throw EaterException.located("call001", getStringLocated());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ import net.sourceforge.plantuml.text.StringLocated;
|
||||||
|
|
||||||
public class EaterInclude extends Eater {
|
public class EaterInclude extends Eater {
|
||||||
|
|
||||||
private String location;
|
private String what;
|
||||||
private PreprocessorIncludeStrategy strategy = PreprocessorIncludeStrategy.DEFAULT;
|
private PreprocessorIncludeStrategy strategy = PreprocessorIncludeStrategy.DEFAULT;
|
||||||
|
|
||||||
public EaterInclude(StringLocated s) {
|
public EaterInclude(StringLocated s) {
|
||||||
|
@ -65,15 +65,15 @@ public class EaterInclude extends Eater {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
skipSpaces();
|
skipSpaces();
|
||||||
this.location = context.applyFunctionsAndVariables(memory,
|
this.what = context.applyFunctionsAndVariables(memory,
|
||||||
new StringLocated(this.eatAllToEnd(), getLineLocation()));
|
new StringLocated(this.eatAllToEnd(), getLineLocation()));
|
||||||
// final TValue value = eatExpression(context, memory);
|
// final TValue value = eatExpression(context, memory);
|
||||||
// this.location = value.toString();
|
// this.location = value.toString();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final String getLocation() {
|
public final String getWhat() {
|
||||||
return location;
|
return what;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final PreprocessorIncludeStrategy getPreprocessorIncludeStrategy() {
|
public final PreprocessorIncludeStrategy getPreprocessorIncludeStrategy() {
|
||||||
|
|
|
@ -38,7 +38,7 @@ import net.sourceforge.plantuml.text.StringLocated;
|
||||||
|
|
||||||
public class EaterIncludesub extends Eater {
|
public class EaterIncludesub extends Eater {
|
||||||
|
|
||||||
private String location;
|
private String what;
|
||||||
|
|
||||||
public EaterIncludesub(StringLocated s) {
|
public EaterIncludesub(StringLocated s) {
|
||||||
super(s);
|
super(s);
|
||||||
|
@ -49,13 +49,13 @@ public class EaterIncludesub extends Eater {
|
||||||
skipSpaces();
|
skipSpaces();
|
||||||
checkAndEatChar("!includesub");
|
checkAndEatChar("!includesub");
|
||||||
skipSpaces();
|
skipSpaces();
|
||||||
this.location = context.applyFunctionsAndVariables(memory,
|
this.what = context.applyFunctionsAndVariables(memory,
|
||||||
new StringLocated(this.eatAllToEnd(), getLineLocation()));
|
new StringLocated(this.eatAllToEnd(), getLineLocation()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final String getLocation() {
|
public final String getWhat() {
|
||||||
return location;
|
return what;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ public class EaterLegacyDefine extends Eater {
|
||||||
skipSpaces();
|
skipSpaces();
|
||||||
checkAndEatChar("!define");
|
checkAndEatChar("!define");
|
||||||
skipSpaces();
|
skipSpaces();
|
||||||
function = eatDeclareFunction(context, memory, true, getLineLocation(), false, TFunctionType.LEGACY_DEFINE);
|
function = eatDeclareFunction(context, memory, true, getStringLocated(), false, TFunctionType.LEGACY_DEFINE);
|
||||||
final String def = this.eatAllToEnd();
|
final String def = this.eatAllToEnd();
|
||||||
// function.setFunctionType(TFunctionType.LEGACY_DEFINE);
|
// function.setFunctionType(TFunctionType.LEGACY_DEFINE);
|
||||||
function.setLegacyDefinition(def);
|
function.setLegacyDefinition(def);
|
||||||
|
|
|
@ -49,7 +49,7 @@ public class EaterLegacyDefineLong extends Eater {
|
||||||
skipSpaces();
|
skipSpaces();
|
||||||
checkAndEatChar("!definelong");
|
checkAndEatChar("!definelong");
|
||||||
skipSpaces();
|
skipSpaces();
|
||||||
function = eatDeclareFunction(context, memory, true, getLineLocation(), true, TFunctionType.LEGACY_DEFINELONG);
|
function = eatDeclareFunction(context, memory, true, getStringLocated(), true, TFunctionType.LEGACY_DEFINELONG);
|
||||||
// function.setFunctionType(TFunctionType.LEGACY_DEFINELONG);
|
// function.setFunctionType(TFunctionType.LEGACY_DEFINELONG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,9 +50,9 @@ public class EaterStartsub extends Eater {
|
||||||
checkAndEatChar("!startsub");
|
checkAndEatChar("!startsub");
|
||||||
skipSpaces();
|
skipSpaces();
|
||||||
this.subname = eatAllToEnd();
|
this.subname = eatAllToEnd();
|
||||||
if (this.subname.matches("\\w+") == false) {
|
if (this.subname.matches("\\w+") == false)
|
||||||
throw EaterException.located("Bad sub name");
|
throw EaterException.located("Bad sub name", getStringLocated());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final String getSubname() {
|
public final String getSubname() {
|
||||||
|
|
|
@ -101,24 +101,24 @@ public class EaterTheme extends Eater {
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Logme.error(e);
|
Logme.error(e);
|
||||||
}
|
}
|
||||||
throw EaterException.located("Cannot load " + realName);
|
throw EaterException.located("Cannot load " + realName, getStringLocated());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (from.startsWith("<") && from.endsWith(">")) {
|
if (from.startsWith("<") && from.endsWith(">")) {
|
||||||
final ReadLine reader = ThemeUtils.getReaderTheme(realName, from);
|
final ReadLine reader = ThemeUtils.getReaderTheme(realName, from);
|
||||||
if (reader == null)
|
if (reader == null)
|
||||||
throw EaterException.located("No such theme " + realName + " in " + from);
|
throw EaterException.located("No such theme " + realName + " in " + from, getStringLocated());
|
||||||
return reader;
|
return reader;
|
||||||
} else if (from.startsWith("http://") || from.startsWith("https://")) {
|
} else if (from.startsWith("http://") || from.startsWith("https://")) {
|
||||||
final SURL url = SURL.create(ThemeUtils.getFullPath(from, realName));
|
final SURL url = SURL.create(ThemeUtils.getFullPath(from, realName));
|
||||||
if (url == null)
|
if (url == null)
|
||||||
throw EaterException.located("Cannot open URL");
|
throw EaterException.located("Cannot open URL", getStringLocated());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return PreprocessorUtils.getReaderInclude(url, getLineLocation(), UTF_8);
|
return PreprocessorUtils.getReaderInclude(url, getStringLocated(), UTF_8);
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
Logme.error(e);
|
Logme.error(e);
|
||||||
throw EaterException.located("Cannot decode charset");
|
throw EaterException.located("Cannot decode charset", getStringLocated());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,12 +126,12 @@ public class EaterTheme extends Eater {
|
||||||
final FileWithSuffix file = context.getFileWithSuffix(from, realName);
|
final FileWithSuffix file = context.getFileWithSuffix(from, realName);
|
||||||
final Reader tmp = file.getReader(UTF_8);
|
final Reader tmp = file.getReader(UTF_8);
|
||||||
if (tmp == null)
|
if (tmp == null)
|
||||||
throw EaterException.located("No such theme " + realName);
|
throw EaterException.located("No such theme " + realName, getStringLocated());
|
||||||
|
|
||||||
return ReadLineReader.create(tmp, "theme " + realName);
|
return ReadLineReader.create(tmp, "theme " + realName);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Logme.error(e);
|
Logme.error(e);
|
||||||
throw EaterException.located("Cannot load " + realName);
|
throw EaterException.located("Cannot load " + realName, getStringLocated());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,16 +51,16 @@ public class FunctionsSet {
|
||||||
|
|
||||||
public TFunction getFunctionSmart(TFunctionSignature searched) {
|
public TFunction getFunctionSmart(TFunctionSignature searched) {
|
||||||
final TFunction func = this.functions.get(searched);
|
final TFunction func = this.functions.get(searched);
|
||||||
if (func != null) {
|
if (func != null)
|
||||||
return func;
|
return func;
|
||||||
}
|
|
||||||
for (TFunction candidate : this.functions.values()) {
|
for (TFunction candidate : this.functions.values()) {
|
||||||
if (candidate.getSignature().sameFunctionNameAs(searched) == false) {
|
if (candidate.getSignature().sameFunctionNameAs(searched) == false)
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
if (candidate.canCover(searched.getNbArg(), searched.getNamedArguments())) {
|
if (candidate.canCover(searched.getNbArg(), searched.getNamedArguments()))
|
||||||
return candidate;
|
return candidate;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -82,9 +82,9 @@ public class FunctionsSet {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addFunction(TFunction func) {
|
public void addFunction(TFunction func) {
|
||||||
if (func.getFunctionType() == TFunctionType.LEGACY_DEFINELONG) {
|
if (func.getFunctionType() == TFunctionType.LEGACY_DEFINELONG)
|
||||||
((TFunctionImpl) func).finalizeEnddefinelong();
|
((TFunctionImpl) func).finalizeEnddefinelong();
|
||||||
}
|
|
||||||
this.functions.put(func.getSignature(), func);
|
this.functions.put(func.getSignature(), func);
|
||||||
this.functions3.add(func.getSignature().getFunctionName() + "(");
|
this.functions3.add(func.getSignature().getFunctionName() + "(");
|
||||||
}
|
}
|
||||||
|
@ -96,9 +96,9 @@ public class FunctionsSet {
|
||||||
|
|
||||||
public void executeLegacyDefine(TContext context, TMemory memory, StringLocated s)
|
public void executeLegacyDefine(TContext context, TMemory memory, StringLocated s)
|
||||||
throws EaterException, EaterExceptionLocated {
|
throws EaterException, EaterExceptionLocated {
|
||||||
if (this.pendingFunction != null) {
|
if (this.pendingFunction != null)
|
||||||
throw EaterException.located("already0048");
|
throw EaterException.located("already0048", s);
|
||||||
}
|
|
||||||
final EaterLegacyDefine legacyDefine = new EaterLegacyDefine(s);
|
final EaterLegacyDefine legacyDefine = new EaterLegacyDefine(s);
|
||||||
legacyDefine.analyze(context, memory);
|
legacyDefine.analyze(context, memory);
|
||||||
final TFunction function = legacyDefine.getFunction();
|
final TFunction function = legacyDefine.getFunction();
|
||||||
|
@ -108,9 +108,9 @@ public class FunctionsSet {
|
||||||
|
|
||||||
public void executeLegacyDefineLong(TContext context, TMemory memory, StringLocated s)
|
public void executeLegacyDefineLong(TContext context, TMemory memory, StringLocated s)
|
||||||
throws EaterException, EaterExceptionLocated {
|
throws EaterException, EaterExceptionLocated {
|
||||||
if (this.pendingFunction != null) {
|
if (this.pendingFunction != null)
|
||||||
throw EaterException.located("already0068");
|
throw EaterException.located("already0068", s);
|
||||||
}
|
|
||||||
final EaterLegacyDefineLong legacyDefineLong = new EaterLegacyDefineLong(s);
|
final EaterLegacyDefineLong legacyDefineLong = new EaterLegacyDefineLong(s);
|
||||||
legacyDefineLong.analyze(context, memory);
|
legacyDefineLong.analyze(context, memory);
|
||||||
this.pendingFunction = legacyDefineLong.getFunction();
|
this.pendingFunction = legacyDefineLong.getFunction();
|
||||||
|
@ -118,48 +118,48 @@ public class FunctionsSet {
|
||||||
|
|
||||||
public void executeDeclareReturnFunction(TContext context, TMemory memory, StringLocated s)
|
public void executeDeclareReturnFunction(TContext context, TMemory memory, StringLocated s)
|
||||||
throws EaterException, EaterExceptionLocated {
|
throws EaterException, EaterExceptionLocated {
|
||||||
if (this.pendingFunction != null) {
|
if (this.pendingFunction != null)
|
||||||
throw EaterException.located("already0068");
|
throw EaterException.located("already0068", s);
|
||||||
}
|
|
||||||
final EaterDeclareReturnFunction declareFunction = new EaterDeclareReturnFunction(s);
|
final EaterDeclareReturnFunction declareFunction = new EaterDeclareReturnFunction(s);
|
||||||
declareFunction.analyze(context, memory);
|
declareFunction.analyze(context, memory);
|
||||||
final boolean finalFlag = declareFunction.getFinalFlag();
|
final boolean finalFlag = declareFunction.getFinalFlag();
|
||||||
final TFunctionSignature declaredSignature = declareFunction.getFunction().getSignature();
|
final TFunctionSignature declaredSignature = declareFunction.getFunction().getSignature();
|
||||||
final TFunction previous = this.functions.get(declaredSignature);
|
final TFunction previous = this.functions.get(declaredSignature);
|
||||||
if (previous != null && (finalFlag || this.functionsFinal.contains(declaredSignature))) {
|
if (previous != null && (finalFlag || this.functionsFinal.contains(declaredSignature)))
|
||||||
throw EaterException.located("This function is already defined");
|
throw EaterException.located("This function is already defined", s);
|
||||||
}
|
|
||||||
if (finalFlag) {
|
if (finalFlag)
|
||||||
this.functionsFinal.add(declaredSignature);
|
this.functionsFinal.add(declaredSignature);
|
||||||
}
|
|
||||||
if (declareFunction.getFunction().hasBody()) {
|
if (declareFunction.getFunction().hasBody())
|
||||||
this.addFunction(declareFunction.getFunction());
|
this.addFunction(declareFunction.getFunction());
|
||||||
} else {
|
else
|
||||||
this.pendingFunction = declareFunction.getFunction();
|
this.pendingFunction = declareFunction.getFunction();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void executeDeclareProcedure(TContext context, TMemory memory, StringLocated s)
|
public void executeDeclareProcedure(TContext context, TMemory memory, StringLocated s)
|
||||||
throws EaterException, EaterExceptionLocated {
|
throws EaterException, EaterExceptionLocated {
|
||||||
if (this.pendingFunction != null) {
|
if (this.pendingFunction != null)
|
||||||
throw EaterException.located("already0068");
|
throw EaterException.located("already0068", s);
|
||||||
}
|
|
||||||
final EaterDeclareProcedure declareFunction = new EaterDeclareProcedure(s);
|
final EaterDeclareProcedure declareFunction = new EaterDeclareProcedure(s);
|
||||||
declareFunction.analyze(context, memory);
|
declareFunction.analyze(context, memory);
|
||||||
final boolean finalFlag = declareFunction.getFinalFlag();
|
final boolean finalFlag = declareFunction.getFinalFlag();
|
||||||
final TFunctionSignature declaredSignature = declareFunction.getFunction().getSignature();
|
final TFunctionSignature declaredSignature = declareFunction.getFunction().getSignature();
|
||||||
final TFunction previous = this.functions.get(declaredSignature);
|
final TFunction previous = this.functions.get(declaredSignature);
|
||||||
if (previous != null && (finalFlag || this.functionsFinal.contains(declaredSignature))) {
|
if (previous != null && (finalFlag || this.functionsFinal.contains(declaredSignature)))
|
||||||
throw EaterException.located("This function is already defined");
|
throw EaterException.located("This function is already defined", s);
|
||||||
}
|
|
||||||
if (finalFlag) {
|
if (finalFlag)
|
||||||
this.functionsFinal.add(declaredSignature);
|
this.functionsFinal.add(declaredSignature);
|
||||||
}
|
|
||||||
if (declareFunction.getFunction().hasBody()) {
|
if (declareFunction.getFunction().hasBody())
|
||||||
this.addFunction(declareFunction.getFunction());
|
this.addFunction(declareFunction.getFunction());
|
||||||
} else {
|
else
|
||||||
this.pendingFunction = declareFunction.getFunction();
|
this.pendingFunction = declareFunction.getFunction();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -322,7 +322,7 @@ public class TContext {
|
||||||
if (e instanceof EaterExceptionLocated)
|
if (e instanceof EaterExceptionLocated)
|
||||||
throw (EaterExceptionLocated) e;
|
throw (EaterExceptionLocated) e;
|
||||||
Logme.error(e);
|
Logme.error(e);
|
||||||
throw EaterException.located("Fatal parsing error");
|
throw EaterException.located("Fatal parsing error", s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,7 +382,7 @@ public class TContext {
|
||||||
} else if (s.getString().matches("^\\s+$")) {
|
} else if (s.getString().matches("^\\s+$")) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
throw EaterException.located("Compile Error " + ftype + " " + type);
|
throw EaterException.located("Compile Error " + ftype + " " + type, s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,7 +465,7 @@ public class TContext {
|
||||||
call.getNamedArguments().keySet());
|
call.getNamedArguments().keySet());
|
||||||
final TFunction function = functionsSet.getFunctionSmart(signature);
|
final TFunction function = functionsSet.getFunctionSmart(signature);
|
||||||
if (function == null)
|
if (function == null)
|
||||||
throw EaterException.located("Function not found " + presentFunction);
|
throw EaterException.located("Function not found " + presentFunction, str);
|
||||||
|
|
||||||
if (function.getFunctionType() == TFunctionType.PROCEDURE) {
|
if (function.getFunctionType() == TFunctionType.PROCEDURE) {
|
||||||
this.pendingAdd = result.toString();
|
this.pendingAdd = result.toString();
|
||||||
|
@ -488,8 +488,8 @@ public class TContext {
|
||||||
call.getNamedArguments());
|
call.getNamedArguments());
|
||||||
result.append(functionReturn.toString());
|
result.append(functionReturn.toString());
|
||||||
i += call.getCurrentPosition() - 1;
|
i += call.getCurrentPosition() - 1;
|
||||||
} else if (new VariableManager(this, memory, str.getLocation()).getVarnameAt(str.getString(), i) != null) {
|
} else if (new VariableManager(this, memory, str).getVarnameAt(str.getString(), i) != null) {
|
||||||
i = new VariableManager(this, memory, str.getLocation()).replaceVariables(str.getString(), i, result);
|
i = new VariableManager(this, memory, str).replaceVariables(str.getString(), i, result);
|
||||||
} else {
|
} else {
|
||||||
result.append(c);
|
result.append(c);
|
||||||
}
|
}
|
||||||
|
@ -512,18 +512,18 @@ public class TContext {
|
||||||
_import.analyze(this, memory);
|
_import.analyze(this, memory);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final SFile file = FileSystem.getInstance().getFile(
|
final SFile file = FileSystem.getInstance()
|
||||||
applyFunctionsAndVariables(memory, new StringLocated(_import.getWhat(), s.getLocation())));
|
.getFile(applyFunctionsAndVariables(memory, new StringLocated(_import.getWhat(), s.getLocation())));
|
||||||
if (file.exists() && file.isDirectory() == false) {
|
if (file.exists() && file.isDirectory() == false) {
|
||||||
importedFiles.add(file);
|
importedFiles.add(file);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Logme.error(e);
|
Logme.error(e);
|
||||||
throw EaterException.located("Cannot import " + e.getMessage());
|
throw EaterException.located("Cannot import " + e.getMessage(), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw EaterException.located("Cannot import");
|
throw EaterException.located("Cannot import", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void executeLog(TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
|
private void executeLog(TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
|
||||||
|
@ -543,12 +543,12 @@ public class TContext {
|
||||||
try {
|
try {
|
||||||
final EaterIncludesub include = new EaterIncludesub(s.getTrimmed());
|
final EaterIncludesub include = new EaterIncludesub(s.getTrimmed());
|
||||||
include.analyze(this, memory);
|
include.analyze(this, memory);
|
||||||
final String location = include.getLocation();
|
final String what = include.getWhat();
|
||||||
final int idx = location.indexOf('!');
|
final int idx = what.indexOf('!');
|
||||||
Sub sub = null;
|
Sub sub = null;
|
||||||
if (idx != -1) {
|
if (idx != -1) {
|
||||||
final String filename = location.substring(0, idx);
|
final String filename = what.substring(0, idx);
|
||||||
final String blocname = location.substring(idx + 1);
|
final String blocname = what.substring(idx + 1);
|
||||||
try {
|
try {
|
||||||
final FileWithSuffix f2 = importedFiles.getFile(filename, null);
|
final FileWithSuffix f2 = importedFiles.getFile(filename, null);
|
||||||
if (f2.fileOk()) {
|
if (f2.fileOk()) {
|
||||||
|
@ -556,10 +556,10 @@ public class TContext {
|
||||||
this.importedFiles = this.importedFiles.withCurrentDir(f2.getParentFile());
|
this.importedFiles = this.importedFiles.withCurrentDir(f2.getParentFile());
|
||||||
final Reader reader = f2.getReader(charset);
|
final Reader reader = f2.getReader(charset);
|
||||||
if (reader == null)
|
if (reader == null)
|
||||||
throw EaterException.located("cannot include " + location);
|
throw EaterException.located("cannot include " + what, s);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ReadLine readerline = ReadLineReader.create(reader, location, s.getLocation());
|
ReadLine readerline = ReadLineReader.create(reader, what, s.getLocation());
|
||||||
readerline = new UncommentReadLine(readerline);
|
readerline = new UncommentReadLine(readerline);
|
||||||
sub = Sub.fromFile(readerline, blocname, this, memory);
|
sub = Sub.fromFile(readerline, blocname, this, memory);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -568,14 +568,14 @@ public class TContext {
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Logme.error(e);
|
Logme.error(e);
|
||||||
throw EaterException.located("cannot include " + location);
|
throw EaterException.located("cannot include " + what, s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sub == null)
|
if (sub == null)
|
||||||
sub = subs.get(location);
|
sub = subs.get(what);
|
||||||
|
|
||||||
if (sub == null)
|
if (sub == null)
|
||||||
throw EaterException.located("cannot include " + location);
|
throw EaterException.located("cannot include " + what, s);
|
||||||
|
|
||||||
executeLinesInternal(memory, sub.lines(), null);
|
executeLinesInternal(memory, sub.lines(), null);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -604,7 +604,7 @@ public class TContext {
|
||||||
} while (true);
|
} while (true);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Logme.error(e);
|
Logme.error(e);
|
||||||
throw EaterException.located("" + e);
|
throw EaterException.located("" + e, s);
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
reader2.close();
|
reader2.close();
|
||||||
|
@ -619,7 +619,7 @@ public class TContext {
|
||||||
eater.analyze(this, memory);
|
eater.analyze(this, memory);
|
||||||
final ReadLine reader = eater.getTheme();
|
final ReadLine reader = eater.getTheme();
|
||||||
if (reader == null)
|
if (reader == null)
|
||||||
throw EaterException.located("No such theme " + eater.getName());
|
throw EaterException.located("No such theme " + eater.getName(), s);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final List<StringLocated> body = new ArrayList<>();
|
final List<StringLocated> body = new ArrayList<>();
|
||||||
|
@ -633,7 +633,7 @@ public class TContext {
|
||||||
} while (true);
|
} while (true);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Logme.error(e);
|
Logme.error(e);
|
||||||
throw EaterException.located("Error reading theme " + e);
|
throw EaterException.located("Error reading theme " + e, s);
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
reader.close();
|
reader.close();
|
||||||
|
@ -646,7 +646,7 @@ public class TContext {
|
||||||
private void executeInclude(TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
|
private void executeInclude(TMemory memory, StringLocated s) throws EaterException, EaterExceptionLocated {
|
||||||
final EaterInclude include = new EaterInclude(s.getTrimmed());
|
final EaterInclude include = new EaterInclude(s.getTrimmed());
|
||||||
include.analyze(this, memory);
|
include.analyze(this, memory);
|
||||||
String location = include.getLocation();
|
String location = include.getWhat();
|
||||||
final PreprocessorIncludeStrategy strategy = include.getPreprocessorIncludeStrategy();
|
final PreprocessorIncludeStrategy strategy = include.getPreprocessorIncludeStrategy();
|
||||||
final int idx = location.lastIndexOf('!');
|
final int idx = location.lastIndexOf('!');
|
||||||
String suf = null;
|
String suf = null;
|
||||||
|
@ -661,7 +661,7 @@ public class TContext {
|
||||||
if (location.startsWith("http://") || location.startsWith("https://")) {
|
if (location.startsWith("http://") || location.startsWith("https://")) {
|
||||||
final SURL url = SURL.create(location);
|
final SURL url = SURL.create(location);
|
||||||
if (url == null)
|
if (url == null)
|
||||||
throw EaterException.located("Cannot open URL");
|
throw EaterException.located("Cannot open URL", s);
|
||||||
|
|
||||||
reader = PreprocessorUtils.getReaderIncludeUrl(url, s, suf, charset);
|
reader = PreprocessorUtils.getReaderIncludeUrl(url, s, suf, charset);
|
||||||
} else if (location.startsWith("<") && location.endsWith(">")) {
|
} else if (location.startsWith("<") && location.endsWith(">")) {
|
||||||
|
@ -677,14 +677,14 @@ public class TContext {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (strategy == PreprocessorIncludeStrategy.ONCE && filesUsedCurrent.contains(f2))
|
if (strategy == PreprocessorIncludeStrategy.ONCE && filesUsedCurrent.contains(f2))
|
||||||
throw EaterException.located("This file has already been included");
|
throw EaterException.located("This file has already been included", s);
|
||||||
|
|
||||||
if (StartDiagramExtractReader.containsStartDiagram(f2, s, charset)) {
|
if (StartDiagramExtractReader.containsStartDiagram(f2, s, charset)) {
|
||||||
reader = StartDiagramExtractReader.build(f2, s, charset);
|
reader = StartDiagramExtractReader.build(f2, s, charset);
|
||||||
} else {
|
} else {
|
||||||
final Reader tmp = f2.getReader(charset);
|
final Reader tmp = f2.getReader(charset);
|
||||||
if (tmp == null)
|
if (tmp == null)
|
||||||
throw EaterException.located("Cannot include file");
|
throw EaterException.located("Cannot include file", s);
|
||||||
|
|
||||||
reader = ReadLineReader.create(tmp, location, s.getLocation());
|
reader = ReadLineReader.create(tmp, location, s.getLocation());
|
||||||
}
|
}
|
||||||
|
@ -713,7 +713,7 @@ public class TContext {
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Logme.error(e);
|
Logme.error(e);
|
||||||
throw EaterException.located("cannot include " + e);
|
throw EaterException.located("cannot include " + e, s);
|
||||||
} finally {
|
} finally {
|
||||||
if (reader != null) {
|
if (reader != null) {
|
||||||
try {
|
try {
|
||||||
|
@ -724,7 +724,7 @@ public class TContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw EaterException.located("cannot include " + location);
|
throw EaterException.located("cannot include " + location, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLegacyDefine(String functionName) {
|
public boolean isLegacyDefine(String functionName) {
|
||||||
|
|
|
@ -148,12 +148,12 @@ public class TFunctionImpl implements TFunction {
|
||||||
return executeReturnLegacyDefine(location.getLocation(), context, memory, args);
|
return executeReturnLegacyDefine(location.getLocation(), context, memory, args);
|
||||||
|
|
||||||
if (functionType != TFunctionType.RETURN_FUNCTION)
|
if (functionType != TFunctionType.RETURN_FUNCTION)
|
||||||
throw EaterException.unlocated("Illegal call here. Is there a return directive in your function?");
|
throw EaterException.unlocated("Illegal call here. Is there a return directive in your function?", location);
|
||||||
|
|
||||||
final TMemory copy = getNewMemory(memory, args, named);
|
final TMemory copy = getNewMemory(memory, args, named);
|
||||||
final TValue result = context.executeLines(copy, body, TFunctionType.RETURN_FUNCTION, true);
|
final TValue result = context.executeLines(copy, body, TFunctionType.RETURN_FUNCTION, true);
|
||||||
if (result == null)
|
if (result == null)
|
||||||
throw EaterException.unlocated("No return directive found in your function");
|
throw EaterException.unlocated("No return directive found in your function", location);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,13 +37,15 @@ package net.sourceforge.plantuml.tim;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import net.sourceforge.plantuml.text.StringLocated;
|
||||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||||
|
|
||||||
public interface TMemory {
|
public interface TMemory {
|
||||||
|
|
||||||
public TValue getVariable(String varname);
|
public TValue getVariable(String varname);
|
||||||
|
|
||||||
public void putVariable(String varname, TValue value, TVariableScope scope) throws EaterException;
|
public void putVariable(String varname, TValue value, TVariableScope scope, StringLocated location)
|
||||||
|
throws EaterException;
|
||||||
|
|
||||||
public void removeVariable(String varname);
|
public void removeVariable(String varname);
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@ import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
import net.sourceforge.plantuml.text.StringLocated;
|
||||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||||
import net.sourceforge.plantuml.utils.Log;
|
import net.sourceforge.plantuml.utils.Log;
|
||||||
|
|
||||||
|
@ -49,10 +50,12 @@ public class TMemoryGlobal extends ExecutionContexts implements TMemory {
|
||||||
private final Map<String, TValue> globalVariables = new HashMap<String, TValue>();
|
private final Map<String, TValue> globalVariables = new HashMap<String, TValue>();
|
||||||
private final TrieImpl variables = new TrieImpl();
|
private final TrieImpl variables = new TrieImpl();
|
||||||
|
|
||||||
|
@Override
|
||||||
public TValue getVariable(String varname) {
|
public TValue getVariable(String varname) {
|
||||||
return this.globalVariables.get(varname);
|
return this.globalVariables.get(varname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void dumpDebug(String message) {
|
public void dumpDebug(String message) {
|
||||||
Log.error("[MemGlobal] Start of memory_dump " + message);
|
Log.error("[MemGlobal] Start of memory_dump " + message);
|
||||||
dumpMemoryInternal();
|
dumpMemoryInternal();
|
||||||
|
@ -68,32 +71,39 @@ public class TMemoryGlobal extends ExecutionContexts implements TMemory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void putVariable(String varname, TValue value, TVariableScope scope) throws EaterException {
|
@Override
|
||||||
|
public void putVariable(String varname, TValue value, TVariableScope scope, StringLocated location)
|
||||||
|
throws EaterException {
|
||||||
Log.info("[MemGlobal] Setting " + varname);
|
Log.info("[MemGlobal] Setting " + varname);
|
||||||
if (scope == TVariableScope.LOCAL) {
|
if (scope == TVariableScope.LOCAL)
|
||||||
throw EaterException.unlocated("Cannot use local variable here");
|
throw EaterException.unlocated("Cannot use local variable here", location);
|
||||||
}
|
|
||||||
this.globalVariables.put(varname, value);
|
this.globalVariables.put(varname, value);
|
||||||
this.variables.add(varname);
|
this.variables.add(varname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void removeVariable(String varname) {
|
public void removeVariable(String varname) {
|
||||||
this.globalVariables.remove(varname);
|
this.globalVariables.remove(varname);
|
||||||
this.variables.remove(varname);
|
this.variables.remove(varname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return globalVariables.isEmpty();
|
return globalVariables.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Set<String> variablesNames() {
|
public Set<String> variablesNames() {
|
||||||
return Collections.unmodifiableSet(globalVariables.keySet());
|
return Collections.unmodifiableSet(globalVariables.keySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Trie variablesNames3() {
|
public Trie variablesNames3() {
|
||||||
return variables;
|
return variables;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public TMemory forkFromGlobal(Map<String, TValue> input) {
|
public TMemory forkFromGlobal(Map<String, TValue> input) {
|
||||||
return new TMemoryLocal(this, input);
|
return new TMemoryLocal(this, input);
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
import net.sourceforge.plantuml.text.StringLocated;
|
||||||
import net.sourceforge.plantuml.tim.expression.TValue;
|
import net.sourceforge.plantuml.tim.expression.TValue;
|
||||||
import net.sourceforge.plantuml.utils.Log;
|
import net.sourceforge.plantuml.utils.Log;
|
||||||
|
|
||||||
|
@ -76,19 +77,21 @@ public class TMemoryLocal extends ExecutionContexts implements TMemory {
|
||||||
Log.error("[MemGlobal] End of memory_dump");
|
Log.error("[MemGlobal] End of memory_dump");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void putVariable(String varname, TValue value, TVariableScope scope) throws EaterException {
|
@Override
|
||||||
|
public void putVariable(String varname, TValue value, TVariableScope scope, StringLocated location)
|
||||||
|
throws EaterException {
|
||||||
if (scope == TVariableScope.GLOBAL) {
|
if (scope == TVariableScope.GLOBAL) {
|
||||||
memoryGlobal.putVariable(varname, value, scope);
|
memoryGlobal.putVariable(varname, value, scope, location);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (scope == TVariableScope.LOCAL || overridenVariables01.containsKey(varname)) {
|
if (scope == TVariableScope.LOCAL || overridenVariables01.containsKey(varname)) {
|
||||||
this.overridenVariables01.put(varname, value);
|
this.overridenVariables01.put(varname, value);
|
||||||
if (this.overridenVariables00 != null) {
|
if (this.overridenVariables00 != null)
|
||||||
this.overridenVariables00.add(varname);
|
this.overridenVariables00.add(varname);
|
||||||
}
|
|
||||||
Log.info("[MemLocal/overrriden] Setting " + varname);
|
Log.info("[MemLocal/overrriden] Setting " + varname);
|
||||||
} else if (memoryGlobal.getVariable(varname) != null) {
|
} else if (memoryGlobal.getVariable(varname) != null) {
|
||||||
memoryGlobal.putVariable(varname, value, scope);
|
memoryGlobal.putVariable(varname, value, scope, location);
|
||||||
} else {
|
} else {
|
||||||
this.localVariables01.put(varname, value);
|
this.localVariables01.put(varname, value);
|
||||||
this.localVariables00.add(varname);
|
this.localVariables00.add(varname);
|
||||||
|
@ -96,12 +99,13 @@ public class TMemoryLocal extends ExecutionContexts implements TMemory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void removeVariable(String varname) {
|
public void removeVariable(String varname) {
|
||||||
if (overridenVariables01.containsKey(varname)) {
|
if (overridenVariables01.containsKey(varname)) {
|
||||||
this.overridenVariables01.remove(varname);
|
this.overridenVariables01.remove(varname);
|
||||||
if (this.overridenVariables00 != null) {
|
if (this.overridenVariables00 != null)
|
||||||
this.overridenVariables00.remove(varname);
|
this.overridenVariables00.remove(varname);
|
||||||
}
|
|
||||||
} else if (memoryGlobal.getVariable(varname) != null) {
|
} else if (memoryGlobal.getVariable(varname) != null) {
|
||||||
memoryGlobal.removeVariable(varname);
|
memoryGlobal.removeVariable(varname);
|
||||||
} else {
|
} else {
|
||||||
|
@ -110,25 +114,27 @@ public class TMemoryLocal extends ExecutionContexts implements TMemory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public TValue getVariable(String varname) {
|
public TValue getVariable(String varname) {
|
||||||
TValue result = overridenVariables01.get(varname);
|
TValue result = overridenVariables01.get(varname);
|
||||||
if (result != null) {
|
if (result != null)
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
result = memoryGlobal.getVariable(varname);
|
result = memoryGlobal.getVariable(varname);
|
||||||
if (result != null) {
|
if (result != null)
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
result = localVariables01.get(varname);
|
result = localVariables01.get(varname);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Trie variablesNames3() {
|
public Trie variablesNames3() {
|
||||||
if (overridenVariables00 == null) {
|
if (overridenVariables00 == null) {
|
||||||
overridenVariables00 = new TrieImpl();
|
overridenVariables00 = new TrieImpl();
|
||||||
for (String name : overridenVariables01.keySet()) {
|
for (String name : overridenVariables01.keySet())
|
||||||
overridenVariables00.add(name);
|
overridenVariables00.add(name);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return new Trie() {
|
return new Trie() {
|
||||||
public void add(String s) {
|
public void add(String s) {
|
||||||
|
@ -140,12 +146,12 @@ public class TMemoryLocal extends ExecutionContexts implements TMemory {
|
||||||
final String s2 = overridenVariables00.getLonguestMatchStartingIn(s);
|
final String s2 = overridenVariables00.getLonguestMatchStartingIn(s);
|
||||||
final String s3 = localVariables00.getLonguestMatchStartingIn(s);
|
final String s3 = localVariables00.getLonguestMatchStartingIn(s);
|
||||||
|
|
||||||
if (s1.length() >= s2.length() && s1.length() >= s3.length()) {
|
if (s1.length() >= s2.length() && s1.length() >= s3.length())
|
||||||
return s1;
|
return s1;
|
||||||
}
|
|
||||||
if (s2.length() >= s3.length() && s2.length() >= s1.length()) {
|
if (s2.length() >= s3.length() && s2.length() >= s1.length())
|
||||||
return s2;
|
return s2;
|
||||||
}
|
|
||||||
return s3;
|
return s3;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -162,14 +168,17 @@ public class TMemoryLocal extends ExecutionContexts implements TMemory {
|
||||||
// return result;
|
// return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return memoryGlobal.isEmpty() && localVariables01.isEmpty() && overridenVariables01.isEmpty();
|
return memoryGlobal.isEmpty() && localVariables01.isEmpty() && overridenVariables01.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Set<String> variablesNames() {
|
public Set<String> variablesNames() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public TMemory forkFromGlobal(Map<String, TValue> input) {
|
public TMemory forkFromGlobal(Map<String, TValue> input) {
|
||||||
return new TMemoryLocal(memoryGlobal, input);
|
return new TMemoryLocal(memoryGlobal, input);
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,10 +53,10 @@ public class TimLoader {
|
||||||
private List<StringLocated> resultList;
|
private List<StringLocated> resultList;
|
||||||
|
|
||||||
public TimLoader(ImportedFiles importedFiles, Defines defines, Charset charset,
|
public TimLoader(ImportedFiles importedFiles, Defines defines, Charset charset,
|
||||||
DefinitionsContainer definitionsContainer) {
|
DefinitionsContainer definitionsContainer, StringLocated location) {
|
||||||
this.context = new TContext(importedFiles, defines, charset, definitionsContainer);
|
this.context = new TContext(importedFiles, defines, charset, definitionsContainer);
|
||||||
try {
|
try {
|
||||||
defines.copyTo(global);
|
defines.copyTo(global, location);
|
||||||
} catch (EaterException e) {
|
} catch (EaterException e) {
|
||||||
Logme.error(e);
|
Logme.error(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,9 +46,9 @@ public class VariableManager {
|
||||||
|
|
||||||
private final TMemory memory;
|
private final TMemory memory;
|
||||||
private final TContext context;
|
private final TContext context;
|
||||||
private final LineLocation location;
|
private final StringLocated location;
|
||||||
|
|
||||||
public VariableManager(TContext context, TMemory memory, LineLocation location) {
|
public VariableManager(TContext context, TMemory memory, StringLocated location) {
|
||||||
this.memory = memory;
|
this.memory = memory;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.location = location;
|
this.location = location;
|
||||||
|
@ -56,9 +56,9 @@ public class VariableManager {
|
||||||
|
|
||||||
public int replaceVariables(String str, int i, StringBuilder result) throws EaterException, EaterExceptionLocated {
|
public int replaceVariables(String str, int i, StringBuilder result) throws EaterException, EaterExceptionLocated {
|
||||||
final String presentVariable = getVarnameAt(str, i);
|
final String presentVariable = getVarnameAt(str, i);
|
||||||
if (result.toString().endsWith("##")) {
|
if (result.toString().endsWith("##"))
|
||||||
result.setLength(result.length() - 2);
|
result.setLength(result.length() - 2);
|
||||||
}
|
|
||||||
final TValue value = memory.getVariable(presentVariable);
|
final TValue value = memory.getVariable(presentVariable);
|
||||||
i += presentVariable.length() - 1;
|
i += presentVariable.length() - 1;
|
||||||
if (value.isJson()) {
|
if (value.isJson()) {
|
||||||
|
@ -75,9 +75,9 @@ public class VariableManager {
|
||||||
} else {
|
} else {
|
||||||
result.append(value.toString());
|
result.append(value.toString());
|
||||||
}
|
}
|
||||||
if (i + 2 < str.length() && str.charAt(i + 1) == '#' && str.charAt(i + 2) == '#') {
|
if (i + 2 < str.length() && str.charAt(i + 1) == '#' && str.charAt(i + 2) == '#')
|
||||||
i += 2;
|
i += 2;
|
||||||
}
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,9 +89,9 @@ public class VariableManager {
|
||||||
i++;
|
i++;
|
||||||
final StringBuilder fieldName = new StringBuilder();
|
final StringBuilder fieldName = new StringBuilder();
|
||||||
while (i < str.length()) {
|
while (i < str.length()) {
|
||||||
if (Character.isJavaIdentifierPart(str.charAt(i)) == false) {
|
if (Character.isJavaIdentifierPart(str.charAt(i)) == false)
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
fieldName.append(str.charAt(i));
|
fieldName.append(str.charAt(i));
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
@ -101,9 +101,9 @@ public class VariableManager {
|
||||||
final StringBuilder inBracket = new StringBuilder();
|
final StringBuilder inBracket = new StringBuilder();
|
||||||
int level = 0;
|
int level = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (str.charAt(i) == '[') {
|
if (str.charAt(i) == '[')
|
||||||
level++;
|
level++;
|
||||||
}
|
|
||||||
if (str.charAt(i) == ']') {
|
if (str.charAt(i) == ']') {
|
||||||
if (level == 0)
|
if (level == 0)
|
||||||
break;
|
break;
|
||||||
|
@ -113,29 +113,29 @@ public class VariableManager {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
final String nbString = context.applyFunctionsAndVariables(memory,
|
final String nbString = context.applyFunctionsAndVariables(memory,
|
||||||
new StringLocated(inBracket.toString(), location));
|
new StringLocated(inBracket.toString(), location.getLocation()));
|
||||||
if (jsonValue instanceof JsonArray) {
|
if (jsonValue instanceof JsonArray) {
|
||||||
final int nb = Integer.parseInt(nbString);
|
final int nb = Integer.parseInt(nbString);
|
||||||
jsonValue = ((JsonArray) jsonValue).get(nb);
|
jsonValue = ((JsonArray) jsonValue).get(nb);
|
||||||
} else if (jsonValue instanceof JsonObject) {
|
} else if (jsonValue instanceof JsonObject) {
|
||||||
jsonValue = ((JsonObject) jsonValue).get(nbString);
|
jsonValue = ((JsonObject) jsonValue).get(nbString);
|
||||||
} else {
|
} else {
|
||||||
throw EaterException.unlocated("Major parsing error");
|
throw EaterException.unlocated("Major parsing error", location);
|
||||||
}
|
|
||||||
if (jsonValue == null) {
|
|
||||||
throw EaterException.unlocated("Data parsing error");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (jsonValue == null)
|
||||||
|
throw EaterException.unlocated("Data parsing error", location);
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (jsonValue != null) {
|
if (jsonValue != null) {
|
||||||
if (jsonValue.isString()) {
|
if (jsonValue.isString())
|
||||||
result.append(jsonValue.asString());
|
result.append(jsonValue.asString());
|
||||||
} else {
|
else
|
||||||
result.append(jsonValue.toString());
|
result.append(jsonValue.toString());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@ -146,13 +146,13 @@ public class VariableManager {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final String varname = memory.variablesNames3().getLonguestMatchStartingIn(s.substring(pos));
|
final String varname = memory.variablesNames3().getLonguestMatchStartingIn(s.substring(pos));
|
||||||
if (varname.length() == 0) {
|
if (varname.length() == 0)
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
if (pos + varname.length() == s.length()
|
if (pos + varname.length() == s.length()
|
||||||
|| TLineType.isLetterOrUnderscoreOrDigit(s.charAt(pos + varname.length())) == false) {
|
|| TLineType.isLetterOrUnderscoreOrDigit(s.charAt(pos + varname.length())) == false)
|
||||||
return varname;
|
return varname;
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,18 +47,12 @@ import net.sourceforge.plantuml.tim.TContext;
|
||||||
import net.sourceforge.plantuml.tim.TFunction;
|
import net.sourceforge.plantuml.tim.TFunction;
|
||||||
import net.sourceforge.plantuml.tim.TFunctionSignature;
|
import net.sourceforge.plantuml.tim.TFunctionSignature;
|
||||||
import net.sourceforge.plantuml.tim.TMemory;
|
import net.sourceforge.plantuml.tim.TMemory;
|
||||||
import net.sourceforge.plantuml.utils.LineLocation;
|
|
||||||
|
|
||||||
public class ReversePolishInterpretor {
|
public class ReversePolishInterpretor {
|
||||||
|
|
||||||
private final TValue result;
|
private final TValue result;
|
||||||
private final boolean trace = false;
|
private final boolean trace = false;
|
||||||
|
|
||||||
public ReversePolishInterpretor(TokenStack queue, Knowledge knowledge, TMemory memory, TContext context)
|
|
||||||
throws EaterException, EaterExceptionLocated {
|
|
||||||
this(null, queue, knowledge, memory, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReversePolishInterpretor(StringLocated location, TokenStack queue, Knowledge knowledge, TMemory memory,
|
public ReversePolishInterpretor(StringLocated location, TokenStack queue, Knowledge knowledge, TMemory memory,
|
||||||
TContext context) throws EaterException, EaterExceptionLocated {
|
TContext context) throws EaterException, EaterExceptionLocated {
|
||||||
|
|
||||||
|
@ -79,45 +73,45 @@ public class ReversePolishInterpretor {
|
||||||
final TValue v2 = stack.removeFirst();
|
final TValue v2 = stack.removeFirst();
|
||||||
final TValue v1 = stack.removeFirst();
|
final TValue v1 = stack.removeFirst();
|
||||||
final TokenOperator op = token.getTokenOperator();
|
final TokenOperator op = token.getTokenOperator();
|
||||||
if (op == null) {
|
if (op == null)
|
||||||
throw EaterException.unlocated("bad op");
|
throw EaterException.unlocated("bad op", location);
|
||||||
}
|
|
||||||
final TValue tmp = op.operate(v1, v2);
|
final TValue tmp = op.operate(v1, v2);
|
||||||
stack.addFirst(tmp);
|
stack.addFirst(tmp);
|
||||||
} else if (token.getTokenType() == TokenType.OPEN_PAREN_FUNC) {
|
} else if (token.getTokenType() == TokenType.OPEN_PAREN_FUNC) {
|
||||||
final int nb = Integer.parseInt(token.getSurface());
|
final int nb = Integer.parseInt(token.getSurface());
|
||||||
final Token token2 = it.nextToken();
|
final Token token2 = it.nextToken();
|
||||||
if (token2.getTokenType() != TokenType.FUNCTION_NAME) {
|
if (token2.getTokenType() != TokenType.FUNCTION_NAME)
|
||||||
throw EaterException.unlocated("rpn43");
|
throw EaterException.unlocated("rpn43", location);
|
||||||
}
|
|
||||||
if (trace)
|
if (trace)
|
||||||
System.err.println("token2=" + token2);
|
System.err.println("token2=" + token2);
|
||||||
final TFunction function = knowledge.getFunction(new TFunctionSignature(token2.getSurface(), nb));
|
final TFunction function = knowledge.getFunction(new TFunctionSignature(token2.getSurface(), nb));
|
||||||
if (trace)
|
if (trace)
|
||||||
System.err.println("function=" + function);
|
System.err.println("function=" + function);
|
||||||
if (function == null) {
|
if (function == null)
|
||||||
throw EaterException.unlocated("Unknown built-in function " + token2.getSurface());
|
throw EaterException.unlocated("Unknown built-in function " + token2.getSurface(), location);
|
||||||
}
|
|
||||||
if (function.canCover(nb, Collections.<String>emptySet()) == false) {
|
if (function.canCover(nb, Collections.<String>emptySet()) == false)
|
||||||
throw EaterException
|
throw EaterException.unlocated(
|
||||||
.unlocated("Bad number of arguments for " + function.getSignature().getFunctionName());
|
"Bad number of arguments for " + function.getSignature().getFunctionName(), location);
|
||||||
}
|
|
||||||
final List<TValue> args = new ArrayList<>();
|
final List<TValue> args = new ArrayList<>();
|
||||||
for (int i = 0; i < nb; i++) {
|
for (int i = 0; i < nb; i++)
|
||||||
args.add(0, stack.removeFirst());
|
args.add(0, stack.removeFirst());
|
||||||
}
|
|
||||||
if (trace)
|
if (trace)
|
||||||
System.err.println("args=" + args);
|
System.err.println("args=" + args);
|
||||||
if (location == null) {
|
if (location == null)
|
||||||
throw EaterException.unlocated("rpn44");
|
throw EaterException.unlocated("rpn44", location);
|
||||||
}
|
|
||||||
final TValue r = function.executeReturnFunction(context, memory, location, args,
|
final TValue r = function.executeReturnFunction(context, memory, location, args,
|
||||||
Collections.<String, TValue>emptyMap());
|
Collections.<String, TValue>emptyMap());
|
||||||
if (trace)
|
if (trace)
|
||||||
System.err.println("r=" + r);
|
System.err.println("r=" + r);
|
||||||
stack.addFirst(r);
|
stack.addFirst(r);
|
||||||
} else {
|
} else {
|
||||||
throw EaterException.unlocated("rpn41");
|
throw EaterException.unlocated("rpn41", location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result = stack.removeFirst();
|
result = stack.removeFirst();
|
||||||
|
|
|
@ -37,6 +37,7 @@ package net.sourceforge.plantuml.tim.expression;
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
import java.util.Deque;
|
import java.util.Deque;
|
||||||
|
|
||||||
|
import net.sourceforge.plantuml.text.StringLocated;
|
||||||
import net.sourceforge.plantuml.tim.EaterException;
|
import net.sourceforge.plantuml.tim.EaterException;
|
||||||
import net.sourceforge.plantuml.tim.EaterExceptionLocated;
|
import net.sourceforge.plantuml.tim.EaterExceptionLocated;
|
||||||
|
|
||||||
|
@ -58,7 +59,8 @@ public class ShuntingYard {
|
||||||
System.err.println("");
|
System.err.println("");
|
||||||
}
|
}
|
||||||
|
|
||||||
public ShuntingYard(TokenIterator it, Knowledge knowledge) throws EaterException, EaterExceptionLocated {
|
public ShuntingYard(TokenIterator it, Knowledge knowledge, StringLocated location)
|
||||||
|
throws EaterException, EaterExceptionLocated {
|
||||||
|
|
||||||
while (it.hasMoreTokens()) {
|
while (it.hasMoreTokens()) {
|
||||||
final Token token = it.nextToken();
|
final Token token = it.nextToken();
|
||||||
|
@ -74,7 +76,7 @@ public class ShuntingYard {
|
||||||
final TValue variable = knowledge.getVariable(name);
|
final TValue variable = knowledge.getVariable(name);
|
||||||
if (variable == null) {
|
if (variable == null) {
|
||||||
if (isVariableName(name) == false)
|
if (isVariableName(name) == false)
|
||||||
throw EaterException.unlocated("Parsing syntax error about " + name);
|
throw EaterException.unlocated("Parsing syntax error about " + name, location);
|
||||||
|
|
||||||
ouputQueue.add(new Token(name, TokenType.QUOTED_STRING, null));
|
ouputQueue.add(new Token(name, TokenType.QUOTED_STRING, null));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -48,7 +48,6 @@ import net.sourceforge.plantuml.tim.EaterException;
|
||||||
import net.sourceforge.plantuml.tim.EaterExceptionLocated;
|
import net.sourceforge.plantuml.tim.EaterExceptionLocated;
|
||||||
import net.sourceforge.plantuml.tim.TContext;
|
import net.sourceforge.plantuml.tim.TContext;
|
||||||
import net.sourceforge.plantuml.tim.TMemory;
|
import net.sourceforge.plantuml.tim.TMemory;
|
||||||
import net.sourceforge.plantuml.utils.LineLocation;
|
|
||||||
|
|
||||||
public class TokenStack {
|
public class TokenStack {
|
||||||
|
|
||||||
|
@ -96,7 +95,7 @@ public class TokenStack {
|
||||||
eater.skipSpaces();
|
eater.skipSpaces();
|
||||||
final char ch = eater.peekChar();
|
final char ch = eater.peekChar();
|
||||||
if (ch == 0)
|
if (ch == 0)
|
||||||
throw EaterException.unlocated("until001");
|
throw EaterException.unlocated("until001", eater.getStringLocated());
|
||||||
|
|
||||||
if (level == 0 && (ch == ',' || ch == ')'))
|
if (level == 0 && (ch == ',' || ch == ')'))
|
||||||
return result;
|
return result;
|
||||||
|
@ -114,12 +113,12 @@ public class TokenStack {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static public void eatUntilCloseParenthesisOrComma(TokenIterator it) throws EaterException {
|
static public void eatUntilCloseParenthesisOrComma(TokenIterator it, StringLocated location) throws EaterException {
|
||||||
int level = 0;
|
int level = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
final Token ch = it.peekToken();
|
final Token ch = it.peekToken();
|
||||||
if (ch == null)
|
if (ch == null)
|
||||||
throw EaterException.unlocated("until002");
|
throw EaterException.unlocated("until002", location);
|
||||||
|
|
||||||
final TokenType typech = ch.getTokenType();
|
final TokenType typech = ch.getTokenType();
|
||||||
if (level == 0 && (typech == TokenType.COMMA || typech == TokenType.CLOSE_PAREN_MATH)
|
if (level == 0 && (typech == TokenType.COMMA || typech == TokenType.CLOSE_PAREN_MATH)
|
||||||
|
@ -136,7 +135,7 @@ public class TokenStack {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int countFunctionArg(TokenIterator it) throws EaterException {
|
private int countFunctionArg(TokenIterator it, StringLocated location) throws EaterException {
|
||||||
// return 42;
|
// return 42;
|
||||||
final TokenType type1 = it.peekToken().getTokenType();
|
final TokenType type1 = it.peekToken().getTokenType();
|
||||||
if (type1 == TokenType.CLOSE_PAREN_MATH || type1 == TokenType.CLOSE_PAREN_FUNC)
|
if (type1 == TokenType.CLOSE_PAREN_MATH || type1 == TokenType.CLOSE_PAREN_FUNC)
|
||||||
|
@ -144,7 +143,7 @@ public class TokenStack {
|
||||||
|
|
||||||
int result = 1;
|
int result = 1;
|
||||||
while (it.hasMoreTokens()) {
|
while (it.hasMoreTokens()) {
|
||||||
eatUntilCloseParenthesisOrComma(it);
|
eatUntilCloseParenthesisOrComma(it, location);
|
||||||
final Token token = it.nextToken();
|
final Token token = it.nextToken();
|
||||||
final TokenType type = token.getTokenType();
|
final TokenType type = token.getTokenType();
|
||||||
if (type == TokenType.CLOSE_PAREN_MATH || type == TokenType.CLOSE_PAREN_FUNC)
|
if (type == TokenType.CLOSE_PAREN_MATH || type == TokenType.CLOSE_PAREN_FUNC)
|
||||||
|
@ -152,13 +151,13 @@ public class TokenStack {
|
||||||
else if (type == TokenType.COMMA)
|
else if (type == TokenType.COMMA)
|
||||||
result++;
|
result++;
|
||||||
else
|
else
|
||||||
throw EaterException.unlocated("count13");
|
throw EaterException.unlocated("count13", location);
|
||||||
|
|
||||||
}
|
}
|
||||||
throw EaterException.unlocated("count12");
|
throw EaterException.unlocated("count12", location);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void guessFunctions() throws EaterException {
|
public void guessFunctions(StringLocated location) throws EaterException {
|
||||||
final Deque<Integer> open = new ArrayDeque<>();
|
final Deque<Integer> open = new ArrayDeque<>();
|
||||||
final Map<Integer, Integer> parens = new HashMap<Integer, Integer>();
|
final Map<Integer, Integer> parens = new HashMap<Integer, Integer>();
|
||||||
for (int i = 0; i < tokens.size(); i++) {
|
for (int i = 0; i < tokens.size(); i++) {
|
||||||
|
@ -178,7 +177,7 @@ public class TokenStack {
|
||||||
assert tokens.get(iclose).getTokenType() == TokenType.CLOSE_PAREN_MATH;
|
assert tokens.get(iclose).getTokenType() == TokenType.CLOSE_PAREN_MATH;
|
||||||
if (iopen > 0 && tokens.get(iopen - 1).getTokenType() == TokenType.PLAIN_TEXT) {
|
if (iopen > 0 && tokens.get(iopen - 1).getTokenType() == TokenType.PLAIN_TEXT) {
|
||||||
tokens.set(iopen - 1, new Token(tokens.get(iopen - 1).getSurface(), TokenType.FUNCTION_NAME, null));
|
tokens.set(iopen - 1, new Token(tokens.get(iopen - 1).getSurface(), TokenType.FUNCTION_NAME, null));
|
||||||
final int nbArg = countFunctionArg(subTokenStack(iopen + 1).tokenIterator());
|
final int nbArg = countFunctionArg(subTokenStack(iopen + 1).tokenIterator(), location);
|
||||||
tokens.set(iopen, new Token("" + nbArg, TokenType.OPEN_PAREN_FUNC, null));
|
tokens.set(iopen, new Token("" + nbArg, TokenType.OPEN_PAREN_FUNC, null));
|
||||||
tokens.set(iclose, new Token(")", TokenType.CLOSE_PAREN_FUNC, null));
|
tokens.set(iclose, new Token(")", TokenType.CLOSE_PAREN_FUNC, null));
|
||||||
}
|
}
|
||||||
|
@ -215,9 +214,9 @@ public class TokenStack {
|
||||||
throws EaterException, EaterExceptionLocated {
|
throws EaterException, EaterExceptionLocated {
|
||||||
final Knowledge knowledge = context.asKnowledge(memory, location.getLocation());
|
final Knowledge knowledge = context.asKnowledge(memory, location.getLocation());
|
||||||
final TokenStack tmp = withoutSpace();
|
final TokenStack tmp = withoutSpace();
|
||||||
tmp.guessFunctions();
|
tmp.guessFunctions(location);
|
||||||
final TokenIterator it = tmp.tokenIterator();
|
final TokenIterator it = tmp.tokenIterator();
|
||||||
final ShuntingYard shuntingYard = new ShuntingYard(it, knowledge);
|
final ShuntingYard shuntingYard = new ShuntingYard(it, knowledge, location);
|
||||||
final ReversePolishInterpretor rpn = new ReversePolishInterpretor(location, shuntingYard.getQueue(), knowledge,
|
final ReversePolishInterpretor rpn = new ReversePolishInterpretor(location, shuntingYard.getQueue(), knowledge,
|
||||||
memory, context);
|
memory, context);
|
||||||
return rpn.getResult();
|
return rpn.getResult();
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
*/
|
*/
|
||||||
package net.sourceforge.plantuml.tim.iterator;
|
package net.sourceforge.plantuml.tim.iterator;
|
||||||
|
|
||||||
|
import net.sourceforge.plantuml.text.StringLocated;
|
||||||
import net.sourceforge.plantuml.tim.EaterException;
|
import net.sourceforge.plantuml.tim.EaterException;
|
||||||
import net.sourceforge.plantuml.tim.EaterExceptionLocated;
|
import net.sourceforge.plantuml.tim.EaterExceptionLocated;
|
||||||
|
|
||||||
|
@ -45,16 +46,19 @@ public abstract class AbstractCodeIterator implements CodeIterator {
|
||||||
this.source = source;
|
this.source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void next() throws EaterException, EaterExceptionLocated {
|
public void next() throws EaterException, EaterExceptionLocated {
|
||||||
source.next();
|
source.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
final public CodePosition getCodePosition() {
|
final public CodePosition getCodePosition() {
|
||||||
return source.getCodePosition();
|
return source.getCodePosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
final public void jumpToCodePosition(CodePosition newPosition) throws EaterException {
|
@Override
|
||||||
source.jumpToCodePosition(newPosition);
|
final public void jumpToCodePosition(CodePosition newPosition, StringLocated location) throws EaterException {
|
||||||
|
source.jumpToCodePosition(newPosition, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ import net.sourceforge.plantuml.tim.EaterException;
|
||||||
import net.sourceforge.plantuml.tim.EaterExceptionLocated;
|
import net.sourceforge.plantuml.tim.EaterExceptionLocated;
|
||||||
|
|
||||||
public interface CodeIterator {
|
public interface CodeIterator {
|
||||||
// ::remove folder when __HAXE__
|
// ::remove folder when __HAXE__
|
||||||
|
|
||||||
public StringLocated peek() throws EaterException, EaterExceptionLocated;
|
public StringLocated peek() throws EaterException, EaterExceptionLocated;
|
||||||
|
|
||||||
|
@ -47,6 +47,6 @@ public interface CodeIterator {
|
||||||
|
|
||||||
public CodePosition getCodePosition();
|
public CodePosition getCodePosition();
|
||||||
|
|
||||||
public void jumpToCodePosition(CodePosition newPosition) throws EaterException;
|
public void jumpToCodePosition(CodePosition newPosition, StringLocated location) throws EaterException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,7 @@ public class CodeIteratorAffectation extends AbstractCodeIterator {
|
||||||
this.logs = log;
|
this.logs = log;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public StringLocated peek() throws EaterException, EaterExceptionLocated {
|
public StringLocated peek() throws EaterException, EaterExceptionLocated {
|
||||||
while (true) {
|
while (true) {
|
||||||
final StringLocated result = source.peek();
|
final StringLocated result = source.peek();
|
||||||
|
@ -81,9 +82,9 @@ public class CodeIteratorAffectation extends AbstractCodeIterator {
|
||||||
this.executeAffectation(context, memory, result);
|
this.executeAffectation(context, memory, result);
|
||||||
return;
|
return;
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
if (e.getColumn() <= lastLocation) {
|
if (e.getColumn() <= lastLocation)
|
||||||
throw EaterException.located("Error in JSON format");
|
throw EaterException.located("Error in JSON format", result);
|
||||||
}
|
|
||||||
lastLocation = e.getColumn();
|
lastLocation = e.getColumn();
|
||||||
next();
|
next();
|
||||||
final StringLocated forward = source.peek();
|
final StringLocated forward = source.peek();
|
||||||
|
|
|
@ -65,9 +65,8 @@ public class CodeIteratorForeach extends AbstractCodeIterator {
|
||||||
int level = 0;
|
int level = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
final StringLocated result = source.peek();
|
final StringLocated result = source.peek();
|
||||||
if (result == null) {
|
if (result == null)
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
final ExecutionContextForeach foreach = memory.peekForeach();
|
final ExecutionContextForeach foreach = memory.peekForeach();
|
||||||
if (foreach != null && foreach.isSkipMe()) {
|
if (foreach != null && foreach.isSkipMe()) {
|
||||||
|
@ -91,15 +90,15 @@ public class CodeIteratorForeach extends AbstractCodeIterator {
|
||||||
continue;
|
continue;
|
||||||
} else if (result.getType() == TLineType.ENDFOREACH) {
|
} else if (result.getType() == TLineType.ENDFOREACH) {
|
||||||
logs.add(result);
|
logs.add(result);
|
||||||
if (foreach == null) {
|
if (foreach == null)
|
||||||
throw EaterException.located("No foreach related to this endforeach");
|
throw EaterException.located("No foreach related to this endforeach", result);
|
||||||
}
|
|
||||||
foreach.inc();
|
foreach.inc();
|
||||||
if (foreach.isSkipMe()) {
|
if (foreach.isSkipMe()) {
|
||||||
memory.pollForeach();
|
memory.pollForeach();
|
||||||
} else {
|
} else {
|
||||||
setLoopVariable(memory, foreach, result);
|
setLoopVariable(memory, foreach, result);
|
||||||
source.jumpToCodePosition(foreach.getStartForeach());
|
source.jumpToCodePosition(foreach.getStartForeach(), result);
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
continue;
|
continue;
|
||||||
|
@ -114,18 +113,18 @@ public class CodeIteratorForeach extends AbstractCodeIterator {
|
||||||
condition.analyze(context, memory);
|
condition.analyze(context, memory);
|
||||||
final ExecutionContextForeach foreach = ExecutionContextForeach.fromValue(condition.getVarname(),
|
final ExecutionContextForeach foreach = ExecutionContextForeach.fromValue(condition.getVarname(),
|
||||||
condition.getJsonArray(), source.getCodePosition());
|
condition.getJsonArray(), source.getCodePosition());
|
||||||
if (condition.isSkip()) {
|
if (condition.isSkip())
|
||||||
foreach.skipMeNow();
|
foreach.skipMeNow();
|
||||||
} else {
|
else
|
||||||
setLoopVariable(memory, foreach, s);
|
setLoopVariable(memory, foreach, s);
|
||||||
}
|
|
||||||
memory.addForeach(foreach);
|
memory.addForeach(foreach);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setLoopVariable(TMemory memory, ExecutionContextForeach foreach, StringLocated position)
|
private void setLoopVariable(TMemory memory, ExecutionContextForeach foreach, StringLocated position)
|
||||||
throws EaterException {
|
throws EaterException {
|
||||||
final JsonValue first = foreach.getJsonArray().get(foreach.currentIndex());
|
final JsonValue first = foreach.getJsonArray().get(foreach.currentIndex());
|
||||||
memory.putVariable(foreach.getVarname(), TValue.fromJson(first), TVariableScope.GLOBAL);
|
memory.putVariable(foreach.getVarname(), TValue.fromJson(first), TVariableScope.GLOBAL, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,18 +118,17 @@ public class CodeIteratorIf extends AbstractCodeIterator {
|
||||||
private void executeElseIf(TContext context, TMemory memory, StringLocated s)
|
private void executeElseIf(TContext context, TMemory memory, StringLocated s)
|
||||||
throws EaterException, EaterExceptionLocated {
|
throws EaterException, EaterExceptionLocated {
|
||||||
final ExecutionContextIf poll = (ExecutionContextIf) memory.peekIf();
|
final ExecutionContextIf poll = (ExecutionContextIf) memory.peekIf();
|
||||||
if (poll == null) {
|
if (poll == null)
|
||||||
throw EaterException.located("No if related to this else");
|
throw EaterException.located("No if related to this else", s);
|
||||||
}
|
|
||||||
|
|
||||||
poll.enteringElseIf();
|
poll.enteringElseIf();
|
||||||
if (poll.hasBeenBurn() == false) {
|
if (poll.hasBeenBurn() == false) {
|
||||||
final EaterElseIf condition = new EaterElseIf(s);
|
final EaterElseIf condition = new EaterElseIf(s);
|
||||||
condition.analyze(context, memory);
|
condition.analyze(context, memory);
|
||||||
final boolean isTrue = condition.isTrue();
|
final boolean isTrue = condition.isTrue();
|
||||||
if (isTrue) {
|
if (isTrue)
|
||||||
poll.nowInSomeElseIf();
|
poll.nowInSomeElseIf();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,17 +148,17 @@ public class CodeIteratorIf extends AbstractCodeIterator {
|
||||||
|
|
||||||
private void executeElse(TContext context, TMemory memory, StringLocated s) throws EaterException {
|
private void executeElse(TContext context, TMemory memory, StringLocated s) throws EaterException {
|
||||||
final ExecutionContextIf poll = (ExecutionContextIf) memory.peekIf();
|
final ExecutionContextIf poll = (ExecutionContextIf) memory.peekIf();
|
||||||
if (poll == null) {
|
if (poll == null)
|
||||||
throw EaterException.located("No if related to this else");
|
throw EaterException.located("No if related to this else", s);
|
||||||
}
|
|
||||||
poll.nowInElse();
|
poll.nowInElse();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void executeEndif(TContext context, TMemory memory, StringLocated s) throws EaterException {
|
private void executeEndif(TContext context, TMemory memory, StringLocated s) throws EaterException {
|
||||||
final ExecutionContextIf poll = (ExecutionContextIf) memory.pollIf();
|
final ExecutionContextIf poll = (ExecutionContextIf) memory.pollIf();
|
||||||
if (poll == null) {
|
if (poll == null)
|
||||||
throw EaterException.located("No if related to this endif");
|
throw EaterException.located("No if related to this endif", s);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,34 +62,38 @@ public class CodeIteratorImpl implements CodeIterator {
|
||||||
this.list = list;
|
this.list = list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public StringLocated peek() {
|
public StringLocated peek() {
|
||||||
if (current == list.size()) {
|
if (current == list.size())
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
if (current > list.size()) {
|
if (current > list.size())
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
|
||||||
return list.get(current);
|
return list.get(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void next() {
|
public void next() {
|
||||||
if (current >= list.size()) {
|
if (current >= list.size())
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
|
||||||
assert current < list.size();
|
assert current < list.size();
|
||||||
current++;
|
current++;
|
||||||
assert current <= list.size();
|
assert current <= list.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public CodePosition getCodePosition() {
|
public CodePosition getCodePosition() {
|
||||||
return new Position(current);
|
return new Position(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void jumpToCodePosition(CodePosition newPosition) throws EaterException {
|
@Override
|
||||||
|
public void jumpToCodePosition(CodePosition newPosition, StringLocated location) throws EaterException {
|
||||||
this.countJump++;
|
this.countJump++;
|
||||||
if (this.countJump > 999) {
|
if (this.countJump > 999)
|
||||||
throw EaterException.unlocated("Infinite loop?");
|
throw EaterException.unlocated("Infinite loop?", location);
|
||||||
}
|
|
||||||
final Position pos = (Position) newPosition;
|
final Position pos = (Position) newPosition;
|
||||||
this.current = pos.pos;
|
this.current = pos.pos;
|
||||||
|
|
||||||
|
|
|
@ -67,13 +67,13 @@ public class CodeIteratorSub extends AbstractCodeIterator {
|
||||||
}
|
}
|
||||||
|
|
||||||
public StringLocated peek() throws EaterException, EaterExceptionLocated {
|
public StringLocated peek() throws EaterException, EaterExceptionLocated {
|
||||||
if (readingInProgress != null) {
|
if (readingInProgress != null)
|
||||||
return readingInProgress.peek();
|
return readingInProgress.peek();
|
||||||
}
|
|
||||||
StringLocated result = source.peek();
|
StringLocated result = source.peek();
|
||||||
if (result == null) {
|
if (result == null)
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
if (result.getType() == TLineType.STARTSUB) {
|
if (result.getType() == TLineType.STARTSUB) {
|
||||||
final EaterStartsub eater = new EaterStartsub(result.getTrimmed());
|
final EaterStartsub eater = new EaterStartsub(result.getTrimmed());
|
||||||
eater.analyze(context, memory);
|
eater.analyze(context, memory);
|
||||||
|
@ -83,7 +83,7 @@ public class CodeIteratorSub extends AbstractCodeIterator {
|
||||||
StringLocated s = null;
|
StringLocated s = null;
|
||||||
while ((s = source.peek()) != null) {
|
while ((s = source.peek()) != null) {
|
||||||
if (s.getType() == TLineType.STARTSUB) {
|
if (s.getType() == TLineType.STARTSUB) {
|
||||||
throw EaterException.located("Cannot nest sub");
|
throw EaterException.located("Cannot nest sub", result);
|
||||||
} else if (s.getType() == TLineType.ENDSUB) {
|
} else if (s.getType() == TLineType.ENDSUB) {
|
||||||
source.next();
|
source.next();
|
||||||
readingInProgress = new CodeIteratorImpl(created.lines());
|
readingInProgress = new CodeIteratorImpl(created.lines());
|
||||||
|
@ -94,9 +94,9 @@ public class CodeIteratorSub extends AbstractCodeIterator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (readingInProgress != null) {
|
if (readingInProgress != null)
|
||||||
return readingInProgress.peek();
|
return readingInProgress.peek();
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,9 +107,9 @@ public class CodeIteratorSub extends AbstractCodeIterator {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
readingInProgress.next();
|
readingInProgress.next();
|
||||||
if (readingInProgress.peek() == null) {
|
if (readingInProgress.peek() == null)
|
||||||
readingInProgress = null;
|
readingInProgress = null;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,9 +64,8 @@ public class CodeIteratorWhile extends AbstractCodeIterator {
|
||||||
int level = 0;
|
int level = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
final StringLocated result = source.peek();
|
final StringLocated result = source.peek();
|
||||||
if (result == null) {
|
if (result == null)
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
final ExecutionContextWhile currentWhile = memory.peekWhile();
|
final ExecutionContextWhile currentWhile = memory.peekWhile();
|
||||||
if (currentWhile != null && currentWhile.isSkipMe()) {
|
if (currentWhile != null && currentWhile.isSkipMe()) {
|
||||||
|
@ -91,14 +90,14 @@ public class CodeIteratorWhile extends AbstractCodeIterator {
|
||||||
} else if (result.getType() == TLineType.ENDWHILE) {
|
} else if (result.getType() == TLineType.ENDWHILE) {
|
||||||
logs.add(result);
|
logs.add(result);
|
||||||
if (currentWhile == null)
|
if (currentWhile == null)
|
||||||
throw EaterException.located("No while related to this endwhile");
|
throw EaterException.located("No while related to this endwhile", result);
|
||||||
|
|
||||||
final TValue value = currentWhile.conditionValue(result, context, memory);
|
final TValue value = currentWhile.conditionValue(result, context, memory);
|
||||||
if (value.toBoolean()) {
|
if (value.toBoolean())
|
||||||
source.jumpToCodePosition(currentWhile.getStartWhile());
|
source.jumpToCodePosition(currentWhile.getStartWhile(), result);
|
||||||
} else {
|
else
|
||||||
memory.pollWhile();
|
memory.pollWhile();
|
||||||
}
|
|
||||||
next();
|
next();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,9 +65,9 @@ public class CallUserFunction extends SimpleReturnFunction {
|
||||||
final List<TValue> args = values.subList(1, values.size());
|
final List<TValue> args = values.subList(1, values.size());
|
||||||
final TFunctionSignature signature = new TFunctionSignature(fname, args.size());
|
final TFunctionSignature signature = new TFunctionSignature(fname, args.size());
|
||||||
final TFunction func = context.getFunctionSmart(signature);
|
final TFunction func = context.getFunctionSmart(signature);
|
||||||
if (func == null) {
|
if (func == null)
|
||||||
throw EaterException.unlocated("Cannot find void function " + fname);
|
throw EaterException.unlocated("Cannot find void function " + fname, location);
|
||||||
}
|
|
||||||
return func.executeReturnFunction(context, memory, location, args, named);
|
return func.executeReturnFunction(context, memory, location, args, named);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ public class Darken extends SimpleReturnFunction {
|
||||||
color = color.darken(ratio);
|
color = color.darken(ratio);
|
||||||
return TValue.fromString(color.asString());
|
return TValue.fromString(color.asString());
|
||||||
} catch (NoSuchColorException e) {
|
} catch (NoSuchColorException e) {
|
||||||
throw EaterException.located("No such color");
|
throw EaterException.located("No such color", location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,10 +71,11 @@ public class DateFunction extends SimpleReturnFunction {
|
||||||
now = 1000L * values.get(1).toInt();
|
now = 1000L * values.get(1).toInt();
|
||||||
else
|
else
|
||||||
now = System.currentTimeMillis();
|
now = System.currentTimeMillis();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return TValue.fromString(new SimpleDateFormat(format).format(now));
|
return TValue.fromString(new SimpleDateFormat(format).format(now));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw EaterException.unlocated("Bad date pattern");
|
throw EaterException.unlocated("Bad date pattern", location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,7 +99,8 @@ public class GetAllStdlib extends SimpleReturnFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw EaterException.located("Error on get_all_stdlib: Too many arguments");
|
assert false; // Should not append because of canCover()
|
||||||
|
throw EaterException.located("Error on get_all_stdlib: Too many arguments", location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,8 @@ public class GetJsonKey extends SimpleReturnFunction {
|
||||||
Map<String, TValue> named) throws EaterException, EaterExceptionLocated {
|
Map<String, TValue> named) throws EaterException, EaterExceptionLocated {
|
||||||
final TValue data = values.get(0);
|
final TValue data = values.get(0);
|
||||||
if (data.isJson() == false)
|
if (data.isJson() == false)
|
||||||
throw EaterException.unlocated("Not JSON data");
|
throw EaterException.unlocated("Not JSON data", location);
|
||||||
|
|
||||||
final JsonValue json = data.toJson();
|
final JsonValue json = data.toJson();
|
||||||
if (json.isObject()) {
|
if (json.isObject()) {
|
||||||
final JsonObject object = (JsonObject) json;
|
final JsonObject object = (JsonObject) json;
|
||||||
|
@ -87,7 +88,7 @@ public class GetJsonKey extends SimpleReturnFunction {
|
||||||
return TValue.fromJson(result);
|
return TValue.fromJson(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw EaterException.unlocated("Bad JSON type");
|
throw EaterException.unlocated("Bad JSON type", location);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ public class InvokeProcedure implements TFunction {
|
||||||
final TFunctionSignature signature = new TFunctionSignature(fname, sublist.size());
|
final TFunctionSignature signature = new TFunctionSignature(fname, sublist.size());
|
||||||
final TFunction func = context.getFunctionSmart(signature);
|
final TFunction func = context.getFunctionSmart(signature);
|
||||||
if (func == null)
|
if (func == null)
|
||||||
throw EaterException.located("Cannot find void function " + fname);
|
throw EaterException.located("Cannot find void function " + fname, location);
|
||||||
|
|
||||||
func.executeProcedureInternal(context, memory, location, sublist, named);
|
func.executeProcedureInternal(context, memory, location, sublist, named);
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ public class IsDark extends SimpleReturnFunction {
|
||||||
final HColor color = HColorSet.instance().getColorLEGACY(colorString);
|
final HColor color = HColorSet.instance().getColorLEGACY(colorString);
|
||||||
return TValue.fromBoolean(color.isDark());
|
return TValue.fromBoolean(color.isDark());
|
||||||
} catch (NoSuchColorException e) {
|
} catch (NoSuchColorException e) {
|
||||||
throw EaterException.located("No such color");
|
throw EaterException.located("No such color", location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ public class IsLight extends SimpleReturnFunction {
|
||||||
final HColor color = HColorSet.instance().getColorLEGACY(colorString);
|
final HColor color = HColorSet.instance().getColorLEGACY(colorString);
|
||||||
return TValue.fromBoolean(!color.isDark());
|
return TValue.fromBoolean(!color.isDark());
|
||||||
} catch (NoSuchColorException e) {
|
} catch (NoSuchColorException e) {
|
||||||
throw EaterException.located("No such color");
|
throw EaterException.located("No such color", location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,7 @@ public class Lighten extends SimpleReturnFunction {
|
||||||
color = color.lighten(ratio);
|
color = color.lighten(ratio);
|
||||||
return TValue.fromString(color.asString());
|
return TValue.fromString(color.asString());
|
||||||
} catch (NoSuchColorException e) {
|
} catch (NoSuchColorException e) {
|
||||||
throw EaterException.located("No such color");
|
throw EaterException.located("No such color", location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,10 +120,11 @@ public class LoadJson extends SimpleReturnFunction {
|
||||||
return TValue.fromJson(jsonValue);
|
return TValue.fromJson(jsonValue);
|
||||||
} catch (ParseException pe) {
|
} catch (ParseException pe) {
|
||||||
Logme.error(pe);
|
Logme.error(pe);
|
||||||
throw EaterException.unlocated("JSON parse issue in source " + path + " on location " + pe.getLocation());
|
throw EaterException.unlocated("JSON parse issue in source " + path + " on location " + pe.getLocation(),
|
||||||
|
location);
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
Logme.error(e);
|
Logme.error(e);
|
||||||
throw EaterException.unlocated("JSON encoding issue in source " + path + ": " + e.getMessage());
|
throw EaterException.unlocated("JSON encoding issue in source " + path + ": " + e.getMessage(), location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,8 @@ public class RandomFunction extends SimpleReturnFunction {
|
||||||
return TValue.fromInt(random.nextInt(max - min) + min);
|
return TValue.fromInt(random.nextInt(max - min) + min);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw EaterException.located("Error on Random: Too many argument");
|
assert false; // Should not append because of canCover()
|
||||||
|
throw EaterException.located("Error on Random: Too many argument", location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ public class ReverseColor extends SimpleReturnFunction {
|
||||||
color = color.reverse();
|
color = color.reverse();
|
||||||
return TValue.fromString(color.asString());
|
return TValue.fromString(color.asString());
|
||||||
} catch (NoSuchColorException e) {
|
} catch (NoSuchColorException e) {
|
||||||
throw EaterException.located("No such color");
|
throw EaterException.located("No such color", location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ public class ReverseHsluvColor extends SimpleReturnFunction {
|
||||||
color = color.reverseHsluv();
|
color = color.reverseHsluv();
|
||||||
return TValue.fromString(color.asString());
|
return TValue.fromString(color.asString());
|
||||||
} catch (NoSuchColorException e) {
|
} catch (NoSuchColorException e) {
|
||||||
throw EaterException.located("No such color");
|
throw EaterException.located("No such color", location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,7 @@ public class SetVariableValue extends SimpleReturnFunction {
|
||||||
// }
|
// }
|
||||||
final String name = values.get(0).toString();
|
final String name = values.get(0).toString();
|
||||||
final TValue value = values.get(1);
|
final TValue value = values.get(1);
|
||||||
memory.putVariable(name, value, TVariableScope.GLOBAL);
|
memory.putVariable(name, value, TVariableScope.GLOBAL, location);
|
||||||
return TValue.fromString("");
|
return TValue.fromString("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ public class Version {
|
||||||
|
|
||||||
// Warning, "version" should be the same in gradle.properties and Version.java
|
// Warning, "version" should be the same in gradle.properties and Version.java
|
||||||
// Any idea anyone how to magically synchronize those :-) ?
|
// Any idea anyone how to magically synchronize those :-) ?
|
||||||
private static final String version = "1.2024.4beta2";
|
private static final String version = "1.2024.4beta3";
|
||||||
|
|
||||||
public static String versionString() {
|
public static String versionString() {
|
||||||
return version;
|
return version;
|
||||||
|
|
Loading…
Reference in New Issue